margin 0.9.28__tar.gz → 0.9.29__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.
Potentially problematic release.
This version of margin might be problematic. Click here for more details.
- {margin-0.9.28/margin.egg-info → margin-0.9.29}/PKG-INFO +1 -1
- {margin-0.9.28 → margin-0.9.29}/margin/flow.py +49 -5
- {margin-0.9.28 → margin-0.9.29/margin.egg-info}/PKG-INFO +1 -1
- {margin-0.9.28 → margin-0.9.29}/pyproject.toml +1 -1
- {margin-0.9.28 → margin-0.9.29}/tests/test_flow.py +88 -7
- {margin-0.9.28 → margin-0.9.29}/LICENSE +0 -0
- {margin-0.9.28 → margin-0.9.29}/NOTICE +0 -0
- {margin-0.9.28 → margin-0.9.29}/README.md +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/__init__.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/__main__.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/algebra.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/anomaly.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/bridge.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/calibrate.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/causal.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/composite.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/confidence.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/config.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/contract.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/controller.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/correlate.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/diff.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/drift.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/events.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/fingerprint.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/forecast.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/health.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/intent.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/ledger.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/loop.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/observation.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/persist.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/policy/__init__.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/policy/compose.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/policy/core.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/policy/temporal.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/policy/trace.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/policy/tuning.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/policy/validate.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/predicates.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/provenance.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/streaming.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/transitions.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/uncertain.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin/validity.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin.egg-info/SOURCES.txt +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin.egg-info/dependency_links.txt +0 -0
- {margin-0.9.28 → margin-0.9.29}/margin.egg-info/top_level.txt +0 -0
- {margin-0.9.28 → margin-0.9.29}/setup.cfg +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_absence.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_algebra.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_anomaly.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_bridge.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_calibrate.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_causal.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_composite.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_confidence.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_config.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_contract.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_controller.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_correlate.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_diff.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_drift.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_events.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_fingerprint_ext.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_float_tolerance.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_forecast.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_health.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_healthcare.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_intent.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_ledger.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_loop.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_neuro.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_observation.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_persist.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_pipeline_features.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_policy.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_policy_compose.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_policy_temporal.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_policy_trace.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_policy_tuning.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_policy_validate.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_predicates.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_printer3d.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_provenance.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_reverse_bridge.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_ros2.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_staleness.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_streaming.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_transformer.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_transitions.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_uncertain.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_validity.py +0 -0
- {margin-0.9.28 → margin-0.9.29}/tests/test_windowing.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: margin
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.29
|
|
4
4
|
Summary: Typed health classification, uncertainty algebra, and correction auditing for any system that measures things and needs to explain what happened.
|
|
5
5
|
Author: Cope Labs LLC
|
|
6
6
|
License: MIT
|
|
@@ -55,7 +55,7 @@ users plug in the full Contract machinery when they need it.
|
|
|
55
55
|
|
|
56
56
|
from __future__ import annotations
|
|
57
57
|
|
|
58
|
-
from dataclasses import dataclass
|
|
58
|
+
from dataclasses import dataclass
|
|
59
59
|
from datetime import datetime
|
|
60
60
|
from enum import Enum
|
|
61
61
|
from typing import Callable, Dict, List, Optional
|
|
@@ -143,6 +143,7 @@ class Stage:
|
|
|
143
143
|
@dataclass
|
|
144
144
|
class FlowResult:
|
|
145
145
|
"""Returned from Flow.observe() and flow advancement helpers."""
|
|
146
|
+
flow_label: str
|
|
146
147
|
stage: str
|
|
147
148
|
stage_index: int
|
|
148
149
|
total_stages: int
|
|
@@ -152,20 +153,29 @@ class FlowResult:
|
|
|
152
153
|
|
|
153
154
|
def to_atom(self) -> str:
|
|
154
155
|
"""
|
|
155
|
-
Compact flow notation.
|
|
156
|
+
Compact flow notation — consistent format across running and complete states.
|
|
157
|
+
|
|
158
|
+
With a flow label::
|
|
156
159
|
|
|
157
160
|
"flow:fermentation:lag_phase[2/5] → ADVANCE"
|
|
158
|
-
"flow:fermentation
|
|
161
|
+
"flow:fermentation[5/5]" # complete
|
|
162
|
+
|
|
163
|
+
Without a flow label (empty)::
|
|
164
|
+
|
|
165
|
+
"flow:lag_phase[2/5] → ADVANCE"
|
|
166
|
+
"flow[5/5]" # complete
|
|
159
167
|
"""
|
|
168
|
+
prefix = f"flow:{self.flow_label}" if self.flow_label else "flow"
|
|
160
169
|
if self.guidance == Guidance.COMPLETE:
|
|
161
|
-
return f"
|
|
170
|
+
return f"{prefix}[{self.total_stages}/{self.total_stages}]"
|
|
162
171
|
return (
|
|
163
|
-
f"
|
|
172
|
+
f"{prefix}:{self.stage}[{self.stage_index + 1}/{self.total_stages}]"
|
|
164
173
|
f" → {self.guidance.value}"
|
|
165
174
|
)
|
|
166
175
|
|
|
167
176
|
def to_dict(self) -> dict:
|
|
168
177
|
return {
|
|
178
|
+
"flow_label": self.flow_label,
|
|
169
179
|
"stage": self.stage,
|
|
170
180
|
"stage_index": self.stage_index,
|
|
171
181
|
"total_stages": self.total_stages,
|
|
@@ -194,6 +204,36 @@ class Flow:
|
|
|
194
204
|
(or a policy layer above) decides whether to call ``advance()``. This
|
|
195
205
|
keeps the flow deterministic and side-effect free, which matters for
|
|
196
206
|
replay, backtesting, and safety-critical use cases.
|
|
207
|
+
|
|
208
|
+
Thread safety
|
|
209
|
+
-------------
|
|
210
|
+
Flow is **not thread-safe**. ``observe()`` mutates the current stage's
|
|
211
|
+
Monitor window; ``advance()`` and ``rollback()`` mutate the stage index.
|
|
212
|
+
If you need to observe a flow from multiple threads, wrap it in a lock
|
|
213
|
+
at the call site. Per-entity flows in a request/response context (one
|
|
214
|
+
Flow instance per tracked entity) are the intended pattern.
|
|
215
|
+
|
|
216
|
+
Predicate ordering
|
|
217
|
+
------------------
|
|
218
|
+
``_classify`` evaluates predicates in strict severity order:
|
|
219
|
+
|
|
220
|
+
1. ``escalate_when`` (highest — safety gate)
|
|
221
|
+
2. ``rollback_when``
|
|
222
|
+
3. ``advance_when``
|
|
223
|
+
4. ``retry_when``
|
|
224
|
+
|
|
225
|
+
A true ``escalate_when`` dominates a true ``advance_when`` — this is
|
|
226
|
+
intentional. When a stage is in an escalation condition, we do not
|
|
227
|
+
advance even if exit criteria are also met. Safety-first semantics.
|
|
228
|
+
|
|
229
|
+
Memory note
|
|
230
|
+
-----------
|
|
231
|
+
Each ``advance()`` creates a fresh Monitor for the new stage without
|
|
232
|
+
pruning the prior stage's Monitor. For a 50-stage pipeline, 50 Monitor
|
|
233
|
+
instances accumulate in ``self._monitors``. This is intentional for
|
|
234
|
+
debuggability but may matter for very long flows. A pruning option
|
|
235
|
+
may be added in a future release; for now, construct a new Flow if
|
|
236
|
+
memory footprint matters.
|
|
197
237
|
"""
|
|
198
238
|
|
|
199
239
|
def __init__(
|
|
@@ -259,6 +299,7 @@ class Flow:
|
|
|
259
299
|
"""
|
|
260
300
|
if self.is_complete:
|
|
261
301
|
return FlowResult(
|
|
302
|
+
flow_label=self.label,
|
|
262
303
|
stage=self.label or "flow",
|
|
263
304
|
stage_index=len(self.stages),
|
|
264
305
|
total_stages=len(self.stages),
|
|
@@ -273,6 +314,7 @@ class Flow:
|
|
|
273
314
|
guidance, reason = self._classify(stage, expr)
|
|
274
315
|
|
|
275
316
|
return FlowResult(
|
|
317
|
+
flow_label=self.label,
|
|
276
318
|
stage=stage.name,
|
|
277
319
|
stage_index=self._index,
|
|
278
320
|
total_stages=len(self.stages),
|
|
@@ -352,6 +394,7 @@ class Flow:
|
|
|
352
394
|
def _status_result(self, reason: str) -> FlowResult:
|
|
353
395
|
if self.is_complete:
|
|
354
396
|
return FlowResult(
|
|
397
|
+
flow_label=self.label,
|
|
355
398
|
stage=self.label or "flow",
|
|
356
399
|
stage_index=len(self.stages),
|
|
357
400
|
total_stages=len(self.stages),
|
|
@@ -360,6 +403,7 @@ class Flow:
|
|
|
360
403
|
reason=reason,
|
|
361
404
|
)
|
|
362
405
|
return FlowResult(
|
|
406
|
+
flow_label=self.label,
|
|
363
407
|
stage=self.current.name,
|
|
364
408
|
stage_index=self._index,
|
|
365
409
|
total_stages=len(self.stages),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: margin
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.29
|
|
4
4
|
Summary: Typed health classification, uncertainty algebra, and correction auditing for any system that measures things and needs to explain what happened.
|
|
5
5
|
Author: Cope Labs LLC
|
|
6
6
|
License: MIT
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "margin"
|
|
7
|
-
version = "0.9.
|
|
7
|
+
version = "0.9.29"
|
|
8
8
|
description = "Typed health classification, uncertainty algebra, and correction auditing for any system that measures things and needs to explain what happened."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {text = "MIT"}
|
|
@@ -4,7 +4,7 @@ import pytest
|
|
|
4
4
|
from margin import (
|
|
5
5
|
Flow, Stage, Guidance,
|
|
6
6
|
Parser, Thresholds, Health, Confidence,
|
|
7
|
-
Expression,
|
|
7
|
+
Expression, Absence,
|
|
8
8
|
)
|
|
9
9
|
|
|
10
10
|
|
|
@@ -298,23 +298,50 @@ class TestReset:
|
|
|
298
298
|
# ---------------------------------------------------------------------------
|
|
299
299
|
|
|
300
300
|
class TestSerialization:
|
|
301
|
-
def
|
|
301
|
+
def test_to_atom_running_includes_flow_label(self):
|
|
302
302
|
f = Flow(stages=[
|
|
303
303
|
Stage(name="lag", parser=_parser({"m": 1.0})),
|
|
304
304
|
Stage(name="exp", parser=_parser({"m": 1.0})),
|
|
305
305
|
], label="ferment")
|
|
306
306
|
result = f.observe({"m": 1.0})
|
|
307
307
|
atom = result.to_atom()
|
|
308
|
-
|
|
309
|
-
assert "1/2
|
|
310
|
-
assert "HOLD" in atom
|
|
308
|
+
# Must include: flow_label, stage_name, position, guidance
|
|
309
|
+
assert atom == "flow:ferment:lag[1/2] → HOLD"
|
|
311
310
|
|
|
312
|
-
def
|
|
311
|
+
def test_to_atom_running_no_label(self):
|
|
312
|
+
f = Flow(stages=[
|
|
313
|
+
Stage(name="lag", parser=_parser({"m": 1.0})),
|
|
314
|
+
Stage(name="exp", parser=_parser({"m": 1.0})),
|
|
315
|
+
])
|
|
316
|
+
result = f.observe({"m": 1.0})
|
|
317
|
+
assert result.to_atom() == "flow:lag[1/2] → HOLD"
|
|
318
|
+
|
|
319
|
+
def test_to_atom_complete_includes_flow_label(self):
|
|
313
320
|
s = Stage(name="only", parser=_parser({"m": 1.0}))
|
|
314
321
|
f = Flow(stages=[s], label="linear")
|
|
315
322
|
f.advance()
|
|
316
323
|
result = f.observe({"m": 1.0})
|
|
317
324
|
assert result.guidance == Guidance.COMPLETE
|
|
325
|
+
assert result.to_atom() == "flow:linear[1/1]"
|
|
326
|
+
|
|
327
|
+
def test_to_atom_complete_no_label(self):
|
|
328
|
+
s = Stage(name="only", parser=_parser({"m": 1.0}))
|
|
329
|
+
f = Flow(stages=[s])
|
|
330
|
+
f.advance()
|
|
331
|
+
result = f.observe({"m": 1.0})
|
|
332
|
+
assert result.to_atom() == "flow[1/1]"
|
|
333
|
+
|
|
334
|
+
def test_concurrent_flows_are_distinguishable(self):
|
|
335
|
+
"""Two flows with same stage names but different labels must
|
|
336
|
+
produce distinguishable atoms — without this, operator dashboards
|
|
337
|
+
can't tell flows apart."""
|
|
338
|
+
f1 = Flow(stages=[Stage(name="step", parser=_parser({"m": 1.0}))], label="service_a")
|
|
339
|
+
f2 = Flow(stages=[Stage(name="step", parser=_parser({"m": 1.0}))], label="service_b")
|
|
340
|
+
r1 = f1.observe({"m": 1.0})
|
|
341
|
+
r2 = f2.observe({"m": 1.0})
|
|
342
|
+
assert r1.to_atom() != r2.to_atom()
|
|
343
|
+
assert "service_a" in r1.to_atom()
|
|
344
|
+
assert "service_b" in r2.to_atom()
|
|
318
345
|
|
|
319
346
|
def test_flow_to_dict(self):
|
|
320
347
|
f = Flow(stages=[
|
|
@@ -328,14 +355,68 @@ class TestSerialization:
|
|
|
328
355
|
|
|
329
356
|
def test_flow_result_to_dict(self):
|
|
330
357
|
s = Stage(name="a", parser=_parser({"m": 1.0}))
|
|
331
|
-
f = Flow(stages=[s])
|
|
358
|
+
f = Flow(stages=[s], label="t")
|
|
332
359
|
result = f.observe({"m": 1.0})
|
|
333
360
|
d = result.to_dict()
|
|
334
361
|
assert d["stage"] == "a"
|
|
362
|
+
assert d["flow_label"] == "t"
|
|
335
363
|
assert d["guidance"] == "HOLD"
|
|
336
364
|
assert "expression" in d
|
|
337
365
|
|
|
338
366
|
|
|
367
|
+
# ---------------------------------------------------------------------------
|
|
368
|
+
# Observe passthrough — absences, confidences
|
|
369
|
+
# ---------------------------------------------------------------------------
|
|
370
|
+
|
|
371
|
+
class TestObservePassthrough:
|
|
372
|
+
def test_absences_flow_through(self):
|
|
373
|
+
"""Absences supplied to Flow.observe() must reach the Monitor and
|
|
374
|
+
produce an OOD observation with typed absence in the Expression."""
|
|
375
|
+
stage = Stage(
|
|
376
|
+
name="s",
|
|
377
|
+
parser=Parser(
|
|
378
|
+
baselines={"m": 1.0, "n": 1.0},
|
|
379
|
+
thresholds=Thresholds(intact=0.8, ablated=0.2),
|
|
380
|
+
),
|
|
381
|
+
)
|
|
382
|
+
f = Flow(stages=[stage])
|
|
383
|
+
result = f.observe({"m": 1.0}, absences={"n": Absence.SENSOR_FAILED})
|
|
384
|
+
obs_by_name = {o.name: o for o in result.expression.observations}
|
|
385
|
+
assert obs_by_name["m"].is_absent is False
|
|
386
|
+
assert obs_by_name["n"].is_absent is True
|
|
387
|
+
assert obs_by_name["n"].absence == Absence.SENSOR_FAILED
|
|
388
|
+
|
|
389
|
+
def test_confidences_flow_through(self):
|
|
390
|
+
stage = Stage(name="s", parser=_parser({"m": 1.0}))
|
|
391
|
+
f = Flow(stages=[stage])
|
|
392
|
+
result = f.observe({"m": 1.0}, confidences={"m": Confidence.LOW})
|
|
393
|
+
m = [o for o in result.expression.observations if o.name == "m"][0]
|
|
394
|
+
assert m.confidence == Confidence.LOW
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
# ---------------------------------------------------------------------------
|
|
398
|
+
# Edge cases
|
|
399
|
+
# ---------------------------------------------------------------------------
|
|
400
|
+
|
|
401
|
+
class TestEdgeCases:
|
|
402
|
+
def test_empty_values_dict(self):
|
|
403
|
+
"""Empty observation should return HOLD and not crash."""
|
|
404
|
+
stage = Stage(name="s", parser=_parser({"m": 1.0}))
|
|
405
|
+
f = Flow(stages=[stage])
|
|
406
|
+
result = f.observe({})
|
|
407
|
+
assert result.guidance == Guidance.HOLD
|
|
408
|
+
assert result.expression is not None
|
|
409
|
+
assert len(result.expression.observations) == 0
|
|
410
|
+
|
|
411
|
+
def test_observe_complete_flow_safe(self):
|
|
412
|
+
"""observe() on a complete flow returns COMPLETE, doesn't raise."""
|
|
413
|
+
f = Flow(stages=[Stage(name="a", parser=_parser({"m": 1.0}))], label="L")
|
|
414
|
+
f.advance()
|
|
415
|
+
r = f.observe({"m": 1.0})
|
|
416
|
+
assert r.guidance == Guidance.COMPLETE
|
|
417
|
+
assert r.to_atom() == "flow:L[1/1]"
|
|
418
|
+
|
|
419
|
+
|
|
339
420
|
# ---------------------------------------------------------------------------
|
|
340
421
|
# Realistic scenario: fermentation
|
|
341
422
|
# ---------------------------------------------------------------------------
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|