linkml 1.8.3__tar.gz → 1.8.5__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.
- {linkml-1.8.3 → linkml-1.8.5}/PKG-INFO +3 -1
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/__init__.py +2 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/common/ifabsent_processor.py +98 -21
- linkml-1.8.5/linkml/generators/common/naming.py +106 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/docgen/index.md.jinja2 +6 -6
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/docgen.py +80 -21
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/golanggen.py +3 -1
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/graphqlgen.py +34 -2
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/jsonschemagen.py +4 -2
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/owlgen.py +36 -17
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/projectgen.py +13 -11
- linkml-1.8.5/linkml/generators/pydanticgen/array.py +662 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/pydanticgen/build.py +4 -2
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/pydanticgen/pydanticgen.py +35 -16
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/pydanticgen/template.py +119 -3
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/pydanticgen/templates/imports.py.jinja +11 -3
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/pydanticgen/templates/module.py.jinja +1 -3
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/pydanticgen/templates/validator.py.jinja +2 -2
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/python/python_ifabsent_processor.py +1 -1
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/pythongen.py +135 -31
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/shaclgen.py +34 -10
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/sparqlgen.py +3 -1
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/sqlalchemygen.py +5 -3
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/sqltablegen.py +4 -2
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/typescriptgen.py +13 -6
- {linkml-1.8.3 → linkml-1.8.5}/linkml/linter/linter.py +2 -1
- {linkml-1.8.3 → linkml-1.8.5}/linkml/transformers/logical_model_transformer.py +3 -3
- {linkml-1.8.3 → linkml-1.8.5}/linkml/transformers/relmodel_transformer.py +18 -4
- {linkml-1.8.3 → linkml-1.8.5}/linkml/utils/converter.py +3 -1
- linkml-1.8.5/linkml/utils/exceptions.py +11 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/utils/execute_tutorial.py +22 -20
- {linkml-1.8.3 → linkml-1.8.5}/linkml/utils/generator.py +6 -4
- {linkml-1.8.3 → linkml-1.8.5}/linkml/utils/mergeutils.py +4 -2
- {linkml-1.8.3 → linkml-1.8.5}/linkml/utils/schema_fixer.py +5 -5
- {linkml-1.8.3 → linkml-1.8.5}/linkml/utils/schemaloader.py +5 -3
- {linkml-1.8.3 → linkml-1.8.5}/linkml/utils/sqlutils.py +3 -1
- {linkml-1.8.3 → linkml-1.8.5}/linkml/validator/plugins/pydantic_validation_plugin.py +1 -1
- {linkml-1.8.3 → linkml-1.8.5}/linkml/validators/jsonschemavalidator.py +3 -1
- {linkml-1.8.3 → linkml-1.8.5}/linkml/validators/sparqlvalidator.py +5 -3
- {linkml-1.8.3 → linkml-1.8.5}/linkml/workspaces/example_runner.py +3 -1
- {linkml-1.8.3 → linkml-1.8.5}/pyproject.toml +11 -4
- {linkml-1.8.3 → linkml-1.8.5}/setup.py +4 -2
- linkml-1.8.3/linkml/generators/pydanticgen/array.py +0 -378
- {linkml-1.8.3 → linkml-1.8.5}/LICENSE +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/README.md +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/__init__.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/_version.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/cli/__init__.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/cli/__main__.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/cli/main.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/PythonGenNotes.md +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/README.md +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/common/__init__.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/common/build.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/common/lifecycle.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/common/template.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/common/type_designators.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/csvgen.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/docgen/class.md.jinja2 +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/docgen/class_diagram.md.jinja2 +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/docgen/common_metadata.md.jinja2 +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/docgen/enum.md.jinja2 +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/docgen/index.tex.jinja2 +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/docgen/schema.md.jinja2 +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/docgen/slot.md.jinja2 +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/docgen/subset.md.jinja2 +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/docgen/type.md.jinja2 +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/dotgen.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/erdiagramgen.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/excelgen.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/golrgen.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/javagen/example_template.java.jinja2 +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/javagen/java_record_template.jinja2 +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/javagen.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/jsonldcontextgen.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/jsonldgen.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/legacy/__init__.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/linkmlgen.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/markdowngen.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/namespacegen.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/oocodegen.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/plantumlgen.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/prefixmapgen.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/protogen.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/pydanticgen/__init__.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/pydanticgen/black.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/pydanticgen/includes.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/pydanticgen/templates/attribute.py.jinja +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/pydanticgen/templates/base_model.py.jinja +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/pydanticgen/templates/class.py.jinja +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/pydanticgen/templates/conditional_import.py.jinja +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/pydanticgen/templates/enum.py.jinja +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/pydanticgen/templates/footer.py.jinja +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/python/__init__.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/rdfgen.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/shacl/__init__.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/shacl/shacl_data_type.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/shacl/shacl_ifabsent_processor.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/shexgen.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/sqlalchemy/__init__.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/sqlalchemy/sqlalchemy_declarative_template.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/sqlalchemy/sqlalchemy_imperative_template.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/sssomgen.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/string_template.md +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/summarygen.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/terminusdbgen.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/yamlgen.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/generators/yumlgen.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/linter/__init__.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/linter/cli.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/linter/config/datamodel/.linkmllint.yaml +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/linter/config/datamodel/__init__.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/linter/config/datamodel/config.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/linter/config/datamodel/config.yaml +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/linter/config/default.yaml +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/linter/config/recommended.yaml +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/linter/formatters/__init__.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/linter/formatters/formatter.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/linter/formatters/json_formatter.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/linter/formatters/markdown_formatter.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/linter/formatters/terminal_formatter.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/linter/formatters/tsv_formatter.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/linter/rules.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/reporting/__init__.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/reporting/model.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/transformers/__init__.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/transformers/model_transformer.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/transformers/schema_renamer.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/utils/__init__.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/utils/cli_utils.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/utils/datautils.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/utils/datavalidator.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/utils/deprecation.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/utils/helpers.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/utils/logictools.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/utils/rawloader.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/utils/schema_builder.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/utils/schemasynopsis.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/utils/typereferences.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/utils/validation.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/validator/__init__.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/validator/cli.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/validator/loaders/__init__.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/validator/loaders/delimited_file_loader.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/validator/loaders/json_loader.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/validator/loaders/loader.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/validator/loaders/passthrough_loader.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/validator/loaders/yaml_loader.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/validator/plugins/__init__.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/validator/plugins/jsonschema_validation_plugin.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/validator/plugins/recommended_slots_plugin.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/validator/plugins/shacl_validation_plugin.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/validator/plugins/validation_plugin.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/validator/report.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/validator/validation_context.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/validator/validator.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/validators/__init__.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/workspaces/__init__.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/workspaces/datamodel/__init__.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/workspaces/datamodel/workspaces.py +0 -0
- {linkml-1.8.3 → linkml-1.8.5}/linkml/workspaces/datamodel/workspaces.yaml +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: linkml
|
3
|
-
Version: 1.8.
|
3
|
+
Version: 1.8.5
|
4
4
|
Summary: Linked Open Data Modeling Language
|
5
5
|
Home-page: https://linkml.io/linkml/
|
6
6
|
Keywords: schema,linked data,data modeling,rdf,owl,biolink
|
@@ -24,6 +24,7 @@ Classifier: Programming Language :: Python :: 3.8
|
|
24
24
|
Classifier: Programming Language :: Python :: 3.9
|
25
25
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
26
26
|
Provides-Extra: black
|
27
|
+
Provides-Extra: numpydantic
|
27
28
|
Provides-Extra: shacl
|
28
29
|
Provides-Extra: tests
|
29
30
|
Requires-Dist: antlr4-python3-runtime (>=4.9.0,<4.10)
|
@@ -37,6 +38,7 @@ Requires-Dist: jsonasobj2 (>=1.0.3,<2.0.0)
|
|
37
38
|
Requires-Dist: jsonschema[format] (>=4.0.0)
|
38
39
|
Requires-Dist: linkml-dataops
|
39
40
|
Requires-Dist: linkml-runtime (>=1.8.1,<2.0.0)
|
41
|
+
Requires-Dist: numpydantic (>=1.6.1) ; (python_version >= "3.9") and (extra == "numpydantic" or extra == "tests")
|
40
42
|
Requires-Dist: openpyxl
|
41
43
|
Requires-Dist: parse
|
42
44
|
Requires-Dist: prefixcommons (>=0.1.7)
|
@@ -10,6 +10,7 @@ from linkml.generators.jsonschemagen import JsonSchemaGenerator
|
|
10
10
|
from linkml.generators.owlgen import OwlSchemaGenerator
|
11
11
|
from linkml.generators.pydanticgen import PydanticGenerator
|
12
12
|
from linkml.generators.pythongen import PythonGenerator
|
13
|
+
from linkml.generators.rdfgen import RDFGenerator
|
13
14
|
from linkml.generators.shaclgen import ShaclGenerator
|
14
15
|
from linkml.generators.shexgen import ShExGenerator
|
15
16
|
from linkml.generators.sqlalchemygen import SQLAlchemyGenerator
|
@@ -50,6 +51,7 @@ __all__ = [
|
|
50
51
|
"ShExGenerator",
|
51
52
|
"SQLAlchemyGenerator",
|
52
53
|
"SQLTableGenerator",
|
54
|
+
"RDFGenerator",
|
53
55
|
]
|
54
56
|
|
55
57
|
# TODO: deprecate usage of these
|
@@ -1,7 +1,13 @@
|
|
1
1
|
import abc
|
2
2
|
import re
|
3
|
+
import sys
|
3
4
|
from abc import ABC
|
4
|
-
from typing import Any, Optional
|
5
|
+
from typing import Any, Optional, Type, Union
|
6
|
+
|
7
|
+
if sys.version_info < (3, 10):
|
8
|
+
from typing_extensions import TypeAlias
|
9
|
+
else:
|
10
|
+
from typing import TypeAlias
|
5
11
|
|
6
12
|
from linkml_runtime import SchemaView
|
7
13
|
from linkml_runtime.linkml_model import (
|
@@ -18,6 +24,7 @@ from linkml_runtime.linkml_model import (
|
|
18
24
|
String,
|
19
25
|
Time,
|
20
26
|
Uri,
|
27
|
+
types,
|
21
28
|
)
|
22
29
|
from linkml_runtime.linkml_model.types import (
|
23
30
|
Curie,
|
@@ -31,6 +38,34 @@ from linkml_runtime.linkml_model.types import (
|
|
31
38
|
Uriorcurie,
|
32
39
|
)
|
33
40
|
|
41
|
+
TYPES_TYPE: TypeAlias = Union[
|
42
|
+
Type[Boolean],
|
43
|
+
Type[Curie],
|
44
|
+
Type[Date],
|
45
|
+
Type[DateOrDatetime],
|
46
|
+
Type[Datetime],
|
47
|
+
Type[Decimal],
|
48
|
+
Type[Double],
|
49
|
+
Type[Float],
|
50
|
+
Type[Integer],
|
51
|
+
Type[Jsonpath],
|
52
|
+
Type[Jsonpointer],
|
53
|
+
Type[Ncname],
|
54
|
+
Type[Nodeidentifier],
|
55
|
+
Type[Objectidentifier],
|
56
|
+
Type[Sparqlpath],
|
57
|
+
Type[String],
|
58
|
+
Type[Time],
|
59
|
+
Type[Uri],
|
60
|
+
Type[Uriorcurie],
|
61
|
+
]
|
62
|
+
|
63
|
+
TYPES = [
|
64
|
+
t
|
65
|
+
for t in types.__dict__.values()
|
66
|
+
if isinstance(t, type) and t.__module__ == types.__name__ and hasattr(t, "type_name")
|
67
|
+
]
|
68
|
+
|
34
69
|
|
35
70
|
class IfAbsentProcessor(ABC):
|
36
71
|
"""
|
@@ -39,7 +74,7 @@ class IfAbsentProcessor(ABC):
|
|
39
74
|
See `<https://w3id.org/linkml/ifabsent>`_.
|
40
75
|
"""
|
41
76
|
|
42
|
-
ifabsent_regex = re.compile("""(?:(?P<type>\w+)\()?[\"\']?(?P<default_value>[^\(\)\"\')]*)[\"\']?\)?""")
|
77
|
+
ifabsent_regex = re.compile(r"""(?:(?P<type>\w+)\()?[\"\']?(?P<default_value>[^\(\)\"\')]*)[\"\']?\)?""")
|
43
78
|
|
44
79
|
def __init__(self, schema_view: SchemaView):
|
45
80
|
self.schema_view = schema_view
|
@@ -61,10 +96,12 @@ class IfAbsentProcessor(ABC):
|
|
61
96
|
if mapped:
|
62
97
|
return custom_default_value
|
63
98
|
|
64
|
-
|
99
|
+
base_type = self._base_type(slot.range)
|
100
|
+
|
101
|
+
if base_type is String:
|
65
102
|
return self.map_string_default_value(ifabsent_default_value, slot, cls)
|
66
103
|
|
67
|
-
if
|
104
|
+
if base_type is Boolean:
|
68
105
|
if re.match(r"^[Tt]rue$", ifabsent_default_value):
|
69
106
|
return self.map_boolean_true_default_value(slot, cls)
|
70
107
|
elif re.match(r"^[Ff]alse$", ifabsent_default_value):
|
@@ -75,19 +112,19 @@ class IfAbsentProcessor(ABC):
|
|
75
112
|
f"value"
|
76
113
|
)
|
77
114
|
|
78
|
-
if
|
115
|
+
if base_type is Integer:
|
79
116
|
return self.map_integer_default_value(ifabsent_default_value, slot, cls)
|
80
117
|
|
81
|
-
if
|
118
|
+
if base_type is Float:
|
82
119
|
return self.map_float_default_value(ifabsent_default_value, slot, cls)
|
83
120
|
|
84
|
-
if
|
121
|
+
if base_type is Double:
|
85
122
|
return self.map_double_default_value(ifabsent_default_value, slot, cls)
|
86
123
|
|
87
|
-
if
|
124
|
+
if base_type is Decimal:
|
88
125
|
return self.map_decimal_default_value(ifabsent_default_value, slot, cls)
|
89
126
|
|
90
|
-
if
|
127
|
+
if base_type is Time:
|
91
128
|
match = re.match(r"^(\d{2}):(\d{2}):(\d{2}).*$", ifabsent_default_value)
|
92
129
|
if match:
|
93
130
|
return self.map_time_default_value(match[1], match[2], match[3], slot, cls)
|
@@ -97,7 +134,7 @@ class IfAbsentProcessor(ABC):
|
|
97
134
|
)
|
98
135
|
|
99
136
|
# TODO manage timezones and offsets
|
100
|
-
if
|
137
|
+
if base_type is Date:
|
101
138
|
match = re.match(r"^(\d{4})-(\d{2})-(\d{2})$", ifabsent_default_value)
|
102
139
|
if match:
|
103
140
|
return self.map_date_default_value(match[1], match[2], match[3], slot, cls)
|
@@ -107,7 +144,7 @@ class IfAbsentProcessor(ABC):
|
|
107
144
|
)
|
108
145
|
|
109
146
|
# TODO manage timezones and offsets
|
110
|
-
if
|
147
|
+
if base_type is Datetime:
|
111
148
|
match = re.match(r"^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}).*$", ifabsent_default_value)
|
112
149
|
if match:
|
113
150
|
return self.map_datetime_default_value(
|
@@ -120,7 +157,7 @@ class IfAbsentProcessor(ABC):
|
|
120
157
|
)
|
121
158
|
|
122
159
|
# TODO manage timezones and offsets
|
123
|
-
if
|
160
|
+
if base_type is DateOrDatetime:
|
124
161
|
match = re.match(r"^(\d{4})-(\d{2})-(\d{2})(?:T(\d{2}):(\d{2}):(\d{2}))?.*$", ifabsent_default_value)
|
125
162
|
if match and (match[4] is None or match[5] is None or match[6] is None):
|
126
163
|
return self.map_date_default_value(match[1], match[2], match[3], slot, cls)
|
@@ -134,31 +171,31 @@ class IfAbsentProcessor(ABC):
|
|
134
171
|
f"datetime value"
|
135
172
|
)
|
136
173
|
|
137
|
-
if
|
174
|
+
if base_type is Uri:
|
138
175
|
return self.map_uri_default_value(ifabsent_default_value, slot, cls)
|
139
176
|
|
140
|
-
if
|
177
|
+
if base_type is Curie:
|
141
178
|
return self.map_curie_default_value(ifabsent_default_value, slot, cls)
|
142
179
|
|
143
|
-
if
|
180
|
+
if base_type is Uriorcurie:
|
144
181
|
return self.map_uri_or_curie_default_value(ifabsent_default_value, slot, cls)
|
145
182
|
|
146
|
-
if
|
183
|
+
if base_type is Ncname:
|
147
184
|
return self.map_nc_name_default_value(ifabsent_default_value, slot, cls)
|
148
185
|
|
149
|
-
if
|
186
|
+
if base_type is Objectidentifier:
|
150
187
|
return self.map_object_identifier_default_value(ifabsent_default_value, slot, cls)
|
151
188
|
|
152
|
-
if
|
189
|
+
if base_type is Nodeidentifier:
|
153
190
|
return self.map_node_identifier_default_value(ifabsent_default_value, slot, cls)
|
154
191
|
|
155
|
-
if
|
192
|
+
if base_type is Jsonpointer:
|
156
193
|
return self.map_json_pointer_default_value(ifabsent_default_value, slot, cls)
|
157
194
|
|
158
|
-
if
|
195
|
+
if base_type is Jsonpath:
|
159
196
|
return self.map_json_path_default_value(ifabsent_default_value, slot, cls)
|
160
197
|
|
161
|
-
if
|
198
|
+
if base_type is Sparqlpath:
|
162
199
|
return self.map_sparql_path_default_value(ifabsent_default_value, slot, cls)
|
163
200
|
|
164
201
|
# -----------------------
|
@@ -173,6 +210,46 @@ class IfAbsentProcessor(ABC):
|
|
173
210
|
|
174
211
|
raise ValueError(f"The ifabsent value `{slot.ifabsent}` of the `{slot.name}` slot could not be processed")
|
175
212
|
|
213
|
+
def _base_type(self, range_: str) -> Optional[TYPES_TYPE]:
|
214
|
+
"""
|
215
|
+
Find the linkml base type that corresponds to either a matching type_name or custom type
|
216
|
+
|
217
|
+
First check for an explicit match of the range == TypeDefinition.type_name
|
218
|
+
Then check for explicit inheritance via typeof
|
219
|
+
Finally check for implicit matching via matching base
|
220
|
+
|
221
|
+
Don't raise here, just return None in case another method of resolution like enums are
|
222
|
+
available
|
223
|
+
"""
|
224
|
+
# first check for matching type using type_name - ie. range is already a base type
|
225
|
+
|
226
|
+
for typ in TYPES:
|
227
|
+
if range_ == typ.type_name:
|
228
|
+
return typ
|
229
|
+
|
230
|
+
# if we're not a type, return None to indicate that, e.g. if an enum's permissible_value
|
231
|
+
if range_ not in self.schema_view.all_types(imports=True):
|
232
|
+
return
|
233
|
+
|
234
|
+
# then check explicit descendents of types
|
235
|
+
# base types do not inherit from one another, so the last ancestor is always a base type
|
236
|
+
# if it is inheriting from a base type
|
237
|
+
ancestor = self.schema_view.type_ancestors(range_)[-1]
|
238
|
+
for typ in TYPES:
|
239
|
+
if ancestor == typ.type_name:
|
240
|
+
return typ
|
241
|
+
|
242
|
+
# finally check if we have a matching base
|
243
|
+
induced_typ = self.schema_view.induced_type(range_)
|
244
|
+
if induced_typ.repr is None and induced_typ.base is None:
|
245
|
+
return None
|
246
|
+
for typ in TYPES:
|
247
|
+
# types always inherit from a single type, and that type is their base
|
248
|
+
# our range can match it with repr or base
|
249
|
+
typ_base = typ.__mro__[1].__name__
|
250
|
+
if typ_base == induced_typ.base:
|
251
|
+
return typ
|
252
|
+
|
176
253
|
@abc.abstractmethod
|
177
254
|
def map_custom_default_values(self, default_value: str, slot: SlotDefinition, cls: ClassDefinition) -> (bool, str):
|
178
255
|
"""
|
@@ -0,0 +1,106 @@
|
|
1
|
+
import logging
|
2
|
+
import re
|
3
|
+
import unicodedata
|
4
|
+
from enum import Enum
|
5
|
+
|
6
|
+
|
7
|
+
class NamingProfiles(str, Enum):
|
8
|
+
# GraphQL naming profile ensures compatibility with the GraphQL specification
|
9
|
+
# WRT names: https://spec.graphql.org/October2021/#Name
|
10
|
+
graphql = "graphql"
|
11
|
+
|
12
|
+
|
13
|
+
class NameCompatibility(object):
|
14
|
+
"""Make a name compatible to the given profile"""
|
15
|
+
|
16
|
+
# heading double underscores and digit reserved to names starting with a digit
|
17
|
+
re_reserved_heading_digit = re.compile("^__[0-9]")
|
18
|
+
# valid name between double underscores is reserved for unicode name transformations
|
19
|
+
re_reserved_unicode_name_transformation = re.compile("__[0-9a-zA-Z][0-9a-zA-Z_]*__")
|
20
|
+
# something like '__U_xxxx_' is reserved for unicode code transformations
|
21
|
+
re_reserved_unicode_code_transformation = re.compile("__U_[0-9a-eA-E]{4}_")
|
22
|
+
# strings starting with a digit
|
23
|
+
re_heading_digit = re.compile("^[0-9]")
|
24
|
+
# character that is neither alphanumeric nor underscore
|
25
|
+
re_no_alphanum_underscore = re.compile("[^0-9a-zA-Z_]")
|
26
|
+
|
27
|
+
def __init__(self, profile: NamingProfiles, do_not_fix: bool = False):
|
28
|
+
"""Specify the naming policy on instantiation"""
|
29
|
+
self.profile = profile
|
30
|
+
self.do_not_fix = do_not_fix
|
31
|
+
|
32
|
+
def _no_heading_digits(self, input: str) -> str:
|
33
|
+
"""Ensure name does not start with a heading digit"""
|
34
|
+
output = input
|
35
|
+
if self.re_heading_digit.match(input):
|
36
|
+
if self.do_not_fix:
|
37
|
+
raise ValueError(f"Name '{input}' starts with digit (illegal GraphQL) and will not be fixed!")
|
38
|
+
else:
|
39
|
+
logging.warning(
|
40
|
+
f"Name '{input}' starts with digit (illegal GraphQL), "
|
41
|
+
+ f"it has been prefixed with '__', resulting in {output}"
|
42
|
+
)
|
43
|
+
output = f"__{input}"
|
44
|
+
return output
|
45
|
+
|
46
|
+
def _transform_char(self, char: str) -> str:
|
47
|
+
"""Transform unsupported characters"""
|
48
|
+
if len(char) != 1:
|
49
|
+
raise Exception(f"Single character expected, but got '{char}'!!")
|
50
|
+
# replace whitespaces with underscores
|
51
|
+
# the transformation cannot be inverted, but is a well-established
|
52
|
+
# and expected transformation
|
53
|
+
if char == " ":
|
54
|
+
return "_"
|
55
|
+
# try to use names for ASCII characters
|
56
|
+
if ord(char) < 128:
|
57
|
+
try:
|
58
|
+
# unicodedata.lookup should be able to invert the transformation
|
59
|
+
return f"__{unicodedata.name(char).replace(' ', '_').replace('-', '_')}__"
|
60
|
+
except ValueError:
|
61
|
+
pass
|
62
|
+
# fallback to code-transformation if none of the previous has worked
|
63
|
+
return f"__U_{ord(char):04X}_"
|
64
|
+
|
65
|
+
def _only_alphanum_underscore(self, input: str) -> str:
|
66
|
+
"""Ensure name does not contain any unsupported characters"""
|
67
|
+
output = input
|
68
|
+
# with re.split and re.findall we get in the same order and separated in two arrays
|
69
|
+
# the substrings between special characters and the special characters
|
70
|
+
no_alphanum_underscore_match = self.re_no_alphanum_underscore.findall(input)
|
71
|
+
if no_alphanum_underscore_match:
|
72
|
+
if self.do_not_fix:
|
73
|
+
raise ValueError(f"Name '{input}' contains a character illegal in GraphQL and will not be fixed!")
|
74
|
+
else:
|
75
|
+
logging.warning(
|
76
|
+
f"Name '{input}' contains a character illegal in GraphQL, "
|
77
|
+
+ f"the resulting encoded name is {output}"
|
78
|
+
)
|
79
|
+
to_keep = self.re_no_alphanum_underscore.split(input)
|
80
|
+
# first comes first substring to keep
|
81
|
+
output = to_keep[0]
|
82
|
+
# each char replacement is followed by the next substring to keep
|
83
|
+
for offset in range(0, len(to_keep) - 1):
|
84
|
+
output = output + self._transform_char(no_alphanum_underscore_match[offset])
|
85
|
+
output = output + to_keep[offset + 1]
|
86
|
+
return output
|
87
|
+
|
88
|
+
def _graphql_compatibility(self, input: str) -> str:
|
89
|
+
"""Ensure name compatibility with GraphQL name policies"""
|
90
|
+
# as of now, some (hopefully) very rare patterns are reserved to mark transformations
|
91
|
+
if self.re_reserved_heading_digit.match(input):
|
92
|
+
raise NotImplementedError("Names starting with a double underscore followed by a digit are not supported!!")
|
93
|
+
if self.re_reserved_unicode_name_transformation.match(input):
|
94
|
+
raise NotImplementedError("Names containing valid names between double underscores are not supported!!")
|
95
|
+
if self.re_reserved_unicode_code_transformation.match(input):
|
96
|
+
raise NotImplementedError("Names containing strings like '__U_xxxx_' are not supported!!")
|
97
|
+
# apply transformation
|
98
|
+
output = input
|
99
|
+
output = self._no_heading_digits(output)
|
100
|
+
output = self._only_alphanum_underscore(output)
|
101
|
+
return output
|
102
|
+
|
103
|
+
def compatible(self, input: str) -> str:
|
104
|
+
"""Make given name compatible with the given naming policy."""
|
105
|
+
if self.profile == "graphql":
|
106
|
+
return self._graphql_compatibility(input)
|
@@ -21,11 +21,11 @@ Name: {{ schema.name }}
|
|
21
21
|
| --- | --- |
|
22
22
|
{% if gen.hierarchical_class_view -%}
|
23
23
|
{% for u, v in gen.class_hierarchy_as_tuples() -%}
|
24
|
-
| {{ " "|safe*u*8 }}{{ gen.link(schemaview.get_class(v)) }} | {{ schemaview.get_class(v).description }} |
|
24
|
+
| {{ " "|safe*u*8 }}{{ gen.link(schemaview.get_class(v), True) }} | {{ schemaview.get_class(v).description }} |
|
25
25
|
{% endfor %}
|
26
26
|
{% else -%}
|
27
27
|
{% for c in gen.all_class_objects()|sort(attribute=sort_by) -%}
|
28
|
-
| {{gen.link(c)}} | {{c.description|enshorten}} |
|
28
|
+
| {{gen.link(c, True)}} | {{c.description|enshorten}} |
|
29
29
|
{% endfor %}
|
30
30
|
{% endif %}
|
31
31
|
|
@@ -34,7 +34,7 @@ Name: {{ schema.name }}
|
|
34
34
|
| Slot | Description |
|
35
35
|
| --- | --- |
|
36
36
|
{% for s in gen.all_slot_objects()|sort(attribute=sort_by) -%}
|
37
|
-
| {{gen.link(s)}} | {{s.description|enshorten}} |
|
37
|
+
| {{gen.link(s, True)}} | {{s.description|enshorten}} |
|
38
38
|
{% endfor %}
|
39
39
|
|
40
40
|
## Enumerations
|
@@ -42,7 +42,7 @@ Name: {{ schema.name }}
|
|
42
42
|
| Enumeration | Description |
|
43
43
|
| --- | --- |
|
44
44
|
{% for e in gen.all_enum_objects()|sort(attribute=sort_by) -%}
|
45
|
-
| {{gen.link(e)}} | {{e.description|enshorten}} |
|
45
|
+
| {{gen.link(e, True)}} | {{e.description|enshorten}} |
|
46
46
|
{% endfor %}
|
47
47
|
|
48
48
|
## Types
|
@@ -50,7 +50,7 @@ Name: {{ schema.name }}
|
|
50
50
|
| Type | Description |
|
51
51
|
| --- | --- |
|
52
52
|
{% for t in gen.all_type_objects()|sort(attribute=sort_by) -%}
|
53
|
-
| {{gen.link(t)}} | {{t.description|enshorten}} |
|
53
|
+
| {{gen.link(t, True)}} | {{t.description|enshorten}} |
|
54
54
|
{% endfor %}
|
55
55
|
|
56
56
|
## Subsets
|
@@ -58,5 +58,5 @@ Name: {{ schema.name }}
|
|
58
58
|
| Subset | Description |
|
59
59
|
| --- | --- |
|
60
60
|
{% for ss in schemaview.all_subsets().values()|sort(attribute='name') -%}
|
61
|
-
| {{gen.link(ss)}} | {{ss.description|enshorten}} |
|
61
|
+
| {{gen.link(ss, True)}} | {{ss.description|enshorten}} |
|
62
62
|
{% endfor %}
|
@@ -50,6 +50,13 @@ DIALECT = MarkdownDialect
|
|
50
50
|
MAX_CHARS_IN_TABLE = 80
|
51
51
|
MAX_RANK = 1000
|
52
52
|
|
53
|
+
SCHEMA_SUBFOLDER = "schemas"
|
54
|
+
CLASS_SUBFOLDER = "classes"
|
55
|
+
SLOT_SUBFOLDER = "slots"
|
56
|
+
ENUM_SUBFOLDER = "enums"
|
57
|
+
TYPE_SUBFOLDER = "types"
|
58
|
+
SUBSET_SUBFOLDER = "subsets"
|
59
|
+
|
53
60
|
|
54
61
|
def enshorten(input):
|
55
62
|
"""
|
@@ -144,6 +151,9 @@ class DocGenerator(Generator):
|
|
144
151
|
include_top_level_diagram: bool = False
|
145
152
|
"""Whether the index page should include a schema diagram"""
|
146
153
|
|
154
|
+
subfolder_type_separation: bool = False
|
155
|
+
"""Whether each type (class, slot, etc.) should be put in separate subfolder for navigation purposes"""
|
156
|
+
|
147
157
|
example_directory: Optional[str] = None
|
148
158
|
example_runner: ExampleRunner = field(default_factory=lambda: ExampleRunner())
|
149
159
|
|
@@ -154,6 +164,7 @@ class DocGenerator(Generator):
|
|
154
164
|
use_slot_uris: bool = False
|
155
165
|
use_class_uris: bool = False
|
156
166
|
hierarchical_class_view: bool = False
|
167
|
+
render_imports: bool = False
|
157
168
|
|
158
169
|
def __post_init__(self):
|
159
170
|
dialect = self.dialect
|
@@ -205,7 +216,11 @@ class DocGenerator(Generator):
|
|
205
216
|
self.logger.debug(f" Generating doc for {schema_name}")
|
206
217
|
imported_schema = sv.schema_map.get(schema_name)
|
207
218
|
out_str = template.render(gen=self, schema=imported_schema, schemaview=sv, **template_vars)
|
208
|
-
self._write(
|
219
|
+
self._write(
|
220
|
+
out_str,
|
221
|
+
f"{directory}/{SCHEMA_SUBFOLDER}" if self.subfolder_type_separation else directory,
|
222
|
+
imported_schema.name,
|
223
|
+
)
|
209
224
|
self.logger.debug("Processing Classes...")
|
210
225
|
template = self._get_template("class")
|
211
226
|
for cn, c in sv.all_classes().items():
|
@@ -214,7 +229,7 @@ class DocGenerator(Generator):
|
|
214
229
|
n = self.name(c)
|
215
230
|
self.logger.debug(f" Generating doc for {n}")
|
216
231
|
out_str = template.render(gen=self, element=c, schemaview=sv, **template_vars)
|
217
|
-
self._write(out_str, directory, n)
|
232
|
+
self._write(out_str, f"{directory}/{CLASS_SUBFOLDER}" if self.subfolder_type_separation else directory, n)
|
218
233
|
self.logger.debug("Processing Slots...")
|
219
234
|
template = self._get_template("slot")
|
220
235
|
for sn, s in sv.all_slots().items():
|
@@ -224,7 +239,7 @@ class DocGenerator(Generator):
|
|
224
239
|
self.logger.debug(f" Generating doc for {n}")
|
225
240
|
s = sv.induced_slot(sn)
|
226
241
|
out_str = template.render(gen=self, element=s, schemaview=sv, **template_vars)
|
227
|
-
self._write(out_str, directory, n)
|
242
|
+
self._write(out_str, f"{directory}/{SLOT_SUBFOLDER}" if self.subfolder_type_separation else directory, n)
|
228
243
|
self.logger.debug("Processing Enums...")
|
229
244
|
template = self._get_template("enum")
|
230
245
|
for en, e in sv.all_enums().items():
|
@@ -233,7 +248,7 @@ class DocGenerator(Generator):
|
|
233
248
|
n = self.name(e)
|
234
249
|
self.logger.debug(f" Generating doc for {n}")
|
235
250
|
out_str = template.render(gen=self, element=e, schemaview=sv, **template_vars)
|
236
|
-
self._write(out_str, directory, n)
|
251
|
+
self._write(out_str, f"{directory}/{ENUM_SUBFOLDER}" if self.subfolder_type_separation else directory, n)
|
237
252
|
self.logger.debug("Processing Types...")
|
238
253
|
template = self._get_template("type")
|
239
254
|
for tn, t in sv.all_types().items():
|
@@ -243,7 +258,7 @@ class DocGenerator(Generator):
|
|
243
258
|
self.logger.debug(f" Generating doc for {n}")
|
244
259
|
t = sv.induced_type(tn)
|
245
260
|
out_str = template.render(gen=self, element=t, schemaview=sv, **template_vars)
|
246
|
-
self._write(out_str, directory, n)
|
261
|
+
self._write(out_str, f"{directory}/{TYPE_SUBFOLDER}" if self.subfolder_type_separation else directory, n)
|
247
262
|
self.logger.debug("Processing Subsets...")
|
248
263
|
template = self._get_template("subset")
|
249
264
|
for _, s in sv.all_subsets().items():
|
@@ -252,7 +267,7 @@ class DocGenerator(Generator):
|
|
252
267
|
n = self.name(s)
|
253
268
|
self.logger.debug(f" Generating doc for {n}")
|
254
269
|
out_str = template.render(gen=self, element=s, schemaview=sv, **template_vars)
|
255
|
-
self._write(out_str, directory, n)
|
270
|
+
self._write(out_str, f"{directory}/{SUBSET_SUBFOLDER}" if self.subfolder_type_separation else directory, n)
|
256
271
|
|
257
272
|
def _write(self, out_str: str, directory: str, name: str) -> None:
|
258
273
|
"""
|
@@ -384,13 +399,19 @@ class DocGenerator(Generator):
|
|
384
399
|
curie = self.uri(element, expand=False)
|
385
400
|
return f"[{curie}]({uri})"
|
386
401
|
|
387
|
-
def link(self, e: Union[Definition, DefinitionName]) -> str:
|
402
|
+
def link(self, e: Union[Definition, DefinitionName], index_link: bool = False) -> str:
|
388
403
|
"""
|
389
404
|
Render an element as a hyperlink
|
390
405
|
|
391
406
|
:param e:
|
407
|
+
:param index_link: Whether this is a link for the index page or not
|
392
408
|
:return:
|
393
409
|
"""
|
410
|
+
if index_link:
|
411
|
+
subfolder = ""
|
412
|
+
else:
|
413
|
+
subfolder = "../"
|
414
|
+
|
394
415
|
if e is None:
|
395
416
|
return "NONE"
|
396
417
|
if not isinstance(e, Definition):
|
@@ -401,20 +422,43 @@ class DocGenerator(Generator):
|
|
401
422
|
if self.use_class_uris:
|
402
423
|
curie = self.schemaview.get_uri(e)
|
403
424
|
if curie is not None:
|
404
|
-
return self._markdown_link(
|
405
|
-
|
425
|
+
return self._markdown_link(
|
426
|
+
n=curie.split(":")[1],
|
427
|
+
name=e.name,
|
428
|
+
subfolder=subfolder + CLASS_SUBFOLDER if self.subfolder_type_separation else None,
|
429
|
+
)
|
430
|
+
return self._markdown_link(
|
431
|
+
camelcase(e.name),
|
432
|
+
subfolder=subfolder + CLASS_SUBFOLDER if self.subfolder_type_separation else None,
|
433
|
+
)
|
406
434
|
elif isinstance(e, EnumDefinition):
|
407
|
-
return self._markdown_link(
|
435
|
+
return self._markdown_link(
|
436
|
+
camelcase(e.name),
|
437
|
+
subfolder=subfolder + ENUM_SUBFOLDER if self.subfolder_type_separation else None,
|
438
|
+
)
|
408
439
|
elif isinstance(e, SlotDefinition):
|
409
440
|
if self.use_slot_uris:
|
410
441
|
curie = self.schemaview.get_uri(e)
|
411
442
|
if curie is not None:
|
412
|
-
return self._markdown_link(
|
413
|
-
|
443
|
+
return self._markdown_link(
|
444
|
+
n=curie.split(":")[1],
|
445
|
+
name=e.name,
|
446
|
+
subfolder=subfolder + SLOT_SUBFOLDER if self.subfolder_type_separation else None,
|
447
|
+
)
|
448
|
+
return self._markdown_link(
|
449
|
+
underscore(e.name),
|
450
|
+
subfolder=subfolder + SLOT_SUBFOLDER if self.subfolder_type_separation else None,
|
451
|
+
)
|
414
452
|
elif isinstance(e, TypeDefinition):
|
415
|
-
return self._markdown_link(
|
453
|
+
return self._markdown_link(
|
454
|
+
camelcase(e.name),
|
455
|
+
subfolder=subfolder + TYPE_SUBFOLDER if self.subfolder_type_separation else None,
|
456
|
+
)
|
416
457
|
elif isinstance(e, SubsetDefinition):
|
417
|
-
return self._markdown_link(
|
458
|
+
return self._markdown_link(
|
459
|
+
camelcase(e.name),
|
460
|
+
subfolder=subfolder + SUBSET_SUBFOLDER if self.subfolder_type_separation else None,
|
461
|
+
)
|
418
462
|
else:
|
419
463
|
return e.name
|
420
464
|
|
@@ -716,7 +760,7 @@ class DocGenerator(Generator):
|
|
716
760
|
Ensures rank is non-null
|
717
761
|
:return: iterator
|
718
762
|
"""
|
719
|
-
elts = self.schemaview.all_classes(imports=self.
|
763
|
+
elts = self.schemaview.all_classes(imports=self.render_imports).values()
|
720
764
|
_ensure_ranked(elts)
|
721
765
|
for e in elts:
|
722
766
|
yield e
|
@@ -728,7 +772,7 @@ class DocGenerator(Generator):
|
|
728
772
|
Ensures rank is non-null
|
729
773
|
:return: iterator
|
730
774
|
"""
|
731
|
-
elts = self.schemaview.all_slots(imports=self.
|
775
|
+
elts = self.schemaview.all_slots(imports=self.render_imports).values()
|
732
776
|
_ensure_ranked(elts)
|
733
777
|
for e in elts:
|
734
778
|
yield e
|
@@ -740,7 +784,7 @@ class DocGenerator(Generator):
|
|
740
784
|
Ensures rank is non-null
|
741
785
|
:return: iterator
|
742
786
|
"""
|
743
|
-
elts = self.schemaview.all_types(imports=self.
|
787
|
+
elts = self.schemaview.all_types(imports=self.render_imports).values()
|
744
788
|
_ensure_ranked(elts)
|
745
789
|
for e in elts:
|
746
790
|
yield e
|
@@ -755,7 +799,7 @@ class DocGenerator(Generator):
|
|
755
799
|
Ensures rank is non-null
|
756
800
|
:return: iterator
|
757
801
|
"""
|
758
|
-
elts = self.schemaview.all_enums(imports=self.
|
802
|
+
elts = self.schemaview.all_enums(imports=self.render_imports).values()
|
759
803
|
_ensure_ranked(elts)
|
760
804
|
for e in elts:
|
761
805
|
yield e
|
@@ -767,7 +811,7 @@ class DocGenerator(Generator):
|
|
767
811
|
Ensures rank is non-null
|
768
812
|
:return: iterator
|
769
813
|
"""
|
770
|
-
elts = self.schemaview.all_subsets(imports=self.
|
814
|
+
elts = self.schemaview.all_subsets(imports=self.render_imports).values()
|
771
815
|
_ensure_ranked(elts)
|
772
816
|
for e in elts:
|
773
817
|
yield e
|
@@ -791,7 +835,7 @@ class DocGenerator(Generator):
|
|
791
835
|
:return: tuples (depth: int, cls: ClassDefinitionName)
|
792
836
|
"""
|
793
837
|
sv = self.schemaview
|
794
|
-
roots = sv.class_roots(mixins=False, imports=self.
|
838
|
+
roots = sv.class_roots(mixins=False, imports=self.render_imports)
|
795
839
|
|
796
840
|
# by default the classes are sorted alphabetically
|
797
841
|
roots = sorted(roots, key=str.casefold, reverse=True)
|
@@ -805,7 +849,7 @@ class DocGenerator(Generator):
|
|
805
849
|
depth, class_name = stack.pop()
|
806
850
|
yield depth, class_name
|
807
851
|
children = sorted(
|
808
|
-
sv.class_children(class_name=class_name, mixins=False, imports=self.
|
852
|
+
sv.class_children(class_name=class_name, mixins=False, imports=self.render_imports),
|
809
853
|
key=str.casefold,
|
810
854
|
reverse=True,
|
811
855
|
)
|
@@ -965,6 +1009,12 @@ class DocGenerator(Generator):
|
|
965
1009
|
default=True,
|
966
1010
|
help="Render class table on index page in a hierarchically indented view",
|
967
1011
|
)
|
1012
|
+
@click.option(
|
1013
|
+
"--render-imports/--no-render-imports",
|
1014
|
+
default=False,
|
1015
|
+
show_default=True,
|
1016
|
+
help="Render also the documentation of elements from imported schemas",
|
1017
|
+
)
|
968
1018
|
@click.option(
|
969
1019
|
"--example-directory",
|
970
1020
|
help="Folder in which example files are found. These are used to make inline examples",
|
@@ -977,6 +1027,11 @@ Include LinkML Schema outside of imports mechanism. Helpful in including deprec
|
|
977
1027
|
YAML, and including it when necessary but not by default (e.g. in documentation or for backwards compatibility)
|
978
1028
|
""",
|
979
1029
|
)
|
1030
|
+
@click.option(
|
1031
|
+
"--subfolder-type-separation/--no-subfolder-type-separation",
|
1032
|
+
default=False,
|
1033
|
+
help="Separate type (class, slot, etc.) outputs in different subfolders for navigation purposes",
|
1034
|
+
)
|
980
1035
|
@click.version_option(__version__, "-V", "--version")
|
981
1036
|
@click.command(name="doc")
|
982
1037
|
def cli(
|
@@ -988,6 +1043,8 @@ def cli(
|
|
988
1043
|
use_slot_uris,
|
989
1044
|
use_class_uris,
|
990
1045
|
hierarchical_class_view,
|
1046
|
+
subfolder_type_separation,
|
1047
|
+
render_imports,
|
991
1048
|
**args,
|
992
1049
|
):
|
993
1050
|
"""Generate documentation folder from a LinkML YAML schema
|
@@ -1018,6 +1075,8 @@ def cli(
|
|
1018
1075
|
use_class_uris=use_class_uris,
|
1019
1076
|
hierarchical_class_view=hierarchical_class_view,
|
1020
1077
|
index_name=index_name,
|
1078
|
+
subfolder_type_separation=subfolder_type_separation,
|
1079
|
+
render_imports=render_imports,
|
1021
1080
|
**args,
|
1022
1081
|
)
|
1023
1082
|
print(gen.serialize())
|