Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Реализовать эндпойнт регистрации #88

Closed
birthdaysgift opened this issue Jul 27, 2023 · 1 comment · Fixed by #98
Closed

Реализовать эндпойнт регистрации #88

birthdaysgift opened this issue Jul 27, 2023 · 1 comment · Fixed by #98
Assignees

Comments

@birthdaysgift
Copy link
Member

birthdaysgift commented Jul 27, 2023

После того как была разработана архитектура эндпойнтов авторизации (#77), необходимо приступить к реализации этих эндпойнтов. Т.к. процессы аутентификации и авторизации требуют наличия зарегистрированного в системе Аккаунта, то в первую очередь нужно реализовать эндпойнт регистрации (src/auth/routes.py :: create_account).

Планируемая архитектура бд:

Account

  • id (primary key)
  • login (unique)
  • email (unique)
  • created_at
  • updated_at

PasswordHash

  • account_id (foreign key, primary key)
  • value

Profile

  • account_id (foreign key, primary key)
  • avatar (nullable, unique)
  • description (nullable)
  • name

В рамках этой задачи необходимо написать реализацию для эндпойнта регистрации.


В процессе реализации были приняты следующие решения:

  • Использование foreign key в качестве primary key для таблиц, имеющих связь один к одному.

    Например, Профиль пользователя всегда связан с одним и только одним Аккаунтом, таким образом в качестве primary key для таблицы Профиля будет использоваться foreign key на айди записи в таблице Аккаунта. Это позволит нам обеспечить соблюдение некоторых инвариантов доменной модели на уровне бд.

  • Отказ от использования default и onupdate в колонках даты и времени.

    Это решение было принято в качестве следствия из разработанного подхода работы с бд, а именно: "бд должна автоматизировать проверку как можно большего количества ограничений, но при этом бд не должна автоматизировать какое-либо изменение данных. Следование этому принципу позволит нам, во-первых, сохранить бизнес логику изменения данных на уровне кода приложения, т.е. сохранить её в явном виде, а не спрятать в бд в виде триггеров и процедур. А во-вторых, обеспечить поддержание целостности данных при попытке внесения изменений в обход кода нашего приложения (например, при проведении миграций).

  • Расположение логики обработчиков ошибок в src/app.py.

    Это решение является временным компромиссом и, возможно, будет изменено во время будущего рефакторинга. Мы приняли это решение в связи с тем, что fastapi позволяет привязывать обработчики ошибок только к экземпляру приложения, но не к отдельным роутам.

  • Отказ от инкапсуляции логики создания зависимых моделей в методах основной модели.

    Например, при создании Аккаунта всегда должен создаваться соответствующий аккаунту Профиль, но на данных момент эндпойнт создания Аккаунта не содержит в себе вызов эндпойнта создания Профиля. Это связано с тем, что после реализации MVP, мы планируем провести рефакторинг кода, связанного с внесением изменений в бд и созданием объектов модели, с помощью внедрения DDD репозиториев, фабрик и агрегатов. Наша "упрощенная" текущая реализация скорее всего позволит перейти на новый подход более безболезненно (по крайней мере сейчас так кажется).

  • Сохранение таймзоны в бд и использование timezone-aware объектов даты и времени.

    Это позволит нам всегда точно знать, что в нашей бд все записи даты и времени добавленные/измененные нашим приложением были сделаны с учетом таймзоны.

  • Использование .flush() вместо .commit() в методах изменяющих данные в бд.

    Все методы вносящие изменения в данные бд будут использовать .flush(), чтобы в нашем коде, в рамках сессии мы могли видеть данные в изменённом виде, но при этом .commit() будет вызываться только в тирдауне get_db, позволяя нам фиксировать изменения атомарно в рамках всего эндпойнта, а не в рамках вызовов отдельных методов. У это подхода тоже есть серьезный недостаток - в связи с особенностями работы Dependency в fastapi, применение изменений в бд будет происходить уже после того как ответ 200 будет отправлен (см комментарий). Но т.к. для решения этой проблемы необходимо проводить отдельный ресёрч, было принято решение исправить это в рамках другой задачи.

Rey-Lane pushed a commit that referenced this issue Aug 12, 2023
Добавлены модели базы данных - Акканут, Профиль, Хэш пароля и базовый
функционал по созданию сущностей.
Rey-Lane pushed a commit that referenced this issue Aug 12, 2023
Добавлены модели базы данных - Акканут, Профиль, Хэш пароля и базовый
функционал по созданию сущностей.
Rey-Lane pushed a commit that referenced this issue Aug 12, 2023
Добавлены модели базы данных - Акканут, Профиль, Хэш пароля и базовый
функционал по созданию сущностей.
Rey-Lane pushed a commit that referenced this issue Aug 20, 2023
Добавлены модели базы данных - Акканут, Профиль, Хэш пароля и базовый
функционал по созданию сущностей.
birthdaysgift pushed a commit that referenced this issue Oct 7, 2023
Добавлены модели базы данных - Акканут, Профиль, Хэш пароля и базовый
функционал по созданию сущностей.
birthdaysgift pushed a commit that referenced this issue Oct 7, 2023
Добавлены модели базы данных - Акканут, Профиль, Хэш пароля и базовый
функционал по созданию сущностей.
birthdaysgift pushed a commit that referenced this issue Nov 4, 2023
Добавлены модели базы данных - Акканут, Профиль, Хэш пароля и базовый
функционал по созданию сущностей.
@birthdaysgift
Copy link
Member Author

birthdaysgift commented Nov 5, 2023

Заметки чтоб не забыть

https://www.postgresql.org/docs/current/datatype-datetime.html#DATATYPE-TIMEZONES
https://stackoverflow.com/a/59932909/8431075
https://stackoverflow.com/a/72533665/8431075

удалённые created_at можем добавить потом на основании значений из "родительских" сущностей

birthdaysgift pushed a commit that referenced this issue Nov 5, 2023
Добавлены модели базы данных - Акканут, Профиль, Хэш пароля и базовый
функционал по созданию сущностей.
birthdaysgift pushed a commit that referenced this issue Nov 5, 2023
Добавлены модели базы данных - Акканут, Профиль, Хэш пароля и базовый
функционал по созданию сущностей.
birthdaysgift pushed a commit that referenced this issue Nov 5, 2023
Добавлены модели базы данных - Акканут, Профиль, Хэш пароля и базовый
функционал по созданию сущностей.
birthdaysgift pushed a commit that referenced this issue Nov 6, 2023
Добавлены модели базы данных - Акканут, Профиль, Хэш пароля и базовый
функционал по созданию сущностей.
birthdaysgift pushed a commit that referenced this issue Nov 7, 2023
Добавлены модели базы данных - Акканут, Профиль, Хэш пароля и базовый
функционал по созданию сущностей.
birthdaysgift pushed a commit that referenced this issue Nov 7, 2023
Добавлены модели базы данных - Акканут, Профиль, Хэш пароля и базовый
функционал по созданию сущностей.
birthdaysgift pushed a commit that referenced this issue Nov 8, 2023
Добавлены модели базы данных - Акканут, Профиль, Хэш пароля и базовый
функционал по созданию сущностей.
birthdaysgift pushed a commit that referenced this issue Nov 9, 2023
Добавлены модели базы данных - Акканут, Профиль, Хэш пароля и базовый
функционал по созданию сущностей.
birthdaysgift pushed a commit that referenced this issue Nov 14, 2023
Добавлены модели базы данных - Акканут, Профиль, Хэш пароля и базовый
функционал по созданию сущностей.
birthdaysgift pushed a commit that referenced this issue Nov 14, 2023
Добавлены модели базы данных - Акканут, Профиль, Хэш пароля и базовый
функционал по созданию сущностей.
birthdaysgift pushed a commit that referenced this issue Nov 15, 2023
Добавлены модели базы данных - Акканут, Профиль, Хэш пароля и базовый
функционал по созданию сущностей.
birthdaysgift pushed a commit that referenced this issue Nov 15, 2023
После того как была разработана архитектура эндпойнтов авторизации (#77), необходимо приступить к реализации этих эндпойнтов. Т.к. процессы аутентификации и авторизации требуют наличия зарегистрированного в системе Аккаунта, то в первую очередь нужно реализовать эндпойнт регистрации (`src/auth/routes.py :: create_account`).

Планируемая архитектура бд:

**Account**

- id (primary key)
- login (unique)
- email (unique)
- created_at
- updated_at

**PasswordHash**

- account_id (foreign key, primary key)
- value

**Profile**

- account_id (foreign key, primary key)
- avatar (nullable, unique)
- description (nullable)
- name

В рамках этой задачи необходимо написать реализацию для эндпойнта регистрации.

---

В процессе реализации были приняты следующие решения:

- **Использование foreign key в качестве primary key для таблиц, имеющих связь один к одному.**

  Например, Профиль пользователя всегда связан с одним и только одним Аккаунтом, таким образом в качестве primary key для таблицы Профиля будет использоваться foreign key на айди записи в таблице Аккаунта. Это позволит нам обеспечить соблюдение некоторых инвариантов доменной модели на уровне бд.

- **Отказ от использования `default` и `onupdate` в колонках даты и времени.**

  Это решение было принято в качестве следствия из разработанного подхода работы с бд, а именно: "бд **должна** автоматизировать проверку как можно большего количества **ограничений**, но при этом бд **не должна** автоматизировать какое-либо **изменение** данных. Следование этому принципу позволит нам, во-первых, сохранить бизнес логику изменения данных на уровне кода приложения, т.е. сохранить её в явном виде, а не спрятать в бд в виде триггеров и процедур. А во-вторых, обеспечить поддержание целостности данных при попытке внесения изменений в обход кода нашего приложения (например, при проведении миграций).

- **Расположение логики обработчиков ошибок в `src/app.py`.**

  Это решение является временным компромиссом и, возможно, будет изменено во время будущего рефакторинга. Мы приняли это решение в связи с тем, что fastapi позволяет привязывать обработчики ошибок только к экземпляру приложения, но не к отдельным роутам.

- **Отказ от инкапсуляции логики создания зависимых моделей в методах основной модели.**

  Например, при создании Аккаунта всегда должен создаваться соответствующий аккаунту Профиль, но на данных момент эндпойнт создания Аккаунта не содержит в себе вызов эндпойнта создания Профиля. Это связано с тем, что после реализации MVP, мы планируем провести рефакторинг кода, связанного с внесением изменений в бд и созданием объектов модели, с помощью внедрения DDD репозиториев, фабрик и агрегатов. Наша "упрощенная" текущая реализация скорее всего позволит перейти на новый подход более безболезненно (по крайней мере сейчас так кажется).

- **Сохранение таймзоны в бд и использование timezone-aware объектов даты и времени.**

  Это позволит нам всегда точно знать, что в нашей бд все записи даты и времени добавленные/измененные нашим приложением были сделаны с учетом таймзоны.

- **Использование `.flush()` вместо `.commit()` в методах изменяющих данные в бд.**

  Все методы вносящие изменения в данные бд будут использовать `.flush()`, чтобы в нашем коде, в рамках сессии мы могли видеть данные в изменённом виде, но при этом `.commit()` будет вызываться только в тирдауне `get_db`, позволяя нам фиксировать изменения атомарно в рамках всего эндпойнта, а не в рамках вызовов отдельных методов. У это подхода тоже есть серьезный недостаток - в связи с особенностями работы `Dependency` в fastapi, применение изменений в бд будет происходить уже после того как ответ 200 будет отправлен (см [комментарий](zhanymkanov/fastapi-best-practices#1 (comment))). Но т.к. для решения этой проблемы необходимо проводить отдельный ресёрч, было принято решение исправить это в рамках [другой](#142) задачи.
birthdaysgift pushed a commit that referenced this issue Nov 15, 2023
После того как была разработана архитектура эндпойнтов авторизации (#77), необходимо приступить к реализации этих эндпойнтов. Т.к. процессы аутентификации и авторизации требуют наличия зарегистрированного в системе Аккаунта, то в первую очередь нужно реализовать эндпойнт регистрации (`src/auth/routes.py :: create_account`).

Планируемая архитектура бд:

**Account**

- id (primary key)
- login (unique)
- email (unique)
- created_at
- updated_at

**PasswordHash**

- account_id (foreign key, primary key)
- value

**Profile**

- account_id (foreign key, primary key)
- avatar (nullable, unique)
- description (nullable)
- name

В рамках этой задачи необходимо написать реализацию для эндпойнта регистрации.

---

В процессе реализации были приняты следующие решения:

- **Использование foreign key в качестве primary key для таблиц, имеющих связь один к одному.**

  Например, Профиль пользователя всегда связан с одним и только одним Аккаунтом, таким образом в качестве primary key для таблицы Профиля будет использоваться foreign key на айди записи в таблице Аккаунта. Это позволит нам обеспечить соблюдение некоторых инвариантов доменной модели на уровне бд.

- **Отказ от использования `default` и `onupdate` в колонках даты и времени.**

  Это решение было принято в качестве следствия из разработанного подхода работы с бд, а именно: "бд **должна** автоматизировать проверку как можно большего количества **ограничений**, но при этом бд **не должна** автоматизировать какое-либо **изменение** данных. Следование этому принципу позволит нам, во-первых, сохранить бизнес логику изменения данных на уровне кода приложения, т.е. сохранить её в явном виде, а не спрятать в бд в виде триггеров и процедур. А во-вторых, обеспечить поддержание целостности данных при попытке внесения изменений в обход кода нашего приложения (например, при проведении миграций).

- **Расположение логики обработчиков ошибок в `src/app.py`.**

  Это решение является временным компромиссом и, возможно, будет изменено во время будущего рефакторинга. Мы приняли это решение в связи с тем, что fastapi позволяет привязывать обработчики ошибок только к экземпляру приложения, но не к отдельным роутам.

- **Отказ от инкапсуляции логики создания зависимых моделей в методах основной модели.**

  Например, при создании Аккаунта всегда должен создаваться соответствующий аккаунту Профиль, но на данных момент эндпойнт создания Аккаунта не содержит в себе вызов эндпойнта создания Профиля. Это связано с тем, что после реализации MVP, мы планируем провести рефакторинг кода, связанного с внесением изменений в бд и созданием объектов модели, с помощью внедрения DDD репозиториев, фабрик и агрегатов. Наша "упрощенная" текущая реализация скорее всего позволит перейти на новый подход более безболезненно (по крайней мере сейчас так кажется).

- **Сохранение таймзоны в бд и использование timezone-aware объектов даты и времени.**

  Это позволит нам всегда точно знать, что в нашей бд все записи даты и времени добавленные/измененные нашим приложением были сделаны с учетом таймзоны.

- **Использование `.flush()` вместо `.commit()` в методах изменяющих данные в бд.**

  Все методы вносящие изменения в данные бд будут использовать `.flush()`, чтобы в нашем коде, в рамках сессии мы могли видеть данные в изменённом виде, но при этом `.commit()` будет вызываться только в тирдауне `get_db`, позволяя нам фиксировать изменения атомарно в рамках всего эндпойнта, а не в рамках вызовов отдельных методов. У это подхода тоже есть серьезный недостаток - в связи с особенностями работы `Dependency` в fastapi, применение изменений в бд будет происходить уже после того как ответ 200 будет отправлен (см [комментарий](zhanymkanov/fastapi-best-practices#1 (comment))). Но т.к. для решения этой проблемы необходимо проводить отдельный ресёрч, было принято решение исправить это в рамках [другой](#142) задачи.
birthdaysgift added a commit that referenced this issue Nov 21, 2023
В рамках работы над задачами добавления сваггера для профиля (#95), дружбы (#100) и желания (#104), мы предполагали, что файл будет иметь строковый тип и будет представлен ссылкой, поэтому в код сваггера мы добавили его в таком виде:
```python
"avatar": "/files/0b928aaa-521f-47ec-8be5-396650e2a187"
```
И схемы для сваггера выглядели соответствующим образом:
```python
class Avatar(str):
    """Avatar value field."""

class Profile(Schema):

    ...  # something here

    avatar: Avatar | None

    ...  # something here
```

Также исходя из этого предположения, во время работы над задачей реализации эндпойнта регистрации (#88) была добавлена колонка `avatar` в модель `Profile` с типом строка:
```python
avatar: Mapped[str | None] = mapped_column(String, unique=True)
```

Но после того, как мы начали работать над задачей добавления сваггера для эндпойнтов файла (#108), мы поняли, что вместо строкового типа нам надо использовать uuid в качестве идентификатора файла. Из этого следует, что нам необходимо внести следующие изменения в уже существующий код, описаный выше:

- Заменить `avatar` (string) на `avatar_id` (uuid) в существующих схемах и примерах сваггера
- Заменить `avatar` (string) на `avatar_id` (uuid) в существующей модели базы данных (`Profile`)

В рамках этой задачи необходимо внести изменения, описанные выше.

---

**Примечания**

Внесения подобных изменений можно было бы избежать, если бы схема для работы с файлами была продумана и добавлена в репозиторий заранее. Т.е. сваггер для эндпойнтов файлов, необходимо было добавить ещё до того, как будет добавлен хоть какой-то сваггер для эндпойнтов приложения, т.к. эндпойнты приложения используют файлы, и необходимо знать заранее как мы планируем работать с файлами.

Но поскольку это не было сделано вовремя, то сейчас необходимо внести правки в уже существующий функционал, а так же добавить сваггер для эндпойнтов файла (#108) и реализацию для них этих эндпойнтов, до того как будет добавлен какой-либо новый функционал приложения.
birthdaysgift added a commit that referenced this issue Nov 24, 2023
В рамках работы над задачами добавления сваггера для профиля (#95), дружбы (#100) и желания (#104), мы предполагали, что файл будет иметь строковый тип и будет представлен ссылкой, поэтому в код сваггера мы добавили его в таком виде:
```python
"avatar": "/files/0b928aaa-521f-47ec-8be5-396650e2a187"
```
И схемы для сваггера выглядели соответствующим образом:
```python
class Avatar(str):
    """Avatar value field."""

class Profile(Schema):

    ...  # something here

    avatar: Avatar | None

    ...  # something here
```

Также исходя из этого предположения, во время работы над задачей реализации эндпойнта регистрации (#88) была добавлена колонка `avatar` в модель `Profile` с типом строка:
```python
avatar: Mapped[str | None] = mapped_column(String, unique=True)
```

Но после того, как мы начали работать над задачей добавления сваггера для эндпойнтов файла (#108), мы поняли, что вместо строкового типа нам надо использовать uuid в качестве идентификатора файла. Из этого следует, что нам необходимо внести следующие изменения в уже существующий код, описаный выше:

- Заменить `avatar` (string) на `avatar_id` (uuid) в существующих схемах и примерах сваггера
- Заменить `avatar` (string) на `avatar_id` (uuid) в существующей модели базы данных (`Profile`)

В рамках этой задачи необходимо внести изменения, описанные выше.

---

**Примечания**

Внесения подобных изменений можно было бы избежать, если бы схема для работы с файлами была продумана и добавлена в репозиторий заранее. Т.е. сваггер для эндпойнтов файлов, необходимо было добавить ещё до того, как будет добавлен хоть какой-то сваггер для эндпойнтов приложения, т.к. эндпойнты приложения используют файлы, и необходимо знать заранее как мы планируем работать с файлами.

Но поскольку это не было сделано вовремя, то сейчас необходимо внести правки в уже существующий функционал, а так же добавить сваггер для эндпойнтов файла (#108) и реализацию для них этих эндпойнтов, до того как будет добавлен какой-либо новый функционал приложения.
birthdaysgift added a commit that referenced this issue Nov 24, 2023
В рамках работы над задачами добавления сваггера для профиля (#95), дружбы (#100) и желания (#104), мы предполагали, что файл будет иметь строковый тип и будет представлен ссылкой, поэтому в код сваггера мы добавили его в таком виде:
```python
"avatar": "/files/0b928aaa-521f-47ec-8be5-396650e2a187"
```
И схемы для сваггера выглядели соответствующим образом:
```python
# src/profile/fields.py:
class Avatar(str):
    """Avatar value field."""

# src/profile/schemas.py:
class Profile(Schema):

    ...  # something here

    avatar: Avatar | None

    ...  # something here
```

Также исходя из этого предположения, во время работы над задачей реализации эндпойнта регистрации (#88) была добавлена колонка `avatar` в модель `Profile` с типом строка:
```python
avatar: Mapped[str | None] = mapped_column(String, unique=True)
```

Но после того, как мы начали работать над задачей добавления сваггера для эндпойнтов файла (#108), мы поняли, что вместо строкового типа нам надо использовать uuid в качестве идентификатора файла. Из этого следует, что нам необходимо внести следующие изменения в уже существующий код, описаный выше:

- Заменить `avatar` (string) на `avatar_id` (uuid) в существующих схемах и примерах сваггера
- Заменить `avatar` (string) на `avatar_id` (uuid) в существующей модели базы данных (`Profile`)

В рамках этой задачи необходимо внести изменения, описанные выше.

---

**Примечания**

Внесения подобных изменений можно было бы избежать, если бы схема для работы с файлами была продумана и добавлена в репозиторий заранее. Т.е. сваггер для эндпойнтов файлов, необходимо было добавить ещё до того, как будет добавлен хоть какой-то сваггер для эндпойнтов приложения, т.к. эндпойнты приложения используют файлы, и необходимо знать заранее как мы планируем работать с файлами.

Но поскольку это не было сделано вовремя, то сейчас необходимо внести правки в уже существующий функционал, а так же добавить сваггер для эндпойнтов файла (#108) и реализацию для них этих эндпойнтов, до того как будет добавлен какой-либо новый функционал приложения.
birthdaysgift added a commit that referenced this issue Nov 26, 2023
Во время работы над реализацией эндпойнта регистрации (#88), было принято решение использовать библиотеку [freezegun](https://github.com/spulec/freezegun#freezegun-let-your-python-tests-travel-through-time), для поверок данных с динамически генерируемыми датами в тестах. Планировалось в тестах "замораживать" время используя определённую константу, и затем использовать эту константу в проверках.

Но в дальнейшем при попытке реализовать эндпойнты файла (#148), выяснилось, что если в тесте мы замораживаем время, а потом посылаем запрос в minio, то сервер minio отклоняет такой запрос с ошибкой, говорящей, что время запроса слишком сильно отличается от времени установленном на сервере.

Чтобы решить эту проблему, мы можем использовать библиотеку [dirty_equals](https://dirty-equals.helpmanual.io/latest/) вместо freezegun для проверки динамически генерируемых значений даты и времени в тестах.

Так же хотелось бы решить одну небольшую проблему возникающую при использовании dirty_equals - сокрытие примеров значений в ассертах. Например, в таком ассерте визуально не понятно, какое значение (хотя бы примерно) будет в колонке id:
```python
assert response.json() == {
    "id": IsPositiveInt(),
    "name": "John Doe",
}
```

Для этого было принято решение слегка модифицировать классы библиотеки dirty_equals и добавить им возможность указать пример значение через аргумент `like`, т.е.:
```python
assert response.json() == {
    "id": PositiveInt(like=42),
    "name": "John Doe",
}
```

При этом значение указанное в аргументе `like`, так же должно проверятся на соответствие используемому классу, т.е. следующий пример должен давать ошибку:
```python
assert response.json() == {
    "id": PositiveInt(like=-1)
    "name": "John Doe",
}
```

В рамках этой задачи необходимо настроить и использовать dirty_equals для проверок автогенерируемых значений.
birthdaysgift added a commit that referenced this issue Nov 26, 2023
Во время работы над реализацией эндпойнта регистрации (#88), было принято решение использовать библиотеку [freezegun](https://github.com/spulec/freezegun#freezegun-let-your-python-tests-travel-through-time), для поверок данных с динамически генерируемыми датами в тестах. Планировалось в тестах "замораживать" время используя определённую константу, и затем использовать эту константу в проверках.

Но в дальнейшем при попытке реализовать эндпойнты файла (#148), выяснилось, что если в тесте мы замораживаем время, а потом посылаем запрос в minio, то сервер minio отклоняет такой запрос с ошибкой, говорящей, что время запроса слишком сильно отличается от времени установленном на сервере.

Чтобы решить эту проблему, мы можем использовать библиотеку [dirty_equals](https://dirty-equals.helpmanual.io/latest/) вместо freezegun для проверки динамически генерируемых значений даты и времени в тестах.

Так же хотелось бы решить одну небольшую проблему возникающую при использовании dirty_equals - сокрытие примеров значений в ассертах. Например, в таком ассерте визуально не понятно, какое значение (хотя бы примерно) будет в колонке id:
```python
assert response.json() == {
    "id": IsPositiveInt(),
    "name": "John Doe",
}
```

Для этого было принято решение слегка модифицировать классы библиотеки dirty_equals и добавить им возможность указать пример значение через аргумент `like`, т.е.:
```python
assert response.json() == {
    "id": PositiveInt(like=42),
    "name": "John Doe",
}
```

При этом значение указанное в аргументе `like`, так же должно проверятся на соответствие используемому классу, т.е. следующий пример должен давать ошибку:
```python
assert response.json() == {
    "id": PositiveInt(like=-1)
    "name": "John Doe",
}
```

В рамках этой задачи необходимо настроить и использовать dirty_equals для проверок автогенерируемых значений.
birthdaysgift added a commit that referenced this issue Nov 27, 2023
Во время работы над реализацией эндпойнта регистрации (#88), было принято решение использовать библиотеку [freezegun](https://github.com/spulec/freezegun#freezegun-let-your-python-tests-travel-through-time), для поверок данных с динамически генерируемыми датами в тестах. Планировалось в тестах "замораживать" время используя определённую константу, и затем использовать эту константу в проверках.

Но в дальнейшем при попытке реализовать эндпойнты файла (#148), выяснилось, что если в тесте мы замораживаем время, а потом посылаем запрос в minio, то сервер minio отклоняет такой запрос с ошибкой, говорящей, что время запроса слишком сильно отличается от времени установленном на сервере.

Чтобы решить эту проблему, мы можем использовать библиотеку [dirty_equals](https://dirty-equals.helpmanual.io/latest/) вместо freezegun для проверки динамически генерируемых значений даты и времени в тестах.

Так же хотелось бы решить одну небольшую проблему возникающую при использовании dirty_equals - сокрытие примеров значений в ассертах. Например, в таком ассерте визуально не понятно, какое значение (хотя бы примерно) будет в колонке id:
```python
assert response.json() == {
    "id": IsPositiveInt(),
    "name": "John Doe",
}
```

Для этого было принято решение слегка модифицировать классы библиотеки dirty_equals и добавить им возможность указать пример значение через аргумент `like`, т.е.:
```python
assert response.json() == {
    "id": PositiveInt(like=42),
    "name": "John Doe",
}
```

При этом значение указанное в аргументе `like`, так же должно проверятся на соответствие используемому классу, т.е. следующий пример должен давать ошибку:
```python
assert response.json() == {
    "id": PositiveInt(like=-1)
    "name": "John Doe",
}
```

В рамках этой задачи необходимо настроить и использовать dirty_equals для проверок автогенерируемых значений.
birthdaysgift added a commit that referenced this issue Nov 27, 2023
Во время работы над реализацией эндпойнта регистрации (#88), было принято решение использовать библиотеку [freezegun](https://github.com/spulec/freezegun#freezegun-let-your-python-tests-travel-through-time), для поверок данных с динамически генерируемыми датами в тестах. Планировалось в тестах "замораживать" время используя определённую константу, и затем использовать эту константу в проверках.

Но в дальнейшем при попытке реализовать эндпойнты файла (#148), выяснилось, что если в тесте мы замораживаем время, а потом посылаем запрос в minio, то сервер minio отклоняет такой запрос с ошибкой, говорящей, что время запроса слишком сильно отличается от времени установленном на сервере.

Чтобы решить эту проблему, мы можем использовать библиотеку [dirty_equals](https://dirty-equals.helpmanual.io/latest/) вместо freezegun для проверки динамически генерируемых значений даты и времени в тестах.

Так же хотелось бы решить одну небольшую проблему возникающую при использовании dirty_equals - сокрытие примеров значений в ассертах. Например, в таком ассерте визуально не понятно, какое значение (хотя бы примерно) будет в колонке id:
```python
assert response.json() == {
    "id": IsPositiveInt(),
    "name": "John Doe",
}
```

Для этого было принято решение слегка модифицировать классы библиотеки dirty_equals и добавить им возможность указать пример значение через аргумент `like`, т.е.:
```python
assert response.json() == {
    "id": PositiveInt(like=42),
    "name": "John Doe",
}
```

При этом значение указанное в аргументе `like`, так же должно проверятся на соответствие используемому классу, т.е. следующий пример должен давать ошибку:
```python
assert response.json() == {
    "id": PositiveInt(like=-1)
    "name": "John Doe",
}
```

В рамках этой задачи необходимо настроить и использовать dirty_equals для проверок автогенерируемых значений.
birthdaysgift added a commit that referenced this issue Nov 27, 2023
Во время работы над реализацией эндпойнта регистрации (#88), было принято решение использовать библиотеку [freezegun](https://github.com/spulec/freezegun#freezegun-let-your-python-tests-travel-through-time), для поверок данных с динамически генерируемыми датами в тестах. Планировалось в тестах "замораживать" время используя определённую константу, и затем использовать эту константу в проверках.

Но в дальнейшем при попытке реализовать эндпойнты файла (#148), выяснилось, что если в тесте мы замораживаем время, а потом посылаем запрос в minio, то сервер minio отклоняет такой запрос с ошибкой, говорящей, что время запроса слишком сильно отличается от времени установленном на сервере.

Чтобы решить эту проблему, мы можем использовать библиотеку [dirty_equals](https://dirty-equals.helpmanual.io/latest/) вместо freezegun для проверки динамически генерируемых значений даты и времени в тестах.

Так же хотелось бы решить одну небольшую проблему возникающую при использовании dirty_equals - сокрытие примеров значений в ассертах. Например, в таком ассерте визуально не понятно, какое значение (хотя бы примерно) будет в колонке id:
```python
assert response.json() == {
    "id": IsPositiveInt(),
    "name": "John Doe",
}
```

Для этого было принято решение слегка модифицировать классы библиотеки dirty_equals и добавить им возможность указать пример значение через аргумент `like`, т.е.:
```python
assert response.json() == {
    "id": PositiveInt(like=42),
    "name": "John Doe",
}
```

При этом значение указанное в аргументе `like`, так же должно проверятся на соответствие используемому классу, т.е. следующий пример должен давать ошибку:
```python
assert response.json() == {
    "id": PositiveInt(like=-1)
    "name": "John Doe",
}
```

В рамках этой задачи необходимо настроить и использовать dirty_equals для проверок автогенерируемых значений.
birthdaysgift added a commit that referenced this issue Nov 27, 2023
Во время работы над реализацией эндпойнта регистрации (#88), было принято решение использовать библиотеку [freezegun](https://github.com/spulec/freezegun#freezegun-let-your-python-tests-travel-through-time), для поверок данных с динамически генерируемыми датами в тестах. Планировалось в тестах "замораживать" время используя определённую константу, и затем использовать эту константу в проверках.

Но в дальнейшем при попытке реализовать эндпойнты файла (#148), выяснилось, что если в тесте мы замораживаем время, а потом посылаем запрос в minio, то сервер minio отклоняет такой запрос с ошибкой, говорящей, что время запроса слишком сильно отличается от времени установленном на сервере.

Чтобы решить эту проблему, мы можем использовать библиотеку [dirty_equals](https://dirty-equals.helpmanual.io/latest/) вместо freezegun для проверки динамически генерируемых значений даты и времени в тестах.

Так же хотелось бы решить одну небольшую проблему возникающую при использовании dirty_equals - сокрытие примеров значений в ассертах. Например, в таком ассерте визуально не понятно, какое значение (хотя бы примерно) будет в колонке id:
```python
assert response.json() == {
    "id": IsPositiveInt(),
    "name": "John Doe",
}
```

Для этого было принято решение слегка модифицировать классы библиотеки dirty_equals и добавить им возможность указать пример значение через аргумент `like`, т.е.:
```python
assert response.json() == {
    "id": PositiveInt(like=42),
    "name": "John Doe",
}
```

При этом значение указанное в аргументе `like`, так же должно проверятся на соответствие используемому классу, т.е. следующий пример должен давать ошибку:
```python
assert response.json() == {
    "id": PositiveInt(like=-1)
    "name": "John Doe",
}
```

В рамках этой задачи необходимо настроить и использовать dirty_equals для проверок автогенерируемых значений.
birthdaysgift added a commit that referenced this issue Jan 23, 2024
Во время реализации эндпойнта регистрации (#88) были добавлены модели Account и Profile, содержащие колонки со строковым типом данных. Но при этом не были выставлены ограничения длины этих строк.

В рамках этой задачи необходимо добавить ограничения длины для колонок строкового типа согласно DDD модели данных.

---

**Особенности реализации**

В процессе работы над задачей выяснилось, что алембик не может обнаружить изменения типа, которое нам было нужно: varchar -> varchar(42), поэтому миграция была написана вручную.

Подробнее об особенности работы алембика в данном случае можно почитать в [обсуждении](sqlalchemy/alembic#1256) в репозитории самого алембика. Здесь же, на всякий случай процитирую основной ответ, закрывающий это обсуждение:

> **zzzeek** (maintainer):
>
> PG allows for unlengthed VARCHAR. the alembic type comparison rules are set so that they only report a "positive" if two parameters don't match. if the number of parameters are different, it does not attempt to guess, so in this case VARCHAR and VARCHAR(6) have a different number of parameters; it's a negative. the overarching priority is to not produce false positives, since a false negative means editing a single migration file to fix for the miss, but a false positive means editing every migration file.
birthdaysgift added a commit that referenced this issue Jan 24, 2024
Во время реализации эндпойнта регистрации (#88) были добавлены модели Account и Profile, содержащие колонки со строковым типом данных. Но при этом не были выставлены ограничения длины этих строк.

В рамках этой задачи необходимо добавить ограничения длины для колонок строкового типа согласно DDD модели данных.

---

**Особенности реализации**

В процессе работы над задачей выяснилось, что алембик не может обнаружить изменения типа, которое нам было нужно: varchar -> varchar(42), поэтому миграция была написана вручную.

Подробнее об особенности работы алембика в данном случае можно почитать в [обсуждении](sqlalchemy/alembic#1256) в репозитории самого алембика. Здесь же, на всякий случай процитирую основной ответ, закрывающий это обсуждение:

> **zzzeek** (maintainer):
>
> PG allows for unlengthed VARCHAR. the alembic type comparison rules are set so that they only report a "positive" if two parameters don't match. if the number of parameters are different, it does not attempt to guess, so in this case VARCHAR and VARCHAR(6) have a different number of parameters; it's a negative. the overarching priority is to not produce false positives, since a false negative means editing a single migration file to fix for the miss, but a false positive means editing every migration file.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.

2 participants