python-cqrs 2.6.1__tar.gz → 3.0.1__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.
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/PKG-INFO +24 -10
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/README.md +21 -9
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/pyproject.toml +3 -1
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/events/event.py +1 -10
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/producer.py +5 -22
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/python_cqrs.egg-info/PKG-INFO +24 -10
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/python_cqrs.egg-info/requires.txt +1 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/LICENSE +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/setup.cfg +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/__init__.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/adapters/__init__.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/adapters/amqp.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/adapters/kafka.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/compressors/__init__.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/compressors/protocol.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/compressors/zlib.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/container/__init__.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/container/di.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/container/protocol.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/decoders/__init__.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/decoders/kafka/__init__.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/decoders/kafka/empty_message.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/deserializers/__init__.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/deserializers/json.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/deserializers/protobuf.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/dispatcher/__init__.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/dispatcher/dispatcher.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/events/__init__.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/events/bootstrap.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/events/event_emitter.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/events/event_handler.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/events/map.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/mediator.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/message_brokers/__init__.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/message_brokers/amqp.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/message_brokers/devnull.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/message_brokers/kafka.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/message_brokers/protocol.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/middlewares/__init__.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/middlewares/base.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/middlewares/logging.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/outbox/__init__.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/outbox/map.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/outbox/mock.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/outbox/repository.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/outbox/sqlalchemy.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/requests/__init__.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/requests/bootstrap.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/requests/map.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/requests/request.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/requests/request_handler.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/response.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/serializers/__init__.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/serializers/default.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/serializers/protobuf.py +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/python_cqrs.egg-info/SOURCES.txt +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/python_cqrs.egg-info/dependency_links.txt +0 -0
- {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/python_cqrs.egg-info/top_level.txt +0 -0
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-cqrs
|
|
3
|
-
Version:
|
|
3
|
+
Version: 3.0.1
|
|
4
4
|
Summary: Python CQRS pattern implementation
|
|
5
5
|
Author-email: Vadim Kozyrevskiy <vadikko2@mail.ru>, Dmitry Kutlubaev <kutlubaev00@mail.ru>
|
|
6
6
|
Maintainer-email: Vadim Kozyrevskiy <vadikko2@mail.ru>
|
|
7
|
+
Project-URL: Documentation, https://vadikko2.github.io/python-cqrs-mkdocs/
|
|
7
8
|
Project-URL: Issues, https://github.com/vadikko2/python-cqrs/issues
|
|
8
9
|
Project-URL: Repository, https://github.com/vadikko2/python-cqrs
|
|
9
10
|
Classifier: Development Status :: 4 - Beta
|
|
@@ -23,6 +24,7 @@ Requires-Dist: sqlalchemy[asyncio]==2.0.*
|
|
|
23
24
|
Requires-Dist: retry-async==0.1.4
|
|
24
25
|
Requires-Dist: python-dotenv==1.0.1
|
|
25
26
|
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: pycln==2.5.0; extra == "dev"
|
|
26
28
|
Requires-Dist: pre-commit==3.8.0; extra == "dev"
|
|
27
29
|
Requires-Dist: pyright==1.1.377; extra == "dev"
|
|
28
30
|
Requires-Dist: ruff==0.6.2; extra == "dev"
|
|
@@ -234,7 +236,7 @@ from cqrs.message_brokers import kafka as kafka_broker
|
|
|
234
236
|
|
|
235
237
|
|
|
236
238
|
producer = kafka_adapter.kafka_producer_factory(
|
|
237
|
-
dsn="localhost:
|
|
239
|
+
dsn="localhost:9092",
|
|
238
240
|
topics=["test.topic1", "test.topic2"],
|
|
239
241
|
)
|
|
240
242
|
broker = kafka_broker.KafkaMessageBroker(producer)
|
|
@@ -312,22 +314,34 @@ It can be utilized in conjunction with the KafkaMessageBroker.
|
|
|
312
314
|
```python
|
|
313
315
|
import asyncio
|
|
314
316
|
import cqrs
|
|
315
|
-
from cqrs.message_brokers import kafka
|
|
317
|
+
from cqrs.message_brokers import kafka
|
|
318
|
+
from cqrs.adapters import kafka as kafka_adapters
|
|
319
|
+
from cqrs.compressors import zlib
|
|
316
320
|
|
|
317
321
|
session_factory = async_sessionmaker(
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
+
create_async_engine(
|
|
323
|
+
f"mysql+asyncmy://{USER}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}",
|
|
324
|
+
isolation_level="REPEATABLE READ",
|
|
325
|
+
)
|
|
322
326
|
)
|
|
323
327
|
|
|
324
328
|
broker = kafka.KafkaMessageBroker(
|
|
325
|
-
|
|
329
|
+
producer=kafka_adapters.kafka_producer_factory(dsn="localhost:9092"),
|
|
326
330
|
)
|
|
327
331
|
|
|
328
|
-
producer = cqrs.EventProducer(cqrs.SqlAlchemyOutboxedEventRepository(session_factory, zlib.ZlibCompressor())
|
|
332
|
+
producer = cqrs.EventProducer(broker, cqrs.SqlAlchemyOutboxedEventRepository(session_factory, zlib.ZlibCompressor()))
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
async def periodically_task():
|
|
336
|
+
async for messages in producer.event_batch_generator():
|
|
337
|
+
for message in messages:
|
|
338
|
+
await producer.send_message(message)
|
|
339
|
+
await producer.repository.commit()
|
|
340
|
+
await asyncio.sleep(10)
|
|
341
|
+
|
|
342
|
+
|
|
329
343
|
loop = asyncio.get_event_loop()
|
|
330
|
-
loop.run_until_complete(
|
|
344
|
+
loop.run_until_complete(periodically_task())
|
|
331
345
|
```
|
|
332
346
|
|
|
333
347
|
A complete example can be found in
|
|
@@ -189,7 +189,7 @@ from cqrs.message_brokers import kafka as kafka_broker
|
|
|
189
189
|
|
|
190
190
|
|
|
191
191
|
producer = kafka_adapter.kafka_producer_factory(
|
|
192
|
-
dsn="localhost:
|
|
192
|
+
dsn="localhost:9092",
|
|
193
193
|
topics=["test.topic1", "test.topic2"],
|
|
194
194
|
)
|
|
195
195
|
broker = kafka_broker.KafkaMessageBroker(producer)
|
|
@@ -267,22 +267,34 @@ It can be utilized in conjunction with the KafkaMessageBroker.
|
|
|
267
267
|
```python
|
|
268
268
|
import asyncio
|
|
269
269
|
import cqrs
|
|
270
|
-
from cqrs.message_brokers import kafka
|
|
270
|
+
from cqrs.message_brokers import kafka
|
|
271
|
+
from cqrs.adapters import kafka as kafka_adapters
|
|
272
|
+
from cqrs.compressors import zlib
|
|
271
273
|
|
|
272
274
|
session_factory = async_sessionmaker(
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
275
|
+
create_async_engine(
|
|
276
|
+
f"mysql+asyncmy://{USER}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}",
|
|
277
|
+
isolation_level="REPEATABLE READ",
|
|
278
|
+
)
|
|
277
279
|
)
|
|
278
280
|
|
|
279
281
|
broker = kafka.KafkaMessageBroker(
|
|
280
|
-
|
|
282
|
+
producer=kafka_adapters.kafka_producer_factory(dsn="localhost:9092"),
|
|
281
283
|
)
|
|
282
284
|
|
|
283
|
-
producer = cqrs.EventProducer(cqrs.SqlAlchemyOutboxedEventRepository(session_factory, zlib.ZlibCompressor())
|
|
285
|
+
producer = cqrs.EventProducer(broker, cqrs.SqlAlchemyOutboxedEventRepository(session_factory, zlib.ZlibCompressor()))
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
async def periodically_task():
|
|
289
|
+
async for messages in producer.event_batch_generator():
|
|
290
|
+
for message in messages:
|
|
291
|
+
await producer.send_message(message)
|
|
292
|
+
await producer.repository.commit()
|
|
293
|
+
await asyncio.sleep(10)
|
|
294
|
+
|
|
295
|
+
|
|
284
296
|
loop = asyncio.get_event_loop()
|
|
285
|
-
loop.run_until_complete(
|
|
297
|
+
loop.run_until_complete(periodically_task())
|
|
286
298
|
```
|
|
287
299
|
|
|
288
300
|
A complete example can be found in
|
|
@@ -29,11 +29,12 @@ maintainers = [{name = "Vadim Kozyrevskiy", email = "vadikko2@mail.ru"}]
|
|
|
29
29
|
name = "python-cqrs"
|
|
30
30
|
readme = "README.md"
|
|
31
31
|
requires-python = ">=3.10"
|
|
32
|
-
version = "
|
|
32
|
+
version = "3.0.1"
|
|
33
33
|
|
|
34
34
|
[project.optional-dependencies]
|
|
35
35
|
dev = [
|
|
36
36
|
# Develope tools
|
|
37
|
+
"pycln==2.5.0",
|
|
37
38
|
"pre-commit==3.8.0",
|
|
38
39
|
"pyright==1.1.377",
|
|
39
40
|
"ruff==0.6.2",
|
|
@@ -60,6 +61,7 @@ protobuf = [
|
|
|
60
61
|
]
|
|
61
62
|
|
|
62
63
|
[project.urls]
|
|
64
|
+
Documentation = "https://vadikko2.github.io/python-cqrs-mkdocs/"
|
|
63
65
|
Issues = "https://github.com/vadikko2/python-cqrs/issues"
|
|
64
66
|
Repository = "https://github.com/vadikko2/python-cqrs"
|
|
65
67
|
|
|
@@ -8,16 +8,7 @@ import dotenv
|
|
|
8
8
|
import pydantic
|
|
9
9
|
|
|
10
10
|
logger = logging.getLogger("cqrs")
|
|
11
|
-
|
|
12
|
-
try:
|
|
13
|
-
from google.protobuf.message import Message # noqa
|
|
14
|
-
except ImportError:
|
|
15
|
-
logger.warning(
|
|
16
|
-
"Please install protobuf dependencies with: `pip install python-cqrs[protobuf]`",
|
|
17
|
-
)
|
|
18
|
-
|
|
19
11
|
dotenv.load_dotenv()
|
|
20
|
-
|
|
21
12
|
DEFAULT_OUTPUT_TOPIC = os.getenv("DEFAULT_OUTPUT_TOPIC", "output_topic")
|
|
22
13
|
|
|
23
14
|
|
|
@@ -52,7 +43,7 @@ class NotificationEvent(Event, typing.Generic[_P], frozen=True):
|
|
|
52
43
|
|
|
53
44
|
model_config = pydantic.ConfigDict(from_attributes=True)
|
|
54
45
|
|
|
55
|
-
def proto(self)
|
|
46
|
+
def proto(self):
|
|
56
47
|
raise NotImplementedError("Method not implemented")
|
|
57
48
|
|
|
58
49
|
def __hash__(self):
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import asyncio
|
|
2
1
|
import logging
|
|
3
2
|
import typing
|
|
4
3
|
|
|
@@ -17,20 +16,18 @@ class EventProducer:
|
|
|
17
16
|
def __init__(
|
|
18
17
|
self,
|
|
19
18
|
message_broker: broker_protocol.MessageBroker,
|
|
20
|
-
repository: repository_protocol.OutboxedEventRepository
|
|
19
|
+
repository: repository_protocol.OutboxedEventRepository,
|
|
21
20
|
):
|
|
22
21
|
self.message_broker = message_broker
|
|
23
22
|
self.repository = repository
|
|
24
23
|
|
|
25
|
-
async def
|
|
24
|
+
async def event_batch_generator(
|
|
26
25
|
self,
|
|
27
26
|
batch_size: int = 100,
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
"""Calls produce periodically with specified delay"""
|
|
27
|
+
) -> typing.AsyncIterator[typing.List[repository_protocol.OutboxedEvent]]:
|
|
28
|
+
"""Return messages for produce"""
|
|
31
29
|
while True:
|
|
32
|
-
await
|
|
33
|
-
await self.produce_batch(batch_size)
|
|
30
|
+
yield await self.repository.get_many(batch_size)
|
|
34
31
|
|
|
35
32
|
async def send_message(self, event: repository_protocol.OutboxedEvent):
|
|
36
33
|
try:
|
|
@@ -60,17 +57,3 @@ class EventProducer:
|
|
|
60
57
|
event.id,
|
|
61
58
|
repository_protocol.EventStatus.PRODUCED,
|
|
62
59
|
)
|
|
63
|
-
|
|
64
|
-
async def produce_batch(self, batch_size: int = 100) -> None:
|
|
65
|
-
if not self.repository:
|
|
66
|
-
logger.debug("Repository not found")
|
|
67
|
-
return
|
|
68
|
-
outboxed_events: typing.List[
|
|
69
|
-
repository_protocol.OutboxedEvent
|
|
70
|
-
] = await self.repository.get_many(
|
|
71
|
-
batch_size,
|
|
72
|
-
)
|
|
73
|
-
logger.debug(f"Got {len(outboxed_events)} new events")
|
|
74
|
-
for event in outboxed_events:
|
|
75
|
-
await self.send_message(event)
|
|
76
|
-
await self.repository.commit()
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-cqrs
|
|
3
|
-
Version:
|
|
3
|
+
Version: 3.0.1
|
|
4
4
|
Summary: Python CQRS pattern implementation
|
|
5
5
|
Author-email: Vadim Kozyrevskiy <vadikko2@mail.ru>, Dmitry Kutlubaev <kutlubaev00@mail.ru>
|
|
6
6
|
Maintainer-email: Vadim Kozyrevskiy <vadikko2@mail.ru>
|
|
7
|
+
Project-URL: Documentation, https://vadikko2.github.io/python-cqrs-mkdocs/
|
|
7
8
|
Project-URL: Issues, https://github.com/vadikko2/python-cqrs/issues
|
|
8
9
|
Project-URL: Repository, https://github.com/vadikko2/python-cqrs
|
|
9
10
|
Classifier: Development Status :: 4 - Beta
|
|
@@ -23,6 +24,7 @@ Requires-Dist: sqlalchemy[asyncio]==2.0.*
|
|
|
23
24
|
Requires-Dist: retry-async==0.1.4
|
|
24
25
|
Requires-Dist: python-dotenv==1.0.1
|
|
25
26
|
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: pycln==2.5.0; extra == "dev"
|
|
26
28
|
Requires-Dist: pre-commit==3.8.0; extra == "dev"
|
|
27
29
|
Requires-Dist: pyright==1.1.377; extra == "dev"
|
|
28
30
|
Requires-Dist: ruff==0.6.2; extra == "dev"
|
|
@@ -234,7 +236,7 @@ from cqrs.message_brokers import kafka as kafka_broker
|
|
|
234
236
|
|
|
235
237
|
|
|
236
238
|
producer = kafka_adapter.kafka_producer_factory(
|
|
237
|
-
dsn="localhost:
|
|
239
|
+
dsn="localhost:9092",
|
|
238
240
|
topics=["test.topic1", "test.topic2"],
|
|
239
241
|
)
|
|
240
242
|
broker = kafka_broker.KafkaMessageBroker(producer)
|
|
@@ -312,22 +314,34 @@ It can be utilized in conjunction with the KafkaMessageBroker.
|
|
|
312
314
|
```python
|
|
313
315
|
import asyncio
|
|
314
316
|
import cqrs
|
|
315
|
-
from cqrs.message_brokers import kafka
|
|
317
|
+
from cqrs.message_brokers import kafka
|
|
318
|
+
from cqrs.adapters import kafka as kafka_adapters
|
|
319
|
+
from cqrs.compressors import zlib
|
|
316
320
|
|
|
317
321
|
session_factory = async_sessionmaker(
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
+
create_async_engine(
|
|
323
|
+
f"mysql+asyncmy://{USER}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}",
|
|
324
|
+
isolation_level="REPEATABLE READ",
|
|
325
|
+
)
|
|
322
326
|
)
|
|
323
327
|
|
|
324
328
|
broker = kafka.KafkaMessageBroker(
|
|
325
|
-
|
|
329
|
+
producer=kafka_adapters.kafka_producer_factory(dsn="localhost:9092"),
|
|
326
330
|
)
|
|
327
331
|
|
|
328
|
-
producer = cqrs.EventProducer(cqrs.SqlAlchemyOutboxedEventRepository(session_factory, zlib.ZlibCompressor())
|
|
332
|
+
producer = cqrs.EventProducer(broker, cqrs.SqlAlchemyOutboxedEventRepository(session_factory, zlib.ZlibCompressor()))
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
async def periodically_task():
|
|
336
|
+
async for messages in producer.event_batch_generator():
|
|
337
|
+
for message in messages:
|
|
338
|
+
await producer.send_message(message)
|
|
339
|
+
await producer.repository.commit()
|
|
340
|
+
await asyncio.sleep(10)
|
|
341
|
+
|
|
342
|
+
|
|
329
343
|
loop = asyncio.get_event_loop()
|
|
330
|
-
loop.run_until_complete(
|
|
344
|
+
loop.run_until_complete(periodically_task())
|
|
331
345
|
```
|
|
332
346
|
|
|
333
347
|
A complete example can be found in
|
|
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
|