perceptkit 0.2.6__tar.gz → 0.2.7__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.
- {perceptkit-0.2.6 → perceptkit-0.2.7}/CHANGELOG.md +9 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/PKG-INFO +1 -1
- {perceptkit-0.2.6 → perceptkit-0.2.7}/pyproject.toml +1 -1
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/kit.py +2 -1
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/retention.py +33 -7
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/test_retention_entry.py +21 -3
- {perceptkit-0.2.6 → perceptkit-0.2.7}/uv.lock +1 -1
- {perceptkit-0.2.6 → perceptkit-0.2.7}/.github/workflows/ci.yml +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/.github/workflows/release.yml +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/.gitignore +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/LICENSE +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/NOTES-packaging.md +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/NOTES-quickstart.md +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/README.md +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/docs/PerceptKit-/344/272/247/345/223/201/347/233/256/346/240/207/344/270/216/345/275/223/345/211/215/345/256/236/347/216/260/345/267/256/350/267/235/345/217/215/351/246/210.md" +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/docs/PerceptKit-/346/204/237/347/237/245/345/255/227/346/256/265/344/270/216/345/255/230/345/202/250-/345/267/245/347/250/213/345/257/271/351/275/220/350/241/245/345/205/205/350/256/250/350/256/272.md" +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/docs/reference-storage-mapping.md +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/examples/end_to_end.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/examples/ios_adapter.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/examples/quickstart.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/__init__.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/algorithms/__init__.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/algorithms/attribution.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/algorithms/glance.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/algorithms/history.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/algorithms/identity.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/algorithms/observation.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/algorithms/streaks.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/algorithms/trend_models.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/algorithms/wake.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/catalog.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/conformance/__init__.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/conformance/memory.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/conformance/report.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/conformance/suite.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/conformance/wake.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/contracts/__init__.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/contracts/_time.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/contracts/availability.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/contracts/context.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/contracts/delivery.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/contracts/errors.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/contracts/event.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/contracts/observation.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/contracts/receipt.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/contracts/records.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/contracts/report.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/contracts/versioning.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/fields.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/manifest/__init__.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/manifest/checks.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/manifest/mapping.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/manifest/minimal.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/manifest/types.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/manifest/units.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/ports/__init__.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/ports/storage.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/ports/wake.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/processing/__init__.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/processing/aggregate.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/processing/dispatch.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/processing/normalize.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/processing/pipeline.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/processing/recompute.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/processing/recurrence.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/processing/scheduled.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/prompts.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/queries/__init__.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/queries/api.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/rules/__init__.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/rules/engine.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/rules/evaluators.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/src/perceptkit/rules/types.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/fixtures/README.md +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/fixtures/ios_snapshot_no_data.json +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/fixtures/ios_snapshot_normal.json +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/fixtures/ios_snapshot_unauthorized.json +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/test_attribution.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/test_catalog.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/test_conformance.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/test_conformance_wake_report.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/test_contracts.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/test_delivery_and_records.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/test_docs_match_code.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/test_edge_cases.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/test_end_to_end.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/test_event_envelope.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/test_examples.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/test_export.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/test_identity.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/test_ios_fixture.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/test_isolation.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/test_manifest.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/test_no_host_leakage.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/test_observation.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/test_pipeline.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/test_projection.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/test_purity.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/test_queries.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/test_recompute.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/test_recurrence.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/test_regressions.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/test_retention.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/test_revision_recompute.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/test_rules.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/test_scheduled.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/test_source_mirror.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/test_streaks.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/test_trend_models.py +0 -0
- {perceptkit-0.2.6 → perceptkit-0.2.7}/tests/test_wake.py +0 -0
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# 变更记录
|
|
2
2
|
|
|
3
|
+
## 0.2.7 — 2026-09-02
|
|
4
|
+
|
|
5
|
+
- **跳过原因带上稳定的 `code`(`SkippedSignal`)。** 0.2.6 的清理计划里,
|
|
6
|
+
跳过理由只有一句中文 —— 这个包的注释都是中文,但**宿主的运维界面不一定是**,
|
|
7
|
+
直接印进一个英文报告里就成了半中半英。一个库不该替宿主决定报告用什么语言:
|
|
8
|
+
`code` 稳定、机器可读,文案归宿主。`SkippedSignal` 仍然能按 `(signal, detail)`
|
|
9
|
+
解包,老调用方不用改。
|
|
10
|
+
(0.2.6 发出去之后接 io 时当场撞到的 —— 那份英文运维报告里蹦出中文。)
|
|
11
|
+
|
|
3
12
|
## 0.2.6 — 2026-09-02
|
|
4
13
|
|
|
5
14
|
外部审查那份清单里剩下的两条(P0-1 / P0-6 的可做部分)。
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "perceptkit"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.7"
|
|
8
8
|
description = "从设备信号判断:有没有发生值得留意的事、值不值得叫醒一次 agent、以及该怎么把此刻的状况讲给它听。不采集数据、不选数据库、不调模型 —— 存储由宿主实现 StoragePort,编排在包内。"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -190,7 +190,8 @@ class PerceptionKit:
|
|
|
190
190
|
],
|
|
191
191
|
# 故意不删的也要列出来 —— 一份只说"删了 0 条"的报告,读不出
|
|
192
192
|
# 「是没到期,还是规则写错了」。
|
|
193
|
-
"skipped": [{"signal":
|
|
193
|
+
"skipped": [{"signal": s.signal, "code": s.code, "detail": s.detail}
|
|
194
|
+
for s in plan.skipped],
|
|
194
195
|
"removed": removed,
|
|
195
196
|
}
|
|
196
197
|
|
|
@@ -93,6 +93,33 @@ class RetentionAction:
|
|
|
93
93
|
before: _dt.date
|
|
94
94
|
|
|
95
95
|
|
|
96
|
+
@dataclass(frozen=True)
|
|
97
|
+
class SkippedSignal:
|
|
98
|
+
"""故意不清的一个信号,以及为什么。
|
|
99
|
+
|
|
100
|
+
``code`` 是稳定的机器可读标识,``detail`` 是给人看的一句话。
|
|
101
|
+
**宿主的运维界面该用 code 自己渲染** —— 一个库不该替宿主决定报告用什么
|
|
102
|
+
语言。这里的 detail 是中文(这个包的注释都是中文),直接印进一个英文
|
|
103
|
+
运维报告里就成了半中半英。
|
|
104
|
+
"""
|
|
105
|
+
|
|
106
|
+
signal: str
|
|
107
|
+
code: str
|
|
108
|
+
detail: str
|
|
109
|
+
|
|
110
|
+
def __iter__(self):
|
|
111
|
+
"""还能按 ``(signal, detail)` 解包 —— 老调用方不用一次全改。"""
|
|
112
|
+
return iter((self.signal, self.detail))
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
#: 稳定的跳过原因。宿主按这个渲染自己的文案。
|
|
116
|
+
SKIP_NO_HISTORY = "no_history"
|
|
117
|
+
SKIP_DETAILS_PERMANENT = "details_permanent"
|
|
118
|
+
SKIP_DETAILS_UNDECLARED = "details_undeclared"
|
|
119
|
+
SKIP_AGGREGATES_PERMANENT = "aggregates_permanent"
|
|
120
|
+
SKIP_AGGREGATES_UNDECLARED = "aggregates_undeclared"
|
|
121
|
+
|
|
122
|
+
|
|
96
123
|
@dataclass
|
|
97
124
|
class RetentionPlan:
|
|
98
125
|
"""要删什么,以及**故意不删什么、为什么**。
|
|
@@ -103,8 +130,7 @@ class RetentionPlan:
|
|
|
103
130
|
"""
|
|
104
131
|
|
|
105
132
|
actions: list[RetentionAction] = _field(default_factory=list)
|
|
106
|
-
|
|
107
|
-
skipped: list[tuple[str, str]] = _field(default_factory=list)
|
|
133
|
+
skipped: list[SkippedSignal] = _field(default_factory=list)
|
|
108
134
|
|
|
109
135
|
|
|
110
136
|
def plan_retention(
|
|
@@ -128,13 +154,13 @@ def plan_retention(
|
|
|
128
154
|
for key in sorted(signals):
|
|
129
155
|
sig = signals[key]
|
|
130
156
|
if not sig.stores_history:
|
|
131
|
-
plan.skipped.append((key, "不进历史表,没东西可清"))
|
|
157
|
+
plan.skipped.append(SkippedSignal(key, SKIP_NO_HISTORY, "不进历史表,没东西可清"))
|
|
132
158
|
continue
|
|
133
159
|
|
|
134
160
|
if sig.history_retention_days == PERMANENT:
|
|
135
|
-
plan.skipped.append((key, "明细永久保存"))
|
|
161
|
+
plan.skipped.append(SkippedSignal(key, SKIP_DETAILS_PERMANENT, "明细永久保存"))
|
|
136
162
|
elif sig.history_retention_days is None:
|
|
137
|
-
plan.skipped.append((key, "没声明明细保留期 —— 跳过,不替它猜一个"))
|
|
163
|
+
plan.skipped.append(SkippedSignal(key, SKIP_DETAILS_UNDECLARED, "没声明明细保留期 —— 跳过,不替它猜一个"))
|
|
138
164
|
else:
|
|
139
165
|
plan.actions.append(RetentionAction(
|
|
140
166
|
key, "observations",
|
|
@@ -142,9 +168,9 @@ def plan_retention(
|
|
|
142
168
|
|
|
143
169
|
agg_days = sig.effective_aggregate_retention_days
|
|
144
170
|
if agg_days == PERMANENT:
|
|
145
|
-
plan.skipped.append((key, "日聚合永久保存"))
|
|
171
|
+
plan.skipped.append(SkippedSignal(key, SKIP_AGGREGATES_PERMANENT, "日聚合永久保存"))
|
|
146
172
|
elif agg_days is None:
|
|
147
|
-
plan.skipped.append((key, "没声明聚合保留期 —— 跳过,不替它猜一个"))
|
|
173
|
+
plan.skipped.append(SkippedSignal(key, SKIP_AGGREGATES_UNDECLARED, "没声明聚合保留期 —— 跳过,不替它猜一个"))
|
|
148
174
|
else:
|
|
149
175
|
plan.actions.append(RetentionAction(
|
|
150
176
|
key, "aggregates",
|
|
@@ -42,7 +42,8 @@ def test_details_and_aggregates_get_their_own_cutoffs():
|
|
|
42
42
|
# 明细 7 天要清,聚合永久不许出现在动作里。
|
|
43
43
|
assert [a.kind for a in photo] == ["observations"]
|
|
44
44
|
assert photo[0].before == (NOW - timedelta(days=7)).date()
|
|
45
|
-
assert ("photo_library_added"
|
|
45
|
+
assert any(sk.signal == "photo_library_added"
|
|
46
|
+
and sk.code == "aggregates_permanent" for sk in plan.skipped)
|
|
46
47
|
|
|
47
48
|
|
|
48
49
|
def test_permanent_never_appears_as_something_to_delete():
|
|
@@ -62,14 +63,31 @@ def test_a_signal_with_no_declared_retention_is_skipped_not_defaulted():
|
|
|
62
63
|
history_retention_days=None, aggregate_retention_days=None)
|
|
63
64
|
plan = plan_retention({"audio_route": sig}, now=NOW)
|
|
64
65
|
assert plan.actions == []
|
|
65
|
-
assert all("
|
|
66
|
+
assert all(sk.code.endswith("undeclared") for sk in plan.skipped)
|
|
66
67
|
|
|
67
68
|
|
|
68
69
|
def test_the_plan_says_why_it_skipped_things():
|
|
69
70
|
"""只说"删了 0 条"的报告,读不出「是没到期,还是规则写错了」。"""
|
|
70
71
|
plan = _plan()
|
|
71
72
|
assert plan.skipped
|
|
72
|
-
assert all(
|
|
73
|
+
assert all(sk.detail.strip() for sk in plan.skipped)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def test_skip_reasons_carry_a_stable_code_for_the_host_to_render():
|
|
77
|
+
"""理由的**文字**是中文(这个包的注释都是中文)。宿主的运维界面不一定是。
|
|
78
|
+
|
|
79
|
+
直接把 detail 印进一个英文报告里就成了半中半英 —— 一个库不该替宿主
|
|
80
|
+
决定报告用什么语言。code 是稳定的,文案归宿主。
|
|
81
|
+
"""
|
|
82
|
+
from perceptkit.retention import (
|
|
83
|
+
SKIP_AGGREGATES_PERMANENT, SKIP_DETAILS_PERMANENT, SKIP_NO_HISTORY,
|
|
84
|
+
SKIP_DETAILS_UNDECLARED, SKIP_AGGREGATES_UNDECLARED,
|
|
85
|
+
)
|
|
86
|
+
known = {SKIP_NO_HISTORY, SKIP_DETAILS_PERMANENT, SKIP_DETAILS_UNDECLARED,
|
|
87
|
+
SKIP_AGGREGATES_PERMANENT, SKIP_AGGREGATES_UNDECLARED}
|
|
88
|
+
plan = _plan()
|
|
89
|
+
assert {sk.code for sk in plan.skipped} <= known
|
|
90
|
+
assert all(sk.code for sk in plan.skipped)
|
|
73
91
|
|
|
74
92
|
|
|
75
93
|
def test_a_dry_run_removes_nothing():
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|