ocr-stringdist 0.0.2__tar.gz → 0.0.4__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.
- {ocr_stringdist-0.0.2 → ocr_stringdist-0.0.4}/.gitignore +0 -1
- {ocr_stringdist-0.0.2 → ocr_stringdist-0.0.4}/Cargo.lock +2 -2
- {ocr_stringdist-0.0.2 → ocr_stringdist-0.0.4}/Cargo.toml +1 -1
- ocr_stringdist-0.0.4/Justfile +14 -0
- {ocr_stringdist-0.0.2 → ocr_stringdist-0.0.4}/PKG-INFO +21 -2
- {ocr_stringdist-0.0.2 → ocr_stringdist-0.0.4}/README.md +19 -0
- {ocr_stringdist-0.0.2 → ocr_stringdist-0.0.4}/example.py +10 -1
- ocr_stringdist-0.0.4/mypy.ini +137 -0
- {ocr_stringdist-0.0.2 → ocr_stringdist-0.0.4}/pyproject.toml +11 -1
- {ocr_stringdist-0.0.2 → ocr_stringdist-0.0.4}/python/ocr_stringdist/__init__.py +3 -3
- ocr_stringdist-0.0.4/python/ocr_stringdist/default_ocr_distances.py +38 -0
- ocr_stringdist-0.0.4/python/ocr_stringdist/matching.py +83 -0
- ocr_stringdist-0.0.4/ruff.toml +88 -0
- ocr_stringdist-0.0.4/tests/test_matching.py +39 -0
- ocr_stringdist-0.0.4/uv.lock +290 -0
- ocr_stringdist-0.0.2/Justfile +0 -12
- ocr_stringdist-0.0.2/python/ocr_stringdist/default_ocr_distances.py +0 -16
- {ocr_stringdist-0.0.2 → ocr_stringdist-0.0.4}/.github/workflows/CI.yml +0 -0
- {ocr_stringdist-0.0.2 → ocr_stringdist-0.0.4}/LICENSE +0 -0
- {ocr_stringdist-0.0.2 → ocr_stringdist-0.0.4}/python/ocr_stringdist/py.typed +0 -0
- {ocr_stringdist-0.0.2 → ocr_stringdist-0.0.4}/src/lib.rs +0 -0
- {ocr_stringdist-0.0.2 → ocr_stringdist-0.0.4}/src/rust_stringdist.rs +0 -0
- {ocr_stringdist-0.0.2 → ocr_stringdist-0.0.4}/src/weighted_levenshtein.rs +0 -0
- {ocr_stringdist-0.0.2 → ocr_stringdist-0.0.4}/tests/test_ocr_stringdist.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
# This file is automatically @generated by Cargo.
|
2
2
|
# It is not intended for manual editing.
|
3
|
-
version =
|
3
|
+
version = 3
|
4
4
|
|
5
5
|
[[package]]
|
6
6
|
name = "ahash"
|
@@ -67,7 +67,7 @@ dependencies = [
|
|
67
67
|
|
68
68
|
[[package]]
|
69
69
|
name = "ocr_stringdist"
|
70
|
-
version = "0.0.
|
70
|
+
version = "0.0.4"
|
71
71
|
dependencies = [
|
72
72
|
"ahash",
|
73
73
|
"pyo3",
|
@@ -1,8 +1,8 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: ocr_stringdist
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.4
|
4
4
|
Classifier: Programming Language :: Rust
|
5
|
-
Classifier: Programming Language :: Python
|
5
|
+
Classifier: Programming Language :: Python
|
6
6
|
Classifier: Operating System :: OS Independent
|
7
7
|
License-File: LICENSE
|
8
8
|
Summary: String distances considering OCR errors.
|
@@ -37,9 +37,12 @@ pip install ocr-stringdist
|
|
37
37
|
- **Weighted Levenshtein Distance**: An adaptation of the classic Levenshtein algorithm with custom substitution costs for character pairs that are commonly confused in OCR models.
|
38
38
|
- **Pre-defined OCR Distance Map**: A built-in distance map for common OCR confusions (e.g., "0" vs "O", "1" vs "l", "5" vs "S").
|
39
39
|
- **Customizable Cost Maps**: Create your own substitution cost maps for specific OCR systems or domains.
|
40
|
+
- **Best Match Finder**: Utility function find_best_candidate to efficiently find the best matching string from a collection of candidates using any specified distance function (including the library's OCR-aware ones). Supports early stopping for performance optimization.
|
40
41
|
|
41
42
|
## Usage
|
42
43
|
|
44
|
+
### Weighted Levenshtein Distance
|
45
|
+
|
43
46
|
```python
|
44
47
|
import ocr_stringdist as osd
|
45
48
|
|
@@ -58,6 +61,22 @@ distance = osd.weighted_levenshtein_distance(
|
|
58
61
|
print(f"Distance with custom map: {distance}")
|
59
62
|
```
|
60
63
|
|
64
|
+
### Finding the Best Candidate
|
65
|
+
|
66
|
+
```python
|
67
|
+
import ocr_stringdist as osd
|
68
|
+
|
69
|
+
s = "apple"
|
70
|
+
candidates = ["apply", "apples", "orange", "appIe"] # 'appIe' has an OCR-like error
|
71
|
+
|
72
|
+
def ocr_aware_distance(s1: str, s2: str) -> float:
|
73
|
+
return osd.weighted_levenshtein_distance(s1, s2, cost_map={("l", "I"): 0.1})
|
74
|
+
|
75
|
+
best_candidate, best_dist = osd.find_best_candidate(s, candidates, ocr_aware_distance)
|
76
|
+
print(f"Best candidate for '{s}' is '{best_candidate}' with distance {best_dist}")
|
77
|
+
# Output: Best candidate for 'apple' is 'appIe' with distance 0.1
|
78
|
+
```
|
79
|
+
|
61
80
|
## Acknowledgements
|
62
81
|
|
63
82
|
This project is inspired by [jellyfish](https://github.com/jamesturk/jellyfish), providing the base implementations of the algorithms used here.
|
@@ -22,9 +22,12 @@ pip install ocr-stringdist
|
|
22
22
|
- **Weighted Levenshtein Distance**: An adaptation of the classic Levenshtein algorithm with custom substitution costs for character pairs that are commonly confused in OCR models.
|
23
23
|
- **Pre-defined OCR Distance Map**: A built-in distance map for common OCR confusions (e.g., "0" vs "O", "1" vs "l", "5" vs "S").
|
24
24
|
- **Customizable Cost Maps**: Create your own substitution cost maps for specific OCR systems or domains.
|
25
|
+
- **Best Match Finder**: Utility function find_best_candidate to efficiently find the best matching string from a collection of candidates using any specified distance function (including the library's OCR-aware ones). Supports early stopping for performance optimization.
|
25
26
|
|
26
27
|
## Usage
|
27
28
|
|
29
|
+
### Weighted Levenshtein Distance
|
30
|
+
|
28
31
|
```python
|
29
32
|
import ocr_stringdist as osd
|
30
33
|
|
@@ -43,6 +46,22 @@ distance = osd.weighted_levenshtein_distance(
|
|
43
46
|
print(f"Distance with custom map: {distance}")
|
44
47
|
```
|
45
48
|
|
49
|
+
### Finding the Best Candidate
|
50
|
+
|
51
|
+
```python
|
52
|
+
import ocr_stringdist as osd
|
53
|
+
|
54
|
+
s = "apple"
|
55
|
+
candidates = ["apply", "apples", "orange", "appIe"] # 'appIe' has an OCR-like error
|
56
|
+
|
57
|
+
def ocr_aware_distance(s1: str, s2: str) -> float:
|
58
|
+
return osd.weighted_levenshtein_distance(s1, s2, cost_map={("l", "I"): 0.1})
|
59
|
+
|
60
|
+
best_candidate, best_dist = osd.find_best_candidate(s, candidates, ocr_aware_distance)
|
61
|
+
print(f"Best candidate for '{s}' is '{best_candidate}' with distance {best_dist}")
|
62
|
+
# Output: Best candidate for 'apple' is 'appIe' with distance 0.1
|
63
|
+
```
|
64
|
+
|
46
65
|
## Acknowledgements
|
47
66
|
|
48
67
|
This project is inspired by [jellyfish](https://github.com/jamesturk/jellyfish), providing the base implementations of the algorithms used here.
|
@@ -1,5 +1,5 @@
|
|
1
|
-
from ocr_stringdist import weighted_levenshtein_distance
|
2
1
|
from icecream import ic
|
2
|
+
from ocr_stringdist import find_best_candidate, weighted_levenshtein_distance
|
3
3
|
|
4
4
|
ic(
|
5
5
|
weighted_levenshtein_distance(
|
@@ -39,3 +39,12 @@ ic(weighted_levenshtein_distance("A", "B", {("A", "B"): 0.0}, symmetric=False))
|
|
39
39
|
ic(weighted_levenshtein_distance("A", "B", {("B", "A"): 0.0}, symmetric=False))
|
40
40
|
ic(weighted_levenshtein_distance("B", "A", {("B", "A"): 0.0}, symmetric=False))
|
41
41
|
ic(weighted_levenshtein_distance("B", "A", {("A", "B"): 0.0}, symmetric=False))
|
42
|
+
|
43
|
+
|
44
|
+
ic(
|
45
|
+
find_best_candidate(
|
46
|
+
"apple",
|
47
|
+
["apply", "apples", "orange", "appIe"],
|
48
|
+
lambda s1, s2: weighted_levenshtein_distance(s1, s2, {("l", "I"): 0.1}),
|
49
|
+
)
|
50
|
+
)
|
@@ -0,0 +1,137 @@
|
|
1
|
+
; Based on https://gist.github.com/CodeByAidan/adb2b9e188256def1fe35b932cba7eb8
|
2
|
+
[mypy]
|
3
|
+
check_untyped_defs = True
|
4
|
+
disallow_any_generics = True
|
5
|
+
disallow_any_unimported = True
|
6
|
+
disallow_subclassing_any = True
|
7
|
+
disallow_untyped_calls = True
|
8
|
+
disallow_untyped_decorators = True
|
9
|
+
disallow_untyped_defs = True
|
10
|
+
ignore_missing_imports = True
|
11
|
+
no_implicit_optional = True
|
12
|
+
pretty = True
|
13
|
+
show_column_numbers = True
|
14
|
+
show_error_codes = True
|
15
|
+
show_error_context = True
|
16
|
+
strict_equality = True
|
17
|
+
warn_return_any = True
|
18
|
+
warn_unused_ignores = True
|
19
|
+
|
20
|
+
; All of this below is just defaults:
|
21
|
+
; -----------------------------------
|
22
|
+
; (if any flags are commented out with a = and nothing after it,
|
23
|
+
; it means there is no default value/custom)
|
24
|
+
; ex. ; mypy_path =
|
25
|
+
; -----------------------------------
|
26
|
+
; (if any flags are commented out with a = and a value after it,
|
27
|
+
; it means that is the default value but it was changed out for
|
28
|
+
; my personal preference in my config above)
|
29
|
+
; ex. ; ignore_missing_imports = False
|
30
|
+
|
31
|
+
; == Import discovery ==
|
32
|
+
; mypy_path =
|
33
|
+
; files =
|
34
|
+
; modules =
|
35
|
+
; packages =
|
36
|
+
; exclude =
|
37
|
+
namespace_packages = True
|
38
|
+
explicit_package_bases = False
|
39
|
+
; ignore_missing_imports = False
|
40
|
+
follow_imports = normal
|
41
|
+
follow_imports_for_stubs = False
|
42
|
+
; python_executable =
|
43
|
+
no_site_packages = False
|
44
|
+
no_silence_site_packages = False
|
45
|
+
|
46
|
+
; == Platform configuration ==
|
47
|
+
; python_version =
|
48
|
+
; platform =
|
49
|
+
; always_true =
|
50
|
+
; always_false =
|
51
|
+
|
52
|
+
; == Disallow dynamic typing ==
|
53
|
+
; disallow_any_unimported = False
|
54
|
+
disallow_any_expr = False
|
55
|
+
disallow_any_decorated = False
|
56
|
+
disallow_any_explicit = False
|
57
|
+
; disallow_any_generics = False
|
58
|
+
; disallow_subclassing_any = False
|
59
|
+
|
60
|
+
; == Untyped definitions and calls ==
|
61
|
+
; disallow_untyped_calls = False
|
62
|
+
; untyped_calls_exclude =
|
63
|
+
; disallow_untyped_defs = False
|
64
|
+
disallow_incomplete_defs = False
|
65
|
+
; check_untyped_defs = False
|
66
|
+
; disallow_untyped_decorators = False
|
67
|
+
|
68
|
+
; == None and Optional handling ==
|
69
|
+
implicit_optional = False
|
70
|
+
strict_optional = True
|
71
|
+
|
72
|
+
; == Configuring warnings ==
|
73
|
+
warn_redundant_casts = False
|
74
|
+
; warn_unused_ignores = False
|
75
|
+
warn_no_return = True
|
76
|
+
; warn_return_any = False
|
77
|
+
warn_unreachable = False
|
78
|
+
|
79
|
+
; == Suppressing errors ==
|
80
|
+
ignore_errors = False
|
81
|
+
|
82
|
+
; == Miscellaneous strictness flags ==
|
83
|
+
allow_untyped_globals = False
|
84
|
+
allow_redefinition = False
|
85
|
+
local_partial_types = False
|
86
|
+
; disable_error_code =
|
87
|
+
; enable_error_code =
|
88
|
+
implicit_reexport = True
|
89
|
+
strict_concatenate = False
|
90
|
+
; strict_equality = False
|
91
|
+
strict = False
|
92
|
+
|
93
|
+
; == Configuring error messages ==
|
94
|
+
; show_error_context = False
|
95
|
+
; show_column_numbers = False
|
96
|
+
hide_error_codes = False
|
97
|
+
; pretty = False
|
98
|
+
color_output = True
|
99
|
+
error_summary = True
|
100
|
+
show_absolute_path = False
|
101
|
+
force_uppercase_builtins = False
|
102
|
+
force_union_syntax = False
|
103
|
+
|
104
|
+
; == Incremental mode ==
|
105
|
+
incremental = True
|
106
|
+
cache_dir = .mypy_cache
|
107
|
+
sqlite_cache = False
|
108
|
+
cache_fine_grained = False
|
109
|
+
skip_version_check = False
|
110
|
+
skip_cache_mtime_checks = False
|
111
|
+
|
112
|
+
; == Advanced options ==
|
113
|
+
; plugins =
|
114
|
+
pdb = False
|
115
|
+
show_traceback = False
|
116
|
+
raise_exceptions = False
|
117
|
+
; custom_typing_module =
|
118
|
+
; custom_typeshed_dir =
|
119
|
+
warn_incomplete_stub = False
|
120
|
+
|
121
|
+
; == Report generation ==
|
122
|
+
; any_exprs_report =
|
123
|
+
; cobertura_xml_report = ; pip install mypy[reports]
|
124
|
+
; html_report = ; pip install mypy[reports]
|
125
|
+
; xslt_html_report = ; pip install mypy[reports]
|
126
|
+
; linecount_report =
|
127
|
+
; linecoverage_report =
|
128
|
+
; lineprecision_report =
|
129
|
+
; txt_report = ; pip install mypy[reports]
|
130
|
+
; xslt_txt_report = ; pip install mypy[reports]
|
131
|
+
; xml_report = ; pip install mypy[reports]
|
132
|
+
|
133
|
+
; == Miscellaneous ==
|
134
|
+
; junit_xml =
|
135
|
+
scripts_are_modules = False
|
136
|
+
warn_unused_configs = False
|
137
|
+
verbosity = 0
|
@@ -8,7 +8,7 @@ dynamic = ["version"]
|
|
8
8
|
requires-python = ">=3.9"
|
9
9
|
classifiers = [
|
10
10
|
"Programming Language :: Rust",
|
11
|
-
"Programming Language :: Python
|
11
|
+
"Programming Language :: Python",
|
12
12
|
"Operating System :: OS Independent",
|
13
13
|
]
|
14
14
|
|
@@ -20,3 +20,13 @@ repository = "https://github.com/NiklasvonM/ocr-stringdist"
|
|
20
20
|
features = ["pyo3/extension-module", "python"]
|
21
21
|
python-source = "python"
|
22
22
|
module-name = "ocr_stringdist._rust_stringdist"
|
23
|
+
|
24
|
+
[dependency-groups]
|
25
|
+
dev = [
|
26
|
+
"icecream>=2.1.4",
|
27
|
+
"maturin>=1.8.3",
|
28
|
+
"mypy>=1.15.0",
|
29
|
+
"pytest>=8.3.5",
|
30
|
+
"ruff>=0.11.6",
|
31
|
+
"wheel>=0.45.1",
|
32
|
+
]
|
@@ -1,13 +1,13 @@
|
|
1
1
|
from typing import Optional
|
2
2
|
|
3
3
|
from ._rust_stringdist import * # noqa: F403
|
4
|
-
|
5
4
|
from .default_ocr_distances import ocr_distance_map
|
6
|
-
|
5
|
+
from .matching import find_best_candidate
|
7
6
|
|
8
7
|
__all__ = [
|
9
8
|
"ocr_distance_map",
|
10
9
|
"weighted_levenshtein_distance", # noqa: F405
|
10
|
+
"find_best_candidate",
|
11
11
|
]
|
12
12
|
|
13
13
|
|
@@ -36,6 +36,6 @@ def weighted_levenshtein_distance(
|
|
36
36
|
"""
|
37
37
|
if cost_map is None:
|
38
38
|
cost_map = ocr_distance_map
|
39
|
-
return _weighted_levenshtein_distance( # noqa: F405
|
39
|
+
return _weighted_levenshtein_distance( # type: ignore # noqa: F405
|
40
40
|
s1, s2, cost_map=cost_map, symmetric=symmetric, default_cost=default_cost
|
41
41
|
)
|
@@ -0,0 +1,38 @@
|
|
1
|
+
ocr_distance_map: dict[tuple[str, str], float] = {
|
2
|
+
("O", "0"): 0.1,
|
3
|
+
("l", "1"): 0.1,
|
4
|
+
("I", "1"): 0.15,
|
5
|
+
("o", "0"): 0.2,
|
6
|
+
("B", "8"): 0.25,
|
7
|
+
("S", "5"): 0.3,
|
8
|
+
("G", "6"): 0.3,
|
9
|
+
("Z", "2"): 0.3,
|
10
|
+
("C", "c"): 0.3,
|
11
|
+
("é", "e"): 0.3,
|
12
|
+
("Ä", "A"): 0.4,
|
13
|
+
("Ö", "O"): 0.4,
|
14
|
+
("Ü", "U"): 0.4,
|
15
|
+
("c", "e"): 0.4,
|
16
|
+
("a", "o"): 0.4,
|
17
|
+
("u", "v"): 0.4,
|
18
|
+
("i", "l"): 0.4,
|
19
|
+
("s", "5"): 0.4,
|
20
|
+
("m", "n"): 0.5,
|
21
|
+
("f", "s"): 0.5,
|
22
|
+
(".", ","): 0.5,
|
23
|
+
("2", "Z"): 0.5,
|
24
|
+
("t", "f"): 0.6,
|
25
|
+
("r", "n"): 0.6,
|
26
|
+
("-", "_"): 0.6,
|
27
|
+
("ß", "B"): 0.6,
|
28
|
+
("h", "b"): 0.7,
|
29
|
+
("v", "y"): 0.7,
|
30
|
+
("i", "j"): 0.7,
|
31
|
+
("é", "á"): 0.7,
|
32
|
+
("E", "F"): 0.8,
|
33
|
+
}
|
34
|
+
"""
|
35
|
+
Pre-defined distance map between characters, considering common OCR errors.
|
36
|
+
The distances are between 0 and 1.
|
37
|
+
This map is intended to be used with `symmetric=True`.
|
38
|
+
"""
|
@@ -0,0 +1,83 @@
|
|
1
|
+
from collections.abc import Callable, Iterable
|
2
|
+
from typing import Optional
|
3
|
+
|
4
|
+
|
5
|
+
def find_best_candidate(
|
6
|
+
s: str,
|
7
|
+
candidates: Iterable[str],
|
8
|
+
distance_fun: Callable[[str, str], float],
|
9
|
+
*,
|
10
|
+
minimize: bool = True,
|
11
|
+
early_return_value: Optional[float] = None,
|
12
|
+
) -> tuple[str, float]:
|
13
|
+
"""
|
14
|
+
Finds the best matching string from a collection of candidates based on a distance function.
|
15
|
+
|
16
|
+
Compares a given string against each string in the 'candidates'
|
17
|
+
iterable using the provided 'distance_fun'. It identifies the candidate
|
18
|
+
that yields the minimum (or maximum, if minimize=False) distance.
|
19
|
+
|
20
|
+
:param s: The reference string to compare against.
|
21
|
+
:type s: str
|
22
|
+
:param candidates: An iterable of candidate strings to compare with 's'.
|
23
|
+
:type candidates: Iterable[str]
|
24
|
+
:param distance_fun: A function that takes two strings (s, candidate) and
|
25
|
+
returns a float representing their distance or similarity.
|
26
|
+
:type distance_fun: Callable[[str, str], float]
|
27
|
+
:param minimize: If True (default), finds the candidate with the minimum
|
28
|
+
distance. If False, finds the candidate with the maximum
|
29
|
+
distance (useful for similarity scores).
|
30
|
+
:type minimize: bool
|
31
|
+
:param early_return_value: If provided, the function will return immediately
|
32
|
+
if a distance is found that is less than or equal
|
33
|
+
to this value (if minimize=True) or greater than
|
34
|
+
or equal to this value (if minimize=False).
|
35
|
+
If None (default), all candidates are checked.
|
36
|
+
:type early_return_value: Optional[float]
|
37
|
+
:raises ValueError: If the 'candidates' iterable is empty.
|
38
|
+
:return: A tuple containing the best matching candidate string and its
|
39
|
+
calculated distance/score.
|
40
|
+
:rtype: tuple[str, float]
|
41
|
+
|
42
|
+
:Example:
|
43
|
+
|
44
|
+
>>> from ocr_stringdist import weighted_levenshtein_distance as distance
|
45
|
+
>>> s = "apple"
|
46
|
+
>>> candidates = ["apply", "apples", "orange", "appIe"]
|
47
|
+
>>> find_best_match(s, candidates, lambda s1, s2: distance(s1, s2, {("l", "I"): 0.1}))
|
48
|
+
('appIe', 0.1)
|
49
|
+
"""
|
50
|
+
if not candidates:
|
51
|
+
raise ValueError("The 'candidates' iterable cannot be empty.")
|
52
|
+
|
53
|
+
best_candidate: str = ""
|
54
|
+
|
55
|
+
if minimize:
|
56
|
+
best_distance = float("inf")
|
57
|
+
|
58
|
+
def is_next_best(current: float, best: float) -> bool:
|
59
|
+
return current < best
|
60
|
+
|
61
|
+
def can_return_early(current: float, threshold: float) -> bool:
|
62
|
+
return current <= threshold
|
63
|
+
else:
|
64
|
+
best_distance = -float("inf")
|
65
|
+
|
66
|
+
def is_next_best(current: float, best: float) -> bool:
|
67
|
+
return current > best
|
68
|
+
|
69
|
+
def can_return_early(current: float, threshold: float) -> bool:
|
70
|
+
return current >= threshold
|
71
|
+
|
72
|
+
for candidate in candidates:
|
73
|
+
current_distance = distance_fun(s, candidate)
|
74
|
+
|
75
|
+
if early_return_value is not None and can_return_early(
|
76
|
+
current_distance, early_return_value
|
77
|
+
):
|
78
|
+
return candidate, current_distance
|
79
|
+
if is_next_best(current_distance, best_distance):
|
80
|
+
best_distance = current_distance
|
81
|
+
best_candidate = candidate
|
82
|
+
|
83
|
+
return best_candidate, best_distance
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# Exclude a variety of commonly ignored directories.
|
2
|
+
exclude = [
|
3
|
+
".bzr",
|
4
|
+
".direnv",
|
5
|
+
".eggs",
|
6
|
+
".git",
|
7
|
+
".git-rewrite",
|
8
|
+
".hg",
|
9
|
+
".ipynb_checkpoints",
|
10
|
+
".mypy_cache",
|
11
|
+
".nox",
|
12
|
+
".pants.d",
|
13
|
+
".pyenv",
|
14
|
+
".pytest_cache",
|
15
|
+
".pytype",
|
16
|
+
".ruff_cache",
|
17
|
+
".svn",
|
18
|
+
".tox",
|
19
|
+
".venv",
|
20
|
+
".vscode",
|
21
|
+
"__pypackages__",
|
22
|
+
"_build",
|
23
|
+
"buck-out",
|
24
|
+
"build",
|
25
|
+
"dist",
|
26
|
+
"node_modules",
|
27
|
+
"site-packages",
|
28
|
+
"venv",
|
29
|
+
]
|
30
|
+
|
31
|
+
line-length = 100
|
32
|
+
indent-width = 4
|
33
|
+
|
34
|
+
# Assume Python 3.9
|
35
|
+
target-version = "py39"
|
36
|
+
|
37
|
+
[lint]
|
38
|
+
select = [
|
39
|
+
# pycodestyle
|
40
|
+
"E",
|
41
|
+
# Pyflakes
|
42
|
+
"F",
|
43
|
+
# pyupgrade
|
44
|
+
"UP",
|
45
|
+
# flake8-bugbear
|
46
|
+
"B",
|
47
|
+
# flake8-simplify
|
48
|
+
"SIM",
|
49
|
+
# isort
|
50
|
+
"I",
|
51
|
+
# refurb
|
52
|
+
"FURB",
|
53
|
+
]
|
54
|
+
ignore = []
|
55
|
+
|
56
|
+
# Allow fix for all enabled rules (when `--fix`) is provided.
|
57
|
+
fixable = ["ALL"]
|
58
|
+
unfixable = []
|
59
|
+
|
60
|
+
# Allow unused variables when underscore-prefixed.
|
61
|
+
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
|
62
|
+
|
63
|
+
[format]
|
64
|
+
# Like Black, use double quotes for strings.
|
65
|
+
quote-style = "double"
|
66
|
+
|
67
|
+
# Like Black, indent with spaces, rather than tabs.
|
68
|
+
indent-style = "space"
|
69
|
+
|
70
|
+
# Like Black, respect magic trailing commas.
|
71
|
+
skip-magic-trailing-comma = false
|
72
|
+
|
73
|
+
# Like Black, automatically detect the appropriate line ending.
|
74
|
+
line-ending = "auto"
|
75
|
+
|
76
|
+
# Enable auto-formatting of code examples in docstrings. Markdown,
|
77
|
+
# reStructuredText code/literal blocks and doctests are all supported.
|
78
|
+
#
|
79
|
+
# This is currently disabled by default, but it is planned for this
|
80
|
+
# to be opt-out in the future.
|
81
|
+
docstring-code-format = false
|
82
|
+
|
83
|
+
# Set the line length limit used when formatting code snippets in
|
84
|
+
# docstrings.
|
85
|
+
#
|
86
|
+
# This only has an effect when the `docstring-code-format` setting is
|
87
|
+
# enabled.
|
88
|
+
docstring-code-line-length = "dynamic"
|
@@ -0,0 +1,39 @@
|
|
1
|
+
from collections.abc import Iterable
|
2
|
+
|
3
|
+
import pytest
|
4
|
+
from ocr_stringdist import find_best_candidate, weighted_levenshtein_distance
|
5
|
+
|
6
|
+
|
7
|
+
@pytest.mark.parametrize(
|
8
|
+
["s", "candidates", "cost_map", "expected_match", "expected_distance"],
|
9
|
+
[
|
10
|
+
("", {"a"}, {}, "a", 1.0),
|
11
|
+
("R0BERT", {"ROBERT", "ALFRED", "Robert"}, {("0", "O"): 0.5}, "ROBERT", 0.5),
|
12
|
+
],
|
13
|
+
)
|
14
|
+
def test_find_best_candidate(
|
15
|
+
s: str,
|
16
|
+
candidates: Iterable[str],
|
17
|
+
cost_map: dict[tuple[str, str], float],
|
18
|
+
expected_match: str,
|
19
|
+
expected_distance: float,
|
20
|
+
) -> None:
|
21
|
+
actual_match, actual_distance = find_best_candidate(
|
22
|
+
s, candidates, lambda s1, s2: weighted_levenshtein_distance(s1, s2, cost_map=cost_map)
|
23
|
+
)
|
24
|
+
assert actual_match == expected_match
|
25
|
+
assert actual_distance == pytest.approx(expected_distance)
|
26
|
+
|
27
|
+
|
28
|
+
def test_find_best_candidate_early_return() -> None:
|
29
|
+
# Exact match is present, but a good enough match is found earlier.
|
30
|
+
assert find_best_candidate(
|
31
|
+
"HANNA", ["ANNA", "HANNA"], weighted_levenshtein_distance, early_return_value=2.0
|
32
|
+
) == ("ANNA", 1.0)
|
33
|
+
|
34
|
+
|
35
|
+
def test_find_best_candidate_maximize() -> None:
|
36
|
+
def similarity(s1: str, s2: str) -> float:
|
37
|
+
return float(s1 == s2)
|
38
|
+
|
39
|
+
assert find_best_candidate("one", {"one", "two"}, similarity, minimize=False) == ("one", 1.0)
|
@@ -0,0 +1,290 @@
|
|
1
|
+
version = 1
|
2
|
+
requires-python = ">=3.9"
|
3
|
+
|
4
|
+
[[package]]
|
5
|
+
name = "asttokens"
|
6
|
+
version = "3.0.0"
|
7
|
+
source = { registry = "https://pypi.org/simple" }
|
8
|
+
sdist = { url = "https://files.pythonhosted.org/packages/4a/e7/82da0a03e7ba5141f05cce0d302e6eed121ae055e0456ca228bf693984bc/asttokens-3.0.0.tar.gz", hash = "sha256:0dcd8baa8d62b0c1d118b399b2ddba3c4aff271d0d7a9e0d4c1681c79035bbc7", size = 61978 }
|
9
|
+
wheels = [
|
10
|
+
{ url = "https://files.pythonhosted.org/packages/25/8a/c46dcc25341b5bce5472c718902eb3d38600a903b14fa6aeecef3f21a46f/asttokens-3.0.0-py3-none-any.whl", hash = "sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2", size = 26918 },
|
11
|
+
]
|
12
|
+
|
13
|
+
[[package]]
|
14
|
+
name = "colorama"
|
15
|
+
version = "0.4.6"
|
16
|
+
source = { registry = "https://pypi.org/simple" }
|
17
|
+
sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 }
|
18
|
+
wheels = [
|
19
|
+
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 },
|
20
|
+
]
|
21
|
+
|
22
|
+
[[package]]
|
23
|
+
name = "exceptiongroup"
|
24
|
+
version = "1.2.2"
|
25
|
+
source = { registry = "https://pypi.org/simple" }
|
26
|
+
sdist = { url = "https://files.pythonhosted.org/packages/09/35/2495c4ac46b980e4ca1f6ad6db102322ef3ad2410b79fdde159a4b0f3b92/exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc", size = 28883 }
|
27
|
+
wheels = [
|
28
|
+
{ url = "https://files.pythonhosted.org/packages/02/cc/b7e31358aac6ed1ef2bb790a9746ac2c69bcb3c8588b41616914eb106eaf/exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b", size = 16453 },
|
29
|
+
]
|
30
|
+
|
31
|
+
[[package]]
|
32
|
+
name = "executing"
|
33
|
+
version = "2.2.0"
|
34
|
+
source = { registry = "https://pypi.org/simple" }
|
35
|
+
sdist = { url = "https://files.pythonhosted.org/packages/91/50/a9d80c47ff289c611ff12e63f7c5d13942c65d68125160cefd768c73e6e4/executing-2.2.0.tar.gz", hash = "sha256:5d108c028108fe2551d1a7b2e8b713341e2cb4fc0aa7dcf966fa4327a5226755", size = 978693 }
|
36
|
+
wheels = [
|
37
|
+
{ url = "https://files.pythonhosted.org/packages/7b/8f/c4d9bafc34ad7ad5d8dc16dd1347ee0e507a52c3adb6bfa8887e1c6a26ba/executing-2.2.0-py2.py3-none-any.whl", hash = "sha256:11387150cad388d62750327a53d3339fad4888b39a6fe233c3afbb54ecffd3aa", size = 26702 },
|
38
|
+
]
|
39
|
+
|
40
|
+
[[package]]
|
41
|
+
name = "icecream"
|
42
|
+
version = "2.1.4"
|
43
|
+
source = { registry = "https://pypi.org/simple" }
|
44
|
+
dependencies = [
|
45
|
+
{ name = "asttokens" },
|
46
|
+
{ name = "colorama" },
|
47
|
+
{ name = "executing" },
|
48
|
+
{ name = "pygments" },
|
49
|
+
]
|
50
|
+
sdist = { url = "https://files.pythonhosted.org/packages/78/5e/9f41831f032b9ce456c919c4989952562fcc2b0eb8c038080c24ce20d6cd/icecream-2.1.4.tar.gz", hash = "sha256:58755e58397d5350a76f25976dee7b607f5febb3c6e1cddfe6b1951896e91573", size = 15872 }
|
51
|
+
wheels = [
|
52
|
+
{ url = "https://files.pythonhosted.org/packages/57/1d/43ef7a6875190e6745ffcd1b12c7aaa7efed082897401e311ee1cd75c8b2/icecream-2.1.4-py3-none-any.whl", hash = "sha256:7bb715f69102cae871b3a361c3b656536db02cfcadac9664c673581cac4df4fd", size = 14782 },
|
53
|
+
]
|
54
|
+
|
55
|
+
[[package]]
|
56
|
+
name = "iniconfig"
|
57
|
+
version = "2.1.0"
|
58
|
+
source = { registry = "https://pypi.org/simple" }
|
59
|
+
sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793 }
|
60
|
+
wheels = [
|
61
|
+
{ url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050 },
|
62
|
+
]
|
63
|
+
|
64
|
+
[[package]]
|
65
|
+
name = "maturin"
|
66
|
+
version = "1.8.3"
|
67
|
+
source = { registry = "https://pypi.org/simple" }
|
68
|
+
dependencies = [
|
69
|
+
{ name = "tomli", marker = "python_full_version < '3.11'" },
|
70
|
+
]
|
71
|
+
sdist = { url = "https://files.pythonhosted.org/packages/30/0b/3fd746cf5cfa3c8d7e20ea08c0dbc2c2c765ae051d0fc43d808a38bc9548/maturin-1.8.3.tar.gz", hash = "sha256:304762f86fd53a8031b1bf006d12572a2aa0a5235485031113195cc0152e1e12", size = 199656 }
|
72
|
+
wheels = [
|
73
|
+
{ url = "https://files.pythonhosted.org/packages/78/80/08579d0184ba743345bbd350a3b6419510ff8a4f6e9e671f713160d41fbb/maturin-1.8.3-py3-none-linux_armv6l.whl", hash = "sha256:fa27466b627150123729b2e611f9f9cfade84d24385d72c6877f78c30de30e89", size = 7758366 },
|
74
|
+
{ url = "https://files.pythonhosted.org/packages/87/1c/00755d28ae277daa828e183c3d118e2923e8b8f0cba4ff708b15d274ac0e/maturin-1.8.3-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:583404d20d7f1d9c8f3c18dcab9014faacabbed6be02da80062c06cd0e279554", size = 15201378 },
|
75
|
+
{ url = "https://files.pythonhosted.org/packages/58/9f/b8738dc55ba3eb149ad2686d3f9b3c24e44b7baff46cc6baa85e5dc8cf5e/maturin-1.8.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:f9ffdac53dfe0089cf19b597410bc552eb34c856ddb41482b243a695e8b549d3", size = 7934215 },
|
76
|
+
{ url = "https://files.pythonhosted.org/packages/18/68/300f1a279486d6f63b624a76b81f0fba82545d027127c1ca4d5ded0d1b43/maturin-1.8.3-py3-none-manylinux_2_12_i686.manylinux2010_i686.musllinux_1_1_i686.whl", hash = "sha256:7949a4a17637341f84e88f4cbf0c155998780bbb7a145ed735725b907881c0ae", size = 7791270 },
|
77
|
+
{ url = "https://files.pythonhosted.org/packages/2e/6d/bf1b8bb9a8b1d9adad242b4089794be318446142975762d04f04ffabae40/maturin-1.8.3-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.musllinux_1_1_x86_64.whl", hash = "sha256:11564fac7486313b7baf3aa4e82c20e1b20364aad3fde2ccbc4c07693c0b7e16", size = 8282824 },
|
78
|
+
{ url = "https://files.pythonhosted.org/packages/18/e9/c601de8699e546774d3f9e761eab374988f88e4ed7006afbb5ff61bb41c0/maturin-1.8.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:8555d8701cdba6c19c4705a22ce4d2a1814efd792f55dc5873262ff903317540", size = 7595855 },
|
79
|
+
{ url = "https://files.pythonhosted.org/packages/34/b8/82ae650e6b589289f4219a480f2b220bcf3d9391ae9ea02cc7a58ef59cfc/maturin-1.8.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:5b2a513468c1c9b4d1728d4b6d3d044b7c183985ef819c9ef15e373b70d99c7d", size = 7634888 },
|
80
|
+
{ url = "https://files.pythonhosted.org/packages/ac/4a/4f898a66cf4697267c447a6f240b6cbcc2dcacd3cab89735bfbd44810be1/maturin-1.8.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.musllinux_1_1_ppc64le.whl", hash = "sha256:2fe8fdff420cfccde127bbc3d8e40835163dcebb6d28c49fffd9aaf1e6ec1090", size = 9810616 },
|
81
|
+
{ url = "https://files.pythonhosted.org/packages/31/bd/21b0d471e6ade0801f27c33672bca4d563eb1d1e624e534f3bef8a01b1ac/maturin-1.8.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:22cd8b6dc490fee99a62590f914f0c04ddad1dd6dbd5c7e933b3f882b1bd78c2", size = 10923701 },
|
82
|
+
{ url = "https://files.pythonhosted.org/packages/6c/07/85c32f03ed757c0626e2fc5a9d6454988228be96a756991702a2a757691b/maturin-1.8.3-py3-none-win32.whl", hash = "sha256:2427924546c9d1079b1c0c6c5c1d380e1b8187baba4e6342cca81597a0f3d697", size = 7016502 },
|
83
|
+
{ url = "https://files.pythonhosted.org/packages/d5/62/f92a130a370dd7aca13c316844b82853647f048cfe1594a81f628ab7101f/maturin-1.8.3-py3-none-win_amd64.whl", hash = "sha256:85f2b882d8235c1c1cb0a38d382ccd5b3ba0674d99cb548d49df9342cc688e36", size = 7953286 },
|
84
|
+
{ url = "https://files.pythonhosted.org/packages/04/95/8379140838cd95472de843e982d0bf674e8dbf25a899c44e2f76b15704d9/maturin-1.8.3-py3-none-win_arm64.whl", hash = "sha256:33939aabf9a06a8a14ca6c399d32616c7e574fcca8d4ff6dcd984441051f32fb", size = 6687772 },
|
85
|
+
]
|
86
|
+
|
87
|
+
[[package]]
|
88
|
+
name = "mypy"
|
89
|
+
version = "1.15.0"
|
90
|
+
source = { registry = "https://pypi.org/simple" }
|
91
|
+
dependencies = [
|
92
|
+
{ name = "mypy-extensions" },
|
93
|
+
{ name = "tomli", marker = "python_full_version < '3.11'" },
|
94
|
+
{ name = "typing-extensions" },
|
95
|
+
]
|
96
|
+
sdist = { url = "https://files.pythonhosted.org/packages/ce/43/d5e49a86afa64bd3839ea0d5b9c7103487007d728e1293f52525d6d5486a/mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43", size = 3239717 }
|
97
|
+
wheels = [
|
98
|
+
{ url = "https://files.pythonhosted.org/packages/68/f8/65a7ce8d0e09b6329ad0c8d40330d100ea343bd4dd04c4f8ae26462d0a17/mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13", size = 10738433 },
|
99
|
+
{ url = "https://files.pythonhosted.org/packages/b4/95/9c0ecb8eacfe048583706249439ff52105b3f552ea9c4024166c03224270/mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559", size = 9861472 },
|
100
|
+
{ url = "https://files.pythonhosted.org/packages/84/09/9ec95e982e282e20c0d5407bc65031dfd0f0f8ecc66b69538296e06fcbee/mypy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b", size = 11611424 },
|
101
|
+
{ url = "https://files.pythonhosted.org/packages/78/13/f7d14e55865036a1e6a0a69580c240f43bc1f37407fe9235c0d4ef25ffb0/mypy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3", size = 12365450 },
|
102
|
+
{ url = "https://files.pythonhosted.org/packages/48/e1/301a73852d40c241e915ac6d7bcd7fedd47d519246db2d7b86b9d7e7a0cb/mypy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b", size = 12551765 },
|
103
|
+
{ url = "https://files.pythonhosted.org/packages/77/ba/c37bc323ae5fe7f3f15a28e06ab012cd0b7552886118943e90b15af31195/mypy-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828", size = 9274701 },
|
104
|
+
{ url = "https://files.pythonhosted.org/packages/03/bc/f6339726c627bd7ca1ce0fa56c9ae2d0144604a319e0e339bdadafbbb599/mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f", size = 10662338 },
|
105
|
+
{ url = "https://files.pythonhosted.org/packages/e2/90/8dcf506ca1a09b0d17555cc00cd69aee402c203911410136cd716559efe7/mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5", size = 9787540 },
|
106
|
+
{ url = "https://files.pythonhosted.org/packages/05/05/a10f9479681e5da09ef2f9426f650d7b550d4bafbef683b69aad1ba87457/mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e", size = 11538051 },
|
107
|
+
{ url = "https://files.pythonhosted.org/packages/e9/9a/1f7d18b30edd57441a6411fcbc0c6869448d1a4bacbaee60656ac0fc29c8/mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c", size = 12286751 },
|
108
|
+
{ url = "https://files.pythonhosted.org/packages/72/af/19ff499b6f1dafcaf56f9881f7a965ac2f474f69f6f618b5175b044299f5/mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f", size = 12421783 },
|
109
|
+
{ url = "https://files.pythonhosted.org/packages/96/39/11b57431a1f686c1aed54bf794870efe0f6aeca11aca281a0bd87a5ad42c/mypy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f", size = 9265618 },
|
110
|
+
{ url = "https://files.pythonhosted.org/packages/98/3a/03c74331c5eb8bd025734e04c9840532226775c47a2c39b56a0c8d4f128d/mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd", size = 10793981 },
|
111
|
+
{ url = "https://files.pythonhosted.org/packages/f0/1a/41759b18f2cfd568848a37c89030aeb03534411eef981df621d8fad08a1d/mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f", size = 9749175 },
|
112
|
+
{ url = "https://files.pythonhosted.org/packages/12/7e/873481abf1ef112c582db832740f4c11b2bfa510e829d6da29b0ab8c3f9c/mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464", size = 11455675 },
|
113
|
+
{ url = "https://files.pythonhosted.org/packages/b3/d0/92ae4cde706923a2d3f2d6c39629134063ff64b9dedca9c1388363da072d/mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee", size = 12410020 },
|
114
|
+
{ url = "https://files.pythonhosted.org/packages/46/8b/df49974b337cce35f828ba6fda228152d6db45fed4c86ba56ffe442434fd/mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e", size = 12498582 },
|
115
|
+
{ url = "https://files.pythonhosted.org/packages/13/50/da5203fcf6c53044a0b699939f31075c45ae8a4cadf538a9069b165c1050/mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22", size = 9366614 },
|
116
|
+
{ url = "https://files.pythonhosted.org/packages/6a/9b/fd2e05d6ffff24d912f150b87db9e364fa8282045c875654ce7e32fffa66/mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445", size = 10788592 },
|
117
|
+
{ url = "https://files.pythonhosted.org/packages/74/37/b246d711c28a03ead1fd906bbc7106659aed7c089d55fe40dd58db812628/mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d", size = 9753611 },
|
118
|
+
{ url = "https://files.pythonhosted.org/packages/a6/ac/395808a92e10cfdac8003c3de9a2ab6dc7cde6c0d2a4df3df1b815ffd067/mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5", size = 11438443 },
|
119
|
+
{ url = "https://files.pythonhosted.org/packages/d2/8b/801aa06445d2de3895f59e476f38f3f8d610ef5d6908245f07d002676cbf/mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036", size = 12402541 },
|
120
|
+
{ url = "https://files.pythonhosted.org/packages/c7/67/5a4268782eb77344cc613a4cf23540928e41f018a9a1ec4c6882baf20ab8/mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357", size = 12494348 },
|
121
|
+
{ url = "https://files.pythonhosted.org/packages/83/3e/57bb447f7bbbfaabf1712d96f9df142624a386d98fb026a761532526057e/mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf", size = 9373648 },
|
122
|
+
{ url = "https://files.pythonhosted.org/packages/5a/fa/79cf41a55b682794abe71372151dbbf856e3008f6767057229e6649d294a/mypy-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e601a7fa172c2131bff456bb3ee08a88360760d0d2f8cbd7a75a65497e2df078", size = 10737129 },
|
123
|
+
{ url = "https://files.pythonhosted.org/packages/d3/33/dd8feb2597d648de29e3da0a8bf4e1afbda472964d2a4a0052203a6f3594/mypy-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:712e962a6357634fef20412699a3655c610110e01cdaa6180acec7fc9f8513ba", size = 9856335 },
|
124
|
+
{ url = "https://files.pythonhosted.org/packages/e4/b5/74508959c1b06b96674b364ffeb7ae5802646b32929b7701fc6b18447592/mypy-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95579473af29ab73a10bada2f9722856792a36ec5af5399b653aa28360290a5", size = 11611935 },
|
125
|
+
{ url = "https://files.pythonhosted.org/packages/6c/53/da61b9d9973efcd6507183fdad96606996191657fe79701b2c818714d573/mypy-1.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f8722560a14cde92fdb1e31597760dc35f9f5524cce17836c0d22841830fd5b", size = 12365827 },
|
126
|
+
{ url = "https://files.pythonhosted.org/packages/c1/72/965bd9ee89540c79a25778cc080c7e6ef40aa1eeac4d52cec7eae6eb5228/mypy-1.15.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fbb8da62dc352133d7d7ca90ed2fb0e9d42bb1a32724c287d3c76c58cbaa9c2", size = 12541924 },
|
127
|
+
{ url = "https://files.pythonhosted.org/packages/46/d0/f41645c2eb263e6c77ada7d76f894c580c9ddb20d77f0c24d34273a4dab2/mypy-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:d10d994b41fb3497719bbf866f227b3489048ea4bbbb5015357db306249f7980", size = 9271176 },
|
128
|
+
{ url = "https://files.pythonhosted.org/packages/09/4e/a7d65c7322c510de2c409ff3828b03354a7c43f5a8ed458a7a131b41c7b9/mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e", size = 2221777 },
|
129
|
+
]
|
130
|
+
|
131
|
+
[[package]]
|
132
|
+
name = "mypy-extensions"
|
133
|
+
version = "1.0.0"
|
134
|
+
source = { registry = "https://pypi.org/simple" }
|
135
|
+
sdist = { url = "https://files.pythonhosted.org/packages/98/a4/1ab47638b92648243faf97a5aeb6ea83059cc3624972ab6b8d2316078d3f/mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782", size = 4433 }
|
136
|
+
wheels = [
|
137
|
+
{ url = "https://files.pythonhosted.org/packages/2a/e2/5d3f6ada4297caebe1a2add3b126fe800c96f56dbe5d1988a2cbe0b267aa/mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", size = 4695 },
|
138
|
+
]
|
139
|
+
|
140
|
+
[[package]]
|
141
|
+
name = "ocr-stringdist"
|
142
|
+
source = { editable = "." }
|
143
|
+
|
144
|
+
[package.dev-dependencies]
|
145
|
+
dev = [
|
146
|
+
{ name = "icecream" },
|
147
|
+
{ name = "maturin" },
|
148
|
+
{ name = "mypy" },
|
149
|
+
{ name = "pytest" },
|
150
|
+
{ name = "ruff" },
|
151
|
+
{ name = "wheel" },
|
152
|
+
]
|
153
|
+
|
154
|
+
[package.metadata]
|
155
|
+
|
156
|
+
[package.metadata.requires-dev]
|
157
|
+
dev = [
|
158
|
+
{ name = "icecream", specifier = ">=2.1.4" },
|
159
|
+
{ name = "maturin", specifier = ">=1.8.3" },
|
160
|
+
{ name = "mypy", specifier = ">=1.15.0" },
|
161
|
+
{ name = "pytest", specifier = ">=8.3.5" },
|
162
|
+
{ name = "ruff", specifier = ">=0.11.6" },
|
163
|
+
{ name = "wheel", specifier = ">=0.45.1" },
|
164
|
+
]
|
165
|
+
|
166
|
+
[[package]]
|
167
|
+
name = "packaging"
|
168
|
+
version = "25.0"
|
169
|
+
source = { registry = "https://pypi.org/simple" }
|
170
|
+
sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727 }
|
171
|
+
wheels = [
|
172
|
+
{ url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469 },
|
173
|
+
]
|
174
|
+
|
175
|
+
[[package]]
|
176
|
+
name = "pluggy"
|
177
|
+
version = "1.5.0"
|
178
|
+
source = { registry = "https://pypi.org/simple" }
|
179
|
+
sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955 }
|
180
|
+
wheels = [
|
181
|
+
{ url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556 },
|
182
|
+
]
|
183
|
+
|
184
|
+
[[package]]
|
185
|
+
name = "pygments"
|
186
|
+
version = "2.19.1"
|
187
|
+
source = { registry = "https://pypi.org/simple" }
|
188
|
+
sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581 }
|
189
|
+
wheels = [
|
190
|
+
{ url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293 },
|
191
|
+
]
|
192
|
+
|
193
|
+
[[package]]
|
194
|
+
name = "pytest"
|
195
|
+
version = "8.3.5"
|
196
|
+
source = { registry = "https://pypi.org/simple" }
|
197
|
+
dependencies = [
|
198
|
+
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
199
|
+
{ name = "exceptiongroup", marker = "python_full_version < '3.11'" },
|
200
|
+
{ name = "iniconfig" },
|
201
|
+
{ name = "packaging" },
|
202
|
+
{ name = "pluggy" },
|
203
|
+
{ name = "tomli", marker = "python_full_version < '3.11'" },
|
204
|
+
]
|
205
|
+
sdist = { url = "https://files.pythonhosted.org/packages/ae/3c/c9d525a414d506893f0cd8a8d0de7706446213181570cdbd766691164e40/pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845", size = 1450891 }
|
206
|
+
wheels = [
|
207
|
+
{ url = "https://files.pythonhosted.org/packages/30/3d/64ad57c803f1fa1e963a7946b6e0fea4a70df53c1a7fed304586539c2bac/pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", size = 343634 },
|
208
|
+
]
|
209
|
+
|
210
|
+
[[package]]
|
211
|
+
name = "ruff"
|
212
|
+
version = "0.11.6"
|
213
|
+
source = { registry = "https://pypi.org/simple" }
|
214
|
+
sdist = { url = "https://files.pythonhosted.org/packages/d9/11/bcef6784c7e5d200b8a1f5c2ddf53e5da0efec37e6e5a44d163fb97e04ba/ruff-0.11.6.tar.gz", hash = "sha256:bec8bcc3ac228a45ccc811e45f7eb61b950dbf4cf31a67fa89352574b01c7d79", size = 4010053 }
|
215
|
+
wheels = [
|
216
|
+
{ url = "https://files.pythonhosted.org/packages/6e/1f/8848b625100ebcc8740c8bac5b5dd8ba97dd4ee210970e98832092c1635b/ruff-0.11.6-py3-none-linux_armv6l.whl", hash = "sha256:d84dcbe74cf9356d1bdb4a78cf74fd47c740bf7bdeb7529068f69b08272239a1", size = 10248105 },
|
217
|
+
{ url = "https://files.pythonhosted.org/packages/e0/47/c44036e70c6cc11e6ee24399c2a1e1f1e99be5152bd7dff0190e4b325b76/ruff-0.11.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:9bc583628e1096148011a5d51ff3c836f51899e61112e03e5f2b1573a9b726de", size = 11001494 },
|
218
|
+
{ url = "https://files.pythonhosted.org/packages/ed/5b/170444061650202d84d316e8f112de02d092bff71fafe060d3542f5bc5df/ruff-0.11.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:f2959049faeb5ba5e3b378709e9d1bf0cab06528b306b9dd6ebd2a312127964a", size = 10352151 },
|
219
|
+
{ url = "https://files.pythonhosted.org/packages/ff/91/f02839fb3787c678e112c8865f2c3e87cfe1744dcc96ff9fc56cfb97dda2/ruff-0.11.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63c5d4e30d9d0de7fedbfb3e9e20d134b73a30c1e74b596f40f0629d5c28a193", size = 10541951 },
|
220
|
+
{ url = "https://files.pythonhosted.org/packages/9e/f3/c09933306096ff7a08abede3cc2534d6fcf5529ccd26504c16bf363989b5/ruff-0.11.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:26a4b9a4e1439f7d0a091c6763a100cef8fbdc10d68593df6f3cfa5abdd9246e", size = 10079195 },
|
221
|
+
{ url = "https://files.pythonhosted.org/packages/e0/0d/a87f8933fccbc0d8c653cfbf44bedda69c9582ba09210a309c066794e2ee/ruff-0.11.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b5edf270223dd622218256569636dc3e708c2cb989242262fe378609eccf1308", size = 11698918 },
|
222
|
+
{ url = "https://files.pythonhosted.org/packages/52/7d/8eac0bd083ea8a0b55b7e4628428203441ca68cd55e0b67c135a4bc6e309/ruff-0.11.6-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:f55844e818206a9dd31ff27f91385afb538067e2dc0beb05f82c293ab84f7d55", size = 12319426 },
|
223
|
+
{ url = "https://files.pythonhosted.org/packages/c2/dc/d0c17d875662d0c86fadcf4ca014ab2001f867621b793d5d7eef01b9dcce/ruff-0.11.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d8f782286c5ff562e4e00344f954b9320026d8e3fae2ba9e6948443fafd9ffc", size = 11791012 },
|
224
|
+
{ url = "https://files.pythonhosted.org/packages/f9/f3/81a1aea17f1065449a72509fc7ccc3659cf93148b136ff2a8291c4bc3ef1/ruff-0.11.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:01c63ba219514271cee955cd0adc26a4083df1956d57847978383b0e50ffd7d2", size = 13949947 },
|
225
|
+
{ url = "https://files.pythonhosted.org/packages/61/9f/a3e34de425a668284e7024ee6fd41f452f6fa9d817f1f3495b46e5e3a407/ruff-0.11.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15adac20ef2ca296dd3d8e2bedc6202ea6de81c091a74661c3666e5c4c223ff6", size = 11471753 },
|
226
|
+
{ url = "https://files.pythonhosted.org/packages/df/c5/4a57a86d12542c0f6e2744f262257b2aa5a3783098ec14e40f3e4b3a354a/ruff-0.11.6-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:4dd6b09e98144ad7aec026f5588e493c65057d1b387dd937d7787baa531d9bc2", size = 10417121 },
|
227
|
+
{ url = "https://files.pythonhosted.org/packages/58/3f/a3b4346dff07ef5b862e2ba06d98fcbf71f66f04cf01d375e871382b5e4b/ruff-0.11.6-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:45b2e1d6c0eed89c248d024ea95074d0e09988d8e7b1dad8d3ab9a67017a5b03", size = 10073829 },
|
228
|
+
{ url = "https://files.pythonhosted.org/packages/93/cc/7ed02e0b86a649216b845b3ac66ed55d8aa86f5898c5f1691797f408fcb9/ruff-0.11.6-py3-none-musllinux_1_2_i686.whl", hash = "sha256:bd40de4115b2ec4850302f1a1d8067f42e70b4990b68838ccb9ccd9f110c5e8b", size = 11076108 },
|
229
|
+
{ url = "https://files.pythonhosted.org/packages/39/5e/5b09840fef0eff1a6fa1dea6296c07d09c17cb6fb94ed5593aa591b50460/ruff-0.11.6-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:77cda2dfbac1ab73aef5e514c4cbfc4ec1fbef4b84a44c736cc26f61b3814cd9", size = 11512366 },
|
230
|
+
{ url = "https://files.pythonhosted.org/packages/6f/4c/1cd5a84a412d3626335ae69f5f9de2bb554eea0faf46deb1f0cb48534042/ruff-0.11.6-py3-none-win32.whl", hash = "sha256:5151a871554be3036cd6e51d0ec6eef56334d74dfe1702de717a995ee3d5b287", size = 10485900 },
|
231
|
+
{ url = "https://files.pythonhosted.org/packages/42/46/8997872bc44d43df986491c18d4418f1caff03bc47b7f381261d62c23442/ruff-0.11.6-py3-none-win_amd64.whl", hash = "sha256:cce85721d09c51f3b782c331b0abd07e9d7d5f775840379c640606d3159cae0e", size = 11558592 },
|
232
|
+
{ url = "https://files.pythonhosted.org/packages/d7/6a/65fecd51a9ca19e1477c3879a7fda24f8904174d1275b419422ac00f6eee/ruff-0.11.6-py3-none-win_arm64.whl", hash = "sha256:3567ba0d07fb170b1b48d944715e3294b77f5b7679e8ba258199a250383ccb79", size = 10682766 },
|
233
|
+
]
|
234
|
+
|
235
|
+
[[package]]
|
236
|
+
name = "tomli"
|
237
|
+
version = "2.2.1"
|
238
|
+
source = { registry = "https://pypi.org/simple" }
|
239
|
+
sdist = { url = "https://files.pythonhosted.org/packages/18/87/302344fed471e44a87289cf4967697d07e532f2421fdaf868a303cbae4ff/tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff", size = 17175 }
|
240
|
+
wheels = [
|
241
|
+
{ url = "https://files.pythonhosted.org/packages/43/ca/75707e6efa2b37c77dadb324ae7d9571cb424e61ea73fad7c56c2d14527f/tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249", size = 131077 },
|
242
|
+
{ url = "https://files.pythonhosted.org/packages/c7/16/51ae563a8615d472fdbffc43a3f3d46588c264ac4f024f63f01283becfbb/tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6", size = 123429 },
|
243
|
+
{ url = "https://files.pythonhosted.org/packages/f1/dd/4f6cd1e7b160041db83c694abc78e100473c15d54620083dbd5aae7b990e/tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a", size = 226067 },
|
244
|
+
{ url = "https://files.pythonhosted.org/packages/a9/6b/c54ede5dc70d648cc6361eaf429304b02f2871a345bbdd51e993d6cdf550/tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee", size = 236030 },
|
245
|
+
{ url = "https://files.pythonhosted.org/packages/1f/47/999514fa49cfaf7a92c805a86c3c43f4215621855d151b61c602abb38091/tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e", size = 240898 },
|
246
|
+
{ url = "https://files.pythonhosted.org/packages/73/41/0a01279a7ae09ee1573b423318e7934674ce06eb33f50936655071d81a24/tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4", size = 229894 },
|
247
|
+
{ url = "https://files.pythonhosted.org/packages/55/18/5d8bc5b0a0362311ce4d18830a5d28943667599a60d20118074ea1b01bb7/tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106", size = 245319 },
|
248
|
+
{ url = "https://files.pythonhosted.org/packages/92/a3/7ade0576d17f3cdf5ff44d61390d4b3febb8a9fc2b480c75c47ea048c646/tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8", size = 238273 },
|
249
|
+
{ url = "https://files.pythonhosted.org/packages/72/6f/fa64ef058ac1446a1e51110c375339b3ec6be245af9d14c87c4a6412dd32/tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff", size = 98310 },
|
250
|
+
{ url = "https://files.pythonhosted.org/packages/6a/1c/4a2dcde4a51b81be3530565e92eda625d94dafb46dbeb15069df4caffc34/tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b", size = 108309 },
|
251
|
+
{ url = "https://files.pythonhosted.org/packages/52/e1/f8af4c2fcde17500422858155aeb0d7e93477a0d59a98e56cbfe75070fd0/tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea", size = 132762 },
|
252
|
+
{ url = "https://files.pythonhosted.org/packages/03/b8/152c68bb84fc00396b83e7bbddd5ec0bd3dd409db4195e2a9b3e398ad2e3/tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8", size = 123453 },
|
253
|
+
{ url = "https://files.pythonhosted.org/packages/c8/d6/fc9267af9166f79ac528ff7e8c55c8181ded34eb4b0e93daa767b8841573/tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192", size = 233486 },
|
254
|
+
{ url = "https://files.pythonhosted.org/packages/5c/51/51c3f2884d7bab89af25f678447ea7d297b53b5a3b5730a7cb2ef6069f07/tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222", size = 242349 },
|
255
|
+
{ url = "https://files.pythonhosted.org/packages/ab/df/bfa89627d13a5cc22402e441e8a931ef2108403db390ff3345c05253935e/tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77", size = 252159 },
|
256
|
+
{ url = "https://files.pythonhosted.org/packages/9e/6e/fa2b916dced65763a5168c6ccb91066f7639bdc88b48adda990db10c8c0b/tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6", size = 237243 },
|
257
|
+
{ url = "https://files.pythonhosted.org/packages/b4/04/885d3b1f650e1153cbb93a6a9782c58a972b94ea4483ae4ac5cedd5e4a09/tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd", size = 259645 },
|
258
|
+
{ url = "https://files.pythonhosted.org/packages/9c/de/6b432d66e986e501586da298e28ebeefd3edc2c780f3ad73d22566034239/tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e", size = 244584 },
|
259
|
+
{ url = "https://files.pythonhosted.org/packages/1c/9a/47c0449b98e6e7d1be6cbac02f93dd79003234ddc4aaab6ba07a9a7482e2/tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98", size = 98875 },
|
260
|
+
{ url = "https://files.pythonhosted.org/packages/ef/60/9b9638f081c6f1261e2688bd487625cd1e660d0a85bd469e91d8db969734/tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4", size = 109418 },
|
261
|
+
{ url = "https://files.pythonhosted.org/packages/04/90/2ee5f2e0362cb8a0b6499dc44f4d7d48f8fff06d28ba46e6f1eaa61a1388/tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7", size = 132708 },
|
262
|
+
{ url = "https://files.pythonhosted.org/packages/c0/ec/46b4108816de6b385141f082ba99e315501ccd0a2ea23db4a100dd3990ea/tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c", size = 123582 },
|
263
|
+
{ url = "https://files.pythonhosted.org/packages/a0/bd/b470466d0137b37b68d24556c38a0cc819e8febe392d5b199dcd7f578365/tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13", size = 232543 },
|
264
|
+
{ url = "https://files.pythonhosted.org/packages/d9/e5/82e80ff3b751373f7cead2815bcbe2d51c895b3c990686741a8e56ec42ab/tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281", size = 241691 },
|
265
|
+
{ url = "https://files.pythonhosted.org/packages/05/7e/2a110bc2713557d6a1bfb06af23dd01e7dde52b6ee7dadc589868f9abfac/tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272", size = 251170 },
|
266
|
+
{ url = "https://files.pythonhosted.org/packages/64/7b/22d713946efe00e0adbcdfd6d1aa119ae03fd0b60ebed51ebb3fa9f5a2e5/tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140", size = 236530 },
|
267
|
+
{ url = "https://files.pythonhosted.org/packages/38/31/3a76f67da4b0cf37b742ca76beaf819dca0ebef26d78fc794a576e08accf/tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2", size = 258666 },
|
268
|
+
{ url = "https://files.pythonhosted.org/packages/07/10/5af1293da642aded87e8a988753945d0cf7e00a9452d3911dd3bb354c9e2/tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744", size = 243954 },
|
269
|
+
{ url = "https://files.pythonhosted.org/packages/5b/b9/1ed31d167be802da0fc95020d04cd27b7d7065cc6fbefdd2f9186f60d7bd/tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec", size = 98724 },
|
270
|
+
{ url = "https://files.pythonhosted.org/packages/c7/32/b0963458706accd9afcfeb867c0f9175a741bf7b19cd424230714d722198/tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69", size = 109383 },
|
271
|
+
{ url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", size = 14257 },
|
272
|
+
]
|
273
|
+
|
274
|
+
[[package]]
|
275
|
+
name = "typing-extensions"
|
276
|
+
version = "4.13.2"
|
277
|
+
source = { registry = "https://pypi.org/simple" }
|
278
|
+
sdist = { url = "https://files.pythonhosted.org/packages/f6/37/23083fcd6e35492953e8d2aaaa68b860eb422b34627b13f2ce3eb6106061/typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef", size = 106967 }
|
279
|
+
wheels = [
|
280
|
+
{ url = "https://files.pythonhosted.org/packages/8b/54/b1ae86c0973cc6f0210b53d508ca3641fb6d0c56823f288d108bc7ab3cc8/typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c", size = 45806 },
|
281
|
+
]
|
282
|
+
|
283
|
+
[[package]]
|
284
|
+
name = "wheel"
|
285
|
+
version = "0.45.1"
|
286
|
+
source = { registry = "https://pypi.org/simple" }
|
287
|
+
sdist = { url = "https://files.pythonhosted.org/packages/8a/98/2d9906746cdc6a6ef809ae6338005b3f21bb568bea3165cfc6a243fdc25c/wheel-0.45.1.tar.gz", hash = "sha256:661e1abd9198507b1409a20c02106d9670b2576e916d58f520316666abca6729", size = 107545 }
|
288
|
+
wheels = [
|
289
|
+
{ url = "https://files.pythonhosted.org/packages/0b/2c/87f3254fd8ffd29e4c02732eee68a83a1d3c346ae39bc6822dcbcb697f2b/wheel-0.45.1-py3-none-any.whl", hash = "sha256:708e7481cc80179af0e556bbf0cc00b8444c7321e2700b8d8580231d13017248", size = 72494 },
|
290
|
+
]
|
ocr_stringdist-0.0.2/Justfile
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
ocr_distance_map: dict[tuple[str, str], float] = {
|
2
|
-
("G", "6"): 0.2,
|
3
|
-
("O", "0"): 0.2,
|
4
|
-
("o", "0"): 0.2,
|
5
|
-
("l", "1"): 0.2,
|
6
|
-
("I", "1"): 0.2,
|
7
|
-
("2", "Z"): 0.2,
|
8
|
-
("B", "8"): 0.2,
|
9
|
-
("S", "5"): 0.3,
|
10
|
-
("s", "5"): 0.3,
|
11
|
-
("E", "F"): 0.8,
|
12
|
-
}
|
13
|
-
"""
|
14
|
-
Pre-defined distance map between characters, considering common OCR errors.
|
15
|
-
The distances are between 0 and 1.
|
16
|
-
"""
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|