Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from dataclasses import dataclass, asdict
- from uuid import (
- UUID,
- uuid4,
- )
- @dataclass
- class Person:
- """
- Информация о пользователе.
- Attrs:
- login: логин пользователя.
- password: пароль пользователя.
- username: имя пользователя.
- metadata: дополнительные сведения о пользователе.
- """
- login: str = ""
- password: str = ""
- username: str = ""
- metadata: str = ""
- class PersonDB:
- _database: dict[UUID, Person]
- _login_registry: set[str]
- _min_password_len = 10
- def __init__(self) -> None:
- """Инициализирует базу данных."""
- self._database = {}
- self._login_registry = set()
- def _check_password(self, password):
- """
- Пароль считается надежным, если
- пароль содержит хотя бы одну букву английского алфавита в верхнем регистре;
- пароль содержит хотя бы одну букву английского алфавита в нижнем регистре;
- пароль содержит хотя бы одну цифру от 0 до 9;
- пароль состоит не менее чем из 10 символов;
- пароль не содержит никаких символов, кроме разрешенных.
- """
- alph_lower = 'abcdefghijklmnopqrstuvwxyz'
- alph_upper = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
- num = '0123456789'
- if len(password) < self._min_password_len:
- return False
- contains_alph_lower = False
- contains_alph_upper = False
- contains_num = False
- for l in password:
- if l in alph_lower:
- contains_alph_lower = True
- elif l in alph_upper:
- contains_alph_upper = True
- elif l in num:
- contains_num = True
- else:
- return False
- return contains_alph_lower and contains_alph_upper and contains_num
- def _check_login(self, login):
- """
- Логин должен быть уникальным и содержать только английские буквы в верхнем и нижнем регистре, а также цифры от 0 до 9. Логин не может быть пустой строкой.
- """
- return login != '' and login.isalnum()
- def _check_login_and_password(self, login, password):
- login_is_ok = self._check_login(login)
- if not login_is_ok:
- raise ValueError("incorrect login")
- if login in self._login_registry:
- raise ValueError("such login already exists")
- password_is_ok = self._check_password(password)
- if not password_is_ok:
- raise ValueError("incorrect password")
- def create_person(self, person: Person) -> UUID:
- """
- Создает новую запись о пользователе в базе данных.
- Args:
- person: данные о пользователе, которые будут помещены в БД.
- Returns:
- UUID - идентификатор, который будет связан с созданной записью.
- Raises:
- ValueError, если логин или пароль не удовлетворяют требованиям.
- """
- self._check_login_and_password(person.login, person.password)
- id = uuid4()
- if id in self._database:
- raise Exception("such id already exists")
- self._login_registry.add(person.login)
- self._database[id] = person
- return id
- def read_person_info(self, person_id: UUID) -> Person:
- """
- Читает актуальные данные пользователя из базы данных.
- Args:
- person_id: идентификатор пользователя в формате UUID.
- Returns:
- Данные о пользователе, упакованные в структуру Person.
- Raises:
- KeyError, если в базе данных нет пользователя с person_id.
- """
- if person_id not in self._database:
- raise KeyError("no person with such id")
- return self._database[person_id]
- def update_person_info(self, person_id: UUID, person_info_new: Person) -> None:
- """
- Обновляет данные о пользователе.
- Args:
- person_id: идентификатор пользователя в формате UUID.
- person_info_new: модель со значениями на обновление. Будут обновлены
- только те поля, чье значение отличается от пустой строки '',
- остальные поля будут оставлены без изменений.
- Raises:
- ValueError, если при обновлении логина или пароля логин или пароль
- не прошли этап валидации.
- KeyError, если в базе данных нет пользователя с person_id.
- """
- if person_id not in self._database:
- raise KeyError("no person with such id")
- self._check_login_and_password(person_info_new.login, person_info_new.password)
- old_login = self._database[person_id].login
- new_person = Person()
- dict_helper = asdict(self._database[person_id])
- print("dict_helper")
- print(dict_helper)
- #сли копироавть каждое поле отдельно - то там будет ссылка или значение копироваться?
- #как надо было без dict_helper?
- new_person.login = dict_helper['login']
- new_person.password = dict_helper['password']
- new_person.username = dict_helper['username']
- new_person.metadata = dict_helper['metadata']
- if person_info_new.login != '':
- self._login_registry.remove(old_login)
- new_person.login = person_info_new.login
- self._login_registry.add(new_person.login)
- if person_info_new.password != '':
- new_person.password = person_info_new.password
- if person_info_new.username != '':
- new_person.username = person_info_new.username
- if person_info_new.metadata != '':
- new_person.metadata = person_info_new.metadata
- self._database[person_id] = new_person
- def delete_person(self, person_id: UUID) -> None:
- """
- Удаляет запись о пользователе.
- Args:
- person_id: идентификатор пользователя в формате UUID.
- Raises:
- KeyError, если в базе данных нет пользователя с person_id.
- """
- if person_id not in self._database:
- raise KeyError("no person with such id")
- self._database.pop(person_id)
- person1 = Person(
- password="Aa1Bb2Cc3Dd4",
- login="login1",
- username="user#1",
- )
- database = PersonDB()
- person1_id = database.create_person(person1)
- assert len(database._database) == 1
- assert len(database._login_registry) == 1
- assert person1_id in database._database
- assert person1.login in database._login_registry
- assert database._database[person1_id] == person1
- persons_wrong = {
- "no-login": Person(
- password="Aa1Bb2Cc3Dd4",
- login="",
- username="user#2",
- ),
- "existed-login": Person(
- password="Aa1Bb2Cc3Dd4",
- login="login1",
- username="user#2",
- ),
- "too-short-password": Person(
- password="12345",
- login="login2",
- username="user#2",
- ),
- "no-lower": Person(
- password="A1B2C3D4E5F",
- login="login2",
- username="user#2",
- ),
- "no-upper": Person(
- password="a1b2c3d4e5f",
- login="login2",
- username="user#2",
- ),
- "no-digits": Person(
- password="aAbBcCdDeEf",
- login="login2",
- username="user#2",
- ),
- }
- for test_name, wrong_person in persons_wrong.items():
- try:
- database.create_person(wrong_person)
- assert False, test_name
- except ValueError:
- assert True
- assert len(database._database) == 1
- assert len(database._login_registry) == 1
- person = database.read_person_info(person1_id)
- assert person1 == person
- assert len(database._database) == 1
- assert len(database._login_registry) == 1
- try:
- fake_id = uuid4()
- person = database.read_person_info(fake_id)
- assert False
- except KeyError:
- assert True
- assert len(database._database) == 1
- assert len(database._login_registry) == 1
- person2 = Person(
- password="AaBbcC1234Dd",
- login="login2",
- username="user#2"
- )
- person2_id = database.create_person(person2)
- assert len(database._database) == 2
- assert len(database._login_registry) == 2
- assert person2_id in database._database
- assert person2.login in database._login_registry
- assert database._database[person2_id] == person2
- person2_updated = Person(
- password="abcDEF123456",
- login="LOGIN2",
- username="user#2",
- )
- person2_update = Person(
- password="abcDEF123456",
- login="LOGIN2",
- username="",
- )
- database.update_person_info(person2_id, person2_update)
- assert len(database._database) == 2
- assert len(database._login_registry) == 2
- assert person2_id in database._database
- assert person2.login not in database._login_registry
- assert person2_updated.login in database._login_registry
- assert database._database[person2_id] == person2_updated
- try:
- fake_id = uuid4()
- database.delete_person(fake_id)
- assert False
- except KeyError:
- assert True
- assert len(database._database) == 2
- assert len(database._login_registry) == 2
- database.delete_person(person2_id)
- assert len(database._database) == 1
- assert len(database._login_registry) == 1
- assert person2_id not in database._database
- assert person2_updated.login not in database._login_registry
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement