pam-python 0.2.13__tar.gz → 0.2.14__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.
- {pam_python-0.2.13/pam_python.egg-info → pam_python-0.2.14}/PKG-INFO +4 -3
- {pam_python-0.2.13 → pam_python-0.2.14}/README.md +3 -2
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/__init__.py +1 -1
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/models/data_input_v2.py +11 -1
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/templates/init/AGENT.md +4 -3
- {pam_python-0.2.13 → pam_python-0.2.14/pam_python.egg-info}/PKG-INFO +4 -3
- {pam_python-0.2.13 → pam_python-0.2.14}/tests/test_data_input_v2.py +52 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/LICENSE.txt +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/api.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/cli.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/datetime_utils.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/interface_task_manager.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/logger.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/models/__init__.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/models/request_command.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/models/sqlite_download.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/reports/__init__.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/reports/area.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/reports/axis.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/reports/bar.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/reports/box_plot.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/reports/bubble.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/reports/candlestick.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/reports/collection.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/reports/definition.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/reports/donut.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/reports/errors.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/reports/fields.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/reports/heatmap.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/reports/line.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/reports/manager.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/reports/metric.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/reports/pie.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/reports/polar_area.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/reports/radar.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/reports/radial_bar.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/reports/range_area.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/reports/range_bar.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/reports/range_transform.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/reports/record.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/reports/report.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/reports/scatter.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/reports/schema.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/reports/store.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/reports/table.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/reports/temporal.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/reports/transport.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/reports/treemap.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/request_file_format.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/result_batch_uploader.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/server.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/service.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/sqlite.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/task_manager.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/temp_file_utils.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/templates/buildcmd/pamb +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/templates/buildcmd/pamb-base.sh +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/templates/init/REPORTS-th.md +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/templates/init/REPORTS.md +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/templates/init/dockerignore.tmpl +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/templates/init/gitignore.tmpl +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/templates/init/main.tmpl +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/templates/init/pylintrc.tmpl +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/templates/init/run_unit_test.bat +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/templates/init/run_unit_test.ps1 +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/templates/init/run_unit_test.sh +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/templates/project/pip/Dockerfile +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/templates/project/pip/requirements.txt +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/templates/project/uv/Dockerfile +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/templates/project/uv/pyproject.toml +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/templates/project/uv/python-version +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/templates/service/common/service.yaml +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/templates/service/pandas/functions.tmpl +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/templates/service/pandas/service.test.tmpl +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/templates/service/pandas/service_class.tmpl +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/templates/service/polars/functions.tmpl +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/templates/service/polars/service.test.tmpl +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/templates/service/polars/service_class.tmpl +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/tester_task.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam/utils.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam_python.egg-info/SOURCES.txt +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam_python.egg-info/dependency_links.txt +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam_python.egg-info/entry_points.txt +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam_python.egg-info/requires.txt +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pam_python.egg-info/top_level.txt +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/pyproject.toml +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/setup.cfg +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/tests/test_api.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/tests/test_cli_templates.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/tests/test_data_error_v2.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/tests/test_data_timeout_v2.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/tests/test_datetime_utils.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/tests/test_range_transform.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/tests/test_report_store.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/tests/test_request_data_v2.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/tests/test_result_batch_uploader.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/tests/test_service_dataframe_output.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/tests/test_sqlite_download_v2.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/tests/test_temp_file_utils.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/tests/test_temporal_mode.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/tests/test_typed_area_report.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/tests/test_typed_bar_report.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/tests/test_typed_box_plot_report.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/tests/test_typed_bubble_report.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/tests/test_typed_candlestick_report.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/tests/test_typed_donut_report.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/tests/test_typed_heatmap_report.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/tests/test_typed_line_report.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/tests/test_typed_metric_report.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/tests/test_typed_pie_report.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/tests/test_typed_polar_area_report.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/tests/test_typed_radar_report.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/tests/test_typed_radial_bar_report.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/tests/test_typed_range_area_report.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/tests/test_typed_range_bar_report.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/tests/test_typed_scatter_report.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/tests/test_typed_table_report.py +0 -0
- {pam_python-0.2.13 → pam_python-0.2.14}/tests/test_typed_treemap_report.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pam-python
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.14
|
|
4
4
|
Summary: Pam Python Library
|
|
5
5
|
Author-email: Narongrit Kanhanoi <narongrit@pams.ai>
|
|
6
6
|
Project-URL: Homepage, https://github.com/heart/pam-python
|
|
@@ -134,8 +134,9 @@ See [Data Plugin Input V2](docs/data-plugin-input-v2.md).
|
|
|
134
134
|
|
|
135
135
|
New Pandas and Polars service projects are generated on the V2 lane by default;
|
|
136
136
|
legacy source can continue using V1 unchanged. For materialized Pandas frames,
|
|
137
|
-
use `data.read_population_pandas()` and
|
|
138
|
-
`data.dataset_at(position).read_pandas()
|
|
137
|
+
use `data.read_population_pandas()` and either
|
|
138
|
+
`data.dataset_at(position).read_pandas()` or
|
|
139
|
+
`data.dataset_named(name).read_pandas()`.
|
|
139
140
|
|
|
140
141
|
When your service is done:
|
|
141
142
|
|
|
@@ -114,8 +114,9 @@ See [Data Plugin Input V2](docs/data-plugin-input-v2.md).
|
|
|
114
114
|
|
|
115
115
|
New Pandas and Polars service projects are generated on the V2 lane by default;
|
|
116
116
|
legacy source can continue using V1 unchanged. For materialized Pandas frames,
|
|
117
|
-
use `data.read_population_pandas()` and
|
|
118
|
-
`data.dataset_at(position).read_pandas()
|
|
117
|
+
use `data.read_population_pandas()` and either
|
|
118
|
+
`data.dataset_at(position).read_pandas()` or
|
|
119
|
+
`data.dataset_named(name).read_pandas()`.
|
|
119
120
|
|
|
120
121
|
When your service is done:
|
|
121
122
|
|
|
@@ -142,6 +142,15 @@ class DataInputV2:
|
|
|
142
142
|
raise IndexError(f"V2 dataset position is out of range: {position}")
|
|
143
143
|
return self.datasets[position]
|
|
144
144
|
|
|
145
|
+
def dataset_named(self, name: str) -> DataInputV2Dataset:
|
|
146
|
+
"""Bind one configured dataset by an unambiguous manifest name."""
|
|
147
|
+
matches = [dataset for dataset in self.datasets if dataset.name == name]
|
|
148
|
+
if not matches:
|
|
149
|
+
raise KeyError(f"V2 dataset name is unknown: {name}")
|
|
150
|
+
if len(matches) > 1:
|
|
151
|
+
raise ValueError(f"V2 dataset name is ambiguous: {name}")
|
|
152
|
+
return matches[0]
|
|
153
|
+
|
|
145
154
|
|
|
146
155
|
def parse_data_input_v2(input_files: list[str]) -> DataInputV2:
|
|
147
156
|
files_by_name = _validate_flat_input_files(input_files)
|
|
@@ -202,6 +211,7 @@ def parse_data_input_v2(input_files: list[str]) -> DataInputV2:
|
|
|
202
211
|
if position in positions:
|
|
203
212
|
raise ValueError("V2 dataset position is duplicated")
|
|
204
213
|
positions.add(position)
|
|
214
|
+
dataset_name = _required_string(raw_dataset, "name")
|
|
205
215
|
dataset_format = _required_format(raw_dataset, "format")
|
|
206
216
|
raw_parts = raw_dataset.get("parts")
|
|
207
217
|
if not isinstance(raw_parts, list):
|
|
@@ -226,7 +236,7 @@ def parse_data_input_v2(input_files: list[str]) -> DataInputV2:
|
|
|
226
236
|
datasets.append(
|
|
227
237
|
DataInputV2Dataset(
|
|
228
238
|
position=position,
|
|
229
|
-
name=
|
|
239
|
+
name=dataset_name,
|
|
230
240
|
type=_required_string(raw_dataset, "type"),
|
|
231
241
|
format=dataset_format,
|
|
232
242
|
row_count=row_count,
|
|
@@ -215,15 +215,16 @@ V2 is a separate, explicit lane. Call `_request_data_v2(...)` with CSV or
|
|
|
215
215
|
Parquet when the PAM adapter is configured for V2. The requested format applies
|
|
216
216
|
to that page and may change on a later request. In `on_data_input`, require
|
|
217
217
|
`req.data_input_v2`, validate the expected dataset count, and bind each dataset
|
|
218
|
-
by its configured position
|
|
218
|
+
by an unambiguous manifest name (or by its configured position when names are
|
|
219
|
+
not unique or the contract requires positional binding):
|
|
219
220
|
|
|
220
221
|
```python
|
|
221
222
|
data = req.data_input_v2
|
|
222
223
|
if data is None or len(data.datasets) != 2:
|
|
223
224
|
raise ValueError("Expected V2 profile and purchase datasets")
|
|
224
225
|
|
|
225
|
-
profile = data.
|
|
226
|
-
purchase = data.
|
|
226
|
+
profile = data.dataset_named("profile")
|
|
227
|
+
purchase = data.dataset_named("purchase")
|
|
227
228
|
|
|
228
229
|
population = data.scan_population_polars()
|
|
229
230
|
profile_frame = profile.scan_polars()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pam-python
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.14
|
|
4
4
|
Summary: Pam Python Library
|
|
5
5
|
Author-email: Narongrit Kanhanoi <narongrit@pams.ai>
|
|
6
6
|
Project-URL: Homepage, https://github.com/heart/pam-python
|
|
@@ -134,8 +134,9 @@ See [Data Plugin Input V2](docs/data-plugin-input-v2.md).
|
|
|
134
134
|
|
|
135
135
|
New Pandas and Polars service projects are generated on the V2 lane by default;
|
|
136
136
|
legacy source can continue using V1 unchanged. For materialized Pandas frames,
|
|
137
|
-
use `data.read_population_pandas()` and
|
|
138
|
-
`data.dataset_at(position).read_pandas()
|
|
137
|
+
use `data.read_population_pandas()` and either
|
|
138
|
+
`data.dataset_at(position).read_pandas()` or
|
|
139
|
+
`data.dataset_named(name).read_pandas()`.
|
|
139
140
|
|
|
140
141
|
When your service is done:
|
|
141
142
|
|
|
@@ -215,6 +215,26 @@ class DataInputV2Test(unittest.TestCase):
|
|
|
215
215
|
with self.assertRaisesRegex(IndexError, "out of range"):
|
|
216
216
|
data_input.dataset_at(1)
|
|
217
217
|
|
|
218
|
+
def test_dataset_named_resolves_unique_manifest_name(self):
|
|
219
|
+
manifest_path = self._write_manifest(self._valid_manifest())
|
|
220
|
+
data_input = parse_data_input_v2(
|
|
221
|
+
[str(manifest_path), str(self.population_path), str(self.dataset_path)]
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
dataset = data_input.dataset_named("demographic")
|
|
225
|
+
|
|
226
|
+
self.assertEqual(0, dataset.position)
|
|
227
|
+
self.assertEqual("demographic", dataset.name)
|
|
228
|
+
|
|
229
|
+
def test_dataset_named_rejects_unknown_name(self):
|
|
230
|
+
manifest_path = self._write_manifest(self._valid_manifest())
|
|
231
|
+
data_input = parse_data_input_v2(
|
|
232
|
+
[str(manifest_path), str(self.population_path), str(self.dataset_path)]
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
with self.assertRaisesRegex(KeyError, "name is unknown: purchase"):
|
|
236
|
+
data_input.dataset_named("purchase")
|
|
237
|
+
|
|
218
238
|
def test_parse_rejects_sha256_mismatch(self):
|
|
219
239
|
manifest = self._valid_manifest()
|
|
220
240
|
manifest["population"]["file"]["sha256"] = "0" * 64
|
|
@@ -249,6 +269,38 @@ class DataInputV2Test(unittest.TestCase):
|
|
|
249
269
|
[str(manifest_path), str(self.population_path), str(self.dataset_path)]
|
|
250
270
|
)
|
|
251
271
|
|
|
272
|
+
def test_dataset_named_rejects_ambiguous_name_without_breaking_positions(self):
|
|
273
|
+
second_dataset_path = self._write_file(
|
|
274
|
+
"dataset_002_event_part_0001.csv",
|
|
275
|
+
b"id,event\ncontact-1,purchase\n",
|
|
276
|
+
)
|
|
277
|
+
manifest = self._valid_manifest()
|
|
278
|
+
manifest["datasets"].append(
|
|
279
|
+
{
|
|
280
|
+
"position": 1,
|
|
281
|
+
"name": "demographic",
|
|
282
|
+
"type": "demographic",
|
|
283
|
+
"format": "csv",
|
|
284
|
+
"row_count": 1,
|
|
285
|
+
"complete": True,
|
|
286
|
+
"parts": [self._metadata(second_dataset_path, 1)],
|
|
287
|
+
}
|
|
288
|
+
)
|
|
289
|
+
manifest_path = self._write_manifest(manifest)
|
|
290
|
+
|
|
291
|
+
data_input = parse_data_input_v2(
|
|
292
|
+
[
|
|
293
|
+
str(manifest_path),
|
|
294
|
+
str(self.population_path),
|
|
295
|
+
str(self.dataset_path),
|
|
296
|
+
str(second_dataset_path),
|
|
297
|
+
]
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
self.assertEqual("demographic", data_input.dataset_at(1).name)
|
|
301
|
+
with self.assertRaisesRegex(ValueError, "name is ambiguous: demographic"):
|
|
302
|
+
data_input.dataset_named("demographic")
|
|
303
|
+
|
|
252
304
|
def test_parse_exposes_event_population_and_half_open_time_window(self):
|
|
253
305
|
manifest = self._valid_manifest()
|
|
254
306
|
manifest["population"]["mode"] = "event_all"
|
|
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
|
|
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
|