sqlobjects 1.7.0__tar.gz → 1.8.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.7.0 → sqlobjects-1.8.0}/CHANGELOG.md +17 -0
- {sqlobjects-1.7.0/sqlobjects.egg-info → sqlobjects-1.8.0}/PKG-INFO +1 -1
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/pyproject.toml +1 -1
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/__init__.py +4 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/queries/executor.py +30 -0
- sqlobjects-1.8.0/sqlobjects/sql_logging.py +156 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0/sqlobjects.egg-info}/PKG-INFO +1 -1
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects.egg-info/SOURCES.txt +1 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/LICENSE +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/README.md +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/docs/rules/01-database-session-guide.md +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/docs/rules/02-model-definition-guide.md +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/docs/rules/03-query-operations-guide.md +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/docs/rules/04-crud-operations-guide.md +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/docs/rules/05-relationships-guide.md +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/docs/rules/06-validation-signals-guide.md +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/docs/rules/07-performance-guide.md +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/docs/rules/README.md +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/setup.cfg +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/_install_rules.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/cascade.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/contrib/__init__.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/contrib/asgi.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/contrib/fastapi.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/database/__init__.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/database/config.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/database/manager.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/exceptions.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/expressions/__init__.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/expressions/aggregate.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/expressions/base.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/expressions/cte.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/expressions/explain.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/expressions/function.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/expressions/mixins.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/expressions/scalar.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/expressions/subquery.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/expressions/terminal.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/expressions/window.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/fields/__init__.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/fields/core.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/fields/functions.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/fields/proxies.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/fields/relations/__init__.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/fields/relations/descriptors.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/fields/relations/managers.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/fields/relations/prefetch.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/fields/relations/strategies.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/fields/relations/utils.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/fields/shortcuts.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/fields/types/__init__.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/fields/types/base.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/fields/types/comparators.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/fields/types/registry.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/fields/utils.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/internal/__init__.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/internal/operations.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/internal/results.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/metadata.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/mixins.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/model.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/objects/__init__.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/objects/bulk.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/objects/core.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/objects/upsert.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/queries/__init__.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/queries/builder.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/queries/dialect.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/queryset.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/session.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/signals.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/utils/__init__.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/utils/inspect.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/utils/naming.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/utils/pattern.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects/validators.py +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects.egg-info/dependency_links.txt +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects.egg-info/entry_points.txt +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects.egg-info/requires.txt +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/sqlobjects.egg-info/top_level.txt +0 -0
- {sqlobjects-1.7.0 → sqlobjects-1.8.0}/tests/test_config.py +0 -0
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
## 1.8.0 (2026-03-26)
|
|
2
|
+
|
|
3
|
+
### Feat
|
|
4
|
+
|
|
5
|
+
- **logging**: export SQLCallerFilter and get_caller_frame in public API
|
|
6
|
+
- **logging**: emit SQL log records in QueryExecutor
|
|
7
|
+
- **logging**: add SQLCallerFilter
|
|
8
|
+
- **logging**: add get_caller_frame() helper
|
|
9
|
+
|
|
10
|
+
### Fix
|
|
11
|
+
|
|
12
|
+
- **logging**: eliminate isEnabledFor race and fix test name
|
|
13
|
+
- **logging**: restore logger level in test_no_log_when_logger_disabled
|
|
14
|
+
- **logging**: guard timing code with isEnabledFor check
|
|
15
|
+
- **logging**: simplify SQLCallerFilter extra_skip_packages handling
|
|
16
|
+
- **logging**: fix frame-skip edge cases and improve code quality
|
|
17
|
+
|
|
1
18
|
## 1.7.0 (2026-03-26)
|
|
2
19
|
|
|
3
20
|
### Feat
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sqlobjects
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.8.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>
|
|
@@ -16,6 +16,7 @@ from .objects import (
|
|
|
16
16
|
TransactionMode,
|
|
17
17
|
)
|
|
18
18
|
from .queryset import Q, QuerySet
|
|
19
|
+
from .sql_logging import SQLCallerFilter, get_caller_frame
|
|
19
20
|
|
|
20
21
|
|
|
21
22
|
__version__ = "0.3.0"
|
|
@@ -41,4 +42,7 @@ __all__ = [
|
|
|
41
42
|
"TransactionMode",
|
|
42
43
|
"ErrorHandling",
|
|
43
44
|
"ConflictResolution",
|
|
45
|
+
# SQL logging
|
|
46
|
+
"SQLCallerFilter",
|
|
47
|
+
"get_caller_frame",
|
|
44
48
|
]
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import gc
|
|
3
|
+
import logging
|
|
4
|
+
import time
|
|
3
5
|
from collections.abc import AsyncGenerator
|
|
4
6
|
from typing import Any, TypeVar, overload
|
|
5
7
|
|
|
@@ -13,6 +15,9 @@ from sqlalchemy import (
|
|
|
13
15
|
)
|
|
14
16
|
|
|
15
17
|
|
|
18
|
+
_sql_logger = logging.getLogger("sqlobjects.sql")
|
|
19
|
+
|
|
20
|
+
|
|
16
21
|
_T = TypeVar("_T")
|
|
17
22
|
|
|
18
23
|
|
|
@@ -230,8 +235,33 @@ class QueryExecutor:
|
|
|
230
235
|
else: # exists
|
|
231
236
|
return False
|
|
232
237
|
|
|
238
|
+
# Compile SQL for logging only when the logger is active (avoids overhead)
|
|
239
|
+
_logging_active = _sql_logger.isEnabledFor(logging.DEBUG)
|
|
240
|
+
sql_str = ""
|
|
241
|
+
params: dict = {}
|
|
242
|
+
t0 = 0.0
|
|
243
|
+
if _logging_active:
|
|
244
|
+
try:
|
|
245
|
+
compiled = query.compile(
|
|
246
|
+
dialect=session.bind.dialect,
|
|
247
|
+
compile_kwargs={"literal_binds": False},
|
|
248
|
+
)
|
|
249
|
+
sql_str = str(compiled)
|
|
250
|
+
params = dict(compiled.params) if compiled.params else {}
|
|
251
|
+
except Exception:
|
|
252
|
+
sql_str = str(query)
|
|
253
|
+
params = {}
|
|
254
|
+
t0 = time.perf_counter()
|
|
255
|
+
|
|
233
256
|
result = await session.execute(query)
|
|
234
257
|
|
|
258
|
+
if _logging_active:
|
|
259
|
+
duration_ms = (time.perf_counter() - t0) * 1000
|
|
260
|
+
_sql_logger.debug(
|
|
261
|
+
sql_str,
|
|
262
|
+
extra={"sql": sql_str, "params": params, "duration_ms": duration_ms},
|
|
263
|
+
)
|
|
264
|
+
|
|
235
265
|
if query_type == "all":
|
|
236
266
|
rows = result.fetchall()
|
|
237
267
|
if model_class:
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"""SQL logging utilities for sqlobjects.
|
|
2
|
+
|
|
3
|
+
Provides get_caller_frame() to surface user-code caller information in SQL log
|
|
4
|
+
records, compatible with standard logging and loguru.
|
|
5
|
+
|
|
6
|
+
Filter strategy:
|
|
7
|
+
- Skips frames from site-packages (covers pip-installed sqlobjects/sqlalchemy)
|
|
8
|
+
- Skips frames whose module name starts with "sqlobjects." or "sqlalchemy."
|
|
9
|
+
(covers editable installs via `pip install -e .`)
|
|
10
|
+
- Skips frames from extra_skip_packages specified by the caller
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import inspect
|
|
16
|
+
import logging
|
|
17
|
+
import os
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
__all__ = ["get_caller_frame", "SQLCallerFilter"]
|
|
21
|
+
|
|
22
|
+
# Exact module names that are always considered internal
|
|
23
|
+
_INTERNAL_MODULES = {"sqlobjects", "sqlalchemy"}
|
|
24
|
+
|
|
25
|
+
# Module name prefixes that are always considered internal
|
|
26
|
+
_INTERNAL_PREFIXES = ("sqlobjects.", "sqlalchemy.")
|
|
27
|
+
|
|
28
|
+
# Absolute path of this file, used to skip itself reliably
|
|
29
|
+
_THIS_FILE = os.path.abspath(__file__)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def get_caller_frame(
|
|
33
|
+
extra_skip_packages: list[str] | None = None,
|
|
34
|
+
max_frames: int = 1,
|
|
35
|
+
) -> str | list[str]:
|
|
36
|
+
"""Inspect the call stack and return the first user-code frame(s).
|
|
37
|
+
|
|
38
|
+
Skips frames from:
|
|
39
|
+
- site-packages (pip install)
|
|
40
|
+
- sqlobjects.* and sqlalchemy.* modules (editable install)
|
|
41
|
+
- extra_skip_packages prefixes provided by the caller
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
extra_skip_packages: Additional module name prefixes to skip
|
|
45
|
+
(e.g. ["myapp.middleware"]). Matched against frame's __name__.
|
|
46
|
+
max_frames: How many user-code frames to return.
|
|
47
|
+
1 returns a str; >1 returns a list[str].
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
Frame string "path/to/file.py:lineno in funcname", or a list of such
|
|
51
|
+
strings when max_frames > 1.
|
|
52
|
+
"""
|
|
53
|
+
skip_prefixes = _INTERNAL_PREFIXES
|
|
54
|
+
if extra_skip_packages:
|
|
55
|
+
skip_prefixes = skip_prefixes + tuple(extra_skip_packages)
|
|
56
|
+
|
|
57
|
+
frames: list[str] = []
|
|
58
|
+
|
|
59
|
+
for frame_info in inspect.stack():
|
|
60
|
+
filepath = frame_info.filename
|
|
61
|
+
module = frame_info.frame.f_globals.get("__name__", "")
|
|
62
|
+
|
|
63
|
+
# Skip site-packages frames (pip-installed third-party libs)
|
|
64
|
+
if "site-packages" in filepath:
|
|
65
|
+
continue
|
|
66
|
+
|
|
67
|
+
# Skip sqlobjects/sqlalchemy frames (editable install)
|
|
68
|
+
if module in _INTERNAL_MODULES or module.startswith(skip_prefixes):
|
|
69
|
+
continue
|
|
70
|
+
|
|
71
|
+
# Skip this helper file itself
|
|
72
|
+
if os.path.abspath(filepath) == _THIS_FILE:
|
|
73
|
+
continue
|
|
74
|
+
|
|
75
|
+
rel_path = _relative_path(filepath)
|
|
76
|
+
frames.append(f"{rel_path}:{frame_info.lineno} in {frame_info.function}")
|
|
77
|
+
|
|
78
|
+
if len(frames) >= max_frames:
|
|
79
|
+
break
|
|
80
|
+
|
|
81
|
+
if not frames:
|
|
82
|
+
return "<unknown>" if max_frames == 1 else ["<unknown>"]
|
|
83
|
+
|
|
84
|
+
return frames[0] if max_frames == 1 else frames
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def _relative_path(filepath: str) -> str:
|
|
88
|
+
"""Return path relative to cwd, or absolute if outside cwd."""
|
|
89
|
+
try:
|
|
90
|
+
return os.path.relpath(filepath)
|
|
91
|
+
except ValueError:
|
|
92
|
+
return filepath
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class SQLCallerFilter(logging.Filter):
|
|
96
|
+
"""logging.Filter that rewrites LogRecord caller fields to user-code location.
|
|
97
|
+
|
|
98
|
+
Inspects the call stack at filter time, skips library frames (site-packages
|
|
99
|
+
and sqlobjects.*/sqlalchemy.* modules for editable installs), and overwrites
|
|
100
|
+
record.filename / record.funcName / record.lineno / record.pathname so that
|
|
101
|
+
any handler (including loguru interception) displays the real user-code
|
|
102
|
+
call site.
|
|
103
|
+
|
|
104
|
+
Also exposes record.caller (str or list[str]) for use in custom Formatters.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
max_frames: Number of user-code frames to capture (default 1).
|
|
108
|
+
When 1, record.caller is a str and record location fields point
|
|
109
|
+
to that single frame.
|
|
110
|
+
When > 1, record.caller is a list[str] and record location fields
|
|
111
|
+
are set from the first (most recent) frame.
|
|
112
|
+
extra_skip_packages: Additional module name prefixes to skip
|
|
113
|
+
(matched against frame's __name__).
|
|
114
|
+
"""
|
|
115
|
+
|
|
116
|
+
def __init__(
|
|
117
|
+
self,
|
|
118
|
+
max_frames: int = 1,
|
|
119
|
+
extra_skip_packages: list[str] | None = None,
|
|
120
|
+
) -> None:
|
|
121
|
+
super().__init__()
|
|
122
|
+
self.max_frames = max_frames
|
|
123
|
+
self.extra_skip_packages: list[str] | None = list(extra_skip_packages) if extra_skip_packages else None
|
|
124
|
+
|
|
125
|
+
def filter(self, record: logging.LogRecord) -> bool:
|
|
126
|
+
caller = get_caller_frame(
|
|
127
|
+
extra_skip_packages=self.extra_skip_packages,
|
|
128
|
+
max_frames=self.max_frames,
|
|
129
|
+
)
|
|
130
|
+
record.caller = caller
|
|
131
|
+
|
|
132
|
+
# Overwrite standard location fields from the first user frame
|
|
133
|
+
first = caller if isinstance(caller, str) else caller[0]
|
|
134
|
+
self._overwrite_record_location(record, first)
|
|
135
|
+
|
|
136
|
+
return True
|
|
137
|
+
|
|
138
|
+
@staticmethod
|
|
139
|
+
def _overwrite_record_location(record: logging.LogRecord, frame_str: str) -> None:
|
|
140
|
+
"""Parse 'path/to/file.py:lineno in funcname' and overwrite record fields.
|
|
141
|
+
|
|
142
|
+
Frame string format: "relative/path/to/file.py:42 in func_name"
|
|
143
|
+
Uses rsplit to handle edge cases where function name could have spaces.
|
|
144
|
+
"""
|
|
145
|
+
try:
|
|
146
|
+
# Split off the function name part (rightmost " in ")
|
|
147
|
+
path_part, func_part = frame_str.rsplit(" in ", 1)
|
|
148
|
+
# Split off the line number (rightmost ":")
|
|
149
|
+
filepath, lineno_str = path_part.rsplit(":", 1)
|
|
150
|
+
record.pathname = os.path.abspath(filepath)
|
|
151
|
+
record.filename = os.path.basename(filepath)
|
|
152
|
+
record.module = os.path.splitext(record.filename)[0]
|
|
153
|
+
record.funcName = func_part.strip()
|
|
154
|
+
record.lineno = int(lineno_str)
|
|
155
|
+
except (ValueError, AttributeError):
|
|
156
|
+
pass # Keep original fields if parsing fails
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sqlobjects
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.8.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
|
|
File without changes
|