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
5 changes: 4 additions & 1 deletion cyclonedx_py/_internal/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
from . import BomBuilder, PropertyName, PurlTypePypi
from .cli_common import add_argument_mc_type, add_argument_pyproject
from .utils.cdx import licenses_fixup, make_bom
from .utils.packaging import metadata2extrefs, metadata2licenses, normalize_packagename
from .utils.packaging import metadata2extrefs, metadata2licenses, metadata2tags, normalize_packagename
from .utils.pep610 import PackageSourceArchive, PackageSourceVcs, packagesource2extref, packagesource4dist
from .utils.pep639 import dist2licenses_from_files as pep639_dist2licenses_from_files
from .utils.pyproject import pyproject2component, pyproject2dependencies, pyproject_load
Expand Down Expand Up @@ -185,6 +185,9 @@ def __add_components(self, bom: 'Bom',
# path of dist-package on disc? naaa... a package may have multiple files/folders on disc
)

if hasattr(component, 'tags'):
component.tags.update(metadata2tags(dist_meta))

# region licenses
component.licenses.update(metadata2licenses(dist_meta, LicenseFactory(),
gather_texts=self._gather_license_texts))
Expand Down
4 changes: 3 additions & 1 deletion cyclonedx_py/_internal/pipenv.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
from .cli_common import add_argument_mc_type, add_argument_pyproject
from .utils.args import arparse_split
from .utils.cdx import make_bom
from .utils.packaging import normalize_packagename
from .utils.packaging import normalize_packagename, to_tags
Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The imported function to_tags does not exist in utils.packaging. The actual function defined in that module is metadata2tags. This will cause an ImportError at runtime.

Suggested change
from .utils.packaging import normalize_packagename, to_tags
from .utils.packaging import normalize_packagename, metadata2tags

Copilot uses AI. Check for mistakes.
from .utils.pyproject import pyproject_file2component
from .utils.secret import redact_auth_from_url

Expand Down Expand Up @@ -175,6 +175,8 @@ def _make_bom(self, root_c: Optional['Component'],
version=package_data['version'][2:] if 'version' in package_data else None,
external_references=self.__make_extrefs(package_name, package_data, source_urls),
)
if hasattr(component, 'tags'):
component.tags.update(to_tags(package_data.get('keywords')))
Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function to_tags does not exist. Based on the implementation in utils/packaging.py, this should call metadata2tags. However, metadata2tags expects a PackageMetadata object, not a raw keywords value. A separate function needs to be created that accepts keywords as a string or list, or this code needs to be adjusted to match the actual function signature.

Copilot uses AI. Check for mistakes.
component.purl = PackageURL(
type=PurlTypePypi,
name=component.name,
Expand Down
10 changes: 8 additions & 2 deletions cyclonedx_py/_internal/poetry.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
from . import BomBuilder, PropertyName, PurlTypePypi
from .cli_common import add_argument_mc_type
from .utils.cdx import make_bom
from .utils.packaging import normalize_packagename
from .utils.packaging import normalize_packagename, to_tags
Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The imported function to_tags does not exist in utils.packaging. The actual function defined in that module is metadata2tags. This will cause an ImportError at runtime.

Suggested change
from .utils.packaging import normalize_packagename, to_tags
from .utils.packaging import normalize_packagename, metadata2tags

Copilot uses AI. Check for mistakes.
from .utils.poetry import poetry2component
from .utils.secret import redact_auth_from_url
from .utils.toml import toml_loads
Expand Down Expand Up @@ -404,7 +404,7 @@ def __make_component4lock(self, package: 'T_NameDict') -> 'Component':
is_vcs = source.get('type') in self.__PACKAGE_SRC_VCS
is_local = source.get('type') in self.__PACKAGE_SRC_LOCAL

return Component(
component = Component(
bom_ref=f'{package["name"]}@{package["version"]}',
name=package['name'],
version=package.get('version'),
Expand Down Expand Up @@ -433,6 +433,12 @@ def __make_component4lock(self, package: 'T_NameDict') -> 'Component':
) if not is_local else None
)

if hasattr(component, 'tags'):
component.tags.update(to_tags(package.get('keywords')))
Copy link

Copilot AI Nov 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function to_tags does not exist. Based on the implementation in utils/packaging.py, this should call metadata2tags. However, metadata2tags expects a PackageMetadata object, not a raw keywords value. A separate function needs to be created that accepts keywords as a string or list, or this code needs to be adjusted to match the actual function signature.

Copilot uses AI. Check for mistakes.
self._logger.debug('component created: %r', component)

return component

def __purl_qualifiers4lock(self, package: 'T_NameDict') -> 'T_NameDict':
# see https://github.com/package-url/purl-spec/blob/master/PURL-SPECIFICATION.rst
qs = {}
Expand Down
16 changes: 16 additions & 0 deletions cyclonedx_py/_internal/utils/packaging.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,22 @@
from ..py_interop.packagemetadata import PackageMetadata


_KEYWORDS_SPLIT_MATCHER = re_compile(r'[;, ]+')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's discuss: why did you use a regular expression, instead of just splitting on comma(,)?
(I am not saying you are wrong,I just dont understand the solution, as I might not know all the details.)



def metadata2tags(metadata: 'PackageMetadata') -> Generator[str, None, None]:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"""
Generate tags from metadata keywords.
"""
keywords_string = metadata.get('Keywords', '')
if keywords_string:
yield from (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can this me simplified?
pseudo code:

filter(None, map(str.strip, 
  _KEYWORDS_SPLIT_MATCHER.split(keywords_string)
))

tag
for tag in (s.strip() for s in _KEYWORDS_SPLIT_MATCHER.split(keywords_string))
if tag
)


def metadata2licenses(metadata: 'PackageMetadata', lfac: 'LicenseFactory',
gather_texts: bool
) -> Generator['License', None, None]:
Expand Down
Loading