deepdoctection 0.45.0__py3-none-any.whl → 0.46.1__py3-none-any.whl

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.

Potentially problematic release.


This version of deepdoctection might be problematic. Click here for more details.

@@ -8,6 +8,7 @@
8
8
  Utilities for maintaining dependencies and dealing with external library packages. Parts of this file is adapted from
9
9
  <https://github.com/huggingface/transformers/blob/master/src/transformers/file_utils.py>
10
10
  """
11
+ import importlib.metadata
11
12
  import importlib.util
12
13
  import multiprocessing as mp
13
14
  import string
@@ -17,7 +18,6 @@ from shutil import which
17
18
  from types import ModuleType
18
19
  from typing import Any, Union, no_type_check
19
20
 
20
- import importlib_metadata
21
21
  import numpy as np
22
22
  from packaging import version
23
23
 
@@ -72,9 +72,9 @@ def get_tf_version() -> str:
72
72
 
73
73
  for pkg in candidates:
74
74
  try:
75
- tf_version = importlib_metadata.version(pkg)
75
+ tf_version = importlib.metadata.version(pkg)
76
76
  break
77
- except importlib_metadata.PackageNotFoundError:
77
+ except importlib.metadata.PackageNotFoundError:
78
78
  pass
79
79
  return tf_version
80
80
 
@@ -175,6 +175,19 @@ def get_pytorch_requirement() -> Requirement:
175
175
  return "torch", pytorch_available(), _PYTORCH_ERR_MSG
176
176
 
177
177
 
178
+ _PYZMQ_AVAILABLE = importlib.util.find_spec("zmq") is not None
179
+
180
+
181
+ def pyzmq_available() -> bool:
182
+ """
183
+ Returns whether pyzmq is installed.
184
+
185
+ Returns:
186
+ bool: True if pyzmq is installed, False otherwise.
187
+ """
188
+ return bool(_PYZMQ_AVAILABLE)
189
+
190
+
178
191
  # lxml
179
192
  _LXML_AVAILABLE = importlib.util.find_spec("lxml") is not None
180
193
  _LXML_ERR_MSG = f"lxml must be installed. {_GENERIC_ERR_MSG}"
@@ -232,7 +245,7 @@ _DISTANCE_ERR_MSG = f"distance must be installed. {_GENERIC_ERR_MSG}"
232
245
 
233
246
  def distance_available() -> bool:
234
247
  """
235
- Returns whether `distance` is available.
248
+ Returns True if `distance` is available.
236
249
 
237
250
  Returns:
238
251
  bool: `True` if `distance` is available, False otherwise.
@@ -250,6 +263,22 @@ def get_distance_requirement() -> Requirement:
250
263
  return "distance", distance_available(), _DISTANCE_ERR_MSG
251
264
 
252
265
 
266
+ # networkx
267
+ _NETWORKX_AVAILABLE = importlib.util.find_spec("networkx") is not None
268
+
269
+
270
+ def networkx_available() -> bool:
271
+ """
272
+ Checks if networkx is installed.
273
+
274
+ Returns:
275
+ bool: True if networkx is installed, False otherwise.
276
+ :return:
277
+ """
278
+ return bool(_NETWORKX_AVAILABLE)
279
+
280
+
281
+ # numpy
253
282
  _NUMPY_V1_ERR_MSG = "numpy v1 must be installed."
254
283
 
255
284
 
@@ -143,6 +143,43 @@ class FileFormatter(logging.Formatter):
143
143
 
144
144
 
145
145
  _LOG_DIR = None
146
+
147
+
148
+ def _coerce_log_level(val: Any) -> Union[int, str]:
149
+ """Normalize environment log level values.
150
+
151
+ Accepts integer values (e.g., ``20``), numeric strings (``"20"``),
152
+ or names case-insensitively (``"info"``, ``"Warn"``, ...). Returns
153
+ either an integer level number or a valid uppercase level name
154
+ accepted by the :mod:`logging` module.
155
+
156
+ Args:
157
+ val: The raw value from the environment variable ``LOG_LEVEL``.
158
+
159
+ Returns:
160
+ int | str: The corresponding logging level as an int or an
161
+ uppercase string. Defaults to ``"INFO"`` if the input is invalid.
162
+ """
163
+ if isinstance(val, int):
164
+ return val
165
+ if val is None:
166
+ return "INFO"
167
+ s = str(val).strip()
168
+ if s.isdigit():
169
+ return int(s)
170
+ name = s.upper()
171
+ if name == "WARN":
172
+ name = "WARNING"
173
+ if name in logging._nameToLevel: # pylint: disable=W0212
174
+ return name
175
+ lvl = logging.getLevelName(name)
176
+ return lvl if isinstance(lvl, int) else "INFO"
177
+
178
+
179
+ # resolve level from LOG_LEVEL only
180
+ _ENV_LOG_LEVEL = os.environ.get("LOG_LEVEL", "INFO")
181
+ _RESOLVED_LOG_LEVEL = _coerce_log_level(_ENV_LOG_LEVEL)
182
+
146
183
  _CONFIG_DICT: dict[str, Any] = {
147
184
  "version": 1,
148
185
  "disable_existing_loggers": False,
@@ -155,7 +192,7 @@ _CONFIG_DICT: dict[str, Any] = {
155
192
  },
156
193
  "root": {
157
194
  "handlers": ["streamhandler"],
158
- "level": os.environ.get("LOG_LEVEL", "INFO"),
195
+ "level": _RESOLVED_LOG_LEVEL,
159
196
  "propagate": os.environ.get("LOG_PROPAGATE", "False") in ENV_VARS_TRUE,
160
197
  },
161
198
  }
@@ -408,8 +408,35 @@ class RotationTransform(BaseTransform):
408
408
  angle: Angle to rotate the image. Must be one of 90, 180, 270, or 360 degrees.
409
409
  """
410
410
  self.angle = angle
411
- self.image_width: Optional[int] = None
412
- self.image_height: Optional[int] = None
411
+ self.image_width: Optional[Union[int, float]] = None
412
+ self.image_height: Optional[Union[int, float]] = None
413
+
414
+ def set_angle(self, angle: Literal[90, 180, 270, 360]) -> None:
415
+ """
416
+ Set angle
417
+
418
+ Args:
419
+ angle: One of 90, 180, 270, or 360 degrees.
420
+ """
421
+ self.angle = angle
422
+
423
+ def set_image_width(self, image_width: Union[int, float]) -> None:
424
+ """
425
+ Set image width
426
+
427
+ Args:
428
+ image_width: Either a positive integer or 1.
429
+ """
430
+ self.image_width = image_width
431
+
432
+ def set_image_height(self, image_height: Union[int, float]) -> None:
433
+ """
434
+ Set image height
435
+
436
+ Args:
437
+ image_height: Either a positive integer or 1.
438
+ """
439
+ self.image_height = image_height
413
440
 
414
441
  def apply_image(self, img: PixelValues) -> PixelValues:
415
442
  """
@@ -442,17 +469,16 @@ class RotationTransform(BaseTransform):
442
469
  raise ValueError("Initialize image_width and image_height first")
443
470
 
444
471
  if self.angle == 90:
445
- coords[:, [0, 1, 2, 3]] = coords[:, [1, 0, 3, 2]]
472
+ self.image_width = self.image_height
473
+ coords[:, [0, 1, 2, 3]] = coords[:, [1, 2, 3, 0]]
446
474
  coords[:, [1, 3]] = self.image_width - coords[:, [1, 3]]
447
- coords[:, [0, 1, 2, 3]] = coords[:, [0, 3, 2, 1]]
448
475
  elif self.angle == 180:
449
- coords[:, [0, 2]] = self.image_width - coords[:, [0, 2]]
450
- coords[:, [1, 3]] = self.image_height - coords[:, [1, 3]]
451
- coords[:, [0, 1, 2, 3]] = coords[:, [2, 3, 0, 1]]
476
+ coords[:, [0, 2]] = self.image_width - coords[:, [2, 0]]
477
+ coords[:, [1, 3]] = self.image_height - coords[:, [3, 1]]
452
478
  elif self.angle == 270:
453
- coords[:, [0, 1, 2, 3]] = coords[:, [1, 0, 3, 2]]
479
+ self.image_height = self.image_width
480
+ coords[:, [0, 1, 2, 3]] = coords[:, [3, 0, 1, 2]]
454
481
  coords[:, [0, 2]] = self.image_height - coords[:, [0, 2]]
455
- coords[:, [0, 1, 2, 3]] = coords[:, [2, 1, 0, 3]]
456
482
 
457
483
  return coords
458
484
 
@@ -473,17 +499,16 @@ class RotationTransform(BaseTransform):
473
499
  raise ValueError("Initialize image_width and image_height first")
474
500
 
475
501
  if self.angle == 90:
476
- coords[:, [0, 1, 2, 3]] = coords[:, [1, 0, 3, 2]]
477
- coords[:, [0, 2]] = self.image_width - coords[:, [0, 2]]
478
- coords[:, [0, 1, 2, 3]] = coords[:, [2, 1, 0, 3]]
502
+ self.image_height = self.image_width
503
+ coords[:, [0, 1, 2, 3]] = coords[:, [3, 0, 1, 2]]
504
+ coords[:, [0, 2]] = self.image_height - coords[:, [0, 2]]
479
505
  elif self.angle == 180:
480
- coords[:, [0, 2]] = self.image_width - coords[:, [0, 2]]
481
- coords[:, [1, 3]] = self.image_height - coords[:, [1, 3]]
482
- coords[:, [0, 1, 2, 3]] = coords[:, [2, 3, 0, 1]]
506
+ coords[:, [0, 2]] = self.image_width - coords[:, [2, 0]]
507
+ coords[:, [1, 3]] = self.image_height - coords[:, [3, 1]]
483
508
  elif self.angle == 270:
484
- coords[:, [0, 1, 2, 3]] = coords[:, [1, 0, 3, 2]]
485
- coords[:, [1, 3]] = self.image_height - coords[:, [1, 3]]
486
- coords[:, [0, 1, 2, 3]] = coords[:, [0, 3, 2, 1]]
509
+ self.image_width = self.image_height
510
+ coords[:, [0, 1, 2, 3]] = coords[:, [1, 2, 3, 0]]
511
+ coords[:, [1, 3]] = self.image_width - coords[:, [1, 3]]
487
512
  return coords
488
513
 
489
514
  def clone(self) -> RotationTransform:
@@ -20,10 +20,11 @@ Visualisation utils. Copied and pasted from
20
20
  """
21
21
 
22
22
  import base64
23
+ import hashlib
23
24
  import os
24
25
  import sys
25
26
  from io import BytesIO
26
- from typing import Any, Optional, Sequence, no_type_check
27
+ from typing import Any, Optional, Sequence, Tuple, Union, no_type_check
27
28
 
28
29
  import numpy as np
29
30
  import numpy.typing as npt
@@ -44,150 +45,60 @@ with try_import() as pil_import_guard:
44
45
 
45
46
  __all__ = ["draw_boxes", "interactive_imshow", "viz_handler"]
46
47
 
47
- _COLORS = (
48
- np.array(
49
- [
50
- 0.667,
51
- 0.333,
52
- 0.500,
53
- 0.667,
54
- 0.667,
55
- 0.500,
56
- 0.667,
57
- 1.000,
58
- 0.500,
59
- 1.000,
60
- 0.000,
61
- 0.500,
62
- 1.000,
63
- 0.333,
64
- 0.500,
65
- 1.000,
66
- 0.667,
67
- 0.500,
68
- 1.000,
69
- 1.000,
70
- 0.500,
71
- 0.000,
72
- 0.333,
73
- 1.000,
74
- 0.000,
75
- 0.667,
76
- 1.000,
77
- 0.000,
78
- 1.000,
79
- 1.000,
80
- 0.333,
81
- 0.000,
82
- 1.000,
83
- 0.333,
84
- 0.333,
85
- 1.000,
86
- 0.333,
87
- 0.667,
88
- 1.000,
89
- 0.333,
90
- 1.000,
91
- 1.000,
92
- 0.667,
93
- 0.000,
94
- 1.000,
95
- 0.667,
96
- 0.333,
97
- 1.000,
98
- 0.667,
99
- 0.667,
100
- 1.000,
101
- 0.667,
102
- 1.000,
103
- 1.000,
104
- 1.000,
105
- 0.000,
106
- 1.000,
107
- 1.000,
108
- 0.333,
109
- 1.000,
110
- 1.000,
111
- 0.667,
112
- 1.000,
113
- 0.333,
114
- 0.000,
115
- 0.000,
116
- 0.500,
117
- 0.000,
118
- 0.000,
119
- 0.667,
120
- 0.000,
121
- 0.000,
122
- 0.833,
123
- 0.000,
124
- 0.000,
125
- 1.000,
126
- 0.000,
127
- 0.000,
128
- 0.000,
129
- 0.167,
130
- 0.000,
131
- 0.000,
132
- 0.333,
133
- 0.000,
134
- 0.000,
135
- 0.500,
136
- 0.000,
137
- 0.000,
138
- 0.667,
139
- 0.000,
140
- 0.000,
141
- 0.833,
142
- 0.000,
143
- 0.000,
144
- 1.000,
145
- 0.000,
146
- 0.000,
147
- 0.000,
148
- 0.167,
149
- 0.000,
150
- 0.000,
151
- 0.333,
152
- 0.000,
153
- 0.000,
154
- 0.500,
155
- 0.000,
156
- 0.000,
157
- 0.667,
158
- 0.000,
159
- 0.000,
160
- 0.833,
161
- 0.000,
162
- 0.000,
163
- 1.000,
164
- 0.000,
165
- 0.000,
166
- 0.000,
167
- 0.143,
168
- 0.143,
169
- 0.143,
170
- 0.857,
171
- 0.857,
172
- 0.857,
173
- ]
174
- )
175
- .astype(np.float32)
176
- .reshape(-1, 3)
48
+ _COLORS = np.array(
49
+ [
50
+ [0.75 , 0.1125 , 0.1125],
51
+ [0.75 , 0.24 , 0.1125],
52
+ [0.75 , 0.3675 , 0.1125],
53
+ [0.75 , 0.495 , 0.1125],
54
+ [0.75 , 0.6225 , 0.1125],
55
+ [0.75 , 0.75 , 0.1125],
56
+ [0.6225 , 0.75 , 0.1125],
57
+ [0.495 , 0.75 , 0.1125],
58
+ [0.3675 , 0.75 , 0.1125],
59
+ [0.24 , 0.75 , 0.1125],
60
+ [0.1125 , 0.75 , 0.1125],
61
+ [0.1125 , 0.75 , 0.24 ],
62
+ [0.1125 , 0.75 , 0.3675],
63
+ [0.1125 , 0.75 , 0.495 ],
64
+ [0.1125 , 0.75 , 0.6225],
65
+ [0.1125 , 0.75 , 0.75 ],
66
+ [0.1125 , 0.6225 , 0.75 ],
67
+ [0.1125 , 0.495 , 0.75 ],
68
+ [0.1125 , 0.3675 , 0.75 ],
69
+ [0.1125 , 0.24 , 0.75 ],
70
+ [0.1125 , 0.1125 , 0.75 ],
71
+ [0.24 , 0.1125 , 0.75 ],
72
+ [0.3675 , 0.1125 , 0.75 ],
73
+ [0.495 , 0.1125 , 0.75 ],
74
+ [0.6225 , 0.1125 , 0.75 ],
75
+ [0.75 , 0.1125 , 0.75 ],
76
+ [0.75 , 0.1125 , 0.6225],
77
+ [0.75 , 0.1125 , 0.495 ],
78
+ [0.75 , 0.1125 , 0.3675],
79
+ [0.75 , 0.1125 , 0.24 ],
80
+ ],
81
+ dtype=float32
177
82
  )
178
83
 
179
84
 
180
- def random_color(rgb: bool = True, maximum: int = 255) -> tuple[int, int, int]:
85
+ def random_color(
86
+ rgb: bool = True, maximum: int = 255, deterministic_input_str: Optional[str] = None
87
+ ) -> tuple[int, int, int]:
181
88
  """
182
89
  Args:
183
90
  rgb: Whether to return RGB colors or BGR colors.
184
91
  maximum: Either 255 or 1.
92
+ deterministic_input_str: A string to use for deterministic color generation.
185
93
 
186
94
  Returns:
187
95
  A tuple of three integers representing the color.
188
96
  """
189
-
190
- idx = np.random.randint(0, len(_COLORS))
97
+ if deterministic_input_str:
98
+ hash_digest = hashlib.md5(deterministic_input_str.encode("utf-8")).hexdigest()
99
+ idx = int(hash_digest, 16) % len(_COLORS)
100
+ else:
101
+ idx = np.random.randint(0, len(_COLORS))
191
102
  ret = _COLORS[idx] * maximum
192
103
  if not rgb:
193
104
  ret = ret[::-1]
@@ -197,7 +108,7 @@ def random_color(rgb: bool = True, maximum: int = 255) -> tuple[int, int, int]:
197
108
  def draw_boxes(
198
109
  np_image: PixelValues,
199
110
  boxes: npt.NDArray[float32],
200
- category_names_list: Optional[list[Optional[str]]] = None,
111
+ category_names_list: Optional[list[Tuple[Union[str, None], Union[str, None]]]] = None,
201
112
  color: Optional[BGR] = None,
202
113
  font_scale: float = 1.0,
203
114
  rectangle_thickness: int = 4,
@@ -210,7 +121,8 @@ def draw_boxes(
210
121
  Args:
211
122
  np_image: Image as `np.ndarray`.
212
123
  boxes: A numpy array of shape Nx4 where each row is `[x1, y1, x2, y2]`.
213
- category_names_list: List of N category names.
124
+ category_names_list: List of N tuples. The first element is the category name, whereas the second element is
125
+ the value, that is going to be displayed in the text box..
214
126
  color: A 3-tuple BGR color (in range `[0, 255]`).
215
127
  font_scale: Font scale of text box.
216
128
  rectangle_thickness: Thickness of bounding box.
@@ -230,13 +142,14 @@ def draw_boxes(
230
142
  category_to_color = {}
231
143
  if box_color_by_category and category_names_list is not None:
232
144
  category_names = set(category_names_list)
233
- category_to_color = {category: random_color() for category in category_names}
234
-
145
+ category_to_color = {
146
+ category[1]: random_color(deterministic_input_str=category[1]) for category in category_names
147
+ }
235
148
  boxes = np.array(boxes, dtype="int32")
236
149
  if category_names_list is not None:
237
150
  assert len(category_names_list) == len(boxes), f"{len(category_names_list)} != {len(boxes)}"
238
151
  else:
239
- category_names_list = [None] * len(boxes)
152
+ category_names_list = [(None, None)] * len(boxes)
240
153
  areas = (boxes[:, 2] - boxes[:, 0] + 1) * (boxes[:, 3] - boxes[:, 1] + 1)
241
154
  sorted_inds = np.argsort(-areas) # draw large ones first
242
155
  assert areas.min() > 0, areas.min()
@@ -255,12 +168,12 @@ def draw_boxes(
255
168
  np_image = cv2.cvtColor(np_image, cv2.COLOR_GRAY2BGR).astype(np.uint8)
256
169
  for i in sorted_inds:
257
170
  box = boxes[i, :]
258
- choose_color = category_to_color.get(category_names_list[i]) if category_to_color is not None else color
171
+ choose_color = category_to_color.get(category_names_list[i][1]) if category_to_color is not None else color
259
172
  if choose_color is None:
260
173
  choose_color = random_color()
261
- if category_names_list[i] is not None:
174
+ if category_names_list[i][0] is not None:
262
175
  np_image = viz_handler.draw_text(
263
- np_image, (box[0], box[1]), category_names_list[i], color=choose_color, font_scale=font_scale
176
+ np_image, (box[0], box[1]), category_names_list[i][0], color=choose_color, font_scale=font_scale
264
177
  )
265
178
  np_image = viz_handler.draw_rectangle(
266
179
  np_image, (box[0], box[1], box[2], box[3]), choose_color, rectangle_thickness
@@ -423,7 +336,7 @@ class VizPackageHandler:
423
336
 
424
337
  @staticmethod
425
338
  def _cv2_read_image(path: PathLikeOrStr) -> PixelValues:
426
- return cv2.imread(os.fspath(path), cv2.IMREAD_COLOR).astype(np.uint8) # type: ignore
339
+ return cv2.imread(os.fspath(path), cv2.IMREAD_COLOR).astype(np.uint8) # type: ignore
427
340
 
428
341
  @staticmethod
429
342
  def _pillow_read_image(path: PathLikeOrStr) -> PixelValues:
@@ -517,7 +430,7 @@ class VizPackageHandler:
517
430
  @staticmethod
518
431
  def _cv2_convert_b64_to_np(image: B64Str) -> PixelValues:
519
432
  np_array = np.fromstring(base64.b64decode(image), np.uint8) # type: ignore
520
- np_array = cv2.imdecode(np_array, cv2.IMREAD_COLOR).astype(np.float32) # type: ignore
433
+ np_array = cv2.imdecode(np_array, cv2.IMREAD_COLOR).astype(np.float32) # type: ignore
521
434
  return np_array.astype(uint8)
522
435
 
523
436
  @staticmethod
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: deepdoctection
3
- Version: 0.45.0
3
+ Version: 0.46.1
4
4
  Summary: Repository for Document AI
5
5
  Home-page: https://github.com/deepdoctection/deepdoctection
6
6
  Author: Dr. Janis Meyer
@@ -19,18 +19,15 @@ Description-Content-Type: text/markdown
19
19
  License-File: LICENSE
20
20
  Requires-Dist: catalogue==2.0.10
21
21
  Requires-Dist: huggingface_hub>=0.26.0
22
- Requires-Dist: importlib-metadata>=5.0.0
23
22
  Requires-Dist: jsonlines==3.1.0
24
23
  Requires-Dist: lazy-imports==0.3.1
25
24
  Requires-Dist: mock==4.0.3
26
- Requires-Dist: networkx>=2.7.1
27
25
  Requires-Dist: numpy>2.0
28
26
  Requires-Dist: packaging>=20.0
29
27
  Requires-Dist: Pillow>=10.0.0
30
28
  Requires-Dist: pypdf>=6.0.0
31
29
  Requires-Dist: pypdfium2>=4.30.0
32
30
  Requires-Dist: pyyaml>=6.0.1
33
- Requires-Dist: pyzmq>=16
34
31
  Requires-Dist: scipy>=1.13.1
35
32
  Requires-Dist: termcolor>=1.1
36
33
  Requires-Dist: tabulate>=0.7.7
@@ -38,18 +35,15 @@ Requires-Dist: tqdm>=4.64.0
38
35
  Provides-Extra: tf
39
36
  Requires-Dist: catalogue==2.0.10; extra == "tf"
40
37
  Requires-Dist: huggingface_hub>=0.26.0; extra == "tf"
41
- Requires-Dist: importlib-metadata>=5.0.0; extra == "tf"
42
38
  Requires-Dist: jsonlines==3.1.0; extra == "tf"
43
39
  Requires-Dist: lazy-imports==0.3.1; extra == "tf"
44
40
  Requires-Dist: mock==4.0.3; extra == "tf"
45
- Requires-Dist: networkx>=2.7.1; extra == "tf"
46
41
  Requires-Dist: numpy>2.0; extra == "tf"
47
42
  Requires-Dist: packaging>=20.0; extra == "tf"
48
43
  Requires-Dist: Pillow>=10.0.0; extra == "tf"
49
44
  Requires-Dist: pypdf>=6.0.0; extra == "tf"
50
45
  Requires-Dist: pypdfium2>=4.30.0; extra == "tf"
51
46
  Requires-Dist: pyyaml>=6.0.1; extra == "tf"
52
- Requires-Dist: pyzmq>=16; extra == "tf"
53
47
  Requires-Dist: scipy>=1.13.1; extra == "tf"
54
48
  Requires-Dist: termcolor>=1.1; extra == "tf"
55
49
  Requires-Dist: tabulate>=0.7.7; extra == "tf"
@@ -62,25 +56,24 @@ Requires-Dist: python-doctr==0.10.0; extra == "tf"
62
56
  Requires-Dist: pycocotools>=2.0.2; extra == "tf"
63
57
  Requires-Dist: boto3==1.34.102; extra == "tf"
64
58
  Requires-Dist: pdfplumber>=0.11.0; extra == "tf"
59
+ Requires-Dist: pyzmq>=16; extra == "tf"
65
60
  Requires-Dist: jdeskew>=0.2.2; extra == "tf"
66
61
  Requires-Dist: apted==1.0.3; extra == "tf"
67
62
  Requires-Dist: distance==0.1.3; extra == "tf"
68
63
  Requires-Dist: lxml>=4.9.1; extra == "tf"
64
+ Requires-Dist: networkx>=2.7.1; extra == "tf"
69
65
  Provides-Extra: pt
70
66
  Requires-Dist: catalogue==2.0.10; extra == "pt"
71
67
  Requires-Dist: huggingface_hub>=0.26.0; extra == "pt"
72
- Requires-Dist: importlib-metadata>=5.0.0; extra == "pt"
73
68
  Requires-Dist: jsonlines==3.1.0; extra == "pt"
74
69
  Requires-Dist: lazy-imports==0.3.1; extra == "pt"
75
70
  Requires-Dist: mock==4.0.3; extra == "pt"
76
- Requires-Dist: networkx>=2.7.1; extra == "pt"
77
71
  Requires-Dist: numpy>2.0; extra == "pt"
78
72
  Requires-Dist: packaging>=20.0; extra == "pt"
79
73
  Requires-Dist: Pillow>=10.0.0; extra == "pt"
80
74
  Requires-Dist: pypdf>=6.0.0; extra == "pt"
81
75
  Requires-Dist: pypdfium2>=4.30.0; extra == "pt"
82
76
  Requires-Dist: pyyaml>=6.0.1; extra == "pt"
83
- Requires-Dist: pyzmq>=16; extra == "pt"
84
77
  Requires-Dist: scipy>=1.13.1; extra == "pt"
85
78
  Requires-Dist: termcolor>=1.1; extra == "pt"
86
79
  Requires-Dist: tabulate>=0.7.7; extra == "pt"
@@ -92,10 +85,12 @@ Requires-Dist: python-doctr==0.10.0; extra == "pt"
92
85
  Requires-Dist: pycocotools>=2.0.2; extra == "pt"
93
86
  Requires-Dist: boto3==1.34.102; extra == "pt"
94
87
  Requires-Dist: pdfplumber>=0.11.0; extra == "pt"
88
+ Requires-Dist: pyzmq>=16; extra == "pt"
95
89
  Requires-Dist: jdeskew>=0.2.2; extra == "pt"
96
90
  Requires-Dist: apted==1.0.3; extra == "pt"
97
91
  Requires-Dist: distance==0.1.3; extra == "pt"
98
92
  Requires-Dist: lxml>=4.9.1; extra == "pt"
93
+ Requires-Dist: networkx>=2.7.1; extra == "pt"
99
94
  Provides-Extra: docs
100
95
  Requires-Dist: tensorpack==0.11; extra == "docs"
101
96
  Requires-Dist: boto3==1.34.102; extra == "docs"