Skip to content

refactor: decompose bom_lib monolith into modular package#54

Merged
JacksonFergusonDev merged 14 commits intomainfrom
refactor
Feb 4, 2026
Merged

refactor: decompose bom_lib monolith into modular package#54
JacksonFergusonDev merged 14 commits intomainfrom
refactor

Conversation

@JacksonFergusonDev
Copy link
Owner

🎯 Objective

This PR executes a major architectural refactor, transitioning the monolithic bom_lib.py into a formal Python package. This move resolves the "God Module" anti-pattern, improves cognitive load for future maintenance, and strictly enforces the Single Responsibility Principle (SRP) across our parsing and sourcing logic.

🛠️ Changes

📦 Core Library (src/bom_lib/)

  • __init__.py: Established as a Facade to the library, utilizing __all__ to define a clean public API.
  • types.py: Centralized all TypedDict and type aliases to prevent circular imports.
  • utils.py: Isolated pure string manipulation and SI unit parsing logic.
  • parser.py: Encapsulated PDF, CSV, and raw text ingestion strategies.
  • classifier.py: Segregated component classification heuristics and value normalization.
  • sourcing.py: Domain-specific logic for "Nerd Economics," purchase buffering, and hardware injection.
  • manager.py: High-level inventory orchestration, including sorting and the newly modularized serialize_inventory.

📂 Relocated Assets

  • Moved constants.py and presets.py into the bom_lib package to keep domain data proximal to the logic that consumes it.

🧪 Quality Assurance

  • tests/test_package.py: Added a new test suite to verify acyclic imports and package integrity.
  • Updated tests/test_parser.py and tests/test_app.py to align with the new import hierarchy.

🔧 Tooling & Integration

  • tools/generate_presets.py: Refactored to utilize the library's serialization logic and updated output paths for the relocated presets.py.
  • app.py: Updated all import references to the new package structure.

🧪 Verification Results

  • Pytest: PASS (All regression and new package integrity tests).
  • Mypy: SUCCESS (Strict type checking passed with no implicit optionals).
  • Ruff: CLEAN (All F401 unused imports resolved via explicit re-exports/__all__).

Updates imports to reference specific submodules (utils, sourcing)
for internal functions that are not exposed in the top-level package API.
Updates presets import path.
Points test imports to src.bom_lib.presets.
Updates import paths for constants and presets to point to the new
src.bom_lib location.
Moves file ingestion strategies (PDF, CSV, text) to src/bom_lib/parser.py.
Handles the complexity of reading different BOM formats and orchestrating
the line-by-line ingestion process. Includes MyPy type-hint fixes for
optional arguments.
Moves inventory management functions (sorting, calculating net needs,
recording parts) to src/bom_lib/manager.py. This serves as the
controller layer for inventory manipulation.
Moves sourcing-specific logic (purchase calculations, search term
generation, and hardware injection) to src/bom_lib/sourcing.py.
This decouples the "Nerd Economics" of buying parts from the parsing
and classification logic.
Moves categorize_part and normalize_value_by_category to
src/bom_lib/classifier.py. The heuristic rules for identifying
components and injecting sockets are now isolated from the parsing
and sourcing logic.
Moves string parsing and formatting logic (natural_sort_key, expand_refs,
float parsing) to src/bom_lib/utils.py. Includes full Google-style
docstrings and dependency updates for constants.
Moves StatsDict, PartData, InventoryType, and the inventory factory
function into src/bom_lib/types.py. This resolves circular import
issues and centralizes data structure definitions.
Deletes the legacy src/bom_lib.py file as its functionality has been fully
distributed into the src/bom_lib/ package.

Moves src/constants.py and src/presets.py into src/bom_lib/ to centralize
all domain logic, configuration, and static data within the package.
…n logic

Moves the `serialize_inventory` logic from the standalone tools script into
`src/bom_lib/manager.py` and exposes it via `__init__.py`. This makes the
text serialization logic available to the main application for future export features.

Updates `tools/generate_presets.py` to:
1. Import `serialize_inventory` from the library rather than defining it inline.
2. Output the generated file to the new location: `src/bom_lib/presets.py`.
Introduces a package-level test to ensure the dependency graph of the
new bom_lib structure remains acyclic. Verifies that the __init__.py
properly initializes and exposes the intended public API.
@JacksonFergusonDev JacksonFergusonDev merged commit 84eaa04 into main Feb 4, 2026
1 check passed
@JacksonFergusonDev JacksonFergusonDev deleted the refactor branch February 4, 2026 01:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant