codarascan 0.2.0__tar.gz → 0.2.1__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 (87) hide show
  1. {codarascan-0.2.0 → codarascan-0.2.1}/CHANGELOG.md +8 -0
  2. {codarascan-0.2.0 → codarascan-0.2.1}/PKG-INFO +50 -7
  3. {codarascan-0.2.0 → codarascan-0.2.1}/README.md +49 -6
  4. {codarascan-0.2.0 → codarascan-0.2.1}/docs/COMPATIBILITY.md +1 -1
  5. {codarascan-0.2.0 → codarascan-0.2.1}/docs/KNOWN_LIMITATIONS.md +1 -1
  6. {codarascan-0.2.0 → codarascan-0.2.1}/docs/WORKER_PROTOCOL.md +8 -0
  7. {codarascan-0.2.0 → codarascan-0.2.1}/pyproject.toml +1 -1
  8. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/__init__.py +1 -1
  9. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/cli.py +16 -2
  10. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/schemas/result.decoded.example.json +2 -2
  11. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/schemas/result.localized.example.json +2 -2
  12. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/schemas/result.schema.json +1 -1
  13. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/schemas/stream.example.json +2 -2
  14. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/schemas/stream.schema.json +1 -1
  15. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/worker.py +10 -7
  16. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan.egg-info/PKG-INFO +50 -7
  17. {codarascan-0.2.0 → codarascan-0.2.1}/CONTRIBUTING.md +0 -0
  18. {codarascan-0.2.0 → codarascan-0.2.1}/LICENSE +0 -0
  19. {codarascan-0.2.0 → codarascan-0.2.1}/MANIFEST.in +0 -0
  20. {codarascan-0.2.0 → codarascan-0.2.1}/MIGRATION.md +0 -0
  21. {codarascan-0.2.0 → codarascan-0.2.1}/NOTICE +0 -0
  22. {codarascan-0.2.0 → codarascan-0.2.1}/SECURITY.md +0 -0
  23. {codarascan-0.2.0 → codarascan-0.2.1}/THIRD_PARTY_NOTICES.md +0 -0
  24. {codarascan-0.2.0 → codarascan-0.2.1}/docs/API.md +0 -0
  25. {codarascan-0.2.0 → codarascan-0.2.1}/docs/RELEASE.md +0 -0
  26. {codarascan-0.2.0 → codarascan-0.2.1}/docs/RELEASE_EVIDENCE_0.1.0.md +0 -0
  27. {codarascan-0.2.0 → codarascan-0.2.1}/docs/RELEASE_EVIDENCE_0.1.2.md +0 -0
  28. {codarascan-0.2.0 → codarascan-0.2.1}/setup.cfg +0 -0
  29. {codarascan-0.2.0 → codarascan-0.2.1}/setup.py +0 -0
  30. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/core/__init__.py +0 -0
  31. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/core/contracts.py +0 -0
  32. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/documents.py +0 -0
  33. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/__init__.py +0 -0
  34. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/catalog.py +0 -0
  35. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/common/__init__.py +0 -0
  36. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/common/base.py +0 -0
  37. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/common/classical_2d.py +0 -0
  38. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/common/classical_2d_extractor.py +0 -0
  39. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/common/classical_2d_localizer.py +0 -0
  40. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/common/classical_localizer.py +0 -0
  41. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/common/detection_classical_2d.py +0 -0
  42. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/common/detection_sttg.py +0 -0
  43. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/common/extraction_classical_2d.py +0 -0
  44. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/common/extraction_vendored.py +0 -0
  45. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/common/linear_recovery.py +0 -0
  46. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/common/linear_review_gate_v2.py +0 -0
  47. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/common/linear_review_gate_v3.py +0 -0
  48. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/common/native/__init__.py +0 -0
  49. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/common/native/loader.py +0 -0
  50. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/common/native/sttg_localizer.py +0 -0
  51. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/common/native/sttg_native.cpp +0 -0
  52. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/common/pdfium_pages.py +0 -0
  53. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/common/recovery/__init__.py +0 -0
  54. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/common/recovery/adaptive.py +0 -0
  55. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/common/recovery/hybrid.py +0 -0
  56. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/common/recovery/locator.py +0 -0
  57. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/common/recovery/matrix.py +0 -0
  58. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/common/recovery/runtime.py +0 -0
  59. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/common/recovery/zxing.py +0 -0
  60. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/common/review_gate.py +0 -0
  61. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/common/tensor_decode.py +0 -0
  62. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/common/tensor_decoder.py +0 -0
  63. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/common/tensor_localizer.py +0 -0
  64. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/common/vendored_decoder.py +0 -0
  65. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/mosaic/__init__.py +0 -0
  66. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/mosaic/detection.py +0 -0
  67. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/mosaic/extraction.py +0 -0
  68. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/panorama/__init__.py +0 -0
  69. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/panorama/extraction.py +0 -0
  70. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/panorama/reconciliation.py +0 -0
  71. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/registry.py +0 -0
  72. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/tessera/__init__.py +0 -0
  73. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/tessera/detection.py +0 -0
  74. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/engines/tessera/extraction.py +0 -0
  75. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/errors.py +0 -0
  76. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/formats.py +0 -0
  77. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/inputs.py +0 -0
  78. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/models.py +0 -0
  79. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/py.typed +0 -0
  80. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/scanner.py +0 -0
  81. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/schemas/worker.schema.json +0 -0
  82. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan/serialization.py +0 -0
  83. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan.egg-info/SOURCES.txt +0 -0
  84. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan.egg-info/dependency_links.txt +0 -0
  85. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan.egg-info/entry_points.txt +0 -0
  86. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan.egg-info/requires.txt +0 -0
  87. {codarascan-0.2.0 → codarascan-0.2.1}/src/codarascan.egg-info/top_level.txt +0 -0
@@ -3,6 +3,14 @@
3
3
  All notable changes are recorded here. CodaraScan follows semantic versioning
4
4
  after 1.0; during 0.x, breaking changes are identified explicitly.
5
5
 
6
+ ## 0.2.1 - 2026-09-09
7
+
8
+ - Make persistent worker request concurrency configurable with
9
+ `codarascan _worker --workers N` and `WorkerServer(..., workers=N)`.
10
+ - Default the persistent request pool to one worker instead of deriving its
11
+ size from the host CPU count, and document its interaction with PDF page
12
+ workers.
13
+
6
14
  ## 0.2.0 - 2026-09-07
7
15
 
8
16
  - Add the Panorama high-recall extraction engine and public
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codarascan
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: Open-source, offline barcode detection, localization, and decoding for images and PDFs
5
5
  Author-email: Abderraouf FELLAHI <ma_fellahi@esi.dz>
6
6
  License-Expression: Apache-2.0
@@ -73,7 +73,7 @@ For teams looking for a universal barcode detection layer, CodaraScan provides o
73
73
  [Formats](#supported-barcode-formats) · [API reference](https://github.com/flh-raouf/codarascan/blob/main/docs/API.md) ·
74
74
  [PyPI](https://pypi.org/project/codarascan/)
75
75
 
76
- > **Alpha notice — CodaraScan 0.2.0 is alpha software.** Its APIs and schemas
76
+ > **Alpha notice — CodaraScan 0.2.1 is alpha software.** Its APIs and schemas
77
77
  > may change during 0.x. Pin an exact version and evaluate it against your own documents before
78
78
  > production use. See the [known limitations](https://github.com/flh-raouf/codarascan/blob/main/docs/KNOWN_LIMITATIONS.md)
79
79
  > and [release policy](https://github.com/flh-raouf/codarascan/blob/main/docs/RELEASE.md).
@@ -89,7 +89,7 @@ Most barcode libraries focus on decoding a clean, tightly cropped symbol. Docume
89
89
  | Barcode decoding | Returns Unicode text, exact raw payload bytes, and a canonical format name |
90
90
  | Document scanning | Reads selected PDF pages, preserves requested order, and supports bounded parallel work |
91
91
  | Batch processing | Scans complete or selected multi-page PDFs and can stream pages without accumulating them |
92
- | Format coverage | 40 selectable formats: 27 linear and 13 matrix selections in version 0.2.0 |
92
+ | Format coverage | 40 selectable formats: 27 linear and 13 matrix selections in version 0.2.1 |
93
93
  | Recovery profiles | `fast` Tessera for lower latency; `robust` Mosaic for stronger recovery; `panorama` for maximum recall |
94
94
  | Local processing | No server, network request, telemetry, external executable, or runtime model download |
95
95
  | Integration | Typed Python API, deterministic JSON, CLI, schemas, and a private persistent worker protocol |
@@ -116,7 +116,7 @@ python -m pip install codarascan
116
116
  For reproducible alpha deployments, pin the current release:
117
117
 
118
118
  ```bash
119
- python -m pip install codarascan==0.2.0
119
+ python -m pip install codarascan==0.2.1
120
120
  ```
121
121
 
122
122
 
@@ -285,7 +285,7 @@ Avoid choosing a mode from synthetic benchmarks alone.
285
285
 
286
286
  ## Supported barcode formats
287
287
 
288
- CodaraScan 0.2.0 exposes **40 selectable barcode formats** generated from the installed ZXing-C++ readable catalog: **27 linear/1D selections** and **13 matrix/2D selections**.
288
+ CodaraScan 0.2.1 exposes **40 selectable barcode formats** generated from the installed ZXing-C++ readable catalog: **27 linear/1D selections** and **13 matrix/2D selections**.
289
289
 
290
290
  ### 1D and linear barcodes
291
291
 
@@ -384,9 +384,52 @@ Human-readable output is the default. `--json` emits one shared-schema result; `
384
384
 
385
385
  Run `codarascan image --help` or `codarascan document --help` for every option.
386
386
 
387
+ ### Understanding `workers`
388
+
389
+ CodaraScan has two separate worker settings, depending on how it is used.
390
+
391
+ For a one-off PDF scan, `--workers` controls how many pages from that PDF may
392
+ be analyzed concurrently:
393
+
394
+ ```bash
395
+ codarascan document archive.pdf --workers 12
396
+ ```
397
+
398
+ CodaraScan starts, scans the PDF, returns the result, and exits. There is no
399
+ need to start a persistent worker process first. Image scans use the `image`
400
+ command without `--workers`, because a single image is processed as one input:
401
+
402
+ ```bash
403
+ codarascan image barcode.png
404
+ ```
405
+
406
+ Backend services and language adapters can instead keep CodaraScan running as
407
+ a persistent process:
408
+
409
+ ```bash
410
+ codarascan _worker --workers 12
411
+ ```
412
+
413
+ Here, `--workers` controls how many separate incoming scan requests may execute
414
+ concurrently. The process receives framed JSON requests through standard input.
415
+ Each PDF request may also provide its own `workers` value, which controls how
416
+ many pages inside that PDF are analyzed concurrently.
417
+
418
+ Choose both values together. For example, 12 concurrent requests with 12 page
419
+ workers per PDF can create up to 144 page-analysis tasks:
420
+
421
+ ```text
422
+ 12 concurrent requests × 12 page workers = up to 144 page tasks
423
+ ```
424
+
425
+ That can increase CPU and memory usage and may reduce overall throughput. A
426
+ service can use several request workers with one page worker per request, or
427
+ fewer request workers with more page workers for large PDFs. Both settings
428
+ default to `1`.
429
+
387
430
  ## Platform support
388
431
 
389
- Official 0.2.0 wheels target:
432
+ Official 0.2.1 wheels target:
390
433
 
391
434
  | Operating system | Architectures | Python |
392
435
  |---|---|---|
@@ -430,7 +473,7 @@ Yes. Barcode detection, decoding, PDF rendering, the CLI, and the worker all run
430
473
 
431
474
  ### Is CodaraScan a universal barcode reader?
432
475
 
433
- It is a multi-format barcode detection layer with 40 selectable 1D and 2D formats in version 0.2.0. No honest scanner can guarantee every barcode under every capture condition, so CodaraScan publishes the exact catalog, evidence, and known limitations instead of making an unlimited compatibility claim.
476
+ It is a multi-format barcode detection layer with 40 selectable 1D and 2D formats in version 0.2.1. No honest scanner can guarantee every barcode under every capture condition, so CodaraScan publishes the exact catalog, evidence, and known limitations instead of making an unlimited compatibility claim.
434
477
 
435
478
 
436
479
  ### Which mode should I use?
@@ -16,7 +16,7 @@ For teams looking for a universal barcode detection layer, CodaraScan provides o
16
16
  [Formats](#supported-barcode-formats) · [API reference](https://github.com/flh-raouf/codarascan/blob/main/docs/API.md) ·
17
17
  [PyPI](https://pypi.org/project/codarascan/)
18
18
 
19
- > **Alpha notice — CodaraScan 0.2.0 is alpha software.** Its APIs and schemas
19
+ > **Alpha notice — CodaraScan 0.2.1 is alpha software.** Its APIs and schemas
20
20
  > may change during 0.x. Pin an exact version and evaluate it against your own documents before
21
21
  > production use. See the [known limitations](https://github.com/flh-raouf/codarascan/blob/main/docs/KNOWN_LIMITATIONS.md)
22
22
  > and [release policy](https://github.com/flh-raouf/codarascan/blob/main/docs/RELEASE.md).
@@ -32,7 +32,7 @@ Most barcode libraries focus on decoding a clean, tightly cropped symbol. Docume
32
32
  | Barcode decoding | Returns Unicode text, exact raw payload bytes, and a canonical format name |
33
33
  | Document scanning | Reads selected PDF pages, preserves requested order, and supports bounded parallel work |
34
34
  | Batch processing | Scans complete or selected multi-page PDFs and can stream pages without accumulating them |
35
- | Format coverage | 40 selectable formats: 27 linear and 13 matrix selections in version 0.2.0 |
35
+ | Format coverage | 40 selectable formats: 27 linear and 13 matrix selections in version 0.2.1 |
36
36
  | Recovery profiles | `fast` Tessera for lower latency; `robust` Mosaic for stronger recovery; `panorama` for maximum recall |
37
37
  | Local processing | No server, network request, telemetry, external executable, or runtime model download |
38
38
  | Integration | Typed Python API, deterministic JSON, CLI, schemas, and a private persistent worker protocol |
@@ -59,7 +59,7 @@ python -m pip install codarascan
59
59
  For reproducible alpha deployments, pin the current release:
60
60
 
61
61
  ```bash
62
- python -m pip install codarascan==0.2.0
62
+ python -m pip install codarascan==0.2.1
63
63
  ```
64
64
 
65
65
 
@@ -228,7 +228,7 @@ Avoid choosing a mode from synthetic benchmarks alone.
228
228
 
229
229
  ## Supported barcode formats
230
230
 
231
- CodaraScan 0.2.0 exposes **40 selectable barcode formats** generated from the installed ZXing-C++ readable catalog: **27 linear/1D selections** and **13 matrix/2D selections**.
231
+ CodaraScan 0.2.1 exposes **40 selectable barcode formats** generated from the installed ZXing-C++ readable catalog: **27 linear/1D selections** and **13 matrix/2D selections**.
232
232
 
233
233
  ### 1D and linear barcodes
234
234
 
@@ -327,9 +327,52 @@ Human-readable output is the default. `--json` emits one shared-schema result; `
327
327
 
328
328
  Run `codarascan image --help` or `codarascan document --help` for every option.
329
329
 
330
+ ### Understanding `workers`
331
+
332
+ CodaraScan has two separate worker settings, depending on how it is used.
333
+
334
+ For a one-off PDF scan, `--workers` controls how many pages from that PDF may
335
+ be analyzed concurrently:
336
+
337
+ ```bash
338
+ codarascan document archive.pdf --workers 12
339
+ ```
340
+
341
+ CodaraScan starts, scans the PDF, returns the result, and exits. There is no
342
+ need to start a persistent worker process first. Image scans use the `image`
343
+ command without `--workers`, because a single image is processed as one input:
344
+
345
+ ```bash
346
+ codarascan image barcode.png
347
+ ```
348
+
349
+ Backend services and language adapters can instead keep CodaraScan running as
350
+ a persistent process:
351
+
352
+ ```bash
353
+ codarascan _worker --workers 12
354
+ ```
355
+
356
+ Here, `--workers` controls how many separate incoming scan requests may execute
357
+ concurrently. The process receives framed JSON requests through standard input.
358
+ Each PDF request may also provide its own `workers` value, which controls how
359
+ many pages inside that PDF are analyzed concurrently.
360
+
361
+ Choose both values together. For example, 12 concurrent requests with 12 page
362
+ workers per PDF can create up to 144 page-analysis tasks:
363
+
364
+ ```text
365
+ 12 concurrent requests × 12 page workers = up to 144 page tasks
366
+ ```
367
+
368
+ That can increase CPU and memory usage and may reduce overall throughput. A
369
+ service can use several request workers with one page worker per request, or
370
+ fewer request workers with more page workers for large PDFs. Both settings
371
+ default to `1`.
372
+
330
373
  ## Platform support
331
374
 
332
- Official 0.2.0 wheels target:
375
+ Official 0.2.1 wheels target:
333
376
 
334
377
  | Operating system | Architectures | Python |
335
378
  |---|---|---|
@@ -373,7 +416,7 @@ Yes. Barcode detection, decoding, PDF rendering, the CLI, and the worker all run
373
416
 
374
417
  ### Is CodaraScan a universal barcode reader?
375
418
 
376
- It is a multi-format barcode detection layer with 40 selectable 1D and 2D formats in version 0.2.0. No honest scanner can guarantee every barcode under every capture condition, so CodaraScan publishes the exact catalog, evidence, and known limitations instead of making an unlimited compatibility claim.
419
+ It is a multi-format barcode detection layer with 40 selectable 1D and 2D formats in version 0.2.1. No honest scanner can guarantee every barcode under every capture condition, so CodaraScan publishes the exact catalog, evidence, and known limitations instead of making an unlimited compatibility claim.
377
420
 
378
421
 
379
422
  ### Which mode should I use?
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## Interpreter and platform matrix
4
4
 
5
- CodaraScan 0.2.0 declares CPython 3.11, 3.12, 3.13, and 3.14. The official
5
+ CodaraScan 0.2.1 declares CPython 3.11, 3.12, 3.13, and 3.14. The official
6
6
  wheel target matrix is:
7
7
 
8
8
  | Platform | Architectures | Wheel expectation |
@@ -1,4 +1,4 @@
1
- # Known limitations in 0.2.0 alpha
1
+ # Known limitations in 0.2.1 alpha
2
2
 
3
3
  - Degraded-corpus validation is deepest for established QR Code, Data Matrix,
4
4
  and common linear workflows. Broader catalog blur, glare, perspective,
@@ -4,6 +4,14 @@
4
4
  adapters. It reads standard input and writes standard output. It opens no
5
5
  socket, HTTP server, or external connection. Warnings use standard error.
6
6
 
7
+ The request pool defaults to one worker. Set `codarascan _worker --workers 4`
8
+ or `python -m codarascan.worker --workers 4` to process up to four requests
9
+ concurrently. Python callers can use `WorkerServer(reader, writer, workers=4)`.
10
+ The count must be a positive integer; it is never inferred from CPU count.
11
+ This controls concurrent requests. The separate `workers` parameter for
12
+ `scan_document` and `iter_document` controls page analysis within each request
13
+ and still defaults to 1 (with explicit `"auto"` supported).
14
+
7
15
  Each message is four bytes containing an unsigned big-endian payload length,
8
16
  followed by exactly that many UTF-8 JSON bytes. JSON may contain newlines and
9
17
  may be larger than a line. The worker applies no additional public frame-size
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "codarascan"
7
- version = "0.2.0"
7
+ version = "0.2.1"
8
8
  description = "Open-source, offline barcode detection, localization, and decoding for images and PDFs"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11,<3.15"
@@ -1,7 +1,7 @@
1
1
  # SPDX-License-Identifier: Apache-2.0
2
2
  """CodaraScan public API."""
3
3
 
4
- __version__ = "0.2.0"
4
+ __version__ = "0.2.1"
5
5
 
6
6
  from .core.contracts import Roi
7
7
  from .documents import DocumentInput, DocumentStream, ErrorPolicy, WorkerCount
@@ -81,6 +81,16 @@ def _workers(value: str) -> int | str:
81
81
  return parsed
82
82
 
83
83
 
84
+ def _request_workers(value: str) -> int:
85
+ try:
86
+ parsed = int(value)
87
+ except ValueError as exc:
88
+ raise argparse.ArgumentTypeError("workers must be a positive integer") from exc
89
+ if parsed < 1:
90
+ raise argparse.ArgumentTypeError("workers must be a positive integer")
91
+ return parsed
92
+
93
+
84
94
  def _add_scanner_options(parser: argparse.ArgumentParser) -> None:
85
95
  parser.add_argument(
86
96
  "--mode", choices=("fast", "robust", "panorama"), default="fast"
@@ -119,7 +129,11 @@ def build_parser() -> argparse.ArgumentParser:
119
129
  document.add_argument("--workers", type=_workers, default=1)
120
130
  document.add_argument("--on-error", choices=("raise", "collect"), default="raise")
121
131
  _add_scanner_options(document)
122
- subparsers.add_parser("_worker")
132
+ worker = subparsers.add_parser("_worker")
133
+ worker.add_argument(
134
+ "--workers", type=_request_workers, default=1,
135
+ help="number of concurrent requests (default: 1)",
136
+ )
123
137
  return parser
124
138
 
125
139
 
@@ -233,7 +247,7 @@ def run(arguments: argparse.Namespace) -> int:
233
247
  if arguments.command == "_worker":
234
248
  from .worker import main as worker_main
235
249
 
236
- return worker_main()
250
+ return worker_main(workers=arguments.workers)
237
251
  scanner = _scanner(arguments)
238
252
  if arguments.command == "image":
239
253
  result: ImageResult | DocumentResult = scanner.scan_image(
@@ -4,9 +4,9 @@
4
4
  "height": 80,
5
5
  "elapsed_ms": 1.25,
6
6
  "metadata": {
7
- "package_version": "0.2.0",
7
+ "package_version": "0.2.1",
8
8
  "engine": "tessera-extractor",
9
- "engine_version": "0.2.0",
9
+ "engine_version": "0.2.1",
10
10
  "decoder_version": "3.1.1",
11
11
  "backend": "native",
12
12
  "mode": "fast"
@@ -4,9 +4,9 @@
4
4
  "height": 80,
5
5
  "elapsed_ms": 1.5,
6
6
  "metadata": {
7
- "package_version": "0.2.0",
7
+ "package_version": "0.2.1",
8
8
  "engine": "mosaic-extractor",
9
- "engine_version": "0.2.0",
9
+ "engine_version": "0.2.1",
10
10
  "decoder_version": "3.1.1",
11
11
  "backend": "python",
12
12
  "mode": "robust"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://codarascan.dev/schemas/result-0.2.0.json",
3
+ "$id": "https://codarascan.dev/schemas/result-0.2.1.json",
4
4
  "title": "CodaraScan result",
5
5
  "oneOf": [
6
6
  { "$ref": "#/$defs/image" },
@@ -5,9 +5,9 @@
5
5
  "errors": [],
6
6
  "elapsed_ms": 4.5,
7
7
  "metadata": {
8
- "package_version": "0.2.0",
8
+ "package_version": "0.2.1",
9
9
  "engine": "tessera-extractor",
10
- "engine_version": "0.2.0",
10
+ "engine_version": "0.2.1",
11
11
  "decoder_version": "3.1.1",
12
12
  "backend": "native",
13
13
  "mode": "fast"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://codarascan.dev/schemas/stream-0.2.0.json",
3
+ "$id": "https://codarascan.dev/schemas/stream-0.2.1.json",
4
4
  "title": "CodaraScan NDJSON document summary",
5
5
  "type": "object",
6
6
  "additionalProperties": false,
@@ -6,7 +6,6 @@ from __future__ import annotations
6
6
  import base64
7
7
  import binascii
8
8
  import json
9
- import os
10
9
  import struct
11
10
  import sys
12
11
  import threading
@@ -15,7 +14,7 @@ from concurrent.futures import Future, ThreadPoolExecutor
15
14
  from typing import Any, BinaryIO, cast
16
15
 
17
16
  from . import __version__
18
- from .errors import CodaraScanError, ProtocolError
17
+ from .errors import CodaraScanError, ConfigurationError, ProtocolError
19
18
  from .scanner import Scanner
20
19
 
21
20
  PROTOCOL_VERSION = 1
@@ -116,7 +115,9 @@ def _error_payload(error: BaseException) -> dict[str, Any]:
116
115
 
117
116
 
118
117
  class WorkerServer:
119
- def __init__(self, reader: BinaryIO, writer: BinaryIO) -> None:
118
+ def __init__(self, reader: BinaryIO, writer: BinaryIO, *, workers: int = 1) -> None:
119
+ if isinstance(workers, bool) or not isinstance(workers, int) or workers < 1:
120
+ raise ConfigurationError("workers must be a positive integer")
120
121
  self.reader = reader
121
122
  self.writer = writer
122
123
  self._write_lock = threading.Lock()
@@ -125,7 +126,7 @@ class WorkerServer:
125
126
  self._active_lock = threading.RLock()
126
127
  self._active: dict[Any, threading.Event] = {}
127
128
  self._executor = ThreadPoolExecutor(
128
- max_workers=max(1, os.cpu_count() or 1),
129
+ max_workers=workers,
129
130
  thread_name_prefix="codarascan-worker",
130
131
  )
131
132
 
@@ -390,12 +391,14 @@ class WorkerServer:
390
391
  future.add_done_callback(completed_callback)
391
392
 
392
393
 
393
- def main() -> int:
394
- return WorkerServer(sys.stdin.buffer, sys.stdout.buffer).run()
394
+ def main(*, workers: int = 1) -> int:
395
+ return WorkerServer(sys.stdin.buffer, sys.stdout.buffer, workers=workers).run()
395
396
 
396
397
 
397
398
  if __name__ == "__main__":
398
- raise SystemExit(main())
399
+ from .cli import main as cli_main
400
+
401
+ raise SystemExit(cli_main(["_worker", *sys.argv[1:]]))
399
402
 
400
403
 
401
404
  __all__ = [
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codarascan
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: Open-source, offline barcode detection, localization, and decoding for images and PDFs
5
5
  Author-email: Abderraouf FELLAHI <ma_fellahi@esi.dz>
6
6
  License-Expression: Apache-2.0
@@ -73,7 +73,7 @@ For teams looking for a universal barcode detection layer, CodaraScan provides o
73
73
  [Formats](#supported-barcode-formats) · [API reference](https://github.com/flh-raouf/codarascan/blob/main/docs/API.md) ·
74
74
  [PyPI](https://pypi.org/project/codarascan/)
75
75
 
76
- > **Alpha notice — CodaraScan 0.2.0 is alpha software.** Its APIs and schemas
76
+ > **Alpha notice — CodaraScan 0.2.1 is alpha software.** Its APIs and schemas
77
77
  > may change during 0.x. Pin an exact version and evaluate it against your own documents before
78
78
  > production use. See the [known limitations](https://github.com/flh-raouf/codarascan/blob/main/docs/KNOWN_LIMITATIONS.md)
79
79
  > and [release policy](https://github.com/flh-raouf/codarascan/blob/main/docs/RELEASE.md).
@@ -89,7 +89,7 @@ Most barcode libraries focus on decoding a clean, tightly cropped symbol. Docume
89
89
  | Barcode decoding | Returns Unicode text, exact raw payload bytes, and a canonical format name |
90
90
  | Document scanning | Reads selected PDF pages, preserves requested order, and supports bounded parallel work |
91
91
  | Batch processing | Scans complete or selected multi-page PDFs and can stream pages without accumulating them |
92
- | Format coverage | 40 selectable formats: 27 linear and 13 matrix selections in version 0.2.0 |
92
+ | Format coverage | 40 selectable formats: 27 linear and 13 matrix selections in version 0.2.1 |
93
93
  | Recovery profiles | `fast` Tessera for lower latency; `robust` Mosaic for stronger recovery; `panorama` for maximum recall |
94
94
  | Local processing | No server, network request, telemetry, external executable, or runtime model download |
95
95
  | Integration | Typed Python API, deterministic JSON, CLI, schemas, and a private persistent worker protocol |
@@ -116,7 +116,7 @@ python -m pip install codarascan
116
116
  For reproducible alpha deployments, pin the current release:
117
117
 
118
118
  ```bash
119
- python -m pip install codarascan==0.2.0
119
+ python -m pip install codarascan==0.2.1
120
120
  ```
121
121
 
122
122
 
@@ -285,7 +285,7 @@ Avoid choosing a mode from synthetic benchmarks alone.
285
285
 
286
286
  ## Supported barcode formats
287
287
 
288
- CodaraScan 0.2.0 exposes **40 selectable barcode formats** generated from the installed ZXing-C++ readable catalog: **27 linear/1D selections** and **13 matrix/2D selections**.
288
+ CodaraScan 0.2.1 exposes **40 selectable barcode formats** generated from the installed ZXing-C++ readable catalog: **27 linear/1D selections** and **13 matrix/2D selections**.
289
289
 
290
290
  ### 1D and linear barcodes
291
291
 
@@ -384,9 +384,52 @@ Human-readable output is the default. `--json` emits one shared-schema result; `
384
384
 
385
385
  Run `codarascan image --help` or `codarascan document --help` for every option.
386
386
 
387
+ ### Understanding `workers`
388
+
389
+ CodaraScan has two separate worker settings, depending on how it is used.
390
+
391
+ For a one-off PDF scan, `--workers` controls how many pages from that PDF may
392
+ be analyzed concurrently:
393
+
394
+ ```bash
395
+ codarascan document archive.pdf --workers 12
396
+ ```
397
+
398
+ CodaraScan starts, scans the PDF, returns the result, and exits. There is no
399
+ need to start a persistent worker process first. Image scans use the `image`
400
+ command without `--workers`, because a single image is processed as one input:
401
+
402
+ ```bash
403
+ codarascan image barcode.png
404
+ ```
405
+
406
+ Backend services and language adapters can instead keep CodaraScan running as
407
+ a persistent process:
408
+
409
+ ```bash
410
+ codarascan _worker --workers 12
411
+ ```
412
+
413
+ Here, `--workers` controls how many separate incoming scan requests may execute
414
+ concurrently. The process receives framed JSON requests through standard input.
415
+ Each PDF request may also provide its own `workers` value, which controls how
416
+ many pages inside that PDF are analyzed concurrently.
417
+
418
+ Choose both values together. For example, 12 concurrent requests with 12 page
419
+ workers per PDF can create up to 144 page-analysis tasks:
420
+
421
+ ```text
422
+ 12 concurrent requests × 12 page workers = up to 144 page tasks
423
+ ```
424
+
425
+ That can increase CPU and memory usage and may reduce overall throughput. A
426
+ service can use several request workers with one page worker per request, or
427
+ fewer request workers with more page workers for large PDFs. Both settings
428
+ default to `1`.
429
+
387
430
  ## Platform support
388
431
 
389
- Official 0.2.0 wheels target:
432
+ Official 0.2.1 wheels target:
390
433
 
391
434
  | Operating system | Architectures | Python |
392
435
  |---|---|---|
@@ -430,7 +473,7 @@ Yes. Barcode detection, decoding, PDF rendering, the CLI, and the worker all run
430
473
 
431
474
  ### Is CodaraScan a universal barcode reader?
432
475
 
433
- It is a multi-format barcode detection layer with 40 selectable 1D and 2D formats in version 0.2.0. No honest scanner can guarantee every barcode under every capture condition, so CodaraScan publishes the exact catalog, evidence, and known limitations instead of making an unlimited compatibility claim.
476
+ It is a multi-format barcode detection layer with 40 selectable 1D and 2D formats in version 0.2.1. No honest scanner can guarantee every barcode under every capture condition, so CodaraScan publishes the exact catalog, evidence, and known limitations instead of making an unlimited compatibility claim.
434
477
 
435
478
 
436
479
  ### Which mode should I use?
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes