dump-things-service 0.2.0__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.
Files changed (36) hide show
  1. datalad-concepts/patches/jsonschemagen_mixins.diff +28 -0
  2. datalad-concepts/patches/jsonschemavalidator_plainyaml.diff +34 -0
  3. datalad-concepts/patches/linkml_runtime_utils_yamlutils.diff +29 -0
  4. datalad-concepts/patches/rdflib_dumper_canonical.diff +22 -0
  5. datalad-concepts/patches/rdflib_loader_typedesignator.diff +27 -0
  6. datalad-concepts/patches/shacl_ifabsent.diff +14 -0
  7. datalad-concepts/patches/shaclgen_annotations.diff +63 -0
  8. datalad-concepts/tools/patch_linkml +18 -0
  9. dump_things_service/__about__.py +1 -0
  10. dump_things_service/__init__.py +38 -0
  11. dump_things_service/config.py +413 -0
  12. dump_things_service/conftest.py +11 -0
  13. dump_things_service/convert.py +178 -0
  14. dump_things_service/dynamic_endpoints.py +56 -0
  15. dump_things_service/main.py +402 -0
  16. dump_things_service/model.py +75 -0
  17. dump_things_service/record.py +327 -0
  18. dump_things_service/resolve_curie.py +23 -0
  19. dump_things_service/tests/__init__.py +0 -0
  20. dump_things_service/tests/create_store.py +118 -0
  21. dump_things_service/tests/fixtures.py +214 -0
  22. dump_things_service/tests/test_basic.py +241 -0
  23. dump_things_service/tests/test_config.py +70 -0
  24. dump_things_service/tests/test_extract_inline.py +313 -0
  25. dump_things_service/tests/test_mapping.py +46 -0
  26. dump_things_service/tests/test_modes.py +148 -0
  27. dump_things_service/tests/test_permission_fetching.py +71 -0
  28. dump_things_service/tests/test_roundtrip.py +118 -0
  29. dump_things_service/tests/test_roundtrip_trr379.py +133 -0
  30. dump_things_service/tests/test_utils.py +40 -0
  31. dump_things_service/tests/test_web_interface.py +84 -0
  32. dump_things_service/tests/testschema.yaml +73 -0
  33. dump_things_service/utils.py +54 -0
  34. dump_things_service-0.2.0.dist-info/METADATA +286 -0
  35. dump_things_service-0.2.0.dist-info/RECORD +36 -0
  36. dump_things_service-0.2.0.dist-info/WHEEL +4 -0
@@ -0,0 +1,28 @@
1
+ This patch has been proposed for inclusion into linkml
2
+ https://github.com/linkml/linkml/pull/1935
3
+ However, it may be a too simple approach.
4
+
5
+ Specifically, the JSON schema output generated from our
6
+ datalad-dataset-components schema referenced any base classes that were not
7
+ abstract, but did not include definitions for mixin classes.
8
+
9
+ This change aligns the criterion to exclude abstract, but not mixin
10
+ classes.
11
+
12
+ It may be possible to exclude the references to mixin classes in the JSON
13
+ schema output, and thereby be able to continue to exclude definitions
14
+ for mixin classes too. However, an attempt to address this in
15
+ `get_type_info_for_slot_subschema()` was not fully successful for me,
16
+ but was impacted by generator parametrization.
17
+ --- jsonschemagen.py 2024-02-21 08:55:38.699043981 +0100
18
+ +++ jsonschemagen.py 2024-02-21 08:55:10.127030454 +0100
19
+ @@ -225,7 +225,8 @@
20
+ )
21
+
22
+ def handle_class(self, cls: ClassDefinition) -> None:
23
+ - if cls.mixin or cls.abstract:
24
+ + #if cls.mixin or cls.abstract:
25
+ + if cls.abstract:
26
+ return
27
+
28
+ subschema_type = "object"
@@ -0,0 +1,34 @@
1
+ See https://github.com/linkml/linkml/issues/1806 for
2
+ problem and rationale re this patch
3
+ --- jsonschemavalidator.py 2024-02-23 16:19:45.946867800 +0100
4
+ +++ jsonschemavalidator.py 2024-02-23 16:18:26.363624044 +0100
5
+ @@ -187,7 +187,27 @@
6
+ inargs["fmt"] = input_format
7
+
8
+ try:
9
+ - data_as_dict = loader.load_as_dict(source=input, **inargs)
10
+ + if input_format == 'yaml':
11
+ + from io import StringIO
12
+ + from hbreader import FileInfo
13
+ + import os
14
+ + import yaml
15
+ + metadata = FileInfo()
16
+ + data = loader._read_source(
17
+ + input,
18
+ + metadata=metadata,
19
+ + accept_header="text/yaml, application/yaml;q=0.9",
20
+ + )
21
+ + if isinstance(data, str):
22
+ + data = StringIO(data)
23
+ + if metadata and metadata.source_file:
24
+ + data.name = os.path.relpath(metadata.source_file,
25
+ + metadata.base_path)
26
+ + data_as_dict = yaml.load(data, yaml.BaseLoader)
27
+ + else:
28
+ + data_as_dict = data
29
+ + else:
30
+ + data_as_dict = loader.load_as_dict(source=input, **inargs)
31
+ except NotImplementedError:
32
+ obj = loader.load(source=input, target_class=py_target_class, **inargs)
33
+ data_as_dict = as_simple_dict(obj)
34
+
@@ -0,0 +1,29 @@
1
+ This patch has been proposed for inclusion in linkml-runtime
2
+ in https://github.com/linkml/linkml-runtime/pull/392
3
+
4
+
5
+ fix type instantiation in _normalize_inlined
6
+
7
+ This commit fixes a problem that was discovered while
8
+ converting between TTL and JSON using the schema
9
+ https://concepts.inm7.de/s/simpleinput/unreleased.yaml
10
+
11
+ The original code used a dictionary as argument to
12
+ the constructor of a pydantic-class, when it should
13
+ have used the **-operator to cnvert the dictionary
14
+ into keyword arguments.
15
+
16
+ diff --git a/linkml_runtime/utils/yamlutils.py b/linkml_runtime/utils/yamlutils.py
17
+ index 8ca8b30..d309091 100644
18
+ --- a/linkml_runtime/utils/yamlutils.py
19
+ +++ b/linkml_runtime/utils/yamlutils.py
20
+ @@ -169,7 +169,7 @@ class YAMLRoot(JsonObj):
21
+ for lek, lev in items(list_entry):
22
+ if lek == key_name and not isinstance(lev, (list, dict, JsonObj)):
23
+ # key_name:value
24
+ - order_up(list_entry[lek], slot_type(list_entry))
25
+ + order_up(list_entry[lek], slot_type(**list_entry))
26
+ break # Not strictly necessary, but
27
+ elif not isinstance(lev, (list, dict, JsonObj)):
28
+ # key: value --> slot_type(key, value)
29
+
@@ -0,0 +1,22 @@
1
+ Make linkml-convert produce deterministic RDF output.
2
+ See https://github.com/linkml/linkml/issues/1943 for details
3
+ and caveats
4
+ --- rdflib_dumper.py 2024-02-24 07:36:07.532183567 +0100
5
+ +++ rdflib_dumper.py 2024-02-24 07:36:26.279874637 +0100
6
+ @@ -6,6 +6,7 @@
7
+
8
+ from curies import Converter
9
+ from rdflib import Graph, URIRef, XSD
10
+ +from rdflib.compare import to_canonical_graph
11
+ from rdflib.term import Node, BNode, Literal
12
+ from rdflib.namespace import RDF
13
+
14
+ @@ -66,7 +67,7 @@
15
+ if schemaview.namespaces()._base:
16
+ g.base = schemaview.namespaces()._base
17
+ self.inject_triples(element, schemaview, g)
18
+ - return g
19
+ + return to_canonical_graph(g)
20
+
21
+ def inject_triples(self, element: Any, schemaview: SchemaView, graph: Graph, target_type: ElementName = None) -> Node:
22
+ """
@@ -0,0 +1,27 @@
1
+ # Populate type-designator slots from graph
2
+ # (for inlined blank-nodes -- but actuallu unclear how the issue reaches).
3
+ #
4
+ # Example of a record it could not handle without this patch (failing to
5
+ # encode `IssuedIdentifier` being the actual type of the identifier.
6
+ #
7
+ # @prefix dlidentifiers: <https://concepts.datalad.org/s/identifiers/unreleased/> .
8
+ # @prefix dlsocial: <https://concepts.datalad.org/s/social/unreleased/> .
9
+ # @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
10
+ #
11
+ # <https://trr379.de/contributors/michael-hanke> a dlsocial:Person ;
12
+ # dlidentifiers:identifier [ a dlidentifiers:IssuedIdentifier ;
13
+ # dlidentifiers:creator "https://orcid.org"^^xsd:anyURI ;
14
+ # dlidentifiers:notation "0000-0001-6398-6370" ;
15
+ # dlidentifiers:schema_agency "Open Researcher and Contributor ID organization" ] ;
16
+ # dlsocial:given_name "Michael" ;
17
+ #
18
+ --- rdflib_loader.py 2025-02-10 01:09:21.627350190 +0100
19
+ +++ rdflib_loader.py 2025-02-10 01:10:15.593488451 +0100
20
+ @@ -106,6 +106,7 @@
21
+ raise ValueError(f'Ambiguous types for {subject} == {type_classes}')
22
+ logger.info(f'Replacing {subject_class} with {type_classes}')
23
+ subject_class = type_classes[0].name
24
+ + dict_obj[type_designator_slot.name] = type_classes[0].class_uri
25
+ # process all triples for this node
26
+ for (_, p, o) in graph.triples((subject, None, None)):
27
+ processed_triples.add((subject,p,o))
@@ -0,0 +1,14 @@
1
+ This patches shacl_ifabsent_processor.py by adding ifabsent handling for the
2
+ uriorcurie type, which is needed for the 'creator' slot in the identifiers schema
3
+ --- shacl_ifabsent_processor.py
4
+ +++ shacl_ifabsent_processor.py
5
+ @@ -62,7 +62,8 @@ class ShaclIfAbsentProcessor(IfAbsentProcessor):
6
+ return Literal(f"{year}-{month}-{day}T{hour}:{minutes}:{seconds}", datatype=ShaclDataType.DATETIME.uri_ref)
7
+
8
+ def map_uri_or_curie_default_value(self, default_value: str, slot: SlotDefinition, cls: ClassDefinition):
9
+ - raise NotImplementedError()
10
+ + uri = URIRef(self.schema_view.expand_curie(default_value))
11
+ + return Literal(uri, datatype=ShaclDataType.URI.uri_ref)
12
+
13
+ def map_curie_default_value(self, default_value: str, slot: SlotDefinition, cls: ClassDefinition):
14
+ return Literal(default_value, datatype=ShaclDataType.CURIE.uri_ref)
@@ -0,0 +1,63 @@
1
+ This patches shaclgen.py to allow improved handling of slot annotations and sh:order.
2
+ Firstly, it introduces the --exclude-order flag that allows to completely disable the
3
+ automatic assignment of the sh:order field to exported property shapes. See:
4
+ https://github.com/psychoinformatics-de/shacl-vue/issues/107#issuecomment-2866073117
5
+ Secondly, if the --exclude-order flag is not used, the patch prevents creation of faulty
6
+ sh:order lists by prioritizing sh:order provided via annotation, since sh:order should
7
+ just be a single numerical value. See for context:
8
+ https://github.com/linkml/linkml/pull/2111#issuecomment-2116208229
9
+ Lastlt, and for a similar reason as before, it only sets sh:path automatically if the
10
+ value has not already been set via annotation.
11
+ --- shaclgen.py
12
+ +++ shaclgen.py
13
+ @@ -30,6 +30,8 @@ class ShaclGenerator(Generator):
14
+ """parameterized suffix to be appended. No suffix per default."""
15
+ include_annotations: bool = False
16
+ """True means include all class / slot / type annotations in generated Node or Property shapes"""
17
+ + exclude_order: bool = False
18
+ + """True means exclude the automatic addition of sh:order to Property shapes"""
19
+ exclude_imports: bool = False
20
+ """If True, elements from imported ontologies won't be included in the generator's output"""
21
+ generatorname = os.path.basename(__file__)
22
+ @@ -114,8 +116,6 @@ class ShaclGenerator(Generator):
23
+ g.add((pnode, p, Literal(v)))
24
+
25
+ prop_pv(SH.path, slot_uri)
26
+ - prop_pv_literal(SH.order, order)
27
+ - order += 1
28
+ prop_pv_literal(SH.name, s.title)
29
+ prop_pv_literal(SH.description, s.description)
30
+ # minCount
31
+ @@ -223,6 +223,18 @@ class ShaclGenerator(Generator):
32
+ default_value = ifabsent_processor.process_slot(s, c)
33
+ if default_value:
34
+ prop_pv(SH.defaultValue, default_value)
35
+ +
36
+ + # Add the order automatically unless the --exclude-order flag was supplied
37
+ + if not self.exclude_order:
38
+ + # sh:order may already have been added to the graph via annotations
39
+ + if not (pnode, SH.order, None) in g:
40
+ + prop_pv_literal(SH.order, order)
41
+ + order += 1
42
+ +
43
+ + # sh:path may already have been added to the graph via annotations
44
+ + if not (pnode, SH.path, None) in g:
45
+ + prop_pv(SH.path, slot_uri)
46
+ +
47
+
48
+ return g
49
+
50
+ @@ -366,6 +378,13 @@ def add_simple_data_type(func: Callable, r: ElementName) -> None:
51
+ show_default=True,
52
+ help="Use --include-annotations to include annotations of slots, types, and classes in the generated SHACL shapes.",
53
+ )
54
+ +@click.option(
55
+ + "--exclude-order/--include-order",
56
+ + default=False,
57
+ + show_default=True,
58
+ + help="Use --exclude-order to exclude sh:order from being added automatically to generated SHACL property shapes. "
59
+ + "Default behavior adds order. This flag has no influence on sh:order being added via annotations.",
60
+ +)
61
+ @click.option(
62
+ "--exclude-imports/--include-imports",
63
+ default=False,
@@ -0,0 +1,18 @@
1
+ #!/bin/bash
2
+ #
3
+ # This script applies patches to the active linkml installation.
4
+ # It is to be executed in the root of the repository.
5
+ #
6
+
7
+ # make JSON schema generation work with mixins
8
+ patch -d $(python -c 'import os; import linkml.generators.jsonschemagen as m; print(os.path.dirname(m.__file__))') < patches/jsonschemagen_mixins.diff
9
+ #patch -d $(python -c 'import os; import linkml.validators.jsonschemavalidator as m; print(os.path.dirname(m.__file__))') < patches/jsonschemavalidator_plainyaml.diff
10
+ #patch -d $(python -c 'import os; import linkml_runtime.dumpers as m; print(os.path.dirname(m.__file__))') < patches/rdflib_dumper_canonical.diff
11
+ # Create correct 'order' properties when generating SHACL
12
+ patch -d $(python -c 'import os; import linkml.generators.shaclgen as m; print(os.path.dirname(m.__file__))') < patches/shaclgen_annotations.diff
13
+ # Allow ifabsent handling of uriorcurie type during SHACL generation
14
+ patch -d $(python -c 'import os; import linkml.generators.shacl.shacl_ifabsent_processor as m; print(os.path.dirname(m.__file__))') < patches/shacl_ifabsent.diff
15
+ # Honor type-designator slots when loading graphs
16
+ patch -d $(python -c 'import os; import linkml_runtime.loaders as m; print(os.path.dirname(m.__file__))') < patches/rdflib_loader_typedesignator.diff
17
+ # Use correct constructor arguments when normalizing inlined objects
18
+ patch -d $(python -c 'import os; import linkml_runtime.utils.yamlutils as m; print(os.path.dirname(m.__file__))') < patches/linkml_runtime_utils_yamlutils.diff
@@ -0,0 +1 @@
1
+ __version__ = '0.2.0'
@@ -0,0 +1,38 @@
1
+ from enum import Enum
2
+ from typing import (
3
+ Any,
4
+ Union,
5
+ )
6
+
7
+ from starlette.status import (
8
+ HTTP_200_OK,
9
+ HTTP_400_BAD_REQUEST,
10
+ HTTP_401_UNAUTHORIZED,
11
+ HTTP_403_FORBIDDEN,
12
+ HTTP_404_NOT_FOUND,
13
+ HTTP_500_INTERNAL_SERVER_ERROR,
14
+ )
15
+
16
+ __all__ = [
17
+ 'Format',
18
+ 'HTTP_200_OK',
19
+ 'HTTP_400_BAD_REQUEST',
20
+ 'HTTP_401_UNAUTHORIZED',
21
+ 'HTTP_403_FORBIDDEN',
22
+ 'HTTP_404_NOT_FOUND',
23
+ 'HTTP_500_INTERNAL_SERVER_ERROR',
24
+ 'JSON',
25
+ 'YAML',
26
+ 'config_file_name',
27
+ ]
28
+
29
+
30
+ class Format(str, Enum):
31
+ json = 'json'
32
+ ttl = 'ttl'
33
+
34
+
35
+ JSON = Union[dict[str, Any], list[Any], str, int, float, None]
36
+ YAML = JSON
37
+
38
+ config_file_name = '.dumpthings.yaml'