Ma ktoś pomysł jak pozbyć się tego błędu?
Błąd
============================= test session starts ==============================
platform linux -- Python 3.11.3, pytest-7.3.1, pluggy-1.0.0
rootdir: /home/lester29/PycharmProjects/example_shop
collected 12 items / 1 error
==================================== ERRORS ====================================
__________________ ERROR collecting tests/shop/test_orders.py __________________
ImportError while importing test module '/home/lester29/PycharmProjects/example_shop/tests/shop/test_orders.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/usr/lib/python3.11/importlib/__init__.py:126: in import_module
return _bootstrap._gcd_import(name[level:], package, level)
tests/shop/test_orders.py:2: in <module>
from example_shop.shop.orders import ShoppingCart, PaymentMethod, Product
example_shop/shop/orders.py:1: in <module>
from .users import User, Address
example_shop/shop/users.py:3: in <module>
from .products import Product
example_shop/shop/products.py:2: in <module>
from .users import User
E ImportError: cannot import name 'User' from partially initialized module 'example_shop.shop.users' (most likely due to a circular import) (/home/lester29/PycharmProjects/example_shop/example_shop/shop/users.py)
=========================== short test summary info ============================
ERROR tests/shop/test_orders.py
!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!
=============================== 1 error in 0.05s ===============================
products.py
from .money import Money
from .users import User
from decimal import Decimal
from typing import Optional
class Discount:
def __init__(self, code: str, percent: Decimal):
self.code = code
self.percent = Decimal(percent)
@property
def percent(self) -> Decimal:
return self._percent
@percent.setter
def percent(self, value: Decimal) -> None:
if isinstance(value, float):
raise TypeError("percent should not be float")
if not 0 < value < 100:
raise ValueError("percent must be a number in range (0; 100)")
self._percent = Decimal(value)
def __str__(self) -> str:
return f"{self.percent}% discount, code: '{self.code}'"
def __repr__(self) -> str:
return f"{self.__class__.__name__}(code={self.code!r}, percent={self.percent!r})"
class Product:
def __init__(self, name: str, price: Money, seller: User, discount: Optional[Discount] = None):
self.name = name
self.price = price
self.seller = seller
self.discount = discount
@property
def discount_price(self) -> Money:
return Money(amount=self.price.amount - self.discount.percent / 100 * self.price.amount,
currency=self.price.currency,
precision=self.price.precision)
def __str__(self) -> str:
return f"Product '{self.name}'"
def __repr__(self) -> str:
return f"{self.__class__.__name__}(name={self.name!r}, price={self.price!r}, " \
f"seller={self.seller!r}, discount={self.discount!r})"
users.py
import enum
from typing import NamedTuple, Optional
from .products import Product
from .payments import PaymentMethod
class Address(NamedTuple):
street: str
apartment_number: str
postal_code: str
city: str
country: str
def __str__(self) -> str:
result = f"{self.street}"
if self.apartment_number:
result += f"/{self.apartment_number}"
result += f", {self.postal_code} {self.city}, {self.country}"
return result
@enum.unique
class UserType(enum.IntEnum):
ADMINISTRATOR = enum.auto()
REGULAR_USER = enum.auto()
COMPANY = enum.auto()
class User:
def __init__(self, nick: str, firstname: str, lastname: str,
user_address: Address, shipping_address: Address,
user_type: UserType = UserType.REGULAR_USER,
payment_method: Optional[PaymentMethod] = None,
sold_products: Optional[list[Product]] = None,
bought_products: Optional[list[Product]] = None):
"""
Create user object (can be regular person or company).
:param nick: a user nickname, required
:param firstname: a user first name, required
:param lastname: a user last name, required
:param user_address: a user address, required
:param shipping_address: a user shipping address, required
:param user_type: a user type, default is regular user
:param payment_method: default payment method
:param sold_products: sold products, default value is empty list
:param bought_products: bought products, default value is empty list
"""
if not nick:
raise ValueError("nick expected to be a non-empty string")
self.nick = nick
if not firstname:
raise ValueError("expected first name to be a non-empty string")
self.firstname = firstname
if not lastname:
raise ValueError("expected last name to be a non-empty string")
self.lastname = lastname
if not user_address:
raise ValueError("expected user address to be a non-empty value")
self.user_address = user_address
if not shipping_address:
raise ValueError("expected shipping address to be a non-empty value")
self.shipping_address = shipping_address
if not user_type:
raise ValueError("expected user type to be a non-empty value")
self.user_type = user_type
if payment_method == PaymentMethod.TEST_CURRENCY and not __debug__:
raise ValueError("using PaymentMethod.TEST_CURRENCY in production environment")
if not payment_method:
raise ValueError("expected payment method to be a non-empty value")
self.payment_method = payment_method
self.sold_products = [] if sold_products is None else sold_products
self.bought_products = [] if bought_products is None else bought_products
def __str__(self) -> str:
return f"{self.nick} ({self.firstname} {self.lastname})"