sqlphilosophy 0.1.9__tar.gz → 0.2.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.
Potentially problematic release.
This version of sqlphilosophy might be problematic. Click here for more details.
- {sqlphilosophy-0.1.9/src/sqlphilosophy.egg-info → sqlphilosophy-0.2.0}/PKG-INFO +3 -1
- {sqlphilosophy-0.1.9 → sqlphilosophy-0.2.0}/README.md +1 -0
- {sqlphilosophy-0.1.9 → sqlphilosophy-0.2.0}/pyproject.toml +1 -0
- sqlphilosophy-0.2.0/src/sqlphilosophy/VERSION +1 -0
- {sqlphilosophy-0.1.9 → sqlphilosophy-0.2.0}/src/sqlphilosophy/aio/protocols.py +25 -19
- {sqlphilosophy-0.1.9 → sqlphilosophy-0.2.0}/src/sqlphilosophy/aio/repository.py +12 -9
- {sqlphilosophy-0.1.9 → sqlphilosophy-0.2.0}/src/sqlphilosophy/sync/protocols.py +27 -19
- {sqlphilosophy-0.1.9 → sqlphilosophy-0.2.0}/src/sqlphilosophy/sync/repository.py +13 -10
- {sqlphilosophy-0.1.9 → sqlphilosophy-0.2.0/src/sqlphilosophy.egg-info}/PKG-INFO +3 -1
- {sqlphilosophy-0.1.9 → sqlphilosophy-0.2.0}/src/sqlphilosophy.egg-info/requires.txt +1 -0
- sqlphilosophy-0.1.9/src/sqlphilosophy/VERSION +0 -1
- {sqlphilosophy-0.1.9 → sqlphilosophy-0.2.0}/LICENSE +0 -0
- {sqlphilosophy-0.1.9 → sqlphilosophy-0.2.0}/MANIFEST.in +0 -0
- {sqlphilosophy-0.1.9 → sqlphilosophy-0.2.0}/setup.cfg +0 -0
- {sqlphilosophy-0.1.9 → sqlphilosophy-0.2.0}/src/sqlphilosophy/__init__.py +0 -0
- {sqlphilosophy-0.1.9 → sqlphilosophy-0.2.0}/src/sqlphilosophy/_repository_shared.py +0 -0
- {sqlphilosophy-0.1.9 → sqlphilosophy-0.2.0}/src/sqlphilosophy/aio/__init__.py +0 -0
- {sqlphilosophy-0.1.9 → sqlphilosophy-0.2.0}/src/sqlphilosophy/aio/query.py +0 -0
- {sqlphilosophy-0.1.9 → sqlphilosophy-0.2.0}/src/sqlphilosophy/audit/__init__.py +0 -0
- {sqlphilosophy-0.1.9 → sqlphilosophy-0.2.0}/src/sqlphilosophy/audit/context.py +0 -0
- {sqlphilosophy-0.1.9 → sqlphilosophy-0.2.0}/src/sqlphilosophy/audit/fields.py +0 -0
- {sqlphilosophy-0.1.9 → sqlphilosophy-0.2.0}/src/sqlphilosophy/audit/listener.py +0 -0
- {sqlphilosophy-0.1.9 → sqlphilosophy-0.2.0}/src/sqlphilosophy/audit/model.py +0 -0
- {sqlphilosophy-0.1.9 → sqlphilosophy-0.2.0}/src/sqlphilosophy/py.typed +0 -0
- {sqlphilosophy-0.1.9 → sqlphilosophy-0.2.0}/src/sqlphilosophy/sorting.py +0 -0
- {sqlphilosophy-0.1.9 → sqlphilosophy-0.2.0}/src/sqlphilosophy/sql.py +0 -0
- {sqlphilosophy-0.1.9 → sqlphilosophy-0.2.0}/src/sqlphilosophy/sync/__init__.py +0 -0
- {sqlphilosophy-0.1.9 → sqlphilosophy-0.2.0}/src/sqlphilosophy/sync/query.py +0 -0
- {sqlphilosophy-0.1.9 → sqlphilosophy-0.2.0}/src/sqlphilosophy/trusted_sql.py +0 -0
- {sqlphilosophy-0.1.9 → sqlphilosophy-0.2.0}/src/sqlphilosophy/types.py +0 -0
- {sqlphilosophy-0.1.9 → sqlphilosophy-0.2.0}/src/sqlphilosophy.egg-info/SOURCES.txt +0 -0
- {sqlphilosophy-0.1.9 → sqlphilosophy-0.2.0}/src/sqlphilosophy.egg-info/dependency_links.txt +0 -0
- {sqlphilosophy-0.1.9 → sqlphilosophy-0.2.0}/src/sqlphilosophy.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sqlphilosophy
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Portable SQLAlchemy repository kit: sync and async CRUD, statement builders, sort/pagination, and SQL helpers.
|
|
5
5
|
Author-email: Josh Martin <denverprogrammer@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -20,6 +20,7 @@ Classifier: Typing :: Typed
|
|
|
20
20
|
Requires-Python: <4.0,>=3.12
|
|
21
21
|
Description-Content-Type: text/markdown
|
|
22
22
|
License-File: LICENSE
|
|
23
|
+
Requires-Dist: servicephilosophy>=0.1.0
|
|
23
24
|
Requires-Dist: sqlalchemy<3,>=2.0
|
|
24
25
|
Provides-Extra: async
|
|
25
26
|
Requires-Dist: greenlet>=3.0; extra == "async"
|
|
@@ -56,6 +57,7 @@ Portable SQLAlchemy repository kit: sync and async CRUD, fluent statement builde
|
|
|
56
57
|
| [Repository guide](./docs/repository-guide.md) | Entry point: overview, transaction model, links to usage pages |
|
|
57
58
|
| [Usage examples](./docs/usage/) | Focused sync/async code examples by feature area |
|
|
58
59
|
| [Strongly typed repositories](./docs/usage/strongly-typed-repositories.md) | Typed subclasses, factories, protocols, and service patterns |
|
|
60
|
+
| [Service factory composition](./docs/usage/service-factory-composition.md) | Compose sqlPhilosophy SQL repos with servicePhilosophy business services |
|
|
59
61
|
| [Before/after SQLAlchemy](./docs/usage/before-after-sqlalchemy.md) | Migration examples: direct SQLAlchemy vs repository-centered code |
|
|
60
62
|
| [Feature matrix](./docs/feature-matrix.md) | Full sync/async capability map |
|
|
61
63
|
| [Typed repository (sync)](./docs/examples/typed_repository_sync.py) | Runnable factory + domain repo example |
|
|
@@ -17,6 +17,7 @@ Portable SQLAlchemy repository kit: sync and async CRUD, fluent statement builde
|
|
|
17
17
|
| [Repository guide](./docs/repository-guide.md) | Entry point: overview, transaction model, links to usage pages |
|
|
18
18
|
| [Usage examples](./docs/usage/) | Focused sync/async code examples by feature area |
|
|
19
19
|
| [Strongly typed repositories](./docs/usage/strongly-typed-repositories.md) | Typed subclasses, factories, protocols, and service patterns |
|
|
20
|
+
| [Service factory composition](./docs/usage/service-factory-composition.md) | Compose sqlPhilosophy SQL repos with servicePhilosophy business services |
|
|
20
21
|
| [Before/after SQLAlchemy](./docs/usage/before-after-sqlalchemy.md) | Migration examples: direct SQLAlchemy vs repository-centered code |
|
|
21
22
|
| [Feature matrix](./docs/feature-matrix.md) | Full sync/async capability map |
|
|
22
23
|
| [Typed repository (sync)](./docs/examples/typed_repository_sync.py) | Runnable factory + domain repo example |
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.2.0
|
|
@@ -8,6 +8,7 @@ from typing import TYPE_CHECKING, Any, Protocol, TypeVar
|
|
|
8
8
|
if TYPE_CHECKING:
|
|
9
9
|
from sqlphilosophy.aio.repository import AsyncBaseRepository
|
|
10
10
|
|
|
11
|
+
from servicephilosophy import RepositoryFactoryProtocol, ServiceRepositoryProtocol
|
|
11
12
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
12
13
|
from sqlalchemy.orm import DeclarativeBase
|
|
13
14
|
|
|
@@ -18,14 +19,35 @@ T = TypeVar("T", bound=DeclarativeBase)
|
|
|
18
19
|
R = TypeVar("R", bound="AsyncBaseRepository[Any, Any]")
|
|
19
20
|
|
|
20
21
|
|
|
21
|
-
class
|
|
22
|
+
class AsyncRepositoryFactory(RepositoryFactoryProtocol, Protocol):
|
|
23
|
+
"""Async session-scoped factory for statement builders and entity repositories."""
|
|
24
|
+
|
|
25
|
+
def create_statement(self, model: type[T]) -> AsyncStatementQueryBuilder[T]:
|
|
26
|
+
"""Return a fluent async read builder for ``model``."""
|
|
27
|
+
...
|
|
28
|
+
|
|
29
|
+
def get_repository(self, repo_class: type[R]) -> R:
|
|
30
|
+
"""Return a cached typed entity repository."""
|
|
31
|
+
...
|
|
32
|
+
|
|
33
|
+
def repository(self, model: type[T]) -> AsyncBaseRepositoryProtocol[T, AsyncRepositoryFactory]:
|
|
34
|
+
"""Return generic CRUD helpers for ``model`` (``AsyncBaseRepository``)."""
|
|
35
|
+
...
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class AsyncBaseRepositoryProtocol[T: DeclarativeBase, U: AsyncRepositoryFactory](
|
|
39
|
+
ServiceRepositoryProtocol[U],
|
|
22
40
|
Protocol,
|
|
23
41
|
):
|
|
24
|
-
"""
|
|
42
|
+
"""Async SQL read/write surface for ``AsyncBaseRepository[T]``.
|
|
43
|
+
|
|
44
|
+
Factory access (``.factory``, ``.maybe_factory``, ``.has_factory``) is inherited
|
|
45
|
+
from ``ServiceRepositoryProtocol``; this protocol adds the mapped model, session,
|
|
46
|
+
and SQLAlchemy CRUD/query methods only.
|
|
47
|
+
"""
|
|
25
48
|
|
|
26
49
|
model: type[T]
|
|
27
50
|
_session: AsyncSession
|
|
28
|
-
_factory: U | None
|
|
29
51
|
|
|
30
52
|
async def get(self, obj_id: PrimaryKey, load_relations: Any = None) -> T: ...
|
|
31
53
|
|
|
@@ -88,19 +110,3 @@ class AsyncBaseRepositoryProtocol[T: DeclarativeBase, U: AsyncRepositoryFactory
|
|
|
88
110
|
values: RowMapping,
|
|
89
111
|
params: RowMapping | None = None,
|
|
90
112
|
) -> int: ...
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
class AsyncRepositoryFactory(Protocol):
|
|
94
|
-
"""Session-scoped factory for async statement builders and entity repositories."""
|
|
95
|
-
|
|
96
|
-
def create_statement(self, model: type[T]) -> AsyncStatementQueryBuilder[T]:
|
|
97
|
-
"""Return a fluent async read builder for ``model``."""
|
|
98
|
-
...
|
|
99
|
-
|
|
100
|
-
def get_repository(self, repo_class: type[R]) -> R:
|
|
101
|
-
"""Return a cached typed entity repository."""
|
|
102
|
-
...
|
|
103
|
-
|
|
104
|
-
def repository(self, model: type[T]) -> AsyncBaseRepositoryProtocol[T, AsyncRepositoryFactory | None]:
|
|
105
|
-
"""Return generic CRUD helpers for ``model`` (``AsyncBaseRepository`` in Phobos)."""
|
|
106
|
-
...
|
|
@@ -5,6 +5,7 @@ from __future__ import annotations
|
|
|
5
5
|
from collections.abc import Sequence
|
|
6
6
|
from typing import Any, cast
|
|
7
7
|
|
|
8
|
+
from servicephilosophy import ServiceRepository
|
|
8
9
|
from sqlalchemy import delete, func, select, update
|
|
9
10
|
from sqlalchemy import inspect as sa_inspect
|
|
10
11
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
@@ -40,18 +41,18 @@ from sqlphilosophy.types import (
|
|
|
40
41
|
LoadRelations = Sequence[LoaderOption]
|
|
41
42
|
|
|
42
43
|
|
|
43
|
-
class AsyncBaseRepository[T: DeclarativeBase, U: AsyncRepositoryFactory
|
|
44
|
+
class AsyncBaseRepository[T: DeclarativeBase, U: AsyncRepositoryFactory](ServiceRepository[U]):
|
|
44
45
|
"""Async session-scoped CRUD helpers for a single mapped model."""
|
|
45
46
|
|
|
46
47
|
def __init__(
|
|
47
48
|
self,
|
|
48
49
|
model: type[T],
|
|
49
50
|
session: AsyncSession,
|
|
50
|
-
factory:
|
|
51
|
+
factory: U | None = None,
|
|
51
52
|
) -> None:
|
|
53
|
+
super().__init__(factory)
|
|
52
54
|
self.model = model
|
|
53
55
|
self._session = session
|
|
54
|
-
self._factory = factory
|
|
55
56
|
self._pk_column = require_single_column_primary_key(model, self.inspect_model(model))
|
|
56
57
|
|
|
57
58
|
@classmethod
|
|
@@ -375,12 +376,14 @@ class AsyncBaseRepository[T: DeclarativeBase, U: AsyncRepositoryFactory | None]:
|
|
|
375
376
|
|
|
376
377
|
def statement(self) -> AsyncStatementQueryBuilder[T]:
|
|
377
378
|
"""Return a fluent statement builder for reads on this model (default read path)."""
|
|
378
|
-
|
|
379
|
-
|
|
379
|
+
factory = self.maybe_factory
|
|
380
|
+
if factory is not None:
|
|
381
|
+
return factory.create_statement(self.model)
|
|
380
382
|
return AsyncSqlAlchemyStatementBuilder(self._session, self.model)
|
|
381
383
|
|
|
382
384
|
def for_repo[R: AsyncBaseRepository[Any, Any]](self, repo_class: type[R]) -> R:
|
|
383
|
-
"""Return a typed entity repository sharing this session and factory.
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
385
|
+
"""Return a typed entity repository sharing this session and factory.
|
|
386
|
+
|
|
387
|
+
Raises ``FactoryRequiredError`` when no factory was configured.
|
|
388
|
+
"""
|
|
389
|
+
return cast(R, self.factory.get_repository(repo_class))
|
|
@@ -8,6 +8,7 @@ from typing import TYPE_CHECKING, Any, Protocol, TypeVar
|
|
|
8
8
|
if TYPE_CHECKING:
|
|
9
9
|
from sqlphilosophy.sync.repository import BaseRepository
|
|
10
10
|
|
|
11
|
+
from servicephilosophy import RepositoryFactoryProtocol, ServiceRepositoryProtocol
|
|
11
12
|
from sqlalchemy.orm import DeclarativeBase, Session
|
|
12
13
|
|
|
13
14
|
from sqlphilosophy.sync.query import StatementQueryBuilder
|
|
@@ -17,12 +18,35 @@ T = TypeVar("T", bound=DeclarativeBase)
|
|
|
17
18
|
R = TypeVar("R", bound="BaseRepository[Any, Any]")
|
|
18
19
|
|
|
19
20
|
|
|
20
|
-
class
|
|
21
|
-
"""
|
|
21
|
+
class RepositoryFactory(RepositoryFactoryProtocol, Protocol):
|
|
22
|
+
"""Sync session-scoped factory for statement builders and entity repositories."""
|
|
23
|
+
|
|
24
|
+
def create_statement(self, model: type[T]) -> StatementQueryBuilder[T]:
|
|
25
|
+
"""Return a fluent read builder for ``model``."""
|
|
26
|
+
...
|
|
27
|
+
|
|
28
|
+
def get_repository(self, repo_class: type[R]) -> R:
|
|
29
|
+
"""Return a cached typed entity repository."""
|
|
30
|
+
...
|
|
31
|
+
|
|
32
|
+
def repository(self, model: type[T]) -> BaseRepositoryProtocol[T, RepositoryFactory]:
|
|
33
|
+
"""Return generic CRUD helpers for ``model`` (``BaseRepository``)."""
|
|
34
|
+
...
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class BaseRepositoryProtocol[T: DeclarativeBase, U: RepositoryFactory](
|
|
38
|
+
ServiceRepositoryProtocol[U],
|
|
39
|
+
Protocol,
|
|
40
|
+
):
|
|
41
|
+
"""SQL read/write surface for ``BaseRepository[T]``.
|
|
42
|
+
|
|
43
|
+
Factory access (``.factory``, ``.maybe_factory``, ``.has_factory``) is inherited
|
|
44
|
+
from ``ServiceRepositoryProtocol``; this protocol adds the mapped model, session,
|
|
45
|
+
and SQLAlchemy CRUD/query methods only.
|
|
46
|
+
"""
|
|
22
47
|
|
|
23
48
|
model: type[T]
|
|
24
49
|
_session: Session
|
|
25
|
-
_factory: U | None
|
|
26
50
|
|
|
27
51
|
def get(self, obj_id: PrimaryKey, load_relations: Any = None) -> T: ...
|
|
28
52
|
|
|
@@ -85,19 +109,3 @@ class BaseRepositoryProtocol[T: DeclarativeBase, U: RepositoryFactory | None](Pr
|
|
|
85
109
|
values: RowMapping,
|
|
86
110
|
params: RowMapping | None = None,
|
|
87
111
|
) -> int: ...
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
class RepositoryFactory(Protocol):
|
|
91
|
-
"""Session-scoped factory for statement builders and entity repositories."""
|
|
92
|
-
|
|
93
|
-
def create_statement(self, model: type[T]) -> StatementQueryBuilder[T]:
|
|
94
|
-
"""Return a fluent read builder for ``model``."""
|
|
95
|
-
...
|
|
96
|
-
|
|
97
|
-
def get_repository(self, repo_class: type[R]) -> R:
|
|
98
|
-
"""Return a cached typed entity repository."""
|
|
99
|
-
...
|
|
100
|
-
|
|
101
|
-
def repository(self, model: type[T]) -> BaseRepositoryProtocol[T, RepositoryFactory | None]:
|
|
102
|
-
"""Return generic CRUD helpers for ``model`` (``BaseRepository`` in Phobos)."""
|
|
103
|
-
...
|
|
@@ -5,6 +5,7 @@ from __future__ import annotations
|
|
|
5
5
|
from collections.abc import Sequence
|
|
6
6
|
from typing import Any, cast
|
|
7
7
|
|
|
8
|
+
from servicephilosophy import ServiceRepository
|
|
8
9
|
from sqlalchemy import delete, func, select, update
|
|
9
10
|
from sqlalchemy import inspect as sa_inspect
|
|
10
11
|
from sqlalchemy.orm import DeclarativeBase, Session
|
|
@@ -37,18 +38,18 @@ from sqlphilosophy.types import (
|
|
|
37
38
|
LoadRelations = Sequence[LoaderOption]
|
|
38
39
|
|
|
39
40
|
|
|
40
|
-
class BaseRepository[T: DeclarativeBase, U: RepositoryFactory
|
|
41
|
-
"""
|
|
41
|
+
class BaseRepository[T: DeclarativeBase, U: RepositoryFactory](ServiceRepository[U]):
|
|
42
|
+
"""Sync session-scoped CRUD helpers for a single mapped model."""
|
|
42
43
|
|
|
43
44
|
def __init__(
|
|
44
45
|
self,
|
|
45
46
|
model: type[T],
|
|
46
47
|
session: Session,
|
|
47
|
-
factory:
|
|
48
|
+
factory: U | None = None,
|
|
48
49
|
) -> None:
|
|
50
|
+
super().__init__(factory)
|
|
49
51
|
self.model = model
|
|
50
52
|
self._session = session
|
|
51
|
-
self._factory = factory
|
|
52
53
|
self._pk_column = require_single_column_primary_key(model, self.inspect_model(model))
|
|
53
54
|
|
|
54
55
|
@classmethod
|
|
@@ -335,12 +336,14 @@ class BaseRepository[T: DeclarativeBase, U: RepositoryFactory | None]:
|
|
|
335
336
|
|
|
336
337
|
def statement(self) -> StatementQueryBuilder[T]:
|
|
337
338
|
"""Return a fluent statement builder for reads on this model (default read path)."""
|
|
338
|
-
|
|
339
|
-
|
|
339
|
+
factory = self.maybe_factory
|
|
340
|
+
if factory is not None:
|
|
341
|
+
return factory.create_statement(self.model)
|
|
340
342
|
return SqlAlchemyStatementBuilder(self._session, self.model)
|
|
341
343
|
|
|
342
344
|
def for_repo[R: BaseRepository[Any, Any]](self, repo_class: type[R]) -> R:
|
|
343
|
-
"""Return a typed entity repository sharing this session and factory.
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
345
|
+
"""Return a typed entity repository sharing this session and factory.
|
|
346
|
+
|
|
347
|
+
Raises ``FactoryRequiredError`` when no factory was configured.
|
|
348
|
+
"""
|
|
349
|
+
return cast(R, self.factory.get_repository(repo_class))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sqlphilosophy
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Portable SQLAlchemy repository kit: sync and async CRUD, statement builders, sort/pagination, and SQL helpers.
|
|
5
5
|
Author-email: Josh Martin <denverprogrammer@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -20,6 +20,7 @@ Classifier: Typing :: Typed
|
|
|
20
20
|
Requires-Python: <4.0,>=3.12
|
|
21
21
|
Description-Content-Type: text/markdown
|
|
22
22
|
License-File: LICENSE
|
|
23
|
+
Requires-Dist: servicephilosophy>=0.1.0
|
|
23
24
|
Requires-Dist: sqlalchemy<3,>=2.0
|
|
24
25
|
Provides-Extra: async
|
|
25
26
|
Requires-Dist: greenlet>=3.0; extra == "async"
|
|
@@ -56,6 +57,7 @@ Portable SQLAlchemy repository kit: sync and async CRUD, fluent statement builde
|
|
|
56
57
|
| [Repository guide](./docs/repository-guide.md) | Entry point: overview, transaction model, links to usage pages |
|
|
57
58
|
| [Usage examples](./docs/usage/) | Focused sync/async code examples by feature area |
|
|
58
59
|
| [Strongly typed repositories](./docs/usage/strongly-typed-repositories.md) | Typed subclasses, factories, protocols, and service patterns |
|
|
60
|
+
| [Service factory composition](./docs/usage/service-factory-composition.md) | Compose sqlPhilosophy SQL repos with servicePhilosophy business services |
|
|
59
61
|
| [Before/after SQLAlchemy](./docs/usage/before-after-sqlalchemy.md) | Migration examples: direct SQLAlchemy vs repository-centered code |
|
|
60
62
|
| [Feature matrix](./docs/feature-matrix.md) | Full sync/async capability map |
|
|
61
63
|
| [Typed repository (sync)](./docs/examples/typed_repository_sync.py) | Runnable factory + domain repo example |
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
0.1.9
|
|
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
|