From 6f5d460c0a39f3783ed723863a5ca0e3d2305665 Mon Sep 17 00:00:00 2001 From: Sergey Sablin Date: Fri, 1 May 2020 12:05:34 +0300 Subject: [PATCH 1/2] HW files --- homework/config.py | 12 +- homework/csv_reader.py | 44 +++++++ homework/csv_recorder.py | 27 +++++ homework/error_log.txt | 6 + homework/info_log.txt | 15 +++ homework/logger.py | 15 +++ homework/output.csv | 3 + homework/patient.py | 242 ++++++++++++++++++++++++++++++++++++--- homework/reader.py | 8 ++ homework/recorder.py | 11 ++ 10 files changed, 360 insertions(+), 23 deletions(-) create mode 100644 homework/csv_reader.py create mode 100644 homework/csv_recorder.py create mode 100644 homework/error_log.txt create mode 100644 homework/info_log.txt create mode 100644 homework/logger.py create mode 100644 homework/output.csv create mode 100644 homework/reader.py create mode 100644 homework/recorder.py diff --git a/homework/config.py b/homework/config.py index 955b991..39e868a 100644 --- a/homework/config.py +++ b/homework/config.py @@ -1,13 +1,13 @@ -GOOD_LOG_FILE = "good_log.txt" +GOOD_LOG_FILE = "info_log.txt" ERROR_LOG_FILE = "error_log.txt" -CSV_PATH = "csv.csv" -PHONE_FORMAT = "79160000000" # Здесь запишите телефон +7-916-000-00-00 в том формате, в котором вы храните телефоны +CSV_PATH = "output.csv" +PHONE_FORMAT = "9160000000" # Здесь запишите телефон +7-916-000-00-00 в том формате, в котором вы храните телефоны PASSPORT_TYPE = "паспорт" # тип документа, когда он паспорт -PASSPORT_FORMAT = "0000 000000" # Здесь запишите номер парспорта 0000 000000 в том формате, в котором вы его храните +PASSPORT_FORMAT = "0000000000" # Здесь запишите номер парспорта 0000 000000 в том формате, в котором вы его храните INTERNATIONAL_PASSPORT_TYPE = "заграничный паспорт" # тип документа, если это загран -INTERNATIONAL_PASSPORT_FORMAT = "00 0000000" # формат хранения заграна для номера 00 0000000 +INTERNATIONAL_PASSPORT_FORMAT = "000000000" # формат хранения заграна для номера 00 0000000 DRIVER_LICENSE_TYPE = "водительское удостоверение" # тип документа, если это водительское удостоверение -DRIVER_LICENSE_FORMAT = "00 00 000000" # формат хранения номера ВУ +DRIVER_LICENSE_FORMAT = "0000000000" # формат хранения номера ВУ diff --git a/homework/csv_reader.py b/homework/csv_reader.py new file mode 100644 index 0000000..0f34a0f --- /dev/null +++ b/homework/csv_reader.py @@ -0,0 +1,44 @@ +from abc import ABC + +import homework.reader as reader +import pandas +import pathlib + + +class CsvReader(reader.Reader, ABC): + def __init__(self, classname, source): + super().__init__(classname, source) + self.classname = classname + self.source = source + self.path = pathlib.Path(source) + self._parse_file() + self.last_modified = self._last_modification_time() + + def _parse_file(self): + self.last_modified = self._last_modification_time() + if self.path.read_bytes() == 0: + self._patients = list() + return + try: + self.df = pandas.read_csv(self.source, sep='|', dtype=str) + except pandas.errors.EmptyDataError: + self._patients = list() + return + + columns = self.df.columns + axes = [self.df[i].values.tolist() for i in columns] + values = dict(zip(columns, axes)) + self._patients = list() + for i in self.df.index: + first_name = str(values['first_name'][i]) + last_name = str(values['last_name'][i]) + birth_date = str(values['birth_date'][i]) + phone = str(values['phone'][i]) + document_id = str(values['document_id'][i]) + document_type = str(values['document_type'][i]) + new_patient = self.classname(first_name, last_name, birth_date, + phone, document_type, document_id) + self._patients.append(new_patient) + + def _last_modification_time(self): + return self.path.stat().st_mtime diff --git a/homework/csv_recorder.py b/homework/csv_recorder.py new file mode 100644 index 0000000..a8cee23 --- /dev/null +++ b/homework/csv_recorder.py @@ -0,0 +1,27 @@ +from abc import ABC + +import homework.recorder as recorder +import pandas +"""Каждому полю объекта, переданному в качестве аргумента, + выделяем колонку с записываемым значением, где и храним данные""" + + +class CsvRecorder(recorder.Recorder, ABC): + def __init__(self, classname, filename): + super().__init__(classname, filename) + d = [p for p in dir(classname) if isinstance(getattr(classname, p), property)] + self.df = pandas.DataFrame(columns=d) + self.filename = filename + self.empty = True + + def record(self, obj): + # Добавим столбцы таблицы с именами свойств (property) объекта + # Значениями таблицы будут значения свойств объекта + insertion = [getattr(obj, column) for column in self.df.columns] + df = pandas.DataFrame([insertion], columns=self.df.columns) + if self.empty: + self.df = df + self.empty = False + else: + self.df = self.df.append(df, ignore_index=True) + self.df.to_csv(self.filename, sep='|') diff --git a/homework/error_log.txt b/homework/error_log.txt new file mode 100644 index 0000000..946e183 --- /dev/null +++ b/homework/error_log.txt @@ -0,0 +1,6 @@ +ERROR [2020-05-01 08:35:13,982] 1111111111 must be string +ERROR [2020-05-01 08:37:16,241] 2000-12-12 must be an alpha +ERROR [2020-05-01 08:37:52,091] 2000-12-12 must be an alpha +ERROR [2020-05-01 09:12:27,090] Bad parameter named "document_type" for Patient +ERROR [2020-05-01 09:13:16,500] Bad parameter named "document_type" for Patient +ERROR [2020-05-01 09:14:22,862] Bad parameter named "document_type" for Patient diff --git a/homework/info_log.txt b/homework/info_log.txt new file mode 100644 index 0000000..a2d65cc --- /dev/null +++ b/homework/info_log.txt @@ -0,0 +1,15 @@ +INFO [2020-05-01 08:52:48,396] Created new Patient Pleg Ivanov +INFO [2020-05-01 08:52:48,397] Patient Pleg Ivanov has been successfully saved +INFO [2020-05-01 08:52:48,424] Created new Patient Oleg Sergeev +INFO [2020-05-01 08:53:01,986] Created new Patient Pleg Ivanov +INFO [2020-05-01 08:53:01,986] Patient Pleg Ivanov has been successfully saved +INFO [2020-05-01 08:53:01,996] Created new Patient Oleg Sergeev +INFO [2020-05-01 08:53:01,996] Patient Oleg Sergeev has been successfully saved +INFO [2020-05-01 09:16:23,279] Created new Patient Pleg Ivanov +INFO [2020-05-01 09:16:23,295] Created new Patient Oleg Sergeev +INFO [2020-05-01 09:37:07,992] Created new Patient Pleg Ivanov +INFO [2020-05-01 09:37:08,005] Created new Patient Oleg Sergeev +INFO [2020-05-01 09:38:08,594] Created new Patient Pleg Ivanov +INFO [2020-05-01 09:38:08,595] Created new Patient Oleg Sergeev +INFO [2020-05-01 09:47:06,480] Created new Patient Pleg Ivanov +INFO [2020-05-01 09:47:06,515] Created new Patient Oleg Sergeev diff --git a/homework/logger.py b/homework/logger.py new file mode 100644 index 0000000..c7b0992 --- /dev/null +++ b/homework/logger.py @@ -0,0 +1,15 @@ +import logging + +error_logger = logging.getLogger("Error logger") +error_logger.setLevel(logging.ERROR) +error_handler = logging.FileHandler('error_log.txt', 'a', 'utf-8') +error_formatter = logging.Formatter("%(levelname)-8s [%(asctime)s] %(message)s") +error_handler.setFormatter(error_formatter) +error_logger.addHandler(error_handler) + +info_logger = logging.getLogger("Info logger") +info_logger.setLevel(logging.INFO) +info_handler = logging.FileHandler('info_log.txt', 'a', 'utf-8') +info_formatter = logging.Formatter("%(levelname)-8s [%(asctime)s] %(message)s") +info_handler.setFormatter(info_formatter) +info_logger.addHandler(info_handler) \ No newline at end of file diff --git a/homework/output.csv b/homework/output.csv new file mode 100644 index 0000000..dad742e --- /dev/null +++ b/homework/output.csv @@ -0,0 +1,3 @@ +|birth_date|document_id|document_type|first_name|last_name|phone +0|2000-12-12|1111111111|паспорт|Pleg|Ivanov|79160000000 +1|2000-11-11|2222222222|паспорт|Oleg|Sergeev|79170000000 diff --git a/homework/patient.py b/homework/patient.py index dad2526..ee6e66c 100644 --- a/homework/patient.py +++ b/homework/patient.py @@ -1,17 +1,225 @@ -class Patient: - def __init__(self, *args, **kwargs): - pass - - def create(*args, **kwargs): - raise NotImplementedError() - - def save(self): - pass - - -class PatientCollection: - def __init__(self, log_file): - pass - - def limit(self, n): - raise NotImplementedError() +from homework.logger import error_logger, info_logger +import homework.csv_recorder as csv_recorder +from homework.csv_reader import CsvReader + + +class Patient(object): + def __init__(self, first_name, last_name, birth_date, + phone, document_type, document_id): + for string in (first_name, last_name, birth_date, phone, document_id, document_type): + if not isinstance(string, str): + error_logger.error(f'{string} must be string') + raise TypeError + for word in (first_name, last_name): + if not word.isalpha(): + error_logger.error(f'{word} must be an alpha') + raise ValueError + + if not self.__check_birth_date(str(birth_date)): + error_logger.error('Bad parameter named "birth_date" for Patient') + raise ValueError + if not self.__check_phone(str(phone)): + error_logger.error('Bad parameter named "phone" for Patient') + raise ValueError + if not self.__check_doc_type(str(document_type)): + error_logger.error('Bad parameter named "document_type" for Patient') + raise ValueError + if not self.__check_doc_id(str(document_id)): + error_logger.error('Bad parameter named "document_id" for Patient') + raise ValueError + + self._first_name = str(first_name) + self._last_name = str(last_name) + self._birth_date = str(birth_date) + self._phone = Patient.parse_phone(phone) + self._doc_type = str(document_type) + self._doc_id = Patient.parse_document_id(document_id) + info_logger.info("Created new Patient {} {}".format(str(first_name), str(last_name))) + + def __str__(self): + return ' '.join((self._first_name, self._last_name, self._birth_date, + self._phone, self._doc_type, self._doc_id)) + + @staticmethod + def create(fname, lname, birth_date, phone, document_type, document_id): + return Patient(fname, lname, birth_date, phone, document_type, document_id) + + @staticmethod + def __check_birth_date(date): + import time + try: + time.strptime(date, '%Y-%m-%d') + res = True + except ValueError: + try: + time.strptime(date, '%Y.%m.%d') + res = True + except ValueError: + res = False + return res + + @staticmethod + def parse_phone(phone): + return phone.replace('+', '').replace('-', '').replace('(', '').replace(')', '').replace(' ', '') + + @staticmethod + def __check_phone(phone): + res = Patient.parse_phone(phone) + if len(res) == 11 and res[0] in {'7', '8'}: + return True + if len(res) == 10: + return True + return False + + @staticmethod + def __check_doc_type(doc_type): + if doc_type in {'водительское удостоверение', 'паспорт', 'заграничный паспорт'}: + return True + return False + + @staticmethod + def parse_document_id(doc_id): + return doc_id.replace(' ', '').replace('-', '').replace('/', '') + + @staticmethod + def __check_doc_id(doc_id): + res = Patient.parse_document_id(doc_id) + if not res.isdigit(): + return False + return True + + def save(self): + info_logger.info("Patient {} {} has been successfully saved".format(self._first_name, self._last_name)) + Patient_recorder.record(self) + + @property + def first_name(self): + return self._first_name + + @first_name.setter + def first_name(self, val): + error_logger.error('First name assignment forbidden') + raise AttributeError('First name assignment forbidden') + + @property + def last_name(self): + return self._last_name + + @last_name.setter + def last_name(self, val): + error_logger.error('Last name assignment forbidden') + raise AttributeError('Last name assignment forbidden') + + @property + def birth_date(self): + return self._birth_date + + @birth_date.setter + def birth_date(self, value): + if not isinstance(value, str): + error_logger.error(f'{value} must be string') + raise TypeError + + if not self.__check_birth_date(str(value)): + error_msg = 'Cannot set new value for field "birth_date": bad value {}'.format(str(value)) + error_logger.error(error_msg) + raise ValueError('Bad parameter {}'.format(str(value))) + + success_msg = "Patient {} field named 'birth_date' changed from {} to {} ".format( + self._first_name + ' ' + self._last_name, self._birth_date, str(value)) + info_logger.info(success_msg) + self._birth_date = str(str(value)) + + @property + def phone(self): + return self._phone + + @phone.setter + def phone(self, value): + if not isinstance(value, str): + error_logger.error(f'{value} must be string') + raise TypeError + + if not self.__check_phone(str(value)): + error_msg = 'Cannot set new value for field "phone": bad value {}'.format(str(value)) + error_logger.error(error_msg) + raise ValueError('Bad parameter {}'.format(str(value))) + + success_msg = "Patient {} field named 'birth_date' changed from {} to {} ".format( + self._first_name + ' ' + self._last_name, self._birth_date, str(value)) + info_logger.info(success_msg) + self._phone = str(value) + + @property + def document_type(self): + return self._doc_type + + @document_type.setter + def document_type(self, value): + if not isinstance(value, str): + error_logger.error(f'{value} must be string') + raise TypeError + if not self.__check_doc_type(str(value)): + error_msg = 'Cannot set new value for field "doc_type": bad value {}'.format(str(value)) + error_logger.error(error_msg) + raise ValueError('Bad parameter {}'.format(str(value))) + success_msg = "Patient {} field named 'birth_date' changed from {} to {} ".format( + self._first_name + ' ' + self._last_name, self._birth_date, str(value)) + info_logger.info(success_msg) + self._doc_type = str(value) + + @property + def document_id(self): + return self._doc_id + + @document_id.setter + def document_id(self, value): + if not isinstance(value, str): + error_logger.error(f'{value} must be string') + raise TypeError + if not self.__check_doc_id(str(value)): + error_msg = 'Cannot set new value for field "doc_id": bad value {}'.format(str(value)) + error_logger.error(error_msg) + raise ValueError('Bad parameter {}'.format(str(value))) + success_msg = "Patient {} field named 'birth_date' changed from {} to {} ".format( + self._first_name + ' ' + self._last_name, self._birth_date, str(value)) + info_logger.info(success_msg) + self._doc_id = str(value) + + +Patient_recorder = csv_recorder.CsvRecorder(Patient, "output.csv") + + +class PatientCollection(object): + def __init__(self, path_to_file): + self.reader = CsvReader(Patient, path_to_file) + + def limit(self, n): + counter = 0 + while counter < n: + if self.reader._last_modification_time() > self.reader.last_modified: + self.reader._parse_file() + if counter < len(self.reader._patients): + yield self.reader._patients[counter] + else: + break + counter += 1 + + def __iter__(self): + counter = 0 + while True: + if counter >= len(self.reader._patients): + raise StopIteration + if self.reader._last_modification_time() > self.reader.last_modified: + self.reader._parse_file() + if counter < len(self.reader._patients): + yield self.reader._patients[counter] + else: + yield + counter += 1 + +# +# p = Patient('Oleg', 'Ivanov', '2000-10-10', '79160000000', 'паспорт', '1111111111') +# p.save() +# p = Patient('Oleg1', 'Ivanov1', '2000-10-10', '79160000001', 'паспорт', '2222222222') +# p.save() diff --git a/homework/reader.py b/homework/reader.py new file mode 100644 index 0000000..eefeead --- /dev/null +++ b/homework/reader.py @@ -0,0 +1,8 @@ +import abc + + +class Reader(object): + @abc.abstractmethod + def __init__(self, classname, source): + """Инициализировать чтение из source""" + diff --git a/homework/recorder.py b/homework/recorder.py new file mode 100644 index 0000000..14465f6 --- /dev/null +++ b/homework/recorder.py @@ -0,0 +1,11 @@ +import abc + + +class Recorder(object): + @abc.abstractmethod + def __init__(self, classname, source): + """Инициализировать запись в source""" + + @abc.abstractmethod + def record(self, obj): + """Записать/дописать файл""" From 751fc61e4ee268b04d460aeb1a44b5d121f3772e Mon Sep 17 00:00:00 2001 From: Sergey Sablin Date: Thu, 7 May 2020 23:31:26 +0300 Subject: [PATCH 2/2] HW3 files --- homework/csv_reader.py | 44 ----------- homework/csv_recorder.py | 27 ------- homework/error_log.txt | 11 +++ homework/info_log.txt | Bin 1075 -> 18083 bytes homework/patient.py | 161 +++++++++++++++++++++++++++------------ homework/reader.py | 8 -- homework/recorder.py | 11 --- 7 files changed, 124 insertions(+), 138 deletions(-) delete mode 100644 homework/csv_reader.py delete mode 100644 homework/csv_recorder.py delete mode 100644 homework/reader.py delete mode 100644 homework/recorder.py diff --git a/homework/csv_reader.py b/homework/csv_reader.py deleted file mode 100644 index 0f34a0f..0000000 --- a/homework/csv_reader.py +++ /dev/null @@ -1,44 +0,0 @@ -from abc import ABC - -import homework.reader as reader -import pandas -import pathlib - - -class CsvReader(reader.Reader, ABC): - def __init__(self, classname, source): - super().__init__(classname, source) - self.classname = classname - self.source = source - self.path = pathlib.Path(source) - self._parse_file() - self.last_modified = self._last_modification_time() - - def _parse_file(self): - self.last_modified = self._last_modification_time() - if self.path.read_bytes() == 0: - self._patients = list() - return - try: - self.df = pandas.read_csv(self.source, sep='|', dtype=str) - except pandas.errors.EmptyDataError: - self._patients = list() - return - - columns = self.df.columns - axes = [self.df[i].values.tolist() for i in columns] - values = dict(zip(columns, axes)) - self._patients = list() - for i in self.df.index: - first_name = str(values['first_name'][i]) - last_name = str(values['last_name'][i]) - birth_date = str(values['birth_date'][i]) - phone = str(values['phone'][i]) - document_id = str(values['document_id'][i]) - document_type = str(values['document_type'][i]) - new_patient = self.classname(first_name, last_name, birth_date, - phone, document_type, document_id) - self._patients.append(new_patient) - - def _last_modification_time(self): - return self.path.stat().st_mtime diff --git a/homework/csv_recorder.py b/homework/csv_recorder.py deleted file mode 100644 index a8cee23..0000000 --- a/homework/csv_recorder.py +++ /dev/null @@ -1,27 +0,0 @@ -from abc import ABC - -import homework.recorder as recorder -import pandas -"""Каждому полю объекта, переданному в качестве аргумента, - выделяем колонку с записываемым значением, где и храним данные""" - - -class CsvRecorder(recorder.Recorder, ABC): - def __init__(self, classname, filename): - super().__init__(classname, filename) - d = [p for p in dir(classname) if isinstance(getattr(classname, p), property)] - self.df = pandas.DataFrame(columns=d) - self.filename = filename - self.empty = True - - def record(self, obj): - # Добавим столбцы таблицы с именами свойств (property) объекта - # Значениями таблицы будут значения свойств объекта - insertion = [getattr(obj, column) for column in self.df.columns] - df = pandas.DataFrame([insertion], columns=self.df.columns) - if self.empty: - self.df = df - self.empty = False - else: - self.df = self.df.append(df, ignore_index=True) - self.df.to_csv(self.filename, sep='|') diff --git a/homework/error_log.txt b/homework/error_log.txt index 946e183..c9b807d 100644 --- a/homework/error_log.txt +++ b/homework/error_log.txt @@ -4,3 +4,14 @@ ERROR [2020-05-01 08:37:52,091] 2000-12-12 must be an alpha ERROR [2020-05-01 09:12:27,090] Bad parameter named "document_type" for Patient ERROR [2020-05-01 09:13:16,500] Bad parameter named "document_type" for Patient ERROR [2020-05-01 09:14:22,862] Bad parameter named "document_type" for Patient +ERROR [2020-05-07 19:58:20,107] Type of parameter must be a string! +ERROR [2020-05-07 19:59:40,150] Type of parameter must be a string! +ERROR [2020-05-07 20:00:57,324] Type of parameter must be a string! +ERROR [2020-05-07 20:59:49,079] Type of parameter must be a string! +ERROR [2020-05-07 21:02:02,485] Type of parameter must be a string! +ERROR [2020-05-07 21:03:52,156] Bad type for Patient +ERROR [2020-05-07 21:07:32,858] Bad type for Patient +ERROR [2020-05-07 21:07:42,562] Bad type for Patient +ERROR [2020-05-07 21:08:47,915] Bad type for Patient +ERROR [2020-05-07 21:24:18,747] Bad value for Patient +ERROR [2020-05-07 22:05:13,038] Bad value for Patient diff --git a/homework/info_log.txt b/homework/info_log.txt index a2d65cc4345dda8f5fa1e3d1eb088e9a44a11f11..426ca1c062960f91736072553de48e9a5b72a4ba 100644 GIT binary patch literal 18083 zcmc&*O^@6*4DGqU!aqO(^l4kV7AUZnCP0rx58K2|3oJH3cC$tQeJPEsm4TslOfu-) z-}58+L{YNm?w6n6Px<$o)mFdL;hi>vsRVeVQJ(f2I%j&wp=^ z&(nv8?elc^a{u_{<;S}>I2Pczf}8%jf13W-w#Vt|+sBXF)6<{d9v=Rkp6*|^Pj7H~ z>k(b=v#wvaub;PVAj~CgR9soXbsS>BT{zLCp9!vz?815=A?-1lIa#Od5|OmOZHLAY z1H#dZMCu=tTasQ>j20oeMM&mYmDW5VYbFU1GvZA`DhEr5hiGQySIx-Cg(DcMkY%za z8J+y17K;h_GCf=?YmW^E31WzaM_XlA%$ql0BS|x~$f%sgtT=qG0M+1ti*bN@zZ!^XKX_n z)nUg{YPe(jk(Jt8gG+8z)>1sZW3lOC7=L|k#@_0sAO5G`m7@dfOBTlSJfVAizNa;; zIq%^k_SW2?G1z3ia`X8bf{uzk@Bde9_CGs@av}-y`JN6sD)zkp3)Wf{!zvMjPui=+ zk?O$1TBBSbKDS^=_4lb^+4ZknB3=r~IHleBz6^e-*zijF?axOAUXEkbMyT+^vYIJ-c71h67Kpz4t3B2>Cl!b3N|(|uC49Ht>U z+nPMwe!KJML-2_JHus{I6KX%HIz+hO{=mZB3uzw~!m{&Gb%?B+j*H;@iYD&j9lGU& z?sRE3xZiOx=lE(~(EDvzH|1`~Map>=?$u$QUwvM$EhofvlevOgiq|E$7P$XL&nUTW z$c;Z-?|_nwruihJ^V^rh`X~DY*c?>0oN`-M=xipxI-NCT<}wvaIWq$`Ky5vm(SbjA zEXkksxf$ECNA>50D~Nc#a-nq?`?I3an~$5(EhijD<;sTa3IR5kyjGF4-x(oni-PKt zPKOj1+SkXGu1fgm76;uYofZK$xch?p3G{0OkcoHqiY4`;4%?!j`lND+^rph)G&(nr zeIkMu+V83snRBNJc`vq(RBItD+b30rh)*tDp15;}p<7Pq{iM?(!Unt8?9u&r)K5a5 zZDu^DH)2~9)P7QR9Cl(J7yf==+)pk_nCLvax14Z%lB*LAZwbh37S8tYz6SlW3W(8t zXUC#vk{hutC&b$JIs~}j{@0MsouESmD-}cDBV@QNe!d#6n@dKxXqlaJ*CNCg%U7+I z(qC=GQr=beSaxlzjzcG*uE7gexi`6bUo-ZJ2wG-ds~Il4U&}DPzs3~cn?H-5SVldv zVkxs8L{XkAF=KrPE=QZ!suG9Z*u3SkoRfkUtE>>4)A<{$fZy*8d?JCB=mEP9NiKBV z3@g1W;iLIJ*|i*YV`4vX$t?LBT8*EJQJ=hG&+j|0*uxA<+AF>fSN7c5edkpPAI{bqCI--v4(9?(0x+4_~*aZm?%4k6gscFmJ?0~C|MC=Ta$tJUF9@+ zb^VNLU9o7Fy%F1TLiI_fLy8NXxd!_V_@pY~qgxzwpLAM8*n(5RoCO^X2AXWJ?S4WcTYJVN~lTHa8 zo%?f(gYJ{6MTRZ^g)#r1kJ3+eEV_CI9^0{pD2P7!9$d7YV^_jQ^L^555n!|VU4&cD z-?O;{e{B)LwkW7RsX7ifj{;ohJHnn3bh00IqaNLILhdI!+hMw=vq8Dxz37V0_oJR5 zgl##Y*0$<6O!fj?1fO(Dc<7cBc4ZGY4`epDjqyQw!he6^kA6bfmJ?!admU0-=$%l` iG&-^EO8Dp&2fMO|)x&0^%ouxCxY(8xrcchyvHt-f&qmb% delta 8 PcmZ47%ea|igE0#L4;lj0 diff --git a/homework/patient.py b/homework/patient.py index ee6e66c..9d58af2 100644 --- a/homework/patient.py +++ b/homework/patient.py @@ -1,31 +1,67 @@ from homework.logger import error_logger, info_logger -import homework.csv_recorder as csv_recorder -from homework.csv_reader import CsvReader +from sqlalchemy import Column, Integer, String, create_engine +from sqlalchemy.orm import sessionmaker +from sqlalchemy.ext.declarative import declarative_base -class Patient(object): +import click + +engine = create_engine('sqlite:///:memory:', echo=False) +Session = sessionmaker(bind=engine) + +session = Session() + +Base = declarative_base() + + +def logging_decorator(func): + def wrapper(self, *args): + if func.__name__ == '__init__': + first_name, last_name, birth_date, \ + phone, document_type, document_id = args + try: + result = func(self, first_name, last_name, birth_date, + phone, document_type, document_id) + info_logger.info("Created new Patient {} {}".format(str(first_name), str(last_name))) + except ValueError: + error_logger.error('Bad value for Patient') + raise ValueError + except TypeError: + error_logger.error('Bad type for Patient') + raise TypeError + return result + elif func.__name__ == 'save': + func(self) + info_logger.info( + "Patient {} {} has been successfully saved".format(self._first_name, self._last_name)) + + return wrapper + + +class Patient(Base): + __tablename__ = 'patients' + id = Column(Integer, primary_key=True) + first_name = Column(String) + last_name = Column(String) + birth_date = Column(String) + phone = Column(String) + document_type = Column(String) + document_id = Column(String) + + @logging_decorator def __init__(self, first_name, last_name, birth_date, phone, document_type, document_id): for string in (first_name, last_name, birth_date, phone, document_id, document_type): if not isinstance(string, str): - error_logger.error(f'{string} must be string') raise TypeError for word in (first_name, last_name): if not word.isalpha(): - error_logger.error(f'{word} must be an alpha') raise ValueError - if not self.__check_birth_date(str(birth_date)): - error_logger.error('Bad parameter named "birth_date" for Patient') - raise ValueError - if not self.__check_phone(str(phone)): - error_logger.error('Bad parameter named "phone" for Patient') - raise ValueError - if not self.__check_doc_type(str(document_type)): - error_logger.error('Bad parameter named "document_type" for Patient') - raise ValueError - if not self.__check_doc_id(str(document_id)): - error_logger.error('Bad parameter named "document_id" for Patient') + if not self.__check_birth_date(str(birth_date)) or \ + not self.__check_phone(str(phone)) or \ + not self.__check_doc_type(str(document_type)) or \ + not self.__check_doc_id(str(document_id)): raise ValueError self._first_name = str(first_name) @@ -88,9 +124,10 @@ def __check_doc_id(doc_id): return False return True + @logging_decorator def save(self): info_logger.info("Patient {} {} has been successfully saved".format(self._first_name, self._last_name)) - Patient_recorder.record(self) + session.add(self) @property def first_name(self): @@ -126,7 +163,7 @@ def birth_date(self, value): raise ValueError('Bad parameter {}'.format(str(value))) success_msg = "Patient {} field named 'birth_date' changed from {} to {} ".format( - self._first_name + ' ' + self._last_name, self._birth_date, str(value)) + self._first_name + ' ' + self._last_name, self._birth_date, str(value)) info_logger.info(success_msg) self._birth_date = str(str(value)) @@ -186,40 +223,68 @@ def document_id(self, value): info_logger.info(success_msg) self._doc_id = str(value) + def __repr__(self): + return "" \ + % (self.first_name, self.last_name, self.birth_date, + self.phone, self.document_type, self.document_id) -Patient_recorder = csv_recorder.CsvRecorder(Patient, "output.csv") +Base.metadata.create_all(engine) -class PatientCollection(object): - def __init__(self, path_to_file): - self.reader = CsvReader(Patient, path_to_file) +class PatientCollection(object): def limit(self, n): - counter = 0 - while counter < n: - if self.reader._last_modification_time() > self.reader.last_modified: - self.reader._parse_file() - if counter < len(self.reader._patients): - yield self.reader._patients[counter] - else: - break - counter += 1 + for patient in session.query(Patient)[:n]: + yield patient def __iter__(self): - counter = 0 - while True: - if counter >= len(self.reader._patients): - raise StopIteration - if self.reader._last_modification_time() > self.reader.last_modified: - self.reader._parse_file() - if counter < len(self.reader._patients): - yield self.reader._patients[counter] - else: - yield - counter += 1 - -# -# p = Patient('Oleg', 'Ivanov', '2000-10-10', '79160000000', 'паспорт', '1111111111') -# p.save() -# p = Patient('Oleg1', 'Ivanov1', '2000-10-10', '79160000001', 'паспорт', '2222222222') -# p.save() + for patient in session.query(Patient).all(): + yield patient + raise StopIteration + + @staticmethod + def size(): + return session.query(Patient).count() + + +@click.group() +def cli(): + pass + + +@click.command() +@click.argument('first_name') +@click.argument('last_name') +@click.option('--birth_date', default='1900-1-1') +@click.option('--phone', default='9161111111') +@click.option('--document_type', default='паспорт') +@click.option('--document_number', default='1111 111111') +def create(first_name, last_name, birth_date, + phone, document_type, document_number): + p = Patient(first_name, last_name, birth_date, + phone, document_type, document_number) + p.save() + + +@click.command() +@click.argument('COUNT', default='10') +def show(c): + p = PatientCollection() + for i in p.limit(c): + click.echo(i) + + +@click.command() +def count(): + click.echo(PatientCollection.size()) + + +cli.add_command(show) +cli.add_command(count) +cli.add_command(create) +if __name__ == '__main__': + p = Patient('o', 'l', '2000-11-11', '9160000000', 'паспорт', '1111111111') + p.save() + s = Patient('oo', 'll', '2000-12-11', '9120000000', 'паспорт', '1211111111') + s.save() + cli() diff --git a/homework/reader.py b/homework/reader.py deleted file mode 100644 index eefeead..0000000 --- a/homework/reader.py +++ /dev/null @@ -1,8 +0,0 @@ -import abc - - -class Reader(object): - @abc.abstractmethod - def __init__(self, classname, source): - """Инициализировать чтение из source""" - diff --git a/homework/recorder.py b/homework/recorder.py deleted file mode 100644 index 14465f6..0000000 --- a/homework/recorder.py +++ /dev/null @@ -1,11 +0,0 @@ -import abc - - -class Recorder(object): - @abc.abstractmethod - def __init__(self, classname, source): - """Инициализировать запись в source""" - - @abc.abstractmethod - def record(self, obj): - """Записать/дописать файл"""