ferrum-orm 0.1.14__tar.gz → 0.1.16__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.
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/Cargo.lock +4 -4
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/Cargo.toml +1 -1
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/PKG-INFO +1 -1
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/crates/ferrum-sql/src/emit.rs +85 -3
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/pyproject.toml +1 -1
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/__init__.py +1 -1
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/drivers/postgres.py +43 -5
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/LICENSE +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/README.md +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/crates/ferrum-core/Cargo.toml +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/crates/ferrum-core/benches/hydrate.rs +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/crates/ferrum-core/src/compile/mod.rs +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/crates/ferrum-core/src/error.rs +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/crates/ferrum-core/src/hydrate/mod.rs +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/crates/ferrum-core/src/ir/metadata.rs +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/crates/ferrum-core/src/ir/mod.rs +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/crates/ferrum-core/src/lib.rs +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/crates/ferrum-core/src/migrate/mod.rs +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/crates/ferrum-pyo3/Cargo.toml +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/crates/ferrum-pyo3/src/lib.rs +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/crates/ferrum-sql/Cargo.toml +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/crates/ferrum-sql/benches/compile.rs +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/crates/ferrum-sql/src/dialect.rs +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/crates/ferrum-sql/src/fts/mod.rs +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/crates/ferrum-sql/src/fts/mssql.rs +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/crates/ferrum-sql/src/fts/mysql.rs +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/crates/ferrum-sql/src/fts/postgres.rs +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/crates/ferrum-sql/src/fts/sqlite.rs +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/crates/ferrum-sql/src/lib.rs +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/_native.pyi +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/cli/__init__.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/cli/app.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/cli/bootstrap.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/cli/init.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/cli/inspectdb_cmd.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/cli/makemigrations_cmd.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/cli/migrate_cmd.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/cli/migrations_cmd.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/cli/resetdb_cmd.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/cli/revert_cmd.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/cli/showmigrations_cmd.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/cli/sqlmigrate_cmd.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/config.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/connection.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/contrib/__init__.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/contrib/fastapi.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/drivers/__init__.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/drivers/mssql.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/drivers/mysql.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/drivers/protocol.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/drivers/sqlite.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/drivers/streaming.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/echo.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/errors.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/expressions.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/ext/__init__.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/ext/fts.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/ext/pgvector.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/hooks.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/migrations/__init__.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/migrations/base.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/migrations/drift.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/migrations/fts/__init__.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/migrations/fts/mssql.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/migrations/fts/mysql.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/migrations/fts/postgres.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/migrations/fts/sqlite.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/migrations/gates.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/migrations/introspect.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/migrations/ledger.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/migrations/loader.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/migrations/operations.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/migrations/orchestrator.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/migrations/tokens.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/models.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/observability.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/py.typed +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/queryset.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/registry.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/relations.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/runtime.py +0 -0
- {ferrum_orm-0.1.14 → ferrum_orm-0.1.16}/python/ferrum/session.py +0 -0
|
@@ -223,7 +223,7 @@ checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6"
|
|
|
223
223
|
|
|
224
224
|
[[package]]
|
|
225
225
|
name = "ferrum-core"
|
|
226
|
-
version = "0.1.
|
|
226
|
+
version = "0.1.16"
|
|
227
227
|
dependencies = [
|
|
228
228
|
"criterion",
|
|
229
229
|
"proptest",
|
|
@@ -234,7 +234,7 @@ dependencies = [
|
|
|
234
234
|
|
|
235
235
|
[[package]]
|
|
236
236
|
name = "ferrum-migrate"
|
|
237
|
-
version = "0.1.
|
|
237
|
+
version = "0.1.16"
|
|
238
238
|
dependencies = [
|
|
239
239
|
"ferrum-core",
|
|
240
240
|
"serde",
|
|
@@ -243,7 +243,7 @@ dependencies = [
|
|
|
243
243
|
|
|
244
244
|
[[package]]
|
|
245
245
|
name = "ferrum-pyo3"
|
|
246
|
-
version = "0.1.
|
|
246
|
+
version = "0.1.16"
|
|
247
247
|
dependencies = [
|
|
248
248
|
"ferrum-core",
|
|
249
249
|
"ferrum-sql",
|
|
@@ -255,7 +255,7 @@ dependencies = [
|
|
|
255
255
|
|
|
256
256
|
[[package]]
|
|
257
257
|
name = "ferrum-sql"
|
|
258
|
-
version = "0.1.
|
|
258
|
+
version = "0.1.16"
|
|
259
259
|
dependencies = [
|
|
260
260
|
"criterion",
|
|
261
261
|
"ferrum-core",
|
|
@@ -1219,6 +1219,11 @@ fn filter_clause(
|
|
|
1219
1219
|
/// `UPDATE … FROM (VALUES …)` requires explicit casts so `PostgreSQL` can infer
|
|
1220
1220
|
/// the correct column types when the VALUES clause contains multiple rows.
|
|
1221
1221
|
/// The cast is appended to the placeholder, e.g. `$1::bigint`, `$2::text`.
|
|
1222
|
+
///
|
|
1223
|
+
/// The cast must be assignment-compatible with the DDL column type, and for PK
|
|
1224
|
+
/// columns it must match exactly: the join predicate `t.pk = v.pk` resolves an
|
|
1225
|
+
/// operator rather than an assignment cast, so a `uuid` column compared against
|
|
1226
|
+
/// a `text` VALUES column fails with `UndefinedFunction` (42883).
|
|
1222
1227
|
fn postgres_value_cast(
|
|
1223
1228
|
field_type: ferrum_core::ir::metadata::FieldType,
|
|
1224
1229
|
placeholder: &str,
|
|
@@ -1226,8 +1231,11 @@ fn postgres_value_cast(
|
|
|
1226
1231
|
use ferrum_core::ir::metadata::FieldType;
|
|
1227
1232
|
let cast = match field_type {
|
|
1228
1233
|
FieldType::Int | FieldType::BigInt => "bigint",
|
|
1229
|
-
FieldType::Float
|
|
1230
|
-
FieldType::
|
|
1234
|
+
FieldType::Float => "double precision",
|
|
1235
|
+
FieldType::Decimal => "numeric",
|
|
1236
|
+
FieldType::Text | FieldType::Enum => "text",
|
|
1237
|
+
FieldType::Uuid => "uuid",
|
|
1238
|
+
FieldType::TsVector => "tsvector",
|
|
1231
1239
|
FieldType::Bool => "boolean",
|
|
1232
1240
|
FieldType::Datetime => "timestamptz",
|
|
1233
1241
|
FieldType::Date => "date",
|
|
@@ -1235,7 +1243,8 @@ fn postgres_value_cast(
|
|
|
1235
1243
|
FieldType::Json => "jsonb",
|
|
1236
1244
|
FieldType::Bytes => "bytea",
|
|
1237
1245
|
FieldType::Vector => "vector",
|
|
1238
|
-
FieldType::ArrayText
|
|
1246
|
+
FieldType::ArrayText => "text[]",
|
|
1247
|
+
FieldType::ArrayUuid => "uuid[]",
|
|
1239
1248
|
FieldType::ArrayInt => "bigint[]",
|
|
1240
1249
|
FieldType::ArrayFloat => "double precision[]",
|
|
1241
1250
|
};
|
|
@@ -2112,6 +2121,79 @@ mod tests {
|
|
|
2112
2121
|
assert!(matches!(err, CompileError::MalformedIr { .. }));
|
|
2113
2122
|
}
|
|
2114
2123
|
|
|
2124
|
+
/// Every VALUES placeholder must carry the cast of its DDL column type.
|
|
2125
|
+
/// A `uuid` PK cast to `text` made `t.id = v.id` resolve `uuid = text`,
|
|
2126
|
+
/// which `PostgreSQL` rejects with `UndefinedFunction` (42883); `uuid[]` and
|
|
2127
|
+
/// `tsvector` columns failed the SET assignment for the same reason.
|
|
2128
|
+
#[test]
|
|
2129
|
+
fn bulk_update_casts_match_column_types() {
|
|
2130
|
+
let field = |name: &str, field_type: FieldType| FieldMeta {
|
|
2131
|
+
name: name.into(),
|
|
2132
|
+
column_name: name.into(),
|
|
2133
|
+
field_type,
|
|
2134
|
+
allowed_operators: vec!["eq".into()],
|
|
2135
|
+
nullable: true,
|
|
2136
|
+
vector_dimensions: None,
|
|
2137
|
+
fts_config: None,
|
|
2138
|
+
fts_source_columns: None,
|
|
2139
|
+
};
|
|
2140
|
+
let meta = ModelMetadata {
|
|
2141
|
+
model_name: "Ticket".into(),
|
|
2142
|
+
table_name: "tickets".into(),
|
|
2143
|
+
fields: vec![
|
|
2144
|
+
field("id", FieldType::Uuid),
|
|
2145
|
+
field("tags", FieldType::ArrayUuid),
|
|
2146
|
+
field("search", FieldType::TsVector),
|
|
2147
|
+
field("amount", FieldType::Decimal),
|
|
2148
|
+
],
|
|
2149
|
+
pk_index: 0,
|
|
2150
|
+
pk_fields: vec![0],
|
|
2151
|
+
full_text_indexes: vec![],
|
|
2152
|
+
};
|
|
2153
|
+
let field_ref = |name: &str, index: usize| FieldRef {
|
|
2154
|
+
name: name.into(),
|
|
2155
|
+
index,
|
|
2156
|
+
};
|
|
2157
|
+
let ir = QuerySetIR {
|
|
2158
|
+
version: IR_VERSION,
|
|
2159
|
+
model_name: "Ticket".into(),
|
|
2160
|
+
operation: Operation::BulkUpdate {
|
|
2161
|
+
pk_fields: vec![field_ref("id", 0)],
|
|
2162
|
+
fields: vec![
|
|
2163
|
+
field_ref("tags", 1),
|
|
2164
|
+
field_ref("search", 2),
|
|
2165
|
+
field_ref("amount", 3),
|
|
2166
|
+
],
|
|
2167
|
+
rows: vec![ferrum_core::ir::BulkUpdateRow {
|
|
2168
|
+
pk_values: vec![BindValue::Text(
|
|
2169
|
+
"00000000-0000-0000-0000-000000000001".into(),
|
|
2170
|
+
)],
|
|
2171
|
+
values: vec![
|
|
2172
|
+
BindValue::TextArray(vec![]),
|
|
2173
|
+
BindValue::Text("lexeme".into()),
|
|
2174
|
+
BindValue::Text("1.005".into()),
|
|
2175
|
+
],
|
|
2176
|
+
}],
|
|
2177
|
+
},
|
|
2178
|
+
filters: vec![],
|
|
2179
|
+
order_by: vec![],
|
|
2180
|
+
limit: None,
|
|
2181
|
+
offset: None,
|
|
2182
|
+
vector_order_by: None,
|
|
2183
|
+
text_rank_by: None,
|
|
2184
|
+
predicate: None,
|
|
2185
|
+
distinct: false,
|
|
2186
|
+
exists: false,
|
|
2187
|
+
joins: vec![],
|
|
2188
|
+
aggregation: None,
|
|
2189
|
+
};
|
|
2190
|
+
let q = emit_bulk_update(Dialect::Postgres, &meta, &ir).unwrap();
|
|
2191
|
+
assert!(q.sql_text.contains("$1::uuid,"), "{}", q.sql_text);
|
|
2192
|
+
assert!(q.sql_text.contains("$2::uuid[]"), "{}", q.sql_text);
|
|
2193
|
+
assert!(q.sql_text.contains("$3::tsvector"), "{}", q.sql_text);
|
|
2194
|
+
assert!(q.sql_text.contains("$4::numeric"), "{}", q.sql_text);
|
|
2195
|
+
}
|
|
2196
|
+
|
|
2115
2197
|
// ── MessagePack wire-format round-trip ───────────────────────────────────
|
|
2116
2198
|
|
|
2117
2199
|
/// IR + metadata `MessagePack`-encoded (NAMED) decode back into the same serde
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import contextlib
|
|
6
|
+
import json
|
|
6
7
|
from collections.abc import AsyncGenerator
|
|
7
8
|
from typing import Any
|
|
8
9
|
|
|
@@ -11,6 +12,41 @@ from ferrum.drivers.streaming import AsyncpgChunkStream
|
|
|
11
12
|
from ferrum.errors import FerrumConfigError, FerrumConnectionError, map_db_error
|
|
12
13
|
|
|
13
14
|
|
|
15
|
+
def _encode_json_param(value: Any) -> str:
|
|
16
|
+
"""Encode a Python value for asyncpg ``json`` / ``jsonb`` text codecs.
|
|
17
|
+
|
|
18
|
+
Ferrum's bind path already ``json.dumps`` JSON fields to text before the
|
|
19
|
+
driver (with SQL ``::jsonb`` casts). Accept pre-serialized strings so a
|
|
20
|
+
codec encoder never double-encodes those binds if a future path sends the
|
|
21
|
+
parameter as a native json/jsonb OID.
|
|
22
|
+
"""
|
|
23
|
+
if isinstance(value, str):
|
|
24
|
+
return value
|
|
25
|
+
return json.dumps(value, default=str, separators=(",", ":"))
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _decode_json_param(value: str) -> Any:
|
|
29
|
+
"""Decode asyncpg ``json`` / ``jsonb`` text into native Python objects."""
|
|
30
|
+
return json.loads(value)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
async def _register_json_codecs(conn: Any) -> None:
|
|
34
|
+
"""Make JSONB/JSON columns hydrate as ``dict`` / ``list``, not ``str``.
|
|
35
|
+
|
|
36
|
+
asyncpg's default is to return ``json``/``jsonb`` as text. Without this,
|
|
37
|
+
``model_construct`` leaves JSON fields as strings and Pydantic consumers
|
|
38
|
+
that expect ``dict`` fail at the agent/MCP boundary.
|
|
39
|
+
"""
|
|
40
|
+
for type_name in ("jsonb", "json"):
|
|
41
|
+
await conn.set_type_codec(
|
|
42
|
+
type_name,
|
|
43
|
+
schema="pg_catalog",
|
|
44
|
+
encoder=_encode_json_param,
|
|
45
|
+
decoder=_decode_json_param,
|
|
46
|
+
format="text",
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
|
|
14
50
|
class _BoundConnection:
|
|
15
51
|
"""Execution surface pinned to a single raw connection inside a transaction.
|
|
16
52
|
|
|
@@ -139,13 +175,15 @@ class AsyncpgDriver:
|
|
|
139
175
|
}
|
|
140
176
|
if self._max_lifetime is not None:
|
|
141
177
|
pool_kwargs["max_inactive_connection_lifetime"] = self._max_lifetime
|
|
142
|
-
if self._statement_timeout_ms is not None:
|
|
143
|
-
timeout_ms = self._statement_timeout_ms
|
|
144
178
|
|
|
145
|
-
|
|
146
|
-
|
|
179
|
+
statement_timeout_ms = self._statement_timeout_ms
|
|
180
|
+
|
|
181
|
+
async def _init_conn(conn: Any) -> None:
|
|
182
|
+
await _register_json_codecs(conn)
|
|
183
|
+
if statement_timeout_ms is not None:
|
|
184
|
+
await conn.execute(f"SET statement_timeout = {statement_timeout_ms}")
|
|
147
185
|
|
|
148
|
-
|
|
186
|
+
pool_kwargs["init"] = _init_conn
|
|
149
187
|
try:
|
|
150
188
|
self._pool = await asyncpg.create_pool(self._dsn, **pool_kwargs)
|
|
151
189
|
except Exception as exc:
|
|
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
|
|
File without changes
|
|
File without changes
|