Skip to content
Open
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
1 change: 0 additions & 1 deletion src/packageurl/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,6 @@ def normalize_name(
"composer",
"luarocks",
"oci",
"npm",
"alpm",
"apk",
"bitnami",
Expand Down
4 changes: 2 additions & 2 deletions src/packageurl/validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -585,8 +585,8 @@ class NpmTypeDefinition(BasePurlType):
default_repository_url = "https://registry.npmjs.org/"
namespace_requirement = "optional"
allowed_qualifiers = {"repository_url"}
namespace_case_sensitive = False
name_case_sensitive = False
namespace_case_sensitive = True
name_case_sensitive = True
version_case_sensitive = True
purl_pattern = "pkg:npm/.*"

Expand Down
19 changes: 19 additions & 0 deletions tests/test_packageurl.py
Original file line number Diff line number Diff line change
Expand Up @@ -388,3 +388,22 @@ def test_no_encoding_to_string():
p.to_string(encode=False)
== "pkg:nuget/an:odd:space/libiconv: character set conversion library@1.9?package-id=e11a609df352e292"
)


def test_npm_name_case_is_preserved_on_parse():
purl = PackageURL.from_string("pkg:npm/Orchestrator@1.0.0")
assert purl.name == "Orchestrator"
assert purl.to_string() == "pkg:npm/Orchestrator@1.0.0"


def test_npm_scoped_name_case_is_preserved_on_parse():
purl = PackageURL.from_string("pkg:npm/%40Scope/MyPackage@1.0.0")
assert purl.namespace == "@Scope"
assert purl.name == "MyPackage"
assert purl.to_string() == "pkg:npm/%40Scope/MyPackage@1.0.0"


def test_npm_uppercase_name_has_no_case_warning():
messages = PackageURL.validate_string(purl="pkg:npm/MyPackage@1.0.0", strict=True)
case_warnings = [m for m in messages if "lowercased" in m.message]
assert not case_warnings
5 changes: 5 additions & 0 deletions tests/test_purl_spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,11 @@ def run_test_case(case: PurlTestCase):
test_group = case.test_group
if test_group not in ("base", "advanced"):
raise Exception(test_group)
if test_group == "base" and case.description == "npm package with uppercase name":
# The pinned spec test data still expects npm names to be
# lowercased, but npm names are case-sensitive now.
# Drop this once the spec submodule is bumped.
pytest.xfail("stale pinned spec expectation: npm names are case-sensitive")
strict = test_group == "base"
messages = PackageURL.validate_string(purl=case.input, strict=strict)
messages = [message.to_dict() for message in messages]
Expand Down