33)
44from typing import List , Union , Optional , Literal , Annotated
55
6- RussianStr = Annotated [str , Field (pattern = r'^[А-Яа-яЁё\s\-]+$' )]
6+ RussianStr = Annotated [str , Field (pattern = r'^[А-Яа-яЁё\s\-0-9 ]+$' )]
77
88class UserSpec (BaseModel ):
9+ """
10+ Модель профиля пользователя.
11+
12+ Атрибуты:
13+ - user_id (int): Идентификатор пользователя.
14+ - username (str): Имя пользователя, состоящее из русских букв, пробелов, дефисов и цифр.
15+ - surname (str): Фамилия пользователя, состоящая из русских букв, пробелов, дефисов и цифр.
16+ - second_name (str, optional): Отчество пользователя, опционально.
17+ - email (str): Электронная почта пользователя, должна содержать '@' и '.'.
18+ - status (Literal['active', 'non-active']): Статус пользователя, может быть 'active' или 'non-active'.
19+
20+ Конфигурация модели:
21+ - `extra='forbid'`: Запрещает наличие дополнительных полей, не указанных в модели.
22+
23+ Валидаторы:
24+ - `validate_email`: Проверяет, что email содержит символы '@' и '.'.
25+ - username и surname должны состоять только из русских букв, пробелов, дефисов и цифр.
26+ - second_name может быть None, если не указано.
27+ - status должен быть либо 'active', либо 'non-active'.
28+
29+ Пример использования:
30+ >>> user = UserSpec(
31+ ... user_id=1,
32+ ... username='Андрей',
33+ ... surname='Савватеев',
34+ ... second_name='Эдуардович',
35+ ... email='deez@nu.ts',
36+ ... status='active'
37+ ... )
38+ >>> print(user)
39+ user_id=1 username='Андрей' surname='Савватеев' second_name='Эдуардович' email='deez@nu.ts' status='active'
40+ """
41+
942 model_config = ConfigDict (extra = 'forbid' )
1043 user_id : int
1144 username : RussianStr
1245 surname : RussianStr
13- second_name : Optional [str ]
46+ second_name : Optional [str ] = None
1447 email : str
1548 status : Literal ['active' , 'non-active' ]
1649
1750 @field_validator ('email' , mode = 'after' )
18- def validate_email (self , value ):
51+ @classmethod
52+ def validate_email (cls , value ):
1953 if '@' not in value or '.' not in value :
2054 raise ValueError ("Email must contain '@' and '.'" )
2155 return value
2256
2357
2458class ProfileSpec (UserSpec ):
59+ """Модель профиля пользователя с дополнительными полями.
60+ Наследуется от UserSpec(user_id, username, surname, second_name, email, status) и добавляет поля `bio` и `url`.
61+
62+ Атрибуты:
63+ - bio (RussianStr): Краткая биография пользователя, состоящая из русских букв, пробелов, дефисов и цифр.
64+ - url (HttpUrl): URL пользователя, должен содержать '://'.
65+
66+ Конфигурация модели:
67+ - `extra='forbid'`: Запрещает наличие дополнительных полей, не указанных в модели.
68+
69+ Валидаторы:
70+ - `validate_url`: Проверяет, что URL содержит '://'.
71+ - `validate_bio`: Проверяет, что биография состоит только из русских букв, пробелов, дефисов и цифр.
72+
73+ Пример использования:
74+ >>> profile = ProfileSpec(
75+ ... user_id=1,
76+ ... username='Андрей',
77+ ... surname='Савватеев',
78+ ... second_name='Эдуардович',
79+ ... email='deez@nu.ts',
80+ ... status='active',
81+ ... bio='Программист и разработчик',
82+ ... url='https://example.com/profile'
83+ ... )
84+ >>> print(profile)
85+ user_id=1 username='Андрей' surname='Савватеев' second_name='Эдуардович' email='deez@nu.ts' status='active' bio='Программист и разработчик' url='https://example.com/profile'
86+ """
87+
2588 bio : RussianStr
2689 url : HttpUrl
2790
2891 @field_validator ('url' , mode = 'after' )
29- def validate_url (self , value ):
30- if '://' not in value :
92+ @classmethod
93+ def validate_url (cls , value ):
94+ if '://' not in str (value ):
3195 raise ValueError ("URL must contain '://'" )
3296 return value
3397
3498
3599class ItemSpec (BaseModel ):
100+ """
101+ Модель спецификации товара.
102+
103+ Атрибуты:
104+ - item_id (int): Идентификатор товара.
105+ - name (str): Название товара, состоящее из русских букв, пробелов, дефисов и цифр.
106+ - desc (str): Описание товара, состоящее из русских букв, пробелов, дефисов и цифр.
107+ - price (float): Цена товара, должна быть больше 0.
108+
109+ Конфигурация модели:
110+ - `extra='forbid'`: Запрещает наличие дополнительных полей, не указанных в модели.
111+
112+ Валидаторы:
113+ - `validate_price`: Проверяет, что цена товара больше 0.
114+ - name и desc должны состоять только из русских букв, пробелов, дефисов и цифр.
115+
116+ Пример использования:
117+ >>> item = ItemSpec(
118+ ... item_id=1,
119+ ... name='Товар 1',
120+ ... desc='Описание товара 1',
121+ ... price=100.0
122+ ... )
123+ >>> print(item)
124+ item_id=1 name='Товар 1' desc='Описание товара 1' price=100.0
125+ """
126+
36127 model_config = {
37128 "extra" : "forbid"
38129 }
@@ -41,41 +132,100 @@ class ItemSpec(BaseModel):
41132 desc : RussianStr
42133 price : float
43134
44- @field_validator ('price' , mode = 'after' )
45- def validate_price (self , value ):
135+ @field_validator ("price" , mode = "after" )
136+ @classmethod
137+ def validate_price (cls , value : float ) -> float :
46138 if value <= 0 :
47139 raise ValueError ("Price must be greater than 0" )
48140 return value
49141
50142
51143class ServiceSpec (BaseModel ):
144+ """
145+ Модель услуги, которую предоставляет магазин.
146+
147+ Атрибуты:
148+ - service_id (int): Идентификатор услуги.
149+ - name (str): Название услуги, состоящее из русских букв, пробелов, дефисов и цифр.
150+ - desc (str): Описание услуги, состоящее из русских букв, пробелов, дефисов и цифр.
151+ - price (float): Цена услуги, должна быть больше 0.
152+
153+ Конфигурация модели:
154+ - `extra='forbid'`: Запрещает наличие дополнительных полей, не указанных в модели.
155+
156+ Валидаторы:
157+ - `validate_price`: Проверяет, что цена услуги больше 0.
158+ - name и desc должны состоять только из русских букв, пробелов, дефисов и цифр.
159+
160+ Пример использования:
161+ >>> service = ServiceSpec(
162+ ... service_id=1,
163+ ... name='Услуга 1',
164+ ... desc='Описание услуги 1',
165+ ... price=100.0
166+ ... )
167+ >>> print(service)
168+ service_id=1 name='Услуга 1' desc='Описание услуги 1' price=100.0
169+ """
170+
52171 model_config = {
53- "extra" : "forbid"
172+ "extra" : "forbid" ,
173+ "populate_by_name" : True
54174 }
55175 service_id : int
56176 name : RussianStr
57177 desc : RussianStr
58178 price : float
59179
60180 @field_validator ('price' , mode = 'after' )
61- def validate_price (self , value ):
181+ @classmethod
182+ def validate_price (cls , value ):
62183 if value <= 0 :
63184 raise ValueError ("Price must be greater than 0" )
64185 return value
65186
66187
67188class OrderLineSpec (BaseModel ):
189+ """
190+ Модель строки заказа, которая содержит информацию о товаре или услуге в заказе.
191+
192+ Атрибуты:
193+ - order_id (int): Идентификатор заказа.
194+ - order_line_id (int): Идентификатор строки заказа, должен быть больше 0 и меньше или равен order_id.
195+ - item_line (Union[ServiceSpec, ItemSpec]): Товар или услуга, которая входит в строку заказа.
196+ - quantity (float): Количество товара или услуги в строке заказа, должно быть больше 0.
197+
198+ Конфигурация модели:
199+ - `extra='forbid'`: Запрещает наличие дополнительных полей, не указанных в модели.
200+
201+ Валидаторы:
202+ - `validate_quantity`: Проверяет, что количество больше 0.
203+ - `validate_order_line_id`: Проверяет, что order_line_id больше 0 и меньше или равен order_id.
204+ - `line_price`: Вычисляет цену строки заказа как произведение quantity и цены товара или услуги.
205+
206+ Пример использования:
207+ >>> item = ItemSpec(item_id=1, name='Товар 1', desc='Описание товара 1', price=100.0)
208+ >>> order_line = OrderLineSpec(
209+ ... order_id=1,
210+ ... order_line_id=1,
211+ ... item_line=item,
212+ ... quantity=2.0
213+ ... )
214+ >>> print(order_line)
215+ order_id=1 order_line_id=1 item_line=ItemSpec(item_id=1, name='Товар 1', desc='Описание товара 1', price=100.0) quantity=2.0 line_price=200.0
216+ """
217+
68218 model_config = {
69219 "extra" : "forbid"
70220 }
71221 order_id : int
72222 order_line_id : int
73223 item_line : Union [ServiceSpec , ItemSpec ]
74224 quantity : float
75- line_price : float
76225
77226 @field_validator ('quantity' , mode = 'after' )
78- def validate_quantity (self , value ):
227+ @classmethod
228+ def validate_quantity (cls , value ):
79229 if value <= 0 :
80230 raise ValueError ("Quantity must be greater than 0" )
81231 return value
@@ -92,6 +242,48 @@ def line_price(self) -> float:
92242
93243
94244class OrderSpec (BaseModel ):
245+ """"
246+ Модель заказа, которая содержит информацию о заказе пользователя.
247+
248+ Атрибуты:
249+ - order_id (int): Идентификатор заказа.
250+ - user_info (ProfileSpec): Профиль пользователя, который сделал заказ.
251+ - items_line (List[OrderLineSpec]): Список строк заказа, каждая из которых содержит информацию о товаре или услуге.
252+
253+ Конфигурация модели:
254+ - `extra='forbid'`: Запрещает наличие дополнительных полей, не указанных в модели.
255+
256+ Валидаторы:
257+ - `validate_order_id`: Проверяет, что order_id больше 0.
258+ - `validate_items_line`: Проверяет, что items_line не пустой и содержит только строки заказа с корректными order_id и order_line_id.
259+
260+ Пример использования:
261+ >>> user_profile = ProfileSpec(
262+ ... user_id=1,
263+ ... username='Андрей',
264+ ... surname='Савватеев',
265+ ... second_name='Эдуардович',
266+ ... email='andrey.savvateev@example.com',
267+ ... status='active',
268+ ... bio='Программист и разработчик',
269+ ... url='https://example.com/profile'
270+ ... )
271+ >>> item = ItemSpec(item_id=1, name='Товар 1', desc='Описание товара 1', price=100.0)
272+ >>> order_line = OrderLineSpec(
273+ ... order_id=1,
274+ ... order_line_id=1,
275+ ... item_line=item,
276+ ... quantity=2.0
277+ ... )
278+ >>> order = OrderSpec(
279+ ... order_id=1,
280+ ... user_info=user_profile,
281+ ... items_line=[order_line]
282+ ... )
283+ >>> print(order)
284+ order_id=1 user_info=ProfileSpec(user_id=1, username='Андрей', surname='Савватеев', second_name='Эдуардович', email='andrey.savvateev@example.com', status='active', bio='Программист и разработчик', url='https://example.com/profile') items_line=[OrderLineSpec(order_id=1, order_line_id=1, item_line=ItemSpec(item_id=1, name='Товар 1', desc='Описание товара 1', price=100.0), quantity=2.0)]
285+ """
286+
95287 model_config = {
96288 "extra" : "forbid"
97289 }
@@ -101,6 +293,42 @@ class OrderSpec(BaseModel):
101293
102294
103295class OrdersSpec (BaseModel ):
296+ """
297+ Модель списка заказов, которая содержит информацию о заказах пользователей.
298+
299+ Атрибуты:
300+ - market_place_orders (List[OrderSpec]): Список заказов на маркетплейсе.
301+
302+ Конфигурация модели:
303+ - `extra='forbid'`: Запрещает наличие дополнительных полей, не указанных в модели.
304+
305+ Пример использования:
306+ >>> user_profile = ProfileSpec(
307+ ... user_id=1,
308+ ... username='Андрей',
309+ ... surname='Савватеев',
310+ ... second_name='Эдуардович',
311+ ... email='andrey.savvateev@example.com',
312+ ... status='active',
313+ ... bio='Программист и разработчик',
314+ ... url='https://example.com/profile'
315+ ... )
316+ >>> item = ItemSpec(item_id=1, name='Товар 1', desc='Описание товара 1', price=100.0)
317+ >>> order_line = OrderLineSpec(
318+ ... order_id=1,
319+ ... order_line_id=1,
320+ ... item_line=item,
321+ ... quantity=2.0
322+ ... )
323+ >>> order = OrderSpec(
324+ ... order_id=1,
325+ ... user_info=user_profile,
326+ ... items_line=[order_line]
327+ ... )
328+ >>> print(order)
329+ order_id=1 user_info=ProfileSpec(user_id=1, username='Андрей', surname='Савватеев', second_name='Эдуардович', email='andrey.savvateev@example.com', status='active', bio='Программист и разработчик', url='https://example.com/profile') items_line=[OrderLineSpec(order_id=1, order_line_id=1, item_line=ItemSpec(item_id=1, name='Товар 1', desc='Описание товара 1', price=100.0), quantity=2.0)]
330+ """
331+
104332 model_config = {
105333 "extra" : "forbid"
106334 }
0 commit comments