Skip to content

Multiple Development (v6 betas) re-joined - #361

Merged
reactive-firewall merged 6 commits into
dev-v6.0from
dev-v6-beta-re-join-316
Aug 23, 2026
Merged

Multiple Development (v6 betas) re-joined#361
reactive-firewall merged 6 commits into
dev-v6.0from
dev-v6-beta-re-join-316

Conversation

@reactive-firewall

@reactive-firewall reactive-firewall commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

Patch Notes

This patch brings the development branch another big step closer to the major v6-series release. Most notably, the major codebase refactoring for GHI-316 (modularization).

Responsibilities are separated (core scanning vs CLI parsing vs formatting), which improves maintainability and testability.

Change Summary:

  • Splits monolithic piplicenses.py into a package piplicenses with submodules:
    • core.py: package discovery, metadata extraction, file text reading
    • cli/: configuration dataclass & argparse glue, pseudo-enum helpers
    • output/: PrettyTable subclasses, table builders, consoles helpers
    • constants.py, sorting.py, tomli_bridge.py, plus __main__.py and package-level __init__.py that re-exports compatibility API.
  • Changes exit/abort behavior: many places now raise SystemExit instead of directly calling sys.exit(...).
  • Changes monkey-patching surface: the global open monkey-patch is restricted / relocated (open is provided via piplicenses.init and piplicenses.output.consoles provides an open alias).
  • Adds a Configuration dataclass to replace argparse.Namespace, with many compatibility properties and deprecation wrappers.
  • Adds many deprecation/compatibility shims (conditional on version substrings) and re-exports to reduce breakage for existing consumers/tests.
  • Adds many TODOs / comments about remaining test changes and known regressions; updates pyproject, CI and linter rules accordingly.

This version also includes these changes:

  • Align with PEP-749 and deprecated use of typing.TYPE_CHECKING conditions
  • Fixed multiple typographical errors
  • Refactored most of the codebase to be more modular
flowchart TD
  %% Single-file to package split
  A["piplicenses.py (single file)"] --> B["piplicenses/__init__.py"]
  A --> C["piplicenses/core.py"]
  A --> D["piplicenses/cli/*.py"]
  A --> E["piplicenses/output/*.py"]
  A --> F["piplicanses/ (other modules: etc.)"]

  %% Optional: make the intended package structure visually explicit
  subgraph PKG["piplicenses/ package"]
    direction TB
    B1["__init__.py"]
    C1["core.py"]
    D1["cli/ (multiple .py files)"]
    E1["output/ (multiple .py files)"]
    F1["etc. (additional modules)"]

    B1 -->|exports/API| B
    C1 -->|core logic| C
    D1 -->|command-line entrypoints| D
    E1 -->|formatters/tables| E
    F1 -->|additional code| F
  end

Loading
  • Added lots of comments about direction of API re-exports that are needed for compatibility with older versions
  • Also fixed a bunch more linter issues
  • Also cleaned up file headers a little
  • And other trivial fixes all over

Impacted GHIs:

Included & Superseded PR/MRs


Important

CI/CD Impacted by Breaking changes 🚧

CI/CD is expected to fail with these (and related) changes, because of:

  • an internal function (e.g., previously piplicenses._handle_multiple_value_field) has moved (and will not be part of a publicly exposed API, and will need to be imported directly for testing). The known fix is to append from piplicenses.output.tables import _handle_multiple_value_field to the imports in test_piplicenses.py
  • restricted effect of monkey-patching directly breaks monkey-patching in tests without a corresponding code change to focus the monkey-patches. The known fix is to refactor all monkey-patching of open (previously applied generally in piplicenses) to focus only on patching open used for writing operations selectively (namely those for file serialization, e.g. currently piplicenses.output.consoles) by replacing:
    - monkeypatch.setattr(piplicenses, "open", mocked_open)
    + monkeypatch.setattr(piplicenses.output.consoles, "open", mocked_open)
  • Early aborts now (and soon all early exits, will) raise the built-in SystemExit instead of directly calling sys.exit(...). While subtle, this change, is still known to have rendered the mocking of system exits in failure-validation testing. The known fix is to handle and even assert the SystemExit
  • due to the new Configuration data class (W.I.P.) some tests that relied on a stable order when comparing multi-value fields need to be sorted in testing to remain reproducible. Namely the known fix is to sort parsed set values when comparing to lists via the sorted Python builtin.
  • New test coverage gaps (e.g., from legacy compatibility re-exports, etc.) remain where new testing will be needed. These remain as Technical debt (for this PR) and will be explored, after the afore-mentioned known fixes are applied in the next patch, in-order to complete GHI-316.

Otherwise, this patch passes the same tests as #351 (and thus supersedes that PR).

…ile the public API is still WIP from (- WIP #316 -)

Also includes other minor improvements like normalizing the module path (e.g., pip-licenses -> piplicenses)
) and deprecated use of `typing.TYPE_CHECKING` conditions
* Also added lots of comments about direction of API re-exports that are needed for compatibility with older versions
* Also fixed a bunch more F401 lint issues
* Also reorganized a bit more
* Also cleaned up file headers a little
* And other trivial fixes all over
 * fixes for breaking-changes to tests will come later
 * This development version also contributes to GHI #81
@reactive-firewall reactive-firewall self-assigned this Aug 20, 2026
@reactive-firewall reactive-firewall added enhancement New feature or request python Pull requests that update python code PEP There is a Python Enhancement Proposal related to this minor change This is a non-breaking change that still requires a version bump labels Aug 20, 2026
@reactive-firewall
reactive-firewall marked this pull request as ready for review August 20, 2026 05:23
@reactive-firewall reactive-firewall added breaking change ⚠️ This change in not something that just goes unnoticed and requires a major version bump and removed minor change This is a non-breaking change that still requires a version bump labels Aug 20, 2026

@reactive-firewall reactive-firewall left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

👍 LGTM;

Note

with caveat: I am the project owner/admin and was this PR's author and I self-reviewed.

Additional Comments: see many in-line comments for more details.

Comment thread piplicenses/cli/config.py
Comment thread piplicenses/cli/config.py
_ignore_packages_map,
):
if _pre_processed_name in _mapping:
if not "6.0" in __version__:

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🧹 NIT: This will need to be removed as "always true" in the future.

⚠️ Breaking changes:

Comment thread piplicenses/cli/config.py
Comment on lines +325 to +341
booleans = {
"summary",
"with_system",
"with_authors",
"with_maintainers",
"with_urls",
"with_description",
"with_license_files",
"with_notice_file",
"with_notice_files",
"with_other_files",
"without_license_paths",
"without_file_paths",
"filter_strings",
"partial_match",
"without_version",
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🧹 NIT: consider further modularizing this to an internal function for future extensibility

e.g.

def _get_canonical_boolean_feilds(self) -> set[str]:
    return {
        "summary",
        "with_system",
        "with_authors",
        "with_maintainers",
        "with_urls",
        "with_description",
        "with_license_files",
        "with_notice_file",
        "with_notice_files",
        "with_other_files",
        "without_license_paths",
        "without_file_paths",
        "filter_strings",
        "partial_match",
        "without_version",
    }
Suggested change
booleans = {
"summary",
"with_system",
"with_authors",
"with_maintainers",
"with_urls",
"with_description",
"with_license_files",
"with_notice_file",
"with_notice_files",
"with_other_files",
"without_license_paths",
"without_file_paths",
"filter_strings",
"partial_match",
"without_version",
}
booleans = self._get_canonical_boolean_feilds()

Comment thread piplicenses/cli/config.py
"partial_match",
"without_version",
}
sets = {"ignore_packages", "packages"}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🧹 NIT: Similarly consider further modularizing this to an internal function for future extensibility

e.g.

def _get_canonical_multi_feilds(self) -> set[str]:
    return {
        "ignore_packages",
        "packages",
        # etc.
    }
Suggested change
sets = {"ignore_packages", "packages"}
sets = self._get_canonical_multi_feilds()

Comment thread piplicenses/cli/config.py
def packages_set(self, value: Union[Iterable[str], None]) -> None:
self.packages = self._normalize_to_set(value)

if "6.1" in __version__:

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🧹 NIT: This will need to be removed as "always true" in the future.

⚠️ Breaking changes:

Comment thread piplicenses/constants.py
Comment on lines 199 to 200
# TODO: [GHI-394](https://github.com/raimon49/pip-licenses/issues/349)
LICENSE_BY_OTHER_FILE_PATTERN = r"[Aa][Uu][Tt][Hh][Oo][Rr][Ss].*|[Cc][Oo][Pp][Yy][Ii][Nn][Gg].*|[Ll][Ee][Gg][Aa][Ll].*"

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

⚠️ Breaking changes:

Comment thread piplicenses/core.py
Comment on lines 428 to 433
"licensefile": legacy_info["license_file"], # DEPRECIATED in v6.0+
"licensetext": legacy_info["license_text"], # DEPRECIATED in v6.0+
"noticefile": legacy_info["notice_file"], # DEPRECIATED in v6.0+
"noticetext": legacy_info["notice_text"], # DEPRECIATED in v6.0+
"otherfile": legacy_info["author_file"], # DEPRECIATED in v6.0+
"othertext": legacy_info["author_text"], # DEPRECIATED in v6.0+

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

⚠️ Breaking changes:

Comment thread piplicenses/core.py
FILE_MISSING = ""
return {
"license_file": license_file or LICENSE_UNKNOWN,
"license_file": license_file or FILE_MISSING,

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

⚠️ Breaking changes:

Comment thread CHANGELOG.md
(SUBJECT TO CHANGE IN NEXT RELEASE)

#### From ALPHA (already backported)
* Align with [PEP-749](https://peps.python.org/pep-0749) and deprecated use of `typing.TYPE_CHECKING` conditions

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

⚠️ Breaking changes:

Comment thread CHANGELOG.md
* Align with [PEP-749](https://peps.python.org/pep-0749) and deprecated use of `typing.TYPE_CHECKING` conditions
* Fixed multiple typographical errors
* Refactored most of the codebase to be more modular (WIP GHI #316)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

This is missing a lot of change details still

@reactive-firewall
reactive-firewall merged commit becf943 into dev-v6.0 Aug 23, 2026
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking change ⚠️ This change in not something that just goes unnoticed and requires a major version bump enhancement New feature or request PEP There is a Python Enhancement Proposal related to this python Pull requests that update python code

Projects

None yet

1 participant