From 95772acbd2676873d1b1c7b2c4a4df0a44c01293 Mon Sep 17 00:00:00 2001 From: Egor Tensin Date: Thu, 16 Jun 2016 15:12:59 +0300 Subject: add CSV database reader --- vk/utils/tracking/db/reader/__init__.py | 5 +++ vk/utils/tracking/db/reader/csv.py | 22 +++++++++++ vk/utils/tracking/db/record.py | 68 +++++++++++++++++++++++++-------- vk/utils/tracking/db/writer/csv.py | 21 +++++----- 4 files changed, 92 insertions(+), 24 deletions(-) create mode 100644 vk/utils/tracking/db/reader/__init__.py create mode 100644 vk/utils/tracking/db/reader/csv.py (limited to 'vk') diff --git a/vk/utils/tracking/db/reader/__init__.py b/vk/utils/tracking/db/reader/__init__.py new file mode 100644 index 0000000..330d5a8 --- /dev/null +++ b/vk/utils/tracking/db/reader/__init__.py @@ -0,0 +1,5 @@ +# Copyright 2016 Egor Tensin +# This file is licensed under the terms of the MIT License. +# See LICENSE.txt for details. + +__all__ = 'csv', diff --git a/vk/utils/tracking/db/reader/csv.py b/vk/utils/tracking/db/reader/csv.py new file mode 100644 index 0000000..b66e397 --- /dev/null +++ b/vk/utils/tracking/db/reader/csv.py @@ -0,0 +1,22 @@ +# Copyright 2016 Egor Tensin +# This file is licensed under the terms of the MIT License. +# See LICENSE.txt for details. + +import csv + +from ..record import Record + +class Reader: + def __init__(self, path): + self._fd = open(path) + self._reader = csv.reader(self._fd) + + def __enter__(self): + self._fd.__enter__() + return self + + def __exit__(self, *args): + self._fd.__exit__(*args) + + def __iter__(self): + return map(Record.from_row, self._reader) diff --git a/vk/utils/tracking/db/record.py b/vk/utils/tracking/db/record.py index 0a1a687..e126442 100644 --- a/vk/utils/tracking/db/record.py +++ b/vk/utils/tracking/db/record.py @@ -5,23 +5,61 @@ from collections import OrderedDict from datetime import datetime -from vk.user import Field +from vk.user import Field as UserField + +def _gen_timestamp(): + return datetime.utcnow().replace(microsecond=0) class Record: - _FIELDS = ( - Field.UID, - Field.FIRST_NAME, - Field.LAST_NAME, - Field.SCREEN_NAME, - Field.ONLINE, - Field.LAST_SEEN, + _USER_FIELDS = ( + UserField.UID, + UserField.FIRST_NAME, + UserField.LAST_NAME, + UserField.SCREEN_NAME, + UserField.ONLINE, + UserField.LAST_SEEN, ) - def __init__(self, user): - self._fields = OrderedDict() - for field in self._FIELDS: - self._fields[field] = user[field] - self._timestamp = datetime.utcnow().replace(microsecond=0) + def __init__(self, fields, timestamp=None): + self._fields = fields + self._timestamp = timestamp if timestamp is not None else _gen_timestamp() + + def __iter__(self): + return iter(self._fields) + + def __contains__(self, field): + return field in self._fields + + def __getitem__(self, field): + return self._fields[field] + + def __setitem__(self, field, value): + self._fields[field] = value + + def get_timestamp(self): + return self._timestamp + + @staticmethod + def _timestamp_from_string(s): + return datetime.fromtimestamp(s) + + def timestamp_to_string(self): + return self.get_timestamp().isoformat() + + @staticmethod + def from_user(user): + fields = OrderedDict() + for field in Record._USER_FIELDS: + fields[field] = user[field] + return Record(fields) + + @staticmethod + def from_row(row): + timestamp = Record._timestamp_from_string(row[0]) + fields = OrderedDict() + for i in range(len(Record._USER_FIELDS)): + fields[Record._USER_FIELDS[i]] = row[i + 1] + return Record(fields, timestamp) - def to_list(self): - return [self._timestamp.isoformat()] + list(self._fields.values()) + def to_row(self): + return [self.timestamp_to_string()] + [self[field] for field in self] diff --git a/vk/utils/tracking/db/writer/csv.py b/vk/utils/tracking/db/writer/csv.py index 4594e09..8dc2299 100644 --- a/vk/utils/tracking/db/writer/csv.py +++ b/vk/utils/tracking/db/writer/csv.py @@ -3,7 +3,6 @@ # See LICENSE.txt for details. import csv -from datetime import datetime from ..record import Record @@ -15,25 +14,29 @@ class Writer: self._fd = open(path, mode) self._writer = csv.writer(self._fd, lineterminator='\n') - def _is_valid(self): + def __bool__(self): return self._fd is not None def __enter__(self): - if not self._is_valid(): - return None + if not self: + return self self._fd.__enter__() return self def __exit__(self, *args): - if self._is_valid(): - self._fd.__exit__(*args) + if not self: + return + self._fd.__exit__(*args) def flush(self): - if self._is_valid(): - self._fd.flush() + if not self: + return + self._fd.flush() def write_record(self, user): - self._write_row(Record(user).to_list()) + if not self: + return + self._write_row(Record.from_user(user).to_row()) self.flush() def _write_row(self, row): -- cgit v1.2.3