Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/specify_cli/presets/_manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ def _validate(self):
# Validate preset metadata
pack = self.data["preset"]
# Check presence AND type: the format/version checks below feed these
# values straight to ``re.match`` and ``packaging.Version``, both of
# values straight to ``re.fullmatch`` and ``packaging.Version``, both of
# which raise a bare TypeError on a non-string. YAML makes that an easy
# authoring slip -- unquoted ``version: 1.0`` parses as a float and
# ``id: 2`` as an int -- and TypeError is not a PresetValidationError,
Expand All @@ -117,7 +117,7 @@ def _validate(self):
)

# Validate pack ID format
if not re.match(r'^[a-z0-9-]+$', pack["id"]):
if not re.fullmatch(r'[a-z0-9-]+', pack["id"]):
raise PresetValidationError(
f"Invalid preset ID '{pack['id']}': "
"must be lowercase alphanumeric with hyphens only"
Expand Down
18 changes: 16 additions & 2 deletions tests/specify_cli/presets/test_manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,15 +199,29 @@ def test_missing_pack_id(self, temp_dir, valid_pack_data):
with pytest.raises(PresetValidationError, match="Missing preset.id"):
PresetManifest(manifest_path)

def test_invalid_pack_id_format(self, temp_dir, valid_pack_data):
@pytest.mark.parametrize(
"pack_id",
["Invalid_ID", "", "test-pack\n", "test-pack\r\n", "test\npack",
" test-pack", "test-pack ", "../test-pack", "test/pack"],
)
def test_invalid_pack_id_format(self, temp_dir, valid_pack_data, pack_id):
"""Test invalid pack ID format."""
valid_pack_data["preset"]["id"] = "Invalid_ID"
valid_pack_data["preset"]["id"] = pack_id
manifest_path = temp_dir / "preset.yml"
with open(manifest_path, 'w') as f:
yaml.dump(valid_pack_data, f)
with pytest.raises(PresetValidationError, match="Invalid preset ID"):
PresetManifest(manifest_path)

@pytest.mark.parametrize("pack_id", ["test-pack", "preset123", "123", "a"])
def test_valid_pack_id_format(self, temp_dir, valid_pack_data, pack_id):
"""Accept IDs containing only lowercase letters, digits, and hyphens."""
valid_pack_data["preset"]["id"] = pack_id
manifest_path = temp_dir / "preset.yml"
manifest_path.write_text(yaml.safe_dump(valid_pack_data), encoding="utf-8")

assert PresetManifest(manifest_path).id == pack_id

def test_invalid_version(self, temp_dir, valid_pack_data):
"""Test invalid semantic version."""
valid_pack_data["preset"]["version"] = "not-a-version"
Expand Down
Loading