Ver código fonte

Sync owel peogress.

Cixo Develop 2 meses atrás
pai
commit
a57205ea90

+ 1 - 0
server_source/__init__.py

@@ -15,6 +15,7 @@ from .config import config_processor
 from .config import config_loader
 
 from .category import category
+from .category import category_manager
 
 from .author import author
 from .author import author_proxy

+ 36 - 1
server_source/attachment.py

@@ -5,17 +5,52 @@ from .constants import constants
 from .validators import validators
 
 class attachment(model):
-    id = field_generator.id()
+    """
+    That model store attachment to the item. Attachment is file, which could
+    be downloaded by the user, like instruction in PDF, or used in frontend 
+    like images.
+
+    Fields
+    ------
+    name : str
+        Name of the attachment visible for user.
+
+    description : str
+        Description of the attachment visible for user.
+    """
+
     name = field_generator.name()
     description = field_generator.description()
 
     def _validators(self) -> dict:
+        """
+        That function return dict of validators which would be used to 
+        validate text fields of the model.
+
+        Returns
+        -------
+        dict
+            Validators which would be used to validate text fields.
+        """
+
         return {
             "name": validators.name,
             "description": validators.description
         }
 
 class attachment_proxy(proxy):   
+    """
+    That class is proxy for the attachment. It could be used to working
+    witch attachments in cleaner and better way.
+
+    Methods
+    -------
+    @classmethod create : proxy
+        That create new attachment from that name.
+
+    
+    """
+
     @classmethod
     def create(cls, name: str) -> proxy:
         return cls(attachment(

+ 118 - 1
server_source/author.py

@@ -5,12 +5,58 @@ from .constants import constants
 from .validators import validators
 
 class author(model):
-    id = field_generator.id()
+    """
+    This model store author or manufacturer who create item. It has name 
+    and surname, because items created by person exists more than created
+    by companies. Name and surname fields would be displayed different way 
+    when is_person is set to False.
+
+    Fields
+    ------
+    name : str
+        Name of the person, or name of the company.
+    
+    surname : str
+        Surname of the person, or second part of the name of the company.
+
+    description : str
+        Description of the author or company.
+
+    is_person : bool
+        Binary flag, which is True when author is the person, or False
+        when author is the company.
+
+    is_company : bool
+        Binary flag, which is True when author is the company, or False 
+        when author is the person.
+
+    Methods
+    -------
+    _validators() : dict
+        Return dict of validator for text fields.
+    """
+
     name = field_generator.name()
     surname = field_generator.surname()
     description = field_generator.description()
+    is_person = field_generator.boolean()
 
+    @property
+    def is_company(self) -> bool:
+        """ Reverse flag for is_person. """
+        
+        return not self.is_person
+    
     def _validators(self) -> dict:
+        """
+        It return dict of validators for text fields.
+
+        Returns
+        -------
+        dict
+            Validators for text fields.
+        """
+
         return {
             "name": validators.name,
             "surname": validators.surname,
@@ -18,18 +64,89 @@ class author(model):
         }
 
 class author_proxy(proxy):
+    """
+    This class is proxy for author. It could be used to make work with 
+    author objects easier and cleaner.
+
+    Methods
+    -------
+    @classmethod create : proxy
+        That method is used to creating new objects.
+
+    set_name : None
+        That set new name and surname of the author.
+
+    set_description : None
+        That set new description of the author.
+    """
+
     @classmethod
     def create(cls, name: str, surname: str) -> proxy:
+        """
+        That create new instance of author with given name and surnme, other
+        fields is set to defaults, that mean description is empty, and author
+        is the person, not a company.
+
+        Parameters
+        ----------
+        name : str
+            Name of the author.
+
+        surname : str
+            Surname of the author.
+
+        Returns
+        -------
+        proxy
+            New proxy with new instance of author inside it.
+        """
+
         return cls(author(
             name = name,
             surname = surname,
+            is_person = True,
             description = contants.empty_text()
         ))
 
     def set_name(self, name: str, surname: str) -> None:
+        """
+        It set new name and surname of the author.
+
+        Parameters
+        ----------
+        name : str
+            New name of the author.
+
+        surname : str
+            Surname of the author.
+        """
+
         self._target.name = name
         self._target.surname = surname
 
     def set_description(self, target: str) -> None:
+        """
+        It set new description of the author.
+
+        Parameters
+        ----------
+        target : str
+            Description of the author.
+        """
+
         self._target.description = target
 
+    def make_person(self) -> None:
+        """
+        It make author the person.
+        """
+
+        self._target.is_person = True
+
+    def make_company(self) -> None:
+        """
+        It make author the company.
+        """
+
+        self._target.is_person = False
+

+ 24 - 2
server_source/category.py

@@ -5,17 +5,39 @@ from .single_set_model import single_set_model
 from .field_generator import field_generator
 from .validators import validators
 from .single_set_manager import single_set_manager
+from .constants import constants
 
 class category(single_set_model):
+    """
+    This class represents single category of items in application. Category
+    must be an strincg, where all letters are small, Category name can also
+    contains numbers, and "-", "_".
+
+    Fields
+    -------
+    content : str 
+        Content of the category.
+
+    Methods
+    -------
+    get_proxy : class <single_set_proxy>
+        Return proxy for that model.
+    """
+
     content = field_generator.name()
 
     def _single_validator(self) -> callable:
         return validators.name
 
-class caterogy_manager(
+class category_manager(
     single_set_manager, 
     target_model = category, 
-    related_models = "items"
+    related_models = constants.get_related_name("item")
 ):
+    """
+    This is manager for categories in app. It base on single set proxu, and
+    for more informations, how to use it, see single_set_manager.
+    """
+
     pass
 

+ 15 - 7
server_source/constants.py

@@ -7,12 +7,20 @@ class constants:
     def app_name() -> str:
         return str("app")
 
+    @classmethod
+    def get_model_name(cls, target: str | type) -> str:
+        if type(target) is not str:
+            target = target.__name__
+
+        return str(cls.app_name() + "." + target)
+
     @staticmethod
-    def related_name(
-        target: str,
-        field: str | None = None
-    ) -> str:
-        if field is None:
-            return target + "_prefetch"
+    def get_related_name(target: str | type, field: str | None = None) -> str:
+        if type(target) is not str:
+            target = target.__name__
+
+        if field is not None:   
+            return str("related_" + target + "_to_field_" + field)
+        
+        return str("related_" + target)
 
-        return target + "_field_ " + field + "_prefetch"

+ 15 - 7
server_source/field_generator.py

@@ -56,20 +56,27 @@ class field_generator:
         return tortoise.fields.IntField
 
     @staticmethod
-    def __connected_names(target: type, field: str | None) -> [str, str]:
-        name = target.__name__
-        model_name = constants.app_name() + "." + name
-        related_name = constants.related_name(name, field)
+    def boolean() -> tortoise.fields.BooleanField:
+        return tortoise.fields.BooleanField()
 
-        return model_name, related_name
+    @staticmethod
+    def __connected_names(
+        target: type, 
+        own: type | str,
+        field: str | None) -> [str, str]:
+        target_model = constants.get_model_name(target)
+        related_field = constants.get_related_name(own, field)
+        
+        return target_model, related_field
 
     @classmethod
     def connected_many(
         cls, 
         target: type, 
+        own: type | str,
         field: str | None = None
     ) -> tortoise.fields.ManyToManyField:
-        model, related = cls.__connected_names(target, field)
+        model, related = cls.__connected_names(target, own, field)
 
         return tortoise.fields.ManyToManyField(
             model,
@@ -80,9 +87,10 @@ class field_generator:
     def connected_single(
         cls, 
         target: type,
+        own: type | str,
         field: str | None = None
     ) -> tortoise.fields.ForeignKeyField:
-        model, related = cls.__connected_names(target, field)
+        model, related = cls.__connected_names(target, own, field)
 
         return tortoise.fields.ForeignKeyField(
             model, 

+ 15 - 5
server_source/item.py

@@ -13,11 +13,21 @@ class item(model):
     description = field_generator.description()
     on_stock = field_generator.stock()
     barcode = field_generator.barcode()
-    category = field_generator.connected_single(category)
-    author = field_generator.connected_single(author)
-    product_type = field_generator.connected_single(product_type)
-    cover = field_generator.connected_single(attachment, "cover")
-    attachments = field_generator.connected_many(attachment, "attachments")
+    category = field_generator.connected_single(category, "item")
+    author = field_generator.connected_single(author, "item")
+    product_type = field_generator.connected_single(product_type, "item")
+    
+    cover = field_generator.connected_single(
+        attachment, 
+        "item", 
+        "cover"
+    )
+    
+    attachments = field_generator.connected_many(
+        attachment, 
+        "item", 
+        "attachments"
+    )
 
     def _validators(self) -> dict:
         return {

+ 8 - 6
server_source/single_set_manager.py

@@ -37,7 +37,7 @@ class single_set_manager(manager):
         target_model = cls._get_model()
         
         result = await target_model \
-        .filter(target_model.content == target) \
+        .filter(content = target) \
         .first()
 
         if result is None:
@@ -47,8 +47,8 @@ class single_set_manager(manager):
 
     @classmethod
     async def _create(cls, content: str) -> single_set_model:
-        result = self \
-        ._get_target_model() \
+        result = cls \
+        ._get_model() \
         .get_proxy() \
         .create(content) \
         .result()
@@ -56,13 +56,17 @@ class single_set_manager(manager):
         await result.save()
         return result
 
+    @classmethod
+    async def all(cls) -> tuple:
+        return tuple(await cls._get_model().all())
+    
     @classmethod
     async def clean(cls, target: str) -> None:  
         target_model = cls._get_model()
         related_models = cls._get_related_models()
 
         target = await target_model \
-        .filter(target_model.content == target) \
+        .filter(content = target) \
         .first()
 
         await target.fetch_related(*related_models)
@@ -73,5 +77,3 @@ class single_set_manager(manager):
 
         await target.delete()
 
-        has_
-

+ 0 - 6
server_source/single_set_model.py

@@ -19,12 +19,6 @@ class single_set_model(model):
             "content": self._single_validator()
         }
 
-    def __new__(cls, *args, **kwargs) -> object:
-        if cls.content == NotImplemented:
-            raise NotImplementedError("Attribute content must be field.")
-
-        super().__new__(*args, **kwargs)
-
     def __repr__(self) -> str:
         return type(self).__name__ + ": \"" + str(self) + "\""
 

+ 0 - 3
server_source/single_set_proxy.py

@@ -11,9 +11,6 @@ class single_set_proxy(proxy):
     def __init_subclass__(cls, target_model: type) -> None:
         super().__init_subclass__()
 
-        if type(target_model) is not type:
-            raise TypeError("Target must be an class.")
-
         if not issubclass(target_model, model):
             raise TypeError("Target must be subclass of single_set_model.")
 

+ 42 - 0
server_tests/007-category.py

@@ -0,0 +1,42 @@
+import sys
+import pathlib
+
+test_file = pathlib.Path(__file__)
+project = test_file.parent.parent
+
+sys.path.append(str(project))
+
+import server_source as source
+from test import test
+
+
+import asyncio
+import tortoise
+
+async def main():
+    modules = {
+        source.model.Meta.app: [ "server_source" ]
+    }
+
+    await tortoise.Tortoise.init(
+        db_url = "sqlite://:memory:", 
+        modules = modules
+    )
+
+    await tortoise.Tortoise.generate_schemas()
+    
+    books = source.category.get_proxy().create("books").result()
+    await books.save()
+
+    test(str(books), "books")
+    test(len(await source.category_manager.all()), 1)
+    loaded_books = await source.category_manager.add("books")
+    test(len(await source.category_manager.all()), 1)
+    games = await source.category_manager.add("games")
+    test(len(await source.category_manager.all()), 2)
+    await source.category_manager.clean("books")
+    test(len(await source.category_manager.all()), 1)
+
+    await tortoise.Tortoise.close_connections()
+
+asyncio.run(main())