docorient 0.3.1__tar.gz → 0.3.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. docorient-0.3.2/CHANGELOG.md +44 -0
  2. {docorient-0.3.1 → docorient-0.3.2}/PKG-INFO +5 -4
  3. {docorient-0.3.1 → docorient-0.3.2}/docs/architecture.md +52 -19
  4. {docorient-0.3.1 → docorient-0.3.2}/docs/contributing.md +1 -2
  5. {docorient-0.3.1 → docorient-0.3.2}/pyproject.toml +5 -4
  6. docorient-0.3.2/src/docorient/_version.py +1 -0
  7. docorient-0.3.1/CHANGELOG.md +0 -22
  8. docorient-0.3.1/src/docorient/_version.py +0 -1
  9. {docorient-0.3.1 → docorient-0.3.2}/.github/workflows/publish.yml +0 -0
  10. {docorient-0.3.1 → docorient-0.3.2}/.gitignore +0 -0
  11. {docorient-0.3.1 → docorient-0.3.2}/LICENSE +0 -0
  12. {docorient-0.3.1 → docorient-0.3.2}/README.md +0 -0
  13. {docorient-0.3.1 → docorient-0.3.2}/src/docorient/__init__.py +0 -0
  14. {docorient-0.3.1 → docorient-0.3.2}/src/docorient/_imaging.py +0 -0
  15. {docorient-0.3.1 → docorient-0.3.2}/src/docorient/batch/__init__.py +0 -0
  16. {docorient-0.3.1 → docorient-0.3.2}/src/docorient/batch/processor.py +0 -0
  17. {docorient-0.3.1 → docorient-0.3.2}/src/docorient/batch/scanner.py +0 -0
  18. {docorient-0.3.1 → docorient-0.3.2}/src/docorient/batch/worker.py +0 -0
  19. {docorient-0.3.1 → docorient-0.3.2}/src/docorient/cli.py +0 -0
  20. {docorient-0.3.1 → docorient-0.3.2}/src/docorient/config.py +0 -0
  21. {docorient-0.3.1 → docorient-0.3.2}/src/docorient/correction.py +0 -0
  22. {docorient-0.3.1 → docorient-0.3.2}/src/docorient/detection/__init__.py +0 -0
  23. {docorient-0.3.1 → docorient-0.3.2}/src/docorient/detection/base.py +0 -0
  24. {docorient-0.3.1 → docorient-0.3.2}/src/docorient/detection/engine.py +0 -0
  25. {docorient-0.3.1 → docorient-0.3.2}/src/docorient/detection/primary.py +0 -0
  26. {docorient-0.3.1 → docorient-0.3.2}/src/docorient/detection/secondary.py +0 -0
  27. {docorient-0.3.1 → docorient-0.3.2}/src/docorient/exceptions.py +0 -0
  28. {docorient-0.3.1 → docorient-0.3.2}/src/docorient/rotation.py +0 -0
  29. {docorient-0.3.1 → docorient-0.3.2}/src/docorient/types.py +0 -0
  30. {docorient-0.3.1 → docorient-0.3.2}/src/docorient/voting.py +0 -0
  31. {docorient-0.3.1 → docorient-0.3.2}/tests/__init__.py +0 -0
  32. {docorient-0.3.1 → docorient-0.3.2}/tests/conftest.py +0 -0
  33. {docorient-0.3.1 → docorient-0.3.2}/tests/test_batch.py +0 -0
  34. {docorient-0.3.1 → docorient-0.3.2}/tests/test_cli.py +0 -0
  35. {docorient-0.3.1 → docorient-0.3.2}/tests/test_correction.py +0 -0
  36. {docorient-0.3.1 → docorient-0.3.2}/tests/test_detection.py +0 -0
@@ -0,0 +1,44 @@
1
+ # Changelog
2
+
3
+ ## 0.3.2 (2026-02-27)
4
+
5
+ - Fix: update project URLs to correct GitHub repository
6
+ - Add changelog link to PyPI metadata
7
+
8
+ ## 0.3.1 (2026-02-27)
9
+
10
+ - Fix: author metadata corrected to Lucas Gabriel Vaz
11
+ - Remove `tesseract` from PyPI keywords
12
+
13
+ ## 0.3.0 (2026-02-27)
14
+
15
+ - **Breaking:** detection engines refactored to class-based architecture with `DetectionEngine` Protocol
16
+ - Introduce `DetectionPipeline` for extensible engine orchestration
17
+ - Introduce `PrimaryEngine` and `SecondaryEngine` classes
18
+ - Extract `rotation.py` and `voting.py` as standalone modules
19
+ - Encapsulate worker state in `WorkerContext` dataclass
20
+ - Transform `_imaging.py` functions into `ImageIO` class
21
+ - Decompose `process_directory` into focused sub-functions
22
+ - Apply custom exceptions (`DetectionError`, `CorrectionError`, `BatchProcessingError`) throughout codebase
23
+ - Export `DetectionEngine`, `DetectionPipeline`, `PrimaryEngine`, `SecondaryEngine` in public API
24
+
25
+ ## 0.2.0 (2026-02-26)
26
+
27
+ - **Breaking:** renamed config params `osd_confidence_threshold` → `secondary_confidence_threshold`, `max_osd_dimension` → `secondary_max_dimension`, `projection_target_dimension` → `primary_max_dimension`
28
+ - **Breaking:** renamed CLI flag `--no-ocr` → `--no-secondary`
29
+ - Internal engines renamed to `primary` and `secondary`
30
+ - Updated `OrientationResult.method` trace strings
31
+
32
+ ## 0.1.1 (2026-02-26)
33
+
34
+ - Docs: added `if __name__ == "__main__":` note for `process_directory` on macOS/Windows
35
+
36
+ ## 0.1.0 (2026-02-25)
37
+
38
+ - Initial release
39
+ - Primary engine for 90°/270° detection
40
+ - Optional secondary engine for 180° detection
41
+ - Single image and batch directory processing
42
+ - Multi-page majority voting
43
+ - Resumable batch processing
44
+ - CLI interface
@@ -1,10 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: docorient
3
- Version: 0.3.1
3
+ Version: 0.3.2
4
4
  Summary: Document image orientation detection and correction.
5
- Project-URL: Homepage, https://github.com/cebraspe-lab/docorient
6
- Project-URL: Repository, https://github.com/cebraspe-lab/docorient
7
- Project-URL: Issues, https://github.com/cebraspe-lab/docorient/issues
5
+ Project-URL: Homepage, https://github.com/lucasleirbag/DocOrient
6
+ Project-URL: Repository, https://github.com/lucasleirbag/DocOrient
7
+ Project-URL: Issues, https://github.com/lucasleirbag/DocOrient/issues
8
+ Project-URL: Changelog, https://github.com/lucasleirbag/DocOrient/blob/main/CHANGELOG.md
8
9
  Author: Lucas Gabriel Vaz
9
10
  License-Expression: MIT
10
11
  License-File: LICENSE
@@ -6,21 +6,24 @@
6
6
  src/docorient/
7
7
  ├── __init__.py Public API re-exports
8
8
  ├── _version.py Version string
9
- ├── _imaging.py Internal image utilities
9
+ ├── _imaging.py ImageIO class for image operations
10
10
  ├── config.py OrientationConfig dataclass
11
11
  ├── types.py Result dataclasses
12
12
  ├── exceptions.py Exception hierarchy
13
+ ├── rotation.py Image rotation utility
14
+ ├── voting.py Majority voting logic
13
15
  ├── correction.py correct_image, correct_document_pages
14
16
  ├── cli.py CLI entry point
15
17
  ├── detection/
16
- │ ├── __init__.py Re-exports detect_orientation
17
- │ ├── engine.py Detection orchestrator
18
- │ ├── primary.py Primary detection engine (90°/270°)
19
- └── secondary.py Secondary detection engine (180°)
18
+ │ ├── __init__.py Re-exports detection API
19
+ │ ├── base.py DetectionEngine Protocol
20
+ │ ├── engine.py DetectionPipeline orchestrator
21
+ ├── primary.py PrimaryEngine (90°/270°)
22
+ │ └── secondary.py SecondaryEngine (180°)
20
23
  └── batch/
21
24
  ├── __init__.py Re-exports process_directory
22
25
  ├── scanner.py Directory scanning and grouping
23
- ├── worker.py Multiprocessing worker logic
26
+ ├── worker.py WorkerContext and multiprocessing logic
24
27
  └── processor.py Batch orchestrator with resume and progress
25
28
  ```
26
29
 
@@ -30,17 +33,22 @@ src/docorient/
30
33
  detect_orientation()
31
34
 
32
35
 
33
- Primary Engine (detection/primary.py)
36
+ DetectionPipeline.run()
37
+ Iterates through list[DetectionEngine]
38
+
39
+
40
+ PrimaryEngine.detect()
34
41
  Analyzes pixel density distribution to determine text alignment.
35
42
 
36
43
  ├── angle ∈ {90, 270} ──► Return result immediately
37
44
 
38
- └── angle = 0 (aligned) ──► Secondary Engine available?
45
+ └── angle = 0 (aligned) ──► SecondaryEngine.detect()
46
+
47
+ is_available()?
39
48
 
40
49
  Yes ─────────┴───────── No
41
50
  ▼ ▼
42
- Secondary Engine Return 0° (no change)
43
- (detection/secondary.py)
51
+ Runs secondary analysis Return 0° (no change)
44
52
  Checks for 180° inversion
45
53
  with confidence scoring
46
54
 
@@ -51,27 +59,52 @@ Analyzes pixel density distribution to determine text alignment.
51
59
  Return 180° Return 0°
52
60
  ```
53
61
 
62
+ ## Engine Architecture
63
+
64
+ The detection system is built on a `DetectionEngine` Protocol:
65
+
66
+ ```
67
+ DetectionEngine (Protocol)
68
+ ├── name: str
69
+ └── detect(image, config) → OrientationResult | None
70
+
71
+ PrimaryEngine implements DetectionEngine
72
+ ├── Always returns OrientationResult (never None)
73
+ └── Detects 0°, 90°, 270° via energy analysis
74
+
75
+ SecondaryEngine implements DetectionEngine
76
+ ├── Returns None when unavailable or low confidence
77
+ └── Detects 180° via optional OCR dependency
78
+
79
+ DetectionPipeline
80
+ ├── Holds list[DetectionEngine] (default: [PrimaryEngine(), SecondaryEngine()])
81
+ └── Executes engines in sequence with short-circuit logic
82
+ ```
83
+
54
84
  ## Batch Processing Pipeline
55
85
 
56
86
  ```
57
87
  process_directory()
58
88
 
59
89
 
90
+ _resolve_output_directory()
91
+ Resolves explicit path or generates UUID
92
+
93
+
60
94
  scan_directory() ← scanner.py
61
95
  Groups images by
62
96
  source document name
63
97
 
64
98
 
65
- Load resume log ← _orientation_done.log
66
- Skip already done files
67
-
68
-
69
- Distribute pending
70
- sources into N batches ← N = effective_workers
99
+ _filter_pending_sources()
100
+ Loads resume log, skips completed
71
101
 
72
102
 
73
- multiprocessing.Pool ← worker.py
103
+ _run_parallel_processing()
74
104
  ┌─────────────────────────────────────┐
105
+ │ multiprocessing.Pool │
106
+ │ WorkerContext encapsulates state │
107
+ │ │
75
108
  │ For each source in batch: │
76
109
  │ 1. Run detection per page │
77
110
  │ 2. Apply majority voting │
@@ -93,12 +126,12 @@ Majority voting resolves this:
93
126
  2. Find the most common angle (`Counter.most_common`)
94
127
  3. Override any unreliable detection that differs from the majority
95
128
 
96
- Implemented in `correction._apply_majority_voting()`, reused by both
129
+ Implemented in `voting.apply_majority_voting()`, reused by both
97
130
  `correct_document_pages()` and `batch/worker._process_single_source()`.
98
131
 
99
132
  ## Multiprocessing Design
100
133
 
101
- - **No shared mutable state** each worker reconstructs `OrientationConfig` from a dict
134
+ - **WorkerContext dataclass** encapsulates all shared state in a single object
102
135
  - **Progress tracking** via `multiprocessing.Value` + `multiprocessing.Lock`
103
136
  - **Resume log** written atomically per source file, protected by the shared lock
104
137
  - **`maxtasksperchild=1`** prevents memory accumulation in long jobs
@@ -28,9 +28,8 @@ ruff check src/ tests/ --fix
28
28
  - No comments — code must be self-explanatory through naming
29
29
  - Descriptive variable names — never single-letter variables in non-trivial scopes
30
30
  - Full type hints on all function signatures
31
- - Docstrings only on public API functions
32
31
  - Functions must do exactly one thing, max ~30 lines of logic
33
- - No global state — configuration is always passed as a parameter
32
+ - Configuration is always passed as a parameter
34
33
 
35
34
  ## Publishing a New Version
36
35
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "docorient"
7
- version = "0.3.1"
7
+ version = "0.3.2"
8
8
  description = "Document image orientation detection and correction."
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -37,9 +37,10 @@ dev = ["pytest >= 8.0", "pytest-cov", "ruff >= 0.4", "build", "twine"]
37
37
  docorient = "docorient.cli:main"
38
38
 
39
39
  [project.urls]
40
- Homepage = "https://github.com/cebraspe-lab/docorient"
41
- Repository = "https://github.com/cebraspe-lab/docorient"
42
- Issues = "https://github.com/cebraspe-lab/docorient/issues"
40
+ Homepage = "https://github.com/lucasleirbag/DocOrient"
41
+ Repository = "https://github.com/lucasleirbag/DocOrient"
42
+ Issues = "https://github.com/lucasleirbag/DocOrient/issues"
43
+ Changelog = "https://github.com/lucasleirbag/DocOrient/blob/main/CHANGELOG.md"
43
44
 
44
45
  [tool.hatch.build.targets.wheel]
45
46
  packages = ["src/docorient"]
@@ -0,0 +1 @@
1
+ __version__ = "0.3.2"
@@ -1,22 +0,0 @@
1
- # Changelog
2
-
3
- ## 0.2.0 (2026-02-26)
4
-
5
- - **Breaking:** renamed config params `osd_confidence_threshold` → `secondary_confidence_threshold`, `max_osd_dimension` → `secondary_max_dimension`, `projection_target_dimension` → `primary_max_dimension`
6
- - **Breaking:** renamed CLI flag `--no-ocr` → `--no-secondary`
7
- - Internal engines renamed to `primary` and `secondary` — no external algorithm references
8
- - Updated `OrientationResult.method` trace strings to `primary(...)` and `secondary(...)`
9
-
10
- ## 0.1.1 (2026-02-26)
11
-
12
- - Docs: added `if __name__ == "__main__":` note for `process_directory` on macOS/Windows
13
-
14
- ## 0.1.0 (2026-02-25)
15
-
16
- - Initial release
17
- - Projection profile engine for 90°/270° detection
18
- - Optional Tesseract OSD engine for 180° detection
19
- - Single image and batch directory processing
20
- - Multi-page majority voting
21
- - Resumable batch processing
22
- - CLI interface
@@ -1 +0,0 @@
1
- __version__ = "0.3.1"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes