Skip to content
106 changes: 106 additions & 0 deletions homework/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
from patient import Patient, PatientCollection
import click
import sqlite3


class OptionEatAll(click.Option):

def __init__(self, *args, **kwargs):
self.save_other_options = kwargs.pop('save_other_options', True)
nargs = kwargs.pop('nargs', -1)
assert nargs == -1, 'nargs, if set, must be -1 not {}'.format(nargs)
super(OptionEatAll, self).__init__(*args, **kwargs)
self._previous_parser_process = None
self._eat_all_parser = None

def add_to_parser(self, parser, ctx):

def parser_process(value, state):
# method to hook to the parser.process
done = False
value = [value]
if self.save_other_options:
# grab everything up to the next option
while state.rargs and not done:
for prefix in self._eat_all_parser.prefixes:
if state.rargs[0].startswith(prefix):
done = True
if not done:
value.append(state.rargs.pop(0))
else:
# grab everything remaining
value += state.rargs
state.rargs[:] = []
value = tuple(value)

# call the actual process
self._previous_parser_process(value, state)

retval = super(OptionEatAll, self).add_to_parser(parser, ctx)
for name in self.opts:
our_parser = parser._long_opt.get(name) or parser._short_opt.get(name)
if our_parser:
self._eat_all_parser = our_parser
self._previous_parser_process = our_parser.process
our_parser.process = parser_process
break
return retval


@click.group()
def cli():
pass


@click.command()
@click.argument('f_name')
@click.argument('s_name')
@click.option('--birth-date', cls=OptionEatAll, type= str)
@click.option('--phone', cls=OptionEatAll, type=str)
@click.option('--document-type', cls=OptionEatAll, type=str)
@click.option('--document-number', cls=OptionEatAll, type=str)
def create(f_name, s_name, birth_date, phone, document_type, document_number):
birth_date = ''.join(birth_date)
phone = ''.join(phone)
document_type = ' '.join(document_type)
document_number = ''.join(document_number)
patient = Patient(f_name, s_name, birth_date, phone, document_type, document_number)
patient.save()
del patient


@click.command()
@click.argument('limit', default=10, type=int)
def show(limit):
collection = PatientCollection('covid_19_db.db')
for i in collection.limit(limit):
print(i)


@click.command()
def count():
collection = PatientCollection('covid_19_db.db')
for i in collection.limit(None):
print(i)


cli.add_command(create)
cli.add_command(show)
cli.add_command(count)

if __name__ == '__main__':
conn = sqlite3.connect('covid_19_db.db')
cursor = conn.cursor()
cursor.execute("""CREATE TABLE IF NOT EXISTS covid_members
(first_name TEXT not null,
last_name TEXT not null,
birth_date TEXT not null,
phone TEXT not null,
document_type TEXT not null,
document_id TEXT not null UNIQUE
);""")

conn.commit()
cursor.close()
conn.close()
cli()
18 changes: 9 additions & 9 deletions homework/config.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
GOOD_LOG_FILE = "good_log.txt"
ERROR_LOG_FILE = "error_log.txt"
CSV_PATH = "csv.csv"
GOOD_LOG_FILE = "success.log"
ERROR_LOG_FILE = "errors.log"
CSV_PATH = "covid_19_db.db"
PHONE_FORMAT = "79160000000" # Здесь запишите телефон +7-916-000-00-00 в том формате, в котором вы храните телефоны

PASSPORT_TYPE = "паспорт" # тип документа, когда он паспорт
PASSPORT_FORMAT = "0000 000000" # Здесь запишите номер парспорта 0000 000000 в том формате, в котором вы его храните
PASSPORT_TYPE = "Паспорт" # тип документа, когда он паспорт
PASSPORT_FORMAT = "0000000000" # Здесь запишите номер парспорта 0000 000000 в том формате, в котором вы его храните

INTERNATIONAL_PASSPORT_TYPE = "заграничный паспорт" # тип документа, если это загран
INTERNATIONAL_PASSPORT_FORMAT = "00 0000000" # формат хранения заграна для номера 00 0000000
INTERNATIONAL_PASSPORT_TYPE = "Заграничный паспорт" # тип документа, если это загран
INTERNATIONAL_PASSPORT_FORMAT = "000000000" # формат хранения заграна для номера 00 0000000

DRIVER_LICENSE_TYPE = "водительское удостоверение" # тип документа, если это водительское удостоверение
DRIVER_LICENSE_FORMAT = "00 00 000000" # формат хранения номера ВУ
DRIVER_LICENSE_TYPE = "Водительские права" # тип документа, если это водительское удостоверение
DRIVER_LICENSE_FORMAT = "0000000000" # формат хранения номера ВУ
68 changes: 68 additions & 0 deletions homework/logg_cvd19.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import logging
import sqlite3

logger_s = logging.getLogger("covid_19_success")
logger_s.setLevel(logging.INFO)
logger_e = logging.getLogger("covid_19_errors")
logger_e.setLevel(logging.ERROR)

formatter = logging.Formatter("%(filename)s[LINE:%(lineno)d]# %(levelname)-8s [%(asctime)s] %(message)s")

handler_success = logging.FileHandler('success.log', 'a', 'utf-8')
handler_errors = logging.FileHandler('errors.log', 'a', 'utf-8')
handler_success.setFormatter(formatter)
handler_errors.setFormatter(formatter)
logger_s.addHandler(handler_success)
logger_e.addHandler(handler_errors)


def decorated_log(func):
def wrapper(*args, **kwargs):
key = None
if func.__name__ == '__init__':
key = 'init'
if func.__name__ == 'save':
key = 'save'
try:
result = func(*args, **kwargs)
if result:
return result
except AttributeError:
logger_e.error('F_name or L_name can not be changed')
raise AttributeError("F_name or L_name can not be changed")
except TypeError:
logger_e.error('Ошибка с типом данных')
raise TypeError("Ошибка с типом данных")
except UnicodeError:
logger_e.error('Something wrong with your decoder in SAVE')
raise UnicodeError('Something wrong with your decoder in SAVE')
except ValueError:
logger_e.error('Ошибка с типом данных')
raise ValueError("Ошибка с данными")
except sqlite3.IntegrityError:
logger_e.error('Данные с таким документом уже существуют')
raise sqlite3.IntegrityError("Данные с таким документом уже существуют")
except sqlite3.OperationalError:
logger_e.error('Проблемы с подключением к базе')
raise sqlite3.OperationalError("Проблемы с подключением к базе")
except sqlite3.DatabaseError:
logger_e.error('Ошибка внутри базы')
raise sqlite3.DatabaseError("Ошибка внутри базы")
except IsADirectoryError:
logger_e.error('Cant write in directory. Problem in SAVE')
raise IsADirectoryError('Cant write in directory. Problem in SAVE')
except PermissionError:
logger_e.error('U cant write in this file. Problem in SAVE')
raise PermissionError('U cant write in this file. Problem in SAVE')
except OSError:
logger_e.error('Some System Error. Problem in SAVE')
raise OSError('Some System Error. Problem in SAVE')
except RuntimeError:
logger_e.error('Something unexpected. Problem in SAVE')
raise RuntimeError('Something unexpected. Problem in SAVE')
else:
if key == 'init':
logger_s.info('Пациент создан')
if key == 'save':
logger_s.info('Пациент сохранен')
return wrapper
122 changes: 122 additions & 0 deletions homework/model_cvd19.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
from abc import ABCMeta
from logg_cvd19 import decorated_log


# TODO Do not logg every time creation of patient
class AutoStorageDescriptor:
def __set_name__(self, owner, name):
self.name = name

def __set__(self, instance, value):
instance.__dict__[self.name] = value

def __get__(self, instance, owner):
if instance is None:
return self
else:
return instance.__dict__[self.name]


class Validated(AutoStorageDescriptor):
def __set__(self, instance, value):
value = self.validate(instance, value)
super(Validated, self).__set__(instance, value)

@classmethod
def validate(cls, instance, value):
raise NotImplementedError("Validate method is not implemented")


class NameValidator(Validated):
@decorated_log
def validate(self, instance, value):
if not isinstance(value, str):
raise TypeError("Wrong type for f_name or l_name")
if value.isalpha():
return value.capitalize()
else:
raise ValueError("Wrong value for f_name or s_name")


class NonBlank(NameValidator):
@decorated_log
def validate(self, instance, value):
if self.name in instance.__dict__ and getattr(instance, self.name):
raise AttributeError("F_name or L_name can not be changed")
return super(NonBlank, self).validate(instance, value)


class RenameOther(Validated):
@decorated_log
def validate(self, instance, value):
if self.name in instance.__dict__ and getattr(instance, self.name):
instance.logger_s.info(f"{self.name} было изменено")
return value
return value


class PhoneValidator(RenameOther):
white_lst = [str(i) for i in range(0, 10)]

@decorated_log
def validate(self, instance, value):
if not isinstance(value, str):
raise TypeError("Wrong type for Phone")
for symbol in value:
if symbol not in self.white_lst:
value = value.replace(symbol, '')
if value.find('8') == 0:
value = value.replace(value[0], '7', 1)
if len(value) != 11:
raise ValueError("Wrong attribute phone")
return RenameOther.validate(self, instance, value)


class BirthValidator(RenameOther):
@decorated_log
def validate(self, instance, value):
if not isinstance(value, str):
raise TypeError("Wrong type for birthday")
for symbol in value:
if symbol.isalpha():
raise ValueError("Wrong value for birthday")
if str(symbol) == ' ' or symbol == '-':
value = value.replace(symbol, '.')
birth_lst = value.split('.')
value = f'{birth_lst[0].zfill(4)}-' \
f'{birth_lst[1].zfill(2)}-' \
f'{birth_lst[2].zfill(2)}'
return RenameOther.validate(self, instance, value)


class DocTypeValidator(RenameOther):
white_lst = ['Паспорт', 'Заграничный паспорт', 'Водительские права']

@decorated_log
def validate(self, instance, value):
if not isinstance(value, str):
raise TypeError("Wrong type for doc_type")
else:
if value.capitalize() in self.white_lst:
value = value.capitalize()
return RenameOther.validate(self, instance, value)
else:
raise ValueError("Wrong doc_type value")


class DocIDValidator(RenameOther):
doc_dict = {'Паспорт': 10, 'Водительские права': 10, 'Заграничный паспорт': 9}
white_lst = [str(i) for i in range(0, 10)]

@decorated_log
def validate(self, instance, value):
if not isinstance(value, str):
raise TypeError("Wrong type for doc_id")
for symbol in value:
if symbol not in self.white_lst:
value = value.replace(symbol, '')
if len(value) == self.doc_dict[getattr(instance, 'document_type')]:
return RenameOther.validate(self, instance, value)
else:
raise ValueError("Wrong doc_id value")

Loading