Skip to content

Commit 75d540b

Browse files
committed
fix: bug in parsing services name
1 parent bf43625 commit 75d540b

3 files changed

Lines changed: 92 additions & 52 deletions

File tree

tests/updater/__init__.py

Whitespace-only changes.

tests/updater/test_components_unit.py

Lines changed: 91 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,27 @@
1-
"""Unit tests for updater.components """
1+
"""Unit tests for updater.components"""
2+
23
import logging
3-
import pytest
4+
from os.path import commonpath
45
from pathlib import Path
56
from unittest.mock import patch, mock_open
67

7-
from updater.components import (
8-
ComponentConfig, ComponentStatus, load_components
9-
)
8+
from updater.components import load_components
109

1110
BUNDLE_YAML = """
12-
pool_internal_minutes: 30
11+
poll_interval_minutes: 1440
1312
components:
1413
- name: klipper
15-
- type: git
16-
- path: ~/klipper
17-
- service: klipper.service
18-
- reset_mode: hard
19-
- order: 1
20-
- name: BlocksScreen
21-
- type: git
22-
- path: ~/BlocksScreen
23-
- service: BlocksScreen.service
24-
- reset_mode: hard
25-
- order: 99
14+
type: git
15+
path: ~/klipper
16+
service: klipper.service
17+
reset_mode: hard
18+
order: 1
19+
- name: blockscreen
20+
type: git
21+
path: ~/BlocksScreen
22+
service: BlocksScreen.service
23+
reset_mode: hard
24+
order: 99
2625
"""
2726

2827
OVERRIDE_YAML = """
@@ -37,53 +36,83 @@
3736
order: 5
3837
"""
3938

39+
4040
def _mock_load(bundled: str, override: str | None = None):
4141
import updater.components as mod
42+
4243
bundled_path = Path(mod.__file__).parent / "components.yaml"
4344

4445
def fake_open(path, *a, **kw):
4546
if Path(path) == bundled_path:
4647
return mock_open(read_data=bundled)()
4748
if override is not None:
4849
return mock_open(read_data=override)()
49-
raise FileNotFoundError(Path)
50+
raise FileNotFoundError(path)
51+
5052
return fake_open
5153

5254

5355
class TestLoadComponents:
5456
def test_load_return_sorted_by_order(self):
55-
with patch("builtins.open", _mock_load(BUNDLE_YAML)), patch("pathlib.Path.exists", return_value=False), patch("pathlib.Path.is_dir", return_value=True):
56-
components = load_components()
57+
with (
58+
patch("builtins.open", _mock_load(BUNDLE_YAML)),
59+
patch("pathlib.Path.exists", return_value=False),
60+
patch("pathlib.Path.is_dir", return_value=True),
61+
):
62+
components = load_components()
5763
names = [c.name for c in components]
58-
assert names.index("klipper") < names.index("BlocksScreen")
59-
64+
assert names.index("klipper") < names.index("blockscreen")
65+
6066
def test_missing_override_file_silently_ignored(self):
61-
with patch("builtins.open", _mock_load(BUNDLE_YAML)), patch("pathlib.Path.exists", return_value=False), patch("pathlib.Path.is_dir", return_value=True):
67+
with (
68+
patch("builtins.open", _mock_load(BUNDLE_YAML)),
69+
patch("pathlib.Path.exists", return_value=False),
70+
patch("pathlib.Path.is_dir", return_value=True),
71+
):
6272
components = load_components()
6373
assert len(components) >= 2
6474

75+
6576
class TestYamlMerge:
66-
def test_ovvrides_path_by_name(self):
67-
with patch("builtins.open", _mock_load(BUNDLE_YAML)), patch("pathlib.Path.exists", return_value=True), patch("pathlib.Path.is_dir", return_value=True):
77+
def test_overrides_path_by_name(self):
78+
with (
79+
patch("builtins.open", _mock_load(BUNDLE_YAML, OVERRIDE_YAML)),
80+
patch("pathlib.Path.exists", return_value=True),
81+
patch("pathlib.Path.is_dir", return_value=True),
82+
):
6883
components = load_components()
6984
klipper = next(c for c in components if c.name == "klipper")
7085
assert str(klipper.path).endswith("costum_klipper")
7186
assert klipper.service == "klipper.service"
7287

73-
def test_appends_new_componentself(self):
74-
with patch("builtins.open", _mock_load(BUNDLE_YAML, OVERRIDE_YAML)), patch("pathlib.Path.exists", return_value=True), patch("pathlib.Path.is_dir", return_value=True):
88+
def test_appends_new_component(self):
89+
with (
90+
patch("builtins.open", _mock_load(BUNDLE_YAML, OVERRIDE_YAML)),
91+
patch("pathlib.Path.exists", return_value=True),
92+
patch("pathlib.Path.is_dir", return_value=True),
93+
):
7594
components = load_components()
7695
assert any(c.name == "my-plugin" for c in components)
96+
7797
def test_keeps_bundled_fields_not_in_override(self):
78-
with patch("builtins.open", _mock_load(BUNDLE_YAML, OVERRIDE_YAML)), patch("pathlib.Path.exists", return_value=True), patch("pathlib.Path.is_dir", return_value=True):
98+
with (
99+
patch("builtins.open", _mock_load(BUNDLE_YAML, OVERRIDE_YAML)),
100+
patch("pathlib.Path.exists", return_value=True),
101+
patch("pathlib.Path.is_dir", return_value=True),
102+
):
79103
components = load_components()
80104
klipper = next(c for c in components if c.name == "klipper")
81-
assert klipper.type == "git"
105+
assert klipper.kind == "git"
82106
assert klipper.reset_mode == "hard"
83107

84108
def test_syntax_error_falls_back_to_bundled(self, caplog):
85-
with patch("builtins.open", _mock_load(BUNDLE_YAML, OVERRIDE_YAML)), patch("pathlib.Path.exists", return_value=True), patch("pathlib.Path.is_dir", return_value=True), \
86-
caplog.at_level(logging.ERROR, logger="updater.components"):
109+
invalid_yaml = "key: [unclosed"
110+
with (
111+
patch("builtins.open", _mock_load(BUNDLE_YAML, invalid_yaml)),
112+
patch("pathlib.Path.exists", return_value=True),
113+
patch("pathlib.Path.is_dir", return_value=True),
114+
caplog.at_level(logging.ERROR, logger="updater.components"),
115+
):
87116
components = load_components()
88117
names = [c.name for c in components]
89118
assert "klipper" in names
@@ -100,9 +129,11 @@ def test_invalid_component_skipped_with_warning(self, caplog):
100129
service: bad.service
101130
order: 10
102131
"""
103-
with patch("builtins.open", _mock_load(bad_yaml)), \
104-
patch("pathlib.Path.exists", return_value=True), \
105-
caplog.at_level(logging.WARNING, logger="updater.components"):
132+
with (
133+
patch("builtins.open", _mock_load(bad_yaml)),
134+
patch("pathlib.Path.exists", return_value=True),
135+
caplog.at_level(logging.WARNING, logger="updater.components"),
136+
):
106137
components = load_components()
107138
assert not any(c.name == "bad" for c in components)
108139
assert any("bad" in r.message for r in caplog.records)
@@ -116,8 +147,10 @@ def test_path_outside_home_rejected(self):
116147
service: outside.service
117148
order: 10
118149
"""
119-
with patch("builtins.open", _mock_load(outside_yaml)), \
120-
patch("pathlib.Path.exists", return_value=False):
150+
with (
151+
patch("builtins.open", _mock_load(outside_yaml)),
152+
patch("pathlib.Path.exists", return_value=False),
153+
):
121154
components = load_components()
122155
assert not any(c.name == "outside" for c in components)
123156

@@ -130,25 +163,31 @@ def test_service_name_with_slash_rejected(self):
130163
service: ../bad.service
131164
order: 10
132165
"""
133-
with patch("builtins.open", _mock_load(bad_yaml)), \
134-
patch("pathlib.Path.exists", return_value=False):
166+
with (
167+
patch("builtins.open", _mock_load(bad_yaml)),
168+
patch("pathlib.Path.exists", return_value=False),
169+
):
135170
components = load_components()
136-
assert not any(c.name == "evil" for c in components)
171+
assert not any(c.name == "bad" for c in components)
137172

138173
def test_service_name_with_shell_metachar_rejected(self):
139174
for metachar in [";", "&", "|", "$", "`"]:
140175
bad_yaml = f"""
141176
components:
142-
- name: bad
143-
type: git
144-
path: ~/bad
145-
service: bad{metachar}cmd.service
146-
order: 10
177+
- name: bad
178+
type: git
179+
path: ~/bad
180+
service: bad{metachar}cmd.service
181+
order: 10
147182
"""
148-
with patch("builtins.open", _mock_load(bad_yaml)), \
149-
patch("pathlib.Path.exists", return_value=False):
183+
with (
184+
patch("builtins.open", _mock_load(bad_yaml)),
185+
patch("pathlib.Path.exists", return_value=False),
186+
):
150187
components = load_components()
151-
assert not any(c.name == "bad" for c in components), f"metachar {metachar!r} not rejected"
188+
assert not any(c.name == "bad" for c in components), (
189+
f"metachar {metachar!r} not rejected"
190+
)
152191

153192
def test_service_name_valid_pattern_accepted(self):
154193
good_yaml = """
@@ -159,9 +198,10 @@ def test_service_name_valid_pattern_accepted(self):
159198
service: my-plugin.service
160199
order: 5
161200
"""
162-
with patch("builtins.open", _mock_load(good_yaml)), \
163-
patch("pathlib.Path.exists", return_value=False), \
164-
patch("pathlib.Path.is_dir", return_value=True):
201+
with (
202+
patch("builtins.open", _mock_load(good_yaml)),
203+
patch("pathlib.Path.exists", return_value=False),
204+
patch("pathlib.Path.is_dir", return_value=True),
205+
):
165206
components = load_components()
166207
assert any(c.name == "my-plugin" for c in components)
167-

updater/components.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
logger = logging.getLogger(__name__)
1414

1515
_SERVICE_RE = re.compile(r"^[a-zA-Z0-9@:._-]+\.service$")
16-
_SERVICE_BANNED = set("/\\..;&|$`") | {" ", "\t"}
16+
_SERVICE_BANNED = set("/\\;&|$`") | {" ", "\t"}
1717

1818
OVERRIDE_PATH = Path("~/printer_data/config/blockscreen_updater.yaml").expanduser()
1919

0 commit comments

Comments
 (0)