PyPlumIO 0.5.31__tar.gz → 0.5.33__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.
- {pyplumio-0.5.31 → pyplumio-0.5.33}/PKG-INFO +1 -1
- {pyplumio-0.5.31 → pyplumio-0.5.33}/PyPlumIO.egg-info/PKG-INFO +1 -1
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/_version.py +2 -2
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/devices/__init__.py +5 -8
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/helpers/parameter.py +4 -3
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/helpers/test_parameter.py +30 -6
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/test_devices.py +0 -4
- {pyplumio-0.5.31 → pyplumio-0.5.33}/.gitattributes +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/.github/CODE_OF_CONDUCT.md +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/.github/dependabot.yml +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/.github/workflows/ci.yml +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/.github/workflows/codeql-analysis.yml +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/.github/workflows/deploy.yml +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/.github/workflows/documentation.yml +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/.gitignore +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/.pre-commit-config.yaml +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/.vscode/settings.json +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/LICENSE +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/MANIFEST.in +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/PyPlumIO.egg-info/SOURCES.txt +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/PyPlumIO.egg-info/dependency_links.txt +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/PyPlumIO.egg-info/requires.txt +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/PyPlumIO.egg-info/top_level.txt +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/README.md +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/docs/Makefile +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/docs/make.bat +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/docs/source/callbacks.rst +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/docs/source/conf.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/docs/source/connecting.rst +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/docs/source/frames.rst +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/docs/source/index.rst +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/docs/source/mixers_thermostats.rst +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/docs/source/protocol.rst +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/docs/source/reading.rst +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/docs/source/schedules.rst +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/docs/source/writing.rst +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/images/ecomax.png +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/images/rs485.png +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/__init__.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/__main__.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/connection.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/const.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/devices/ecomax.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/devices/ecoster.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/devices/mixer.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/devices/thermostat.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/exceptions.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/filters.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/frames/__init__.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/frames/messages.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/frames/requests.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/frames/responses.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/helpers/__init__.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/helpers/data_types.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/helpers/event_manager.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/helpers/factory.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/helpers/schedule.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/helpers/task_manager.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/helpers/timeout.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/helpers/uid.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/protocol.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/py.typed +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/stream.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/structures/__init__.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/structures/alerts.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/structures/boiler_load.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/structures/boiler_power.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/structures/ecomax_parameters.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/structures/fan_power.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/structures/frame_versions.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/structures/fuel_consumption.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/structures/fuel_level.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/structures/lambda_sensor.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/structures/mixer_parameters.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/structures/mixer_sensors.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/structures/modules.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/structures/network_info.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/structures/output_flags.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/structures/outputs.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/structures/pending_alerts.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/structures/product_info.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/structures/program_version.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/structures/regulator_data.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/structures/regulator_data_schema.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/structures/schedules.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/structures/statuses.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/structures/temperatures.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/structures/thermostat_parameters.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/structures/thermostat_sensors.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyplumio/utils.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/pyproject.toml +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/requirements.txt +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/requirements_docs.txt +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/requirements_test.txt +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/setup.cfg +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/__init__.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/conftest.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/frames/test_init.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/frames/test_messages.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/frames/test_requests.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/frames/test_responses.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/helpers/__init__.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/helpers/test_data_types.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/helpers/test_event_manager.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/helpers/test_factory.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/helpers/test_schedule.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/helpers/test_task_manager.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/helpers/test_timeout.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/helpers/test_uid.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/ruff.toml +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/test_connection.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/test_filters.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/test_init.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/test_main.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/test_protocol.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/test_stream.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/test_utils.py +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/testdata/messages/regulator_data.json +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/testdata/messages/sensor_data.json +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/testdata/requests/alerts.json +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/testdata/requests/ecomax_control.json +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/testdata/requests/ecomax_parameters.json +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/testdata/requests/mixer_parameters.json +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/testdata/requests/set_ecomax_parameter.json +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/testdata/requests/set_mixer_parameter.json +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/testdata/requests/set_schedule.json +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/testdata/requests/set_thermostat_parameter.json +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/testdata/requests/thermostat_parameters.json +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/testdata/responses/alerts.json +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/testdata/responses/device_available.json +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/testdata/responses/ecomax_parameters.json +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/testdata/responses/mixer_parameters.json +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/testdata/responses/password.json +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/testdata/responses/program_version.json +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/testdata/responses/regulator_data_schema.json +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/testdata/responses/schedules.json +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/testdata/responses/thermostat_parameters.json +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/testdata/responses/uid.json +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/testdata/unknown/unknown_ecomax_parameter.json +0 -0
- {pyplumio-0.5.31 → pyplumio-0.5.33}/tests/testdata/unknown/unknown_mixer_parameter.json +0 -0
@@ -151,15 +151,12 @@ class PhysicalDevice(Device, ABC):
|
|
151
151
|
|
152
152
|
self.subscribe(ATTR_FRAME_VERSIONS, update_frame_versions)
|
153
153
|
|
154
|
-
def has_frame_version(self, frame_type: int, version: int
|
154
|
+
def has_frame_version(self, frame_type: FrameType | int, version: int) -> bool:
|
155
155
|
"""Return True if frame data is up to date, False otherwise."""
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
return True
|
161
|
-
|
162
|
-
return False
|
156
|
+
return (
|
157
|
+
frame_type in self._frame_versions
|
158
|
+
and self._frame_versions[frame_type] == version
|
159
|
+
)
|
163
160
|
|
164
161
|
def supports_frame_type(self, frame_type: int) -> bool:
|
165
162
|
"""Check if frame type is supported by the device."""
|
@@ -187,9 +187,6 @@ class Parameter(ABC):
|
|
187
187
|
def validate(self, value: ParameterValue) -> int:
|
188
188
|
"""Validate a parameter value."""
|
189
189
|
value = _normalize_parameter_value(value)
|
190
|
-
if value == self.values.value:
|
191
|
-
raise ValueError("Parameter value is unchanged.")
|
192
|
-
|
193
190
|
if value < self.values.min_value or value > self.values.max_value:
|
194
191
|
raise ValueError(
|
195
192
|
f"Value must be between '{self.min_value}' and '{self.max_value}'"
|
@@ -209,6 +206,10 @@ class Parameter(ABC):
|
|
209
206
|
self, value: Any, retries: int = 5, timeout: float = 5.0
|
210
207
|
) -> bool:
|
211
208
|
"""Try to set a parameter value."""
|
209
|
+
if value == self.values.value:
|
210
|
+
# Value is unchanged
|
211
|
+
return True
|
212
|
+
|
212
213
|
self._previous_value = self._values.value
|
213
214
|
self._values.value = value
|
214
215
|
self._pending_update = True
|
@@ -113,9 +113,6 @@ async def test_number_validate(number: Number) -> None:
|
|
113
113
|
"""Test the number validation."""
|
114
114
|
assert number.validate(2)
|
115
115
|
|
116
|
-
with pytest.raises(ValueError):
|
117
|
-
number.validate(1)
|
118
|
-
|
119
116
|
with pytest.raises(ValueError):
|
120
117
|
number.validate(6)
|
121
118
|
|
@@ -135,9 +132,6 @@ async def test_switch_validate(switch: Switch) -> None:
|
|
135
132
|
"""Test the switch validation."""
|
136
133
|
assert switch.validate(STATE_ON)
|
137
134
|
|
138
|
-
with pytest.raises(ValueError):
|
139
|
-
assert switch.validate(STATE_OFF)
|
140
|
-
|
141
135
|
with pytest.raises(ValueError):
|
142
136
|
switch.validate(2)
|
143
137
|
|
@@ -264,6 +258,36 @@ def test_switch_repr(switch: Switch) -> None:
|
|
264
258
|
)
|
265
259
|
|
266
260
|
|
261
|
+
@patch("asyncio.Queue.put")
|
262
|
+
async def test_number_request_with_unchanged_value(
|
263
|
+
mock_put, number: Number, bypass_asyncio_sleep, caplog
|
264
|
+
) -> None:
|
265
|
+
"""Test that a frame doesn't get dispatched if it's value is unchanged."""
|
266
|
+
assert not number.pending_update
|
267
|
+
assert not await number.set(5, retries=3)
|
268
|
+
assert number.pending_update
|
269
|
+
assert mock_put.await_count == 3 # type: ignore [unreachable]
|
270
|
+
mock_put.reset_mock()
|
271
|
+
assert "Timed out while trying to set 'test_number' parameter" in caplog.text
|
272
|
+
await number.set(5)
|
273
|
+
mock_put.assert_not_awaited()
|
274
|
+
|
275
|
+
|
276
|
+
@patch("asyncio.Queue.put")
|
277
|
+
async def test_switch_request_with_unchanged_value(
|
278
|
+
mock_put, switch: Switch, bypass_asyncio_sleep, caplog
|
279
|
+
) -> None:
|
280
|
+
"""Test that a frame doesn't get dispatched if it's value is unchanged."""
|
281
|
+
assert not switch.pending_update
|
282
|
+
assert not await switch.set(True, retries=3)
|
283
|
+
assert switch.pending_update
|
284
|
+
assert mock_put.await_count == 3 # type: ignore [unreachable]
|
285
|
+
mock_put.reset_mock()
|
286
|
+
assert "Timed out while trying to set 'test_switch' parameter" in caplog.text
|
287
|
+
await switch.set(True)
|
288
|
+
mock_put.assert_not_awaited()
|
289
|
+
|
290
|
+
|
267
291
|
@patch("pyplumio.helpers.parameter.Switch.set")
|
268
292
|
async def test_switch_turn_on(mock_set, switch: Switch) -> None:
|
269
293
|
"""Test that switch can be turned on."""
|
@@ -165,15 +165,11 @@ async def test_async_setup_error() -> None:
|
|
165
165
|
|
166
166
|
async def test_frame_versions_update(ecomax: EcoMAX) -> None:
|
167
167
|
"""Test requesting updated frames."""
|
168
|
-
assert not ecomax.has_frame_version(RegulatorDataSchemaRequest.frame_type)
|
169
168
|
test_data = load_json_test_data("messages/sensor_data.json")[0]
|
170
169
|
with patch("asyncio.Queue.put_nowait") as mock_put_nowait:
|
171
170
|
ecomax.handle_frame(SensorDataMessage(message=test_data["message"]))
|
172
171
|
await ecomax.wait_until_done()
|
173
172
|
|
174
|
-
assert not ecomax.has_frame_version(RegulatorDataSchemaRequest.frame_type, 0)
|
175
|
-
assert ecomax.has_frame_version(RegulatorDataSchemaRequest.frame_type, 45559)
|
176
|
-
|
177
173
|
mock_put_nowait.assert_has_calls(
|
178
174
|
[
|
179
175
|
call(RegulatorDataSchemaRequest(recipient=DeviceType.ECOMAX)),
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|