sqlobjects 1.4.0__tar.gz → 1.6.0__tar.gz
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.
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/CHANGELOG.md +12 -0
- {sqlobjects-1.4.0/sqlobjects.egg-info → sqlobjects-1.6.0}/PKG-INFO +1 -1
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/pyproject.toml +1 -1
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/cascade.py +37 -2
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/metadata.py +55 -2
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/model.py +9 -2
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/queryset.py +3 -2
- {sqlobjects-1.4.0 → sqlobjects-1.6.0/sqlobjects.egg-info}/PKG-INFO +1 -1
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/LICENSE +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/README.md +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/docs/rules/01-database-session-guide.md +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/docs/rules/02-model-definition-guide.md +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/docs/rules/03-query-operations-guide.md +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/docs/rules/04-crud-operations-guide.md +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/docs/rules/05-relationships-guide.md +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/docs/rules/06-validation-signals-guide.md +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/docs/rules/07-performance-guide.md +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/docs/rules/README.md +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/setup.cfg +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/__init__.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/_install_rules.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/contrib/__init__.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/contrib/asgi.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/contrib/fastapi.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/database/__init__.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/database/config.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/database/manager.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/exceptions.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/expressions/__init__.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/expressions/aggregate.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/expressions/base.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/expressions/cte.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/expressions/explain.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/expressions/function.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/expressions/mixins.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/expressions/scalar.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/expressions/subquery.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/expressions/terminal.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/expressions/window.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/fields/__init__.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/fields/core.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/fields/functions.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/fields/proxies.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/fields/relations/__init__.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/fields/relations/descriptors.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/fields/relations/managers.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/fields/relations/prefetch.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/fields/relations/strategies.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/fields/relations/utils.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/fields/shortcuts.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/fields/types/__init__.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/fields/types/base.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/fields/types/comparators.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/fields/types/registry.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/fields/utils.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/internal/__init__.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/internal/operations.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/internal/results.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/mixins.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/objects/__init__.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/objects/bulk.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/objects/core.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/objects/upsert.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/queries/__init__.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/queries/builder.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/queries/dialect.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/queries/executor.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/session.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/signals.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/utils/__init__.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/utils/inspect.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/utils/naming.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/utils/pattern.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects/validators.py +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects.egg-info/SOURCES.txt +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects.egg-info/dependency_links.txt +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects.egg-info/entry_points.txt +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects.egg-info/requires.txt +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/sqlobjects.egg-info/top_level.txt +0 -0
- {sqlobjects-1.4.0 → sqlobjects-1.6.0}/tests/test_config.py +0 -0
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
## 1.6.0 (2026-03-18)
|
|
2
|
+
|
|
3
|
+
### Feat
|
|
4
|
+
|
|
5
|
+
- **metadata**: add foreignkey() constraint builder
|
|
6
|
+
|
|
7
|
+
## 1.5.0 (2026-03-16)
|
|
8
|
+
|
|
9
|
+
### Feat
|
|
10
|
+
|
|
11
|
+
- **cascade**: unify cascade strategy with auto-detection for Model.delete()
|
|
12
|
+
|
|
1
13
|
## 1.4.0 (2026-03-11)
|
|
2
14
|
|
|
3
15
|
### Feat
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sqlobjects
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.6.0
|
|
4
4
|
Summary: Django-style async ORM library based on SQLAlchemy with chainable queries, Q objects, and relationship loading
|
|
5
5
|
Author-email: XtraVisions <gitadmin@xtravisions.com>, Chen Hao <chenhao@xtravisions.com>
|
|
6
6
|
Maintainer-email: XtraVisions <gitadmin@xtravisions.com>, Chen Hao <chenhao@xtravisions.com>
|
|
@@ -28,6 +28,7 @@ __all__ = [
|
|
|
28
28
|
"normalize_onupdate",
|
|
29
29
|
"normalize_cascade",
|
|
30
30
|
"has_cascade_delete_relations",
|
|
31
|
+
"has_delete_signals",
|
|
31
32
|
]
|
|
32
33
|
|
|
33
34
|
|
|
@@ -130,6 +131,30 @@ def has_cascade_delete_relations(model_class) -> bool:
|
|
|
130
131
|
return False
|
|
131
132
|
|
|
132
133
|
|
|
134
|
+
def has_delete_signals(model_class) -> bool:
|
|
135
|
+
"""Check if model class has delete signal handlers defined.
|
|
136
|
+
|
|
137
|
+
Args:
|
|
138
|
+
model_class: Model class to check
|
|
139
|
+
|
|
140
|
+
Returns:
|
|
141
|
+
True if model has before_delete/after_delete handlers, False otherwise
|
|
142
|
+
"""
|
|
143
|
+
from .signals import SignalMixin
|
|
144
|
+
|
|
145
|
+
if not issubclass(model_class, SignalMixin):
|
|
146
|
+
return False
|
|
147
|
+
|
|
148
|
+
for method_name in ("before_delete", "after_delete"):
|
|
149
|
+
method = getattr(model_class, method_name, None)
|
|
150
|
+
if method is None:
|
|
151
|
+
continue
|
|
152
|
+
# Must be defined on the model itself, not inherited from SignalMixin
|
|
153
|
+
if method_name in model_class.__dict__:
|
|
154
|
+
return True
|
|
155
|
+
return False
|
|
156
|
+
|
|
157
|
+
|
|
133
158
|
def normalize_cascade(cascade: CascadeType) -> str:
|
|
134
159
|
"""Normalize cascade parameter to SQLAlchemy string format."""
|
|
135
160
|
if cascade is None:
|
|
@@ -344,7 +369,7 @@ class CascadeExecutor:
|
|
|
344
369
|
return instance
|
|
345
370
|
|
|
346
371
|
async def execute_delete_operation(
|
|
347
|
-
self, target, cascade_strategy: str = "
|
|
372
|
+
self, target, cascade_strategy: str = "auto", session: "AsyncSession | None" = None
|
|
348
373
|
) -> int:
|
|
349
374
|
"""Execute delete operation with cascade handling."""
|
|
350
375
|
if session is None:
|
|
@@ -355,7 +380,8 @@ class CascadeExecutor:
|
|
|
355
380
|
return await self._execute_queryset_delete(target, cascade_strategy, session)
|
|
356
381
|
|
|
357
382
|
# Handle single instance deletion
|
|
358
|
-
|
|
383
|
+
if has_cascade_delete_relations(target.__class__):
|
|
384
|
+
await self._delete_related_objects(target, session)
|
|
359
385
|
await target._delete_internal(session=session) # noqa
|
|
360
386
|
return 1
|
|
361
387
|
|
|
@@ -478,6 +504,15 @@ class CascadeExecutor:
|
|
|
478
504
|
|
|
479
505
|
async def _execute_queryset_delete(self, queryset, cascade_strategy: str, session: "AsyncSession") -> int:
|
|
480
506
|
"""Execute QuerySet delete with different cascade strategies."""
|
|
507
|
+
if cascade_strategy == "auto":
|
|
508
|
+
model_class = queryset._model_class
|
|
509
|
+
if has_delete_signals(model_class):
|
|
510
|
+
cascade_strategy = "full"
|
|
511
|
+
elif has_cascade_delete_relations(model_class):
|
|
512
|
+
cascade_strategy = "fast"
|
|
513
|
+
else:
|
|
514
|
+
cascade_strategy = "none"
|
|
515
|
+
|
|
481
516
|
if cascade_strategy == "full":
|
|
482
517
|
return await self._delete_with_full_cascade(queryset, session)
|
|
483
518
|
elif cascade_strategy == "fast":
|
|
@@ -22,6 +22,7 @@ __all__ = [
|
|
|
22
22
|
"index",
|
|
23
23
|
"constraint",
|
|
24
24
|
"unique",
|
|
25
|
+
"foreignkey",
|
|
25
26
|
]
|
|
26
27
|
|
|
27
28
|
_FIELD_NAME_PATTERN = re.compile(r"\b([a-zA-Z_][a-zA-Z0-9_]*)\b")
|
|
@@ -37,7 +38,7 @@ class _RawModelConfig:
|
|
|
37
38
|
verbose_name_plural: str | None = None
|
|
38
39
|
ordering: list[str] = field(default_factory=list)
|
|
39
40
|
indexes: list[Index] = field(default_factory=list)
|
|
40
|
-
constraints: list[CheckConstraint | UniqueConstraint] = field(default_factory=list)
|
|
41
|
+
constraints: list[CheckConstraint | UniqueConstraint | ForeignKeyConstraint] = field(default_factory=list)
|
|
41
42
|
description: str | None = None
|
|
42
43
|
db_options: dict[str, dict[str, Any]] = field(default_factory=dict)
|
|
43
44
|
custom: dict[str, Any] = field(default_factory=dict)
|
|
@@ -52,7 +53,7 @@ class ModelConfig:
|
|
|
52
53
|
verbose_name_plural: str
|
|
53
54
|
ordering: list[str] = field(default_factory=list)
|
|
54
55
|
indexes: list[Index] = field(default_factory=list)
|
|
55
|
-
constraints: list[CheckConstraint | UniqueConstraint] = field(default_factory=list)
|
|
56
|
+
constraints: list[CheckConstraint | UniqueConstraint | ForeignKeyConstraint] = field(default_factory=list)
|
|
56
57
|
description: str | None = None
|
|
57
58
|
db_options: dict[str, dict[str, Any]] = field(default_factory=dict)
|
|
58
59
|
custom: dict[str, Any] = field(default_factory=dict)
|
|
@@ -1109,3 +1110,55 @@ def unique(
|
|
|
1109
1110
|
>>> unique("first_name", "last_name", name="uq_full_name")
|
|
1110
1111
|
"""
|
|
1111
1112
|
return UniqueConstraint(*fields, name=name, **kwargs)
|
|
1113
|
+
|
|
1114
|
+
|
|
1115
|
+
def foreignkey(
|
|
1116
|
+
fields: str | list[str],
|
|
1117
|
+
references: str | list[str],
|
|
1118
|
+
*,
|
|
1119
|
+
name: str | None = None,
|
|
1120
|
+
ondelete: str | None = None,
|
|
1121
|
+
onupdate: str | None = None,
|
|
1122
|
+
deferrable: bool = False,
|
|
1123
|
+
initially: str = "IMMEDIATE",
|
|
1124
|
+
**kwargs: Any,
|
|
1125
|
+
) -> ForeignKeyConstraint:
|
|
1126
|
+
"""Create a ForeignKeyConstraint with convenient field name support.
|
|
1127
|
+
|
|
1128
|
+
Use this in Config.constraints for explicit constraint definition, custom
|
|
1129
|
+
names, or composite foreign keys. For simple single-column foreign keys,
|
|
1130
|
+
prefer the ``foreign_key()`` field descriptor instead.
|
|
1131
|
+
|
|
1132
|
+
Args:
|
|
1133
|
+
fields: Local field name(s) as string or list of strings.
|
|
1134
|
+
references: Referenced column(s) as "Table.column" or list thereof.
|
|
1135
|
+
Supports class names (e.g. "User.id") or table names (e.g. "users.id").
|
|
1136
|
+
name: Constraint name (optional, auto-generated if not provided).
|
|
1137
|
+
ondelete: Referential action on delete (CASCADE, SET NULL, RESTRICT, etc.).
|
|
1138
|
+
onupdate: Referential action on update.
|
|
1139
|
+
deferrable: Whether the constraint can be deferred.
|
|
1140
|
+
initially: Initial deferral state ("IMMEDIATE" or "DEFERRED").
|
|
1141
|
+
**kwargs: Additional SQLAlchemy ForeignKeyConstraint arguments.
|
|
1142
|
+
|
|
1143
|
+
Returns:
|
|
1144
|
+
SQLAlchemy ForeignKeyConstraint instance.
|
|
1145
|
+
|
|
1146
|
+
Examples:
|
|
1147
|
+
>>> foreignkey("author_id", "User.id")
|
|
1148
|
+
>>> foreignkey("author_id", "User.id", name="fk_posts_author", ondelete="CASCADE")
|
|
1149
|
+
>>> foreignkey(["a_id", "b_id"], ["A.id", "B.id"])
|
|
1150
|
+
"""
|
|
1151
|
+
if isinstance(fields, str):
|
|
1152
|
+
fields = [fields]
|
|
1153
|
+
if isinstance(references, str):
|
|
1154
|
+
references = [references]
|
|
1155
|
+
return ForeignKeyConstraint(
|
|
1156
|
+
fields,
|
|
1157
|
+
references,
|
|
1158
|
+
name=name,
|
|
1159
|
+
ondelete=ondelete,
|
|
1160
|
+
onupdate=onupdate,
|
|
1161
|
+
deferrable=deferrable or None,
|
|
1162
|
+
initially=initially if deferrable else None,
|
|
1163
|
+
**kwargs,
|
|
1164
|
+
)
|
|
@@ -278,11 +278,14 @@ class ModelMixin(DataConversionMixin, SignalMixin):
|
|
|
278
278
|
return await self._save_internal(validate=validate, session=session)
|
|
279
279
|
|
|
280
280
|
@emit_signals(Operation.DELETE)
|
|
281
|
-
async def delete(self, cascade: bool =
|
|
281
|
+
async def delete(self, cascade: bool | None = None):
|
|
282
282
|
"""Delete this model instance from the database with cascade support.
|
|
283
283
|
|
|
284
284
|
Args:
|
|
285
|
-
cascade: Whether to handle cascade deletion
|
|
285
|
+
cascade: Whether to handle cascade deletion.
|
|
286
|
+
None (default): auto-detect based on model relationships
|
|
287
|
+
True: force cascade handling
|
|
288
|
+
False: skip cascade, direct delete
|
|
286
289
|
|
|
287
290
|
Raises:
|
|
288
291
|
PrimaryKeyError: If instance has no primary key values or delete fails
|
|
@@ -292,6 +295,10 @@ class ModelMixin(DataConversionMixin, SignalMixin):
|
|
|
292
295
|
|
|
293
296
|
session = self.get_session()
|
|
294
297
|
|
|
298
|
+
# Auto-detect cascade need when not explicitly specified
|
|
299
|
+
if cascade is None:
|
|
300
|
+
cascade = self._has_on_delete_relations()
|
|
301
|
+
|
|
295
302
|
# Use cascade executor for cascade operations
|
|
296
303
|
if cascade:
|
|
297
304
|
executor = CascadeExecutor()
|
|
@@ -1221,12 +1221,13 @@ class QuerySet(Generic[T]):
|
|
|
1221
1221
|
return await executor.execute_update_operation(self, values)
|
|
1222
1222
|
|
|
1223
1223
|
@emit_signals(Operation.DELETE, is_bulk=True)
|
|
1224
|
-
async def delete(self, cascade: str = "
|
|
1224
|
+
async def delete(self, cascade: str = "auto") -> int:
|
|
1225
1225
|
"""Perform bulk delete on objects matching query conditions.
|
|
1226
1226
|
|
|
1227
1227
|
Args:
|
|
1228
1228
|
cascade: Cascade deletion strategy
|
|
1229
|
-
- "
|
|
1229
|
+
- "auto" (default): Automatically choose based on model relationships
|
|
1230
|
+
- "full": Complete cascade deletion with full ORM functionality
|
|
1230
1231
|
- "fast": Fast cascade deletion with minimal ORM processing
|
|
1231
1232
|
- "none": Direct SQL deletion without ORM cascade processing
|
|
1232
1233
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sqlobjects
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.6.0
|
|
4
4
|
Summary: Django-style async ORM library based on SQLAlchemy with chainable queries, Q objects, and relationship loading
|
|
5
5
|
Author-email: XtraVisions <gitadmin@xtravisions.com>, Chen Hao <chenhao@xtravisions.com>
|
|
6
6
|
Maintainer-email: XtraVisions <gitadmin@xtravisions.com>, Chen Hao <chenhao@xtravisions.com>
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|