docling-core 0.0.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 docling-core might be problematic. Click here for more details.
- docling_core/__init__.py +6 -0
- docling_core/py.typed +0 -0
- docling_core/resources/schemas/doc/ANN.json +171 -0
- docling_core/resources/schemas/doc/DOC.json +300 -0
- docling_core/resources/schemas/doc/OCR-output.json +166 -0
- docling_core/resources/schemas/doc/RAW.json +158 -0
- docling_core/resources/schemas/generated/ccs_document_schema.json +1071 -0
- docling_core/resources/schemas/generated/minimal_document_schema_flat.json +1129 -0
- docling_core/resources/schemas/search/search_doc_mapping.json +104 -0
- docling_core/resources/schemas/search/search_doc_mapping_v2.json +256 -0
- docling_core/search/__init__.py +6 -0
- docling_core/search/json_schema_to_search_mapper.py +406 -0
- docling_core/search/mapping.py +29 -0
- docling_core/search/meta.py +93 -0
- docling_core/search/package.py +56 -0
- docling_core/types/__init__.py +25 -0
- docling_core/types/base.py +248 -0
- docling_core/types/doc/__init__.py +6 -0
- docling_core/types/doc/base.py +199 -0
- docling_core/types/doc/doc_ann.py +76 -0
- docling_core/types/doc/doc_ocr.py +83 -0
- docling_core/types/doc/doc_raw.py +187 -0
- docling_core/types/doc/document.py +393 -0
- docling_core/types/gen/__init__.py +6 -0
- docling_core/types/gen/generic.py +33 -0
- docling_core/types/nlp/__init__.py +6 -0
- docling_core/types/nlp/qa.py +74 -0
- docling_core/types/nlp/qa_labels.py +118 -0
- docling_core/types/rec/__init__.py +6 -0
- docling_core/types/rec/attribute.py +55 -0
- docling_core/types/rec/base.py +90 -0
- docling_core/types/rec/predicate.py +133 -0
- docling_core/types/rec/record.py +95 -0
- docling_core/types/rec/statement.py +41 -0
- docling_core/types/rec/subject.py +77 -0
- docling_core/utils/__init__.py +6 -0
- docling_core/utils/alias.py +27 -0
- docling_core/utils/ds_generate_docs.py +144 -0
- docling_core/utils/ds_generate_jsonschema.py +62 -0
- docling_core/utils/validate.py +86 -0
- docling_core/utils/validators.py +100 -0
- docling_core-0.0.1.dist-info/LICENSE +21 -0
- docling_core-0.0.1.dist-info/METADATA +133 -0
- docling_core-0.0.1.dist-info/RECORD +46 -0
- docling_core-0.0.1.dist-info/WHEEL +4 -0
- docling_core-0.0.1.dist-info/entry_points.txt +5 -0
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright IBM Corp. 2024 - 2024
|
|
3
|
+
# SPDX-License-Identifier: MIT
|
|
4
|
+
#
|
|
5
|
+
|
|
6
|
+
"""Methods to convert a JSON Schema into a search database schema."""
|
|
7
|
+
import re
|
|
8
|
+
from copy import deepcopy
|
|
9
|
+
from typing import Any, Optional, Pattern, Tuple, TypedDict
|
|
10
|
+
|
|
11
|
+
from jsonref import JsonRef
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class SearchIndexDefinition(TypedDict):
|
|
15
|
+
"""Data type for an index basic definition (settings and mappings)."""
|
|
16
|
+
|
|
17
|
+
settings: dict
|
|
18
|
+
mappings: dict
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class JsonSchemaToSearchMapper:
|
|
22
|
+
"""Map a JSON Schema to an search database schema.
|
|
23
|
+
|
|
24
|
+
The generated database schema is a mapping describing the fields from the
|
|
25
|
+
JSON Schema and how they should be indexed in a Lucene index of a search database.
|
|
26
|
+
|
|
27
|
+
Potential issues:
|
|
28
|
+
- Tuples may not be converted properly (e.g., Tuple[float,float,float,str,str])
|
|
29
|
+
- Method `_remove_keys` may lead to wrong results if a field is named `properties`.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
def __init__(
|
|
33
|
+
self,
|
|
34
|
+
settings_extra: Optional[dict] = None,
|
|
35
|
+
mappings_extra: Optional[dict] = None,
|
|
36
|
+
):
|
|
37
|
+
"""Create an instance of the mapper with default settings."""
|
|
38
|
+
self.settings = {
|
|
39
|
+
"analysis": {
|
|
40
|
+
# Create a normalizer for lowercase ascii folding,
|
|
41
|
+
# this is used in keyword fields
|
|
42
|
+
"normalizer": {
|
|
43
|
+
"lowercase_asciifolding": {
|
|
44
|
+
"type": "custom",
|
|
45
|
+
"filter": ["lowercase", "asciifolding"],
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
self.settings_extra = settings_extra
|
|
52
|
+
self.mappings_extra = mappings_extra
|
|
53
|
+
|
|
54
|
+
self._re_es_flag = re.compile(r"^(?:x-es-)(.*)")
|
|
55
|
+
|
|
56
|
+
self._rm_keys = (
|
|
57
|
+
"description",
|
|
58
|
+
"required",
|
|
59
|
+
"title",
|
|
60
|
+
"additionalProperties",
|
|
61
|
+
"format",
|
|
62
|
+
"enum",
|
|
63
|
+
"pattern",
|
|
64
|
+
"$comment",
|
|
65
|
+
"default",
|
|
66
|
+
"minItems",
|
|
67
|
+
"maxItems",
|
|
68
|
+
"minimum",
|
|
69
|
+
"maximum",
|
|
70
|
+
"minLength",
|
|
71
|
+
"maxLength",
|
|
72
|
+
"exclusiveMinimum",
|
|
73
|
+
"exclusiveMaximum",
|
|
74
|
+
"$defs",
|
|
75
|
+
"const",
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
self._suppress_key = "x-es-suppress"
|
|
79
|
+
|
|
80
|
+
self._type_format_mappings: dict[tuple[str, str], str] = {
|
|
81
|
+
("string", "date-time"): "date",
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
self._type_mappings = {
|
|
85
|
+
"number": "double",
|
|
86
|
+
"string": "text",
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
self._types_to_remove = ("object",)
|
|
90
|
+
|
|
91
|
+
def get_index_definition(self, schema: dict) -> SearchIndexDefinition:
|
|
92
|
+
"""Generates a search database schema from a JSON Schema.
|
|
93
|
+
|
|
94
|
+
The search database schema consists of the sections `settings` and `mappings`,
|
|
95
|
+
which define the fields, their data types, and other specifications to index
|
|
96
|
+
JSON documents into a Lucene index.
|
|
97
|
+
"""
|
|
98
|
+
mapping = JsonRef.replace_refs(schema)
|
|
99
|
+
|
|
100
|
+
mapping = self._merge_unions(mapping)
|
|
101
|
+
|
|
102
|
+
mapping = self._clean_types(mapping)
|
|
103
|
+
|
|
104
|
+
mapping = self._collapse_arrays(mapping)
|
|
105
|
+
|
|
106
|
+
mapping = self._remove_keys(mapping, self._rm_keys)
|
|
107
|
+
|
|
108
|
+
mapping = self._suppress(mapping, self._suppress_key)
|
|
109
|
+
|
|
110
|
+
mapping = self._translate_keys_re(mapping)
|
|
111
|
+
|
|
112
|
+
mapping = self._clean(mapping)
|
|
113
|
+
|
|
114
|
+
mapping.pop("definitions", None)
|
|
115
|
+
|
|
116
|
+
result = SearchIndexDefinition(
|
|
117
|
+
settings=self.settings,
|
|
118
|
+
mappings=mapping,
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
if self.mappings_extra:
|
|
122
|
+
result["mappings"] = {**result["mappings"], **self.mappings_extra}
|
|
123
|
+
|
|
124
|
+
if self.settings_extra:
|
|
125
|
+
result["settings"] = {**result["settings"], **self.settings_extra}
|
|
126
|
+
|
|
127
|
+
return result
|
|
128
|
+
|
|
129
|
+
def _merge_unions(self, doc: dict) -> dict:
|
|
130
|
+
"""Merge objects of type anyOf, allOf, or oneOf (options).
|
|
131
|
+
|
|
132
|
+
Args:
|
|
133
|
+
doc: A JSON schema or a transformation towards a search database mappings.
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
A transformation of a JSON schema by merging option fields.
|
|
137
|
+
"""
|
|
138
|
+
|
|
139
|
+
def _clean(value: Any) -> Any:
|
|
140
|
+
if isinstance(value, list):
|
|
141
|
+
return [_clean(v) for v in value]
|
|
142
|
+
|
|
143
|
+
if isinstance(value, dict):
|
|
144
|
+
union: list = []
|
|
145
|
+
merged_union: dict = {}
|
|
146
|
+
|
|
147
|
+
for k, v in value.items():
|
|
148
|
+
if k in ("oneOf", "allOf", "anyOf"):
|
|
149
|
+
union.extend(v)
|
|
150
|
+
else:
|
|
151
|
+
merged_union[k] = v
|
|
152
|
+
|
|
153
|
+
if not union:
|
|
154
|
+
return {k: _clean(v) for k, v in value.items()}
|
|
155
|
+
|
|
156
|
+
for u in union:
|
|
157
|
+
if not isinstance(u, dict):
|
|
158
|
+
continue
|
|
159
|
+
|
|
160
|
+
for k, v in u.items():
|
|
161
|
+
if k == "type" and v == "null": # null values are irrelevant
|
|
162
|
+
continue
|
|
163
|
+
elif not isinstance(v, dict) or k not in merged_union:
|
|
164
|
+
merged_union[k] = _clean(v)
|
|
165
|
+
elif isinstance(v, dict) and k in merged_union:
|
|
166
|
+
merged_union[k] = _clean({**merged_union[k], **v})
|
|
167
|
+
|
|
168
|
+
return merged_union
|
|
169
|
+
|
|
170
|
+
return value
|
|
171
|
+
|
|
172
|
+
return _clean(doc)
|
|
173
|
+
|
|
174
|
+
def _clean_types(self, doc: dict) -> dict:
|
|
175
|
+
"""Clean field types originated from a JSON schema to obtain search mappings.
|
|
176
|
+
|
|
177
|
+
Args:
|
|
178
|
+
doc: A JSON schema or a transformation towards a search database mappings.
|
|
179
|
+
|
|
180
|
+
Returns:
|
|
181
|
+
A transformation of a JSON schema by merging option fields.
|
|
182
|
+
"""
|
|
183
|
+
|
|
184
|
+
def _clean(value: Any) -> Any:
|
|
185
|
+
if isinstance(value, list):
|
|
186
|
+
return [_clean(v) for v in value]
|
|
187
|
+
|
|
188
|
+
if isinstance(value, dict):
|
|
189
|
+
if isinstance(value.get("type"), str):
|
|
190
|
+
t: str = value["type"]
|
|
191
|
+
|
|
192
|
+
# Tuples
|
|
193
|
+
if t == "array" and isinstance(value.get("items"), list):
|
|
194
|
+
items: list = value["items"]
|
|
195
|
+
|
|
196
|
+
if items:
|
|
197
|
+
value["items"] = value["items"][0]
|
|
198
|
+
else:
|
|
199
|
+
value["items"] = {}
|
|
200
|
+
|
|
201
|
+
# Unwanted types, such as 'object'
|
|
202
|
+
if t in self._types_to_remove:
|
|
203
|
+
value.pop("type", None)
|
|
204
|
+
|
|
205
|
+
# Map formats
|
|
206
|
+
f: str = value.get("format", "")
|
|
207
|
+
if (t, f) in self._type_format_mappings:
|
|
208
|
+
value["type"] = self._type_format_mappings[(t, f)]
|
|
209
|
+
value.pop("format", None)
|
|
210
|
+
|
|
211
|
+
# Map types, such as 'string' to 'text'
|
|
212
|
+
elif t in self._type_mappings:
|
|
213
|
+
value["type"] = self._type_mappings[t]
|
|
214
|
+
|
|
215
|
+
return {k: _clean(v) for k, v in value.items()}
|
|
216
|
+
|
|
217
|
+
return value
|
|
218
|
+
|
|
219
|
+
return _clean(doc)
|
|
220
|
+
|
|
221
|
+
@staticmethod
|
|
222
|
+
def _collapse_arrays(doc: dict) -> dict:
|
|
223
|
+
"""Collapse arrays from a JSON schema to match a search database mappings.
|
|
224
|
+
|
|
225
|
+
Args:
|
|
226
|
+
doc: A JSON schema or a transformation towards a search database mappings.
|
|
227
|
+
|
|
228
|
+
Returns:
|
|
229
|
+
A transformation of a JSON schema by collapsing arrays.
|
|
230
|
+
"""
|
|
231
|
+
|
|
232
|
+
def __collapse(d_: Any) -> Any:
|
|
233
|
+
if isinstance(d_, list):
|
|
234
|
+
return [v for v in (__collapse(v) for v in d_)]
|
|
235
|
+
|
|
236
|
+
if isinstance(d_, dict):
|
|
237
|
+
if "type" in d_ and d_["type"] == "array" and "items" in d_:
|
|
238
|
+
collapsed = __collapse(d_["items"])
|
|
239
|
+
|
|
240
|
+
d_ = deepcopy(d_)
|
|
241
|
+
d_.pop("items", None)
|
|
242
|
+
d_.pop("type", None)
|
|
243
|
+
|
|
244
|
+
merged = {**d_, **collapsed}
|
|
245
|
+
|
|
246
|
+
return merged
|
|
247
|
+
|
|
248
|
+
return {k: __collapse(v) for k, v in d_.items()}
|
|
249
|
+
|
|
250
|
+
return d_
|
|
251
|
+
|
|
252
|
+
return __collapse(doc)
|
|
253
|
+
|
|
254
|
+
@staticmethod
|
|
255
|
+
def _suppress(doc: dict, suppress_key: str) -> dict:
|
|
256
|
+
"""Remove a key from a JSON schema to match a search database mappings.
|
|
257
|
+
|
|
258
|
+
Args:
|
|
259
|
+
doc: A JSON schema or a transformation towards a search database mappings.
|
|
260
|
+
key: The name of a field to be removed from the `doc`.
|
|
261
|
+
|
|
262
|
+
Returns:
|
|
263
|
+
A transformation of a JSON schema by removing the field `suppress_key`.
|
|
264
|
+
"""
|
|
265
|
+
|
|
266
|
+
def __suppress(d_: Any) -> Any:
|
|
267
|
+
if isinstance(d_, list):
|
|
268
|
+
return [v for v in (__suppress(v) for v in d_)]
|
|
269
|
+
|
|
270
|
+
if isinstance(d_, dict):
|
|
271
|
+
if suppress_key in d_ and d_[suppress_key] is True:
|
|
272
|
+
return {}
|
|
273
|
+
else:
|
|
274
|
+
return {
|
|
275
|
+
k: v for k, v in ((k, __suppress(v)) for k, v in d_.items())
|
|
276
|
+
}
|
|
277
|
+
return d_
|
|
278
|
+
|
|
279
|
+
return __suppress(doc)
|
|
280
|
+
|
|
281
|
+
@staticmethod
|
|
282
|
+
def _remove_keys(doc: dict, keys: Tuple[str, ...]) -> dict:
|
|
283
|
+
"""Remove keys from a JSON schema to match a search database mappings.
|
|
284
|
+
|
|
285
|
+
Args:
|
|
286
|
+
doc: A JSON schema or a transformation towards a search database mappings.
|
|
287
|
+
keys: Fields to be removed from the `doc`.
|
|
288
|
+
|
|
289
|
+
Returns:
|
|
290
|
+
A transformation of a JSON schema by removing the fields in `keys`.
|
|
291
|
+
"""
|
|
292
|
+
|
|
293
|
+
def __remove(d_: Any) -> Any:
|
|
294
|
+
if isinstance(d_, list):
|
|
295
|
+
return [v for v in (__remove(v) for v in d_)]
|
|
296
|
+
|
|
297
|
+
if isinstance(d_, dict):
|
|
298
|
+
result = {}
|
|
299
|
+
for k, v in d_.items():
|
|
300
|
+
if k == "properties" and isinstance(v, dict):
|
|
301
|
+
# All properties must be included, they are not to be removed,
|
|
302
|
+
# even if they have a name of a key that's to be removed.
|
|
303
|
+
result[k] = {p_k: __remove(p_v) for p_k, p_v in v.items()}
|
|
304
|
+
elif k not in keys:
|
|
305
|
+
result[k] = __remove(v)
|
|
306
|
+
|
|
307
|
+
return result
|
|
308
|
+
|
|
309
|
+
return d_
|
|
310
|
+
|
|
311
|
+
return __remove(doc)
|
|
312
|
+
|
|
313
|
+
@staticmethod
|
|
314
|
+
def _remove_keys_re(doc: dict, regx: Pattern) -> dict:
|
|
315
|
+
"""Remove keys from a JSON schema to match a search database mappings.
|
|
316
|
+
|
|
317
|
+
Args:
|
|
318
|
+
doc: A JSON schema or a transformation towards a search database mappings.
|
|
319
|
+
keys: A pattern defining the fields to be removed from the `doc`.
|
|
320
|
+
|
|
321
|
+
Returns:
|
|
322
|
+
A transformation of a JSON schema by removing fields with a name pattern.
|
|
323
|
+
"""
|
|
324
|
+
|
|
325
|
+
def __remove(d_: Any) -> Any:
|
|
326
|
+
if isinstance(d_, list):
|
|
327
|
+
return [v for v in (__remove(v) for v in d_)]
|
|
328
|
+
|
|
329
|
+
if isinstance(d_, dict):
|
|
330
|
+
return {
|
|
331
|
+
k: v
|
|
332
|
+
for k, v in (
|
|
333
|
+
(k, __remove(v)) for k, v in d_.items() if not regx.match(k)
|
|
334
|
+
)
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
return d_
|
|
338
|
+
|
|
339
|
+
return __remove(doc)
|
|
340
|
+
|
|
341
|
+
def _translate_keys_re(self, doc: dict) -> dict:
|
|
342
|
+
"""Translate marked keys from a JSON schema to match a search database mappings.
|
|
343
|
+
|
|
344
|
+
The keys to be translated should have a name that matches the pattern defined
|
|
345
|
+
by this class patter, for instance, a name starting with `x-es-`.
|
|
346
|
+
|
|
347
|
+
Args:
|
|
348
|
+
doc: A JSON schema or a transformation towards a search database mappings.
|
|
349
|
+
|
|
350
|
+
Returns:
|
|
351
|
+
A transformation of a JSON schema towards a search database mappings.
|
|
352
|
+
"""
|
|
353
|
+
|
|
354
|
+
def __translate(d_: Any) -> Any:
|
|
355
|
+
if isinstance(d_, list):
|
|
356
|
+
return [v for v in (__translate(v) for v in d_)]
|
|
357
|
+
|
|
358
|
+
if isinstance(d_, dict):
|
|
359
|
+
new_dict = {}
|
|
360
|
+
for k, v in d_.items():
|
|
361
|
+
new_dict[k] = __translate(v)
|
|
362
|
+
|
|
363
|
+
delkeys = []
|
|
364
|
+
for k in list(new_dict.keys()):
|
|
365
|
+
k_ = self._re_es_flag.sub(r"\1", k)
|
|
366
|
+
if k_ != k:
|
|
367
|
+
new_dict[k_] = new_dict[k]
|
|
368
|
+
delkeys.append(k)
|
|
369
|
+
|
|
370
|
+
for k in delkeys:
|
|
371
|
+
new_dict.pop(k, None)
|
|
372
|
+
|
|
373
|
+
return new_dict
|
|
374
|
+
|
|
375
|
+
return d_
|
|
376
|
+
|
|
377
|
+
return __translate(doc)
|
|
378
|
+
|
|
379
|
+
@staticmethod
|
|
380
|
+
def _clean(doc: dict) -> dict:
|
|
381
|
+
"""Recursively remove empty lists, dicts, strings, or None elements from a dict.
|
|
382
|
+
|
|
383
|
+
Args:
|
|
384
|
+
doc: A JSON schema or a transformation towards a search database mappings.
|
|
385
|
+
|
|
386
|
+
Returns:
|
|
387
|
+
A transformation of a JSON schema by removing empty objects.
|
|
388
|
+
"""
|
|
389
|
+
|
|
390
|
+
def _empty(x) -> bool:
|
|
391
|
+
return x is None or x == {} or x == [] or x == ""
|
|
392
|
+
|
|
393
|
+
def _clean(d_: Any) -> Any:
|
|
394
|
+
if isinstance(d_, list):
|
|
395
|
+
return [v for v in (_clean(v) for v in d_) if not _empty(v)]
|
|
396
|
+
|
|
397
|
+
if isinstance(d_, dict):
|
|
398
|
+
return {
|
|
399
|
+
k: v
|
|
400
|
+
for k, v in ((k, _clean(v)) for k, v in d_.items())
|
|
401
|
+
if not _empty(v)
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
return d_
|
|
405
|
+
|
|
406
|
+
return _clean(doc)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright IBM Corp. 2024 - 2024
|
|
3
|
+
# SPDX-License-Identifier: MIT
|
|
4
|
+
#
|
|
5
|
+
|
|
6
|
+
"""Methods to define fields in an index mapping of a search database."""
|
|
7
|
+
from typing import Any, Optional
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def es_field(
|
|
11
|
+
*,
|
|
12
|
+
type: Optional[str] = None,
|
|
13
|
+
ignore_above: Optional[int] = None,
|
|
14
|
+
term_vector: Optional[str] = None,
|
|
15
|
+
**kwargs: Any,
|
|
16
|
+
):
|
|
17
|
+
"""Create x-es kwargs to be passed to a `pydantic.Field` via unpacking."""
|
|
18
|
+
all_kwargs = {**kwargs}
|
|
19
|
+
|
|
20
|
+
if type is not None:
|
|
21
|
+
all_kwargs["type"] = type
|
|
22
|
+
|
|
23
|
+
if ignore_above is not None:
|
|
24
|
+
all_kwargs["ignore_above"] = ignore_above
|
|
25
|
+
|
|
26
|
+
if term_vector is not None:
|
|
27
|
+
all_kwargs["term_vector"] = term_vector
|
|
28
|
+
|
|
29
|
+
return {f"x-es-{k}": v for k, v in all_kwargs.items()}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright IBM Corp. 2024 - 2024
|
|
3
|
+
# SPDX-License-Identifier: MIT
|
|
4
|
+
#
|
|
5
|
+
|
|
6
|
+
"""Models and methods to define the metadata fields in database index mappings."""
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Generic, Optional, TypeVar
|
|
9
|
+
|
|
10
|
+
from pydantic import BaseModel, Field, StrictStr, ValidationInfo, field_validator
|
|
11
|
+
|
|
12
|
+
from docling_core.search.package import Package
|
|
13
|
+
from docling_core.types.base import CollectionTypeEnum, StrictDateTime, UniqueList
|
|
14
|
+
from docling_core.utils.alias import AliasModel
|
|
15
|
+
|
|
16
|
+
ClassificationT = TypeVar("ClassificationT", bound=str)
|
|
17
|
+
DomainT = TypeVar("DomainT", bound=str)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class S3Path(BaseModel, extra="forbid"):
|
|
21
|
+
"""The path details within a cloud object storage for CCS-parsed files."""
|
|
22
|
+
|
|
23
|
+
bucket: StrictStr
|
|
24
|
+
prefix: StrictStr
|
|
25
|
+
infix: StrictStr
|
|
26
|
+
|
|
27
|
+
def __hash__(self):
|
|
28
|
+
"""Return the hash value for this S3Path object."""
|
|
29
|
+
return hash((type(self),) + tuple(self.__dict__.values()))
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class S3CcsData(BaseModel, extra="forbid"):
|
|
33
|
+
"""The access details to a cloud object storage for CCS-parsed files."""
|
|
34
|
+
|
|
35
|
+
endpoint: StrictStr
|
|
36
|
+
paths: UniqueList[S3Path] = Field(min_length=1)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class DocumentLicense(BaseModel, extra="forbid"):
|
|
40
|
+
"""Document license for a search database index within the index mappings."""
|
|
41
|
+
|
|
42
|
+
code: Optional[list[StrictStr]] = None
|
|
43
|
+
text: Optional[list[StrictStr]] = None
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class Meta(AliasModel, Generic[ClassificationT, DomainT], extra="forbid"):
|
|
47
|
+
"""Metadata of a search database index within the index mappings."""
|
|
48
|
+
|
|
49
|
+
aliases: Optional[list[StrictStr]] = None
|
|
50
|
+
created: StrictDateTime
|
|
51
|
+
description: Optional[StrictStr] = None
|
|
52
|
+
source: StrictStr
|
|
53
|
+
storage: Optional[StrictStr] = None
|
|
54
|
+
display_name: Optional[StrictStr] = None
|
|
55
|
+
type: CollectionTypeEnum
|
|
56
|
+
classification: Optional[list[ClassificationT]] = None
|
|
57
|
+
version: UniqueList[Package] = Field(min_length=1)
|
|
58
|
+
license: Optional[StrictStr] = None
|
|
59
|
+
filename: Optional[Path] = None
|
|
60
|
+
domain: Optional[list[DomainT]] = None
|
|
61
|
+
reference: Optional[StrictStr] = Field(default=None, alias="$ref")
|
|
62
|
+
ccs_s3_data: Optional[S3CcsData] = None
|
|
63
|
+
document_license: Optional[DocumentLicense] = None
|
|
64
|
+
index_key: Optional[StrictStr] = None
|
|
65
|
+
project_key: Optional[StrictStr] = None
|
|
66
|
+
|
|
67
|
+
@field_validator("reference")
|
|
68
|
+
@classmethod
|
|
69
|
+
def reference_for_document(cls, v, info: ValidationInfo):
|
|
70
|
+
"""Validate the reference field for indexes of type Document."""
|
|
71
|
+
if "type" in info.data and info.data["type"] == "Document":
|
|
72
|
+
if v and v != "ccs:schemas#/Document":
|
|
73
|
+
raise ValueError("wrong reference value for Document type")
|
|
74
|
+
else:
|
|
75
|
+
return "ccs:schemas#/Document"
|
|
76
|
+
else:
|
|
77
|
+
return v
|
|
78
|
+
|
|
79
|
+
@field_validator("version")
|
|
80
|
+
@classmethod
|
|
81
|
+
def version_has_schema(cls, v):
|
|
82
|
+
"""Validate that the docling-core library is always set in version field."""
|
|
83
|
+
docling_core = [item for item in v if item.name == "docling-core"]
|
|
84
|
+
if not docling_core:
|
|
85
|
+
raise ValueError(
|
|
86
|
+
"the version should include at least a valid docling-core package"
|
|
87
|
+
)
|
|
88
|
+
elif len(docling_core) > 1:
|
|
89
|
+
raise ValueError(
|
|
90
|
+
"the version must not include more than 1 docling-core package"
|
|
91
|
+
)
|
|
92
|
+
else:
|
|
93
|
+
return v
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright IBM Corp. 2024 - 2024
|
|
3
|
+
# SPDX-License-Identifier: MIT
|
|
4
|
+
#
|
|
5
|
+
|
|
6
|
+
"""Models and methods to define a package model."""
|
|
7
|
+
|
|
8
|
+
import importlib.metadata
|
|
9
|
+
import re
|
|
10
|
+
from typing import Final
|
|
11
|
+
|
|
12
|
+
from pydantic import BaseModel, StrictStr, StringConstraints
|
|
13
|
+
from typing_extensions import Annotated
|
|
14
|
+
|
|
15
|
+
VERSION_PATTERN: Final = (
|
|
16
|
+
r"^(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)"
|
|
17
|
+
r"(?:-(?P<prerelease>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)"
|
|
18
|
+
r"(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+"
|
|
19
|
+
r"(?P<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$"
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class Package(BaseModel, extra="forbid"):
|
|
24
|
+
"""Representation of a software package.
|
|
25
|
+
|
|
26
|
+
The version needs to comply with Semantic Versioning 2.0.0.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
name: StrictStr
|
|
30
|
+
version: Annotated[str, StringConstraints(strict=True, pattern=VERSION_PATTERN)] = (
|
|
31
|
+
importlib.metadata.version("docling-core")
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
def __hash__(self):
|
|
35
|
+
"""Return the hash value for this S3Path object."""
|
|
36
|
+
return hash((type(self),) + tuple(self.__dict__.values()))
|
|
37
|
+
|
|
38
|
+
def get_major(self):
|
|
39
|
+
"""Get the major version of this package."""
|
|
40
|
+
return re.match(VERSION_PATTERN, self.version)["major"]
|
|
41
|
+
|
|
42
|
+
def get_minor(self):
|
|
43
|
+
"""Get the major version of this package."""
|
|
44
|
+
return re.match(VERSION_PATTERN, self.version)["minor"]
|
|
45
|
+
|
|
46
|
+
def get_patch(self):
|
|
47
|
+
"""Get the major version of this package."""
|
|
48
|
+
return re.match(VERSION_PATTERN, self.version)["patch"]
|
|
49
|
+
|
|
50
|
+
def get_pre_release(self):
|
|
51
|
+
"""Get the pre-release version of this package."""
|
|
52
|
+
return re.match(VERSION_PATTERN, self.version)["prerelease"]
|
|
53
|
+
|
|
54
|
+
def get_build_metadata(self):
|
|
55
|
+
"""Get the build metadata version of this package."""
|
|
56
|
+
return re.match(VERSION_PATTERN, self.version)["buildmetadata"]
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright IBM Corp. 2024 - 2024
|
|
3
|
+
# SPDX-License-Identifier: MIT
|
|
4
|
+
#
|
|
5
|
+
|
|
6
|
+
"""Define the main types."""
|
|
7
|
+
|
|
8
|
+
from docling_core.types.doc.base import BoundingBox # noqa
|
|
9
|
+
from docling_core.types.doc.base import Table # noqa
|
|
10
|
+
from docling_core.types.doc.base import TableCell # noqa
|
|
11
|
+
from docling_core.types.doc.base import ( # noqa
|
|
12
|
+
BaseCell,
|
|
13
|
+
BaseText,
|
|
14
|
+
PageDimensions,
|
|
15
|
+
PageReference,
|
|
16
|
+
Prov,
|
|
17
|
+
Ref,
|
|
18
|
+
)
|
|
19
|
+
from docling_core.types.doc.document import ( # noqa
|
|
20
|
+
CCSDocumentDescription as DocumentDescription,
|
|
21
|
+
)
|
|
22
|
+
from docling_core.types.doc.document import CCSFileInfoObject as FileInfoObject # noqa
|
|
23
|
+
from docling_core.types.doc.document import ExportedCCSDocument as Document # noqa
|
|
24
|
+
from docling_core.types.gen.generic import Generic # noqa
|
|
25
|
+
from docling_core.types.rec.record import Record # noqa
|