PyDataToolsKit 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,154 @@
1
+ import json
2
+ import os
3
+
4
+ from datetime import date, timedelta
5
+ from typing import Generic, TypeVar, Any
6
+
7
+ from Decorators.functions.retry import Retry #type: ignore
8
+ from Decorators.functions.validateType import ValidateType #type: ignore
9
+
10
+ T = TypeVar("T")
11
+
12
+
13
+ class Repository(Generic[T]):
14
+ """Persists entities as a JSON list and provides basic CRUD operations."""
15
+
16
+ def __init__(self, path: str, entity_type: type[T]):
17
+ self.path = path
18
+ self.entity_type = entity_type
19
+
20
+ try:
21
+ self.last_time = os.path.getmtime(self.path)
22
+ except FileNotFoundError:
23
+ self.last_time = 0
24
+
25
+ self.loaded = None
26
+ self.load()
27
+
28
+ def load(self):
29
+
30
+ if os.path.getmtime(self.path) != self.last_time and self.loaded is not None or self.loaded is None:
31
+ with open(self.path, "r", encoding="utf-8") as f:
32
+ datas = json.load(f)
33
+ self.last_time = os.path.getmtime(self.path)
34
+
35
+ instances = []
36
+
37
+ for data in datas:
38
+
39
+ if callable(getattr(self.entity_type, "builder", None)):
40
+ instance = self.entity_type.builder(data)
41
+
42
+ if isinstance(data, dict) and data.get("ID") is not None and hasattr(instance, "ID"):
43
+ instance.ID = data["ID"]
44
+ reserve_id = getattr(type(instance), "_reserve_id", None)
45
+ if callable(reserve_id):
46
+ reserve_id(data["ID"])
47
+
48
+ instances.append(instance)
49
+
50
+ self.loaded = instances
51
+ return self.loaded
52
+ else:
53
+ return self.loaded
54
+
55
+ @Retry(cathed_exception=json.JSONDecodeError, amount=3)
56
+ def save(self):
57
+
58
+ if self.loaded is not None:
59
+ with open(self.path, "w", encoding="utf-8") as f:
60
+ json.dump([e.toJson() for e in self.loaded if callable(getattr(e, "toJson", None))], f, indent=4)
61
+
62
+ def create(self, entity: Any):
63
+
64
+ if isinstance(entity, self.entity_type):
65
+ if self.loaded is None:
66
+ self.loaded = self.load()
67
+
68
+ self.loaded.append(entity)
69
+ self.save()
70
+ else:
71
+ raise TypeError(f"L'entité est de type {type(entity)}. Le type de la base de données est {self.entity_type}")
72
+
73
+ @ValidateType()
74
+ def update(self, given_id: int, entity: Any):
75
+
76
+ if isinstance(entity, self.entity_type):
77
+
78
+ if self.loaded is None:
79
+ self.loaded = self.load()
80
+
81
+ target = next((e for e in self.loaded if hasattr(e, "ID") and e.ID == given_id), None)
82
+
83
+ if target is not None:
84
+ for index, targets in enumerate(self.loaded):
85
+ if targets.ID == target.ID:
86
+ entity.ID = target.ID
87
+ self.loaded[index] = entity
88
+ break
89
+
90
+ self.save()
91
+
92
+ else:
93
+ raise NameError("Le nom donné ne correspond à aucune entité")
94
+
95
+ else:
96
+ raise TypeError(f"L'entité est de type {type(entity)}. Le type de la base de données est {self.entity_type}")
97
+
98
+ @ValidateType()
99
+ def find_by_id(self, given_id: int):
100
+
101
+ if self.loaded is None:
102
+ self.loaded = self.load()
103
+
104
+ target = next((e for e in self.loaded if hasattr(e, "ID") and e.ID == given_id), None)
105
+ if target is None:
106
+ raise ValueError(f"L'id {given_id} ne correspond à aucune entité")
107
+
108
+ else:
109
+ return target
110
+
111
+ def clear_from_date(self):
112
+
113
+ if self.loaded is None:
114
+ self.loaded = self.load()
115
+
116
+ today = date.today
117
+
118
+ targets = []
119
+
120
+ for entity in self.loaded:
121
+ if hasattr(entity, "date"):
122
+
123
+ if entity.date < today:
124
+ targets.append(entity)
125
+
126
+ for target in targets:
127
+ self.loaded.remove(target)
128
+
129
+ self.save()
130
+
131
+ @ValidateType()
132
+ def delete(self, given_id: int):
133
+
134
+ if self.loaded is None:
135
+ self.loaded = self.load()
136
+
137
+ target_index = next(
138
+ (index for index, entity in enumerate(self.loaded) if hasattr(entity, "ID") and entity.ID == given_id),
139
+ None,
140
+ )
141
+
142
+ if target_index is None:
143
+ raise ValueError(f"L'id {given_id} ne correspond à aucune entité")
144
+
145
+ del self.loaded[target_index]
146
+ self.save()
147
+
148
+ def ensure_file(self):
149
+ try:
150
+ with open(self.path, "r", encoding="utf-8") as f:
151
+ pass
152
+ except FileNotFoundError:
153
+ with open(self.path, "w", encoding="utf-8") as f:
154
+ json.dump([], f, indent=4)
PyData/database.py ADDED
@@ -0,0 +1,39 @@
1
+ import json
2
+ from typing import TypeVar
3
+
4
+ from .classes.repository import Repository
5
+
6
+ T = TypeVar("T")
7
+
8
+ def Database(path: str, entity_type: type[T]):
9
+ """
10
+ Mets à disposition:
11
+ - save : Sauvegarde d'entité
12
+ - delete_by_name: Suppression par le nom si l'entité a cet attribut
13
+ - load: Renvoie la base complète
14
+ - find_by_name : Renvoie une entité par son nom si elle a cet attribut
15
+ - update_by_name: Modifie une entité existante par son nom si elle a cet attribut
16
+ - clear_from_date: Supprime les entité ayant une date dépassée
17
+ - ensure_file: Créer le fichier json à partir du chemin préciser
18
+ """
19
+ def decorator(cls):
20
+
21
+ def __init__(self, *args, **kwargs):
22
+ return Repository.__init__(
23
+ self,
24
+ path=path,
25
+ entity_type=entity_type
26
+ )
27
+
28
+ repository = type(
29
+ cls.__name__,
30
+ (cls, Repository),
31
+ {
32
+ "__init__" : __init__,
33
+ "path" : path,
34
+ "entity_type" : entity_type
35
+ }
36
+ )
37
+
38
+ return repository
39
+ return decorator
PyData/entity.py ADDED
@@ -0,0 +1,31 @@
1
+ import pygame
2
+ from enum import Enum
3
+
4
+ def Entity():
5
+
6
+ def decorator(cls):
7
+
8
+ def toJson(self):
9
+ result = {}
10
+
11
+ for key, value in vars(self).items():
12
+ if isinstance(value, pygame.Rect):
13
+ result[key] = {
14
+ "x": value.x,
15
+ "y": value.y,
16
+ "width": value.width,
17
+ "height": value.height
18
+ }
19
+
20
+ elif isinstance(value, Enum):
21
+ result[key] = value.value
22
+
23
+ elif hasattr(value, "toJson"):
24
+ result[key] = value.toJson()
25
+ else:
26
+ result[key] = value
27
+
28
+ return result
29
+ cls.toJson = toJson
30
+ return cls
31
+ return decorator
PyData/id.py ADDED
@@ -0,0 +1,38 @@
1
+ import json
2
+
3
+ def Id(file: str):
4
+ def decorator(cls):
5
+ cls._ID = 1
6
+
7
+ def reserve_id(entity_id):
8
+ if isinstance(entity_id, int):
9
+ cls._ID = max(cls._ID, entity_id + 1)
10
+
11
+ cls._reserve_id = staticmethod(reserve_id)
12
+
13
+ with open(file, "r", encoding="utf-8") as f:
14
+
15
+ for entity in json.load(f):
16
+
17
+ entity_id = entity.get("ID", None)
18
+
19
+ if entity_id is not None:
20
+ reserve_id(entity_id)
21
+
22
+ original_init = cls.__init__
23
+
24
+ def __init__(self, *args, **kwargs):
25
+ original_init(self, *args, **kwargs)
26
+
27
+ entity_id = getattr(self, "ID", None)
28
+ if entity_id is not None:
29
+ reserve_id(entity_id)
30
+ return
31
+
32
+ self.ID = cls._ID
33
+ cls._ID += 1
34
+
35
+ cls.__init__ = __init__
36
+ return cls
37
+
38
+ return decorator
@@ -0,0 +1,5 @@
1
+ Metadata-Version: 2.4
2
+ Name: PyDataToolsKit
3
+ Version: 1.0.0
4
+ Summary: Bibliothèque facilitant les transitions Entity/Repository
5
+ Requires-Dist: DecoratorsToolKit>=1.0.0
@@ -0,0 +1,8 @@
1
+ PyData/database.py,sha256=arGKuv1T6lRxABSpyvPYX_DXcZJ8mnQb54SFhu4CjWY,1175
2
+ PyData/entity.py,sha256=850bck_8Yh9EneDSwuUL3SbV2zntHmdZGIguB5eWHTc,832
3
+ PyData/id.py,sha256=qfIfi-tFYrEw0eVu_iwPFg4b2qXJJrecN6od-MvlkzA,942
4
+ PyData/classes/repository.py,sha256=sQu_if8_N9dQGCpiekAmW7QiIM3AvXD2MHzq8alTlJg,4897
5
+ pydatatoolskit-1.0.0.dist-info/METADATA,sha256=F-9nmZQ9dK4yQHA_mGhBTJusY7VCK8oDk3R0D2kXJoY,171
6
+ pydatatoolskit-1.0.0.dist-info/WHEEL,sha256=mOdXR9C3wMVov7cSY8PY-XCzo3SmmWCHvGQr5csJoao,91
7
+ pydatatoolskit-1.0.0.dist-info/top_level.txt,sha256=sjkXs1KOSOZFRyjGnuA56SAYB48pQ_RWqKA5j7sFBZ4,7
8
+ pydatatoolskit-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.2.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ PyData