linkml 1.8.2__py3-none-any.whl → 1.8.4__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 (50) hide show
  1. linkml/cli/main.py +4 -0
  2. linkml/generators/__init__.py +2 -0
  3. linkml/generators/common/ifabsent_processor.py +286 -0
  4. linkml/generators/docgen/index.md.jinja2 +6 -6
  5. linkml/generators/docgen.py +64 -14
  6. linkml/generators/golanggen.py +3 -1
  7. linkml/generators/jsonldcontextgen.py +0 -1
  8. linkml/generators/jsonschemagen.py +4 -2
  9. linkml/generators/owlgen.py +36 -17
  10. linkml/generators/projectgen.py +13 -11
  11. linkml/generators/pydanticgen/array.py +340 -56
  12. linkml/generators/pydanticgen/build.py +4 -2
  13. linkml/generators/pydanticgen/pydanticgen.py +46 -24
  14. linkml/generators/pydanticgen/template.py +108 -3
  15. linkml/generators/pydanticgen/templates/imports.py.jinja +11 -3
  16. linkml/generators/pydanticgen/templates/module.py.jinja +1 -3
  17. linkml/generators/pydanticgen/templates/validator.py.jinja +2 -2
  18. linkml/generators/python/__init__.py +1 -0
  19. linkml/generators/python/python_ifabsent_processor.py +92 -0
  20. linkml/generators/pythongen.py +19 -31
  21. linkml/generators/shacl/__init__.py +1 -3
  22. linkml/generators/shacl/shacl_data_type.py +1 -1
  23. linkml/generators/shacl/shacl_ifabsent_processor.py +89 -0
  24. linkml/generators/shaclgen.py +39 -13
  25. linkml/generators/sparqlgen.py +3 -1
  26. linkml/generators/sqlalchemygen.py +5 -3
  27. linkml/generators/sqltablegen.py +4 -2
  28. linkml/generators/typescriptgen.py +13 -6
  29. linkml/linter/linter.py +2 -1
  30. linkml/transformers/logical_model_transformer.py +3 -3
  31. linkml/transformers/relmodel_transformer.py +18 -4
  32. linkml/utils/converter.py +3 -1
  33. linkml/utils/exceptions.py +11 -0
  34. linkml/utils/execute_tutorial.py +22 -20
  35. linkml/utils/generator.py +6 -4
  36. linkml/utils/mergeutils.py +4 -2
  37. linkml/utils/schema_fixer.py +5 -5
  38. linkml/utils/schemaloader.py +5 -3
  39. linkml/utils/sqlutils.py +3 -1
  40. linkml/validator/plugins/pydantic_validation_plugin.py +1 -1
  41. linkml/validators/jsonschemavalidator.py +3 -1
  42. linkml/validators/sparqlvalidator.py +5 -3
  43. linkml/workspaces/example_runner.py +3 -1
  44. {linkml-1.8.2.dist-info → linkml-1.8.4.dist-info}/METADATA +3 -1
  45. {linkml-1.8.2.dist-info → linkml-1.8.4.dist-info}/RECORD +48 -45
  46. linkml/generators/shacl/ifabsent_processor.py +0 -59
  47. linkml/utils/ifabsent_functions.py +0 -138
  48. {linkml-1.8.2.dist-info → linkml-1.8.4.dist-info}/LICENSE +0 -0
  49. {linkml-1.8.2.dist-info → linkml-1.8.4.dist-info}/WHEEL +0 -0
  50. {linkml-1.8.2.dist-info → linkml-1.8.4.dist-info}/entry_points.txt +0 -0
@@ -41,9 +41,12 @@ from linkml.generators.pydanticgen.template import (
41
41
  PydanticModule,
42
42
  PydanticTemplateModel,
43
43
  )
44
+ from linkml.generators.python.python_ifabsent_processor import PythonIfAbsentProcessor
44
45
  from linkml.utils import deprecation_warning
45
46
  from linkml.utils.generator import shared_arguments
46
- from linkml.utils.ifabsent_functions import ifabsent_value_declaration
47
+
48
+ logger = logging.getLogger(__name__)
49
+
47
50
 
48
51
  if int(PYDANTIC_VERSION[0]) == 1:
49
52
  deprecation_warning("pydantic-v1")
@@ -67,7 +70,9 @@ def _get_pyrange(t: TypeDefinition, sv: SchemaView) -> str:
67
70
  DEFAULT_IMPORTS = (
68
71
  Imports()
69
72
  + Import(module="__future__", objects=[ObjectImport(name="annotations")])
70
- + Import(module="datetime", objects=[ObjectImport(name="datetime"), ObjectImport(name="date")])
73
+ + Import(
74
+ module="datetime", objects=[ObjectImport(name="datetime"), ObjectImport(name="date"), ObjectImport(name="time")]
75
+ )
71
76
  + Import(module="decimal", objects=[ObjectImport(name="Decimal")])
72
77
  + Import(module="enum", objects=[ObjectImport(name="Enum")])
73
78
  + Import(module="re")
@@ -187,7 +192,7 @@ class PydanticGenerator(OOCodeGenerator, LifecycleMixin):
187
192
  template_dir: Optional[Union[str, Path]] = None
188
193
  """
189
194
  Override templates for each PydanticTemplateModel.
190
-
195
+
191
196
  Directory with templates that override the default :attr:`.PydanticTemplateModel.template`
192
197
  for each class. If a matching template is not found in the override directory,
193
198
  the default templates will be used.
@@ -216,7 +221,7 @@ class PydanticGenerator(OOCodeGenerator, LifecycleMixin):
216
221
  )
217
222
 
218
223
  """
219
- imports: Optional[List[Import]] = None
224
+ imports: Optional[Union[List[Import], Imports]] = None
220
225
  """
221
226
  Additional imports to inject into generated module.
222
227
 
@@ -264,6 +269,13 @@ class PydanticGenerator(OOCodeGenerator, LifecycleMixin):
264
269
  else:
265
270
  from typing_extensions import Literal
266
271
 
272
+ """
273
+ sort_imports: bool = True
274
+ """
275
+ Before returning from :meth:`.PydanticGenerator.render`, sort imports with :meth:`.Imports.sort`
276
+
277
+ Default ``True``, but optional in case import order must be explicitly given,
278
+ eg. to avoid circular import errors in complex generator subclasses.
267
279
  """
268
280
  metadata_mode: Union[MetadataMode, str, None] = MetadataMode.AUTO
269
281
  """
@@ -356,8 +368,8 @@ class PydanticGenerator(OOCodeGenerator, LifecycleMixin):
356
368
  try:
357
369
  return compile_python(pycode)
358
370
  except NameError as e:
359
- logging.error(f"Code:\n{pycode}")
360
- logging.error(f"Error compiling generated python code: {e}")
371
+ logger.error(f"Code:\n{pycode}")
372
+ logger.error(f"Error compiling generated python code: {e}")
361
373
  raise e
362
374
 
363
375
  def _get_classes(self, sv: SchemaView) -> Tuple[List[ClassDefinition], Optional[List[ClassDefinition]]]:
@@ -446,11 +458,12 @@ class PydanticGenerator(OOCodeGenerator, LifecycleMixin):
446
458
 
447
459
  def generate_slot(self, slot: SlotDefinition, cls: ClassDefinition) -> SlotResult:
448
460
  slot_args = {
449
- k: slot._as_dict.get(k, None)
461
+ k: getattr(slot, k, None)
450
462
  for k in PydanticAttribute.model_fields.keys()
451
- if slot._as_dict.get(k, None) is not None
463
+ if getattr(slot, k, None) is not None
452
464
  }
453
- slot_args["name"] = underscore(slot.name)
465
+ slot_alias = slot.alias if slot.alias else slot.name
466
+ slot_args["name"] = underscore(slot_alias)
454
467
  slot_args["description"] = slot.description.replace('"', '\\"') if slot.description is not None else None
455
468
  predef = self.predefined_slot_values.get(camelcase(cls.name), {}).get(slot.name, None)
456
469
  if predef is not None:
@@ -526,6 +539,7 @@ class PydanticGenerator(OOCodeGenerator, LifecycleMixin):
526
539
  """
527
540
  if self._predefined_slot_values is None:
528
541
  sv = self.schemaview
542
+ ifabsent_processor = PythonIfAbsentProcessor(sv)
529
543
  slot_values = defaultdict(dict)
530
544
  for class_def in sv.all_classes().values():
531
545
  for slot_name in sv.class_slots(class_def.name):
@@ -541,10 +555,10 @@ class PydanticGenerator(OOCodeGenerator, LifecycleMixin):
541
555
  slot.name
542
556
  ]
543
557
  elif slot.ifabsent is not None:
544
- value = ifabsent_value_declaration(slot.ifabsent, sv, class_def, slot)
558
+ value = ifabsent_processor.process_slot(slot, class_def)
545
559
  slot_values[camelcase(class_def.name)][slot.name] = value
546
560
 
547
- self._predefined_slot_values = slot_values
561
+ self._predefined_slot_values = slot_values
548
562
 
549
563
  return self._predefined_slot_values
550
564
 
@@ -662,7 +676,7 @@ class PydanticGenerator(OOCodeGenerator, LifecycleMixin):
662
676
  else:
663
677
  # TODO: default ranges in schemagen
664
678
  # pyrange = 'str'
665
- # logging.error(f'range: {s.range} is unknown')
679
+ # logger.error(f'range: {s.range} is unknown')
666
680
  raise Exception(f"range: {slot_range}")
667
681
  return pyrange
668
682
 
@@ -918,14 +932,20 @@ class PydanticGenerator(OOCodeGenerator, LifecycleMixin):
918
932
  return Import(module=module, objects=[ObjectImport(name=camelcase(class_name))], is_schema=True)
919
933
 
920
934
  def render(self) -> PydanticModule:
935
+ """
936
+ Render the schema to a :class:`PydanticModule` model
937
+ """
921
938
  sv: SchemaView
922
939
  sv = self.schemaview
923
940
 
924
941
  # imports
925
942
  imports = DEFAULT_IMPORTS
926
943
  if self.imports is not None:
927
- for i in self.imports:
928
- imports += i
944
+ if isinstance(self.imports, Imports):
945
+ imports += self.imports
946
+ else:
947
+ for i in self.imports:
948
+ imports += i
929
949
  if self.split_mode == SplitMode.FULL:
930
950
  imports += self._get_imports()
931
951
 
@@ -962,13 +982,14 @@ class PydanticGenerator(OOCodeGenerator, LifecycleMixin):
962
982
  class_results = self.after_generate_classes(class_results, sv)
963
983
 
964
984
  classes = {r.cls.name: r.cls for r in class_results}
965
-
966
985
  injected_classes = self._clean_injected_classes(injected_classes)
967
986
 
987
+ imports.render_sorted = self.sort_imports
988
+
968
989
  module = PydanticModule(
969
990
  metamodel_version=self.schema.metamodel_version,
970
991
  version=self.schema.version,
971
- python_imports=imports.imports,
992
+ python_imports=imports,
972
993
  base_model=base_model,
973
994
  injected_classes=injected_classes,
974
995
  enums=enums,
@@ -984,7 +1005,8 @@ class PydanticGenerator(OOCodeGenerator, LifecycleMixin):
984
1005
 
985
1006
  Args:
986
1007
  rendered_module ( :class:`.PydanticModule` ): Optional, if schema was previously
987
- rendered with :meth:`.render` , use that, otherwise :meth:`.render` fresh.
1008
+ rendered with :meth:`~.PydanticGenerator.render` , use that,
1009
+ otherwise :meth:`~.PydanticGenerator.render` fresh.
988
1010
  """
989
1011
  if rendered_module is not None:
990
1012
  module = rendered_module
@@ -1061,7 +1083,7 @@ class PydanticGenerator(OOCodeGenerator, LifecycleMixin):
1061
1083
  # interpret all imported schema paths as relative to that
1062
1084
  output_path.parent.mkdir(parents=True, exist_ok=True)
1063
1085
  serialized = generator.serialize(rendered_module=rendered)
1064
- with open(output_path, "w") as ofile:
1086
+ with open(output_path, "w", encoding="utf-8") as ofile:
1065
1087
  ofile.write(serialized)
1066
1088
 
1067
1089
  results.append(
@@ -1080,7 +1102,7 @@ class PydanticGenerator(OOCodeGenerator, LifecycleMixin):
1080
1102
  rel_path = _import_to_path(generated_import.module)
1081
1103
  abs_path = (output_path.parent / rel_path).resolve()
1082
1104
  abs_path.parent.mkdir(parents=True, exist_ok=True)
1083
- with open(abs_path, "w") as ofile:
1105
+ with open(abs_path, "w", encoding="utf-8") as ofile:
1084
1106
  ofile.write(serialized)
1085
1107
 
1086
1108
  results.append(
@@ -1123,7 +1145,7 @@ def _ensure_inits(paths: List[Path]):
1123
1145
  common_path = Path(os.path.commonpath(paths))
1124
1146
 
1125
1147
  if not (ipath := (common_path / "__init__.py")).exists():
1126
- with open(ipath, "w") as ifile:
1148
+ with open(ipath, "w", encoding="utf-8") as ifile:
1127
1149
  ifile.write(" \n")
1128
1150
 
1129
1151
  for path in paths:
@@ -1131,7 +1153,7 @@ def _ensure_inits(paths: List[Path]):
1131
1153
  path = path.parent
1132
1154
  while path != common_path:
1133
1155
  if not (ipath := (path / "__init__.py")).exists():
1134
- with open(ipath, "w") as ifile:
1156
+ with open(ipath, "w", encoding="utf-8") as ifile:
1135
1157
  ifile.write(" \n")
1136
1158
  path = path.parent
1137
1159
 
@@ -1144,9 +1166,9 @@ def _ensure_inits(paths: List[Path]):
1144
1166
  help="""
1145
1167
  Optional jinja2 template directory to use for class generation.
1146
1168
 
1147
- Pass a directory containing templates with the same name as any of the default
1148
- :class:`.PydanticTemplateModel` templates to override them. The given directory will be
1149
- searched for matching templates, and use the default templates as a fallback
1169
+ Pass a directory containing templates with the same name as any of the default
1170
+ :class:`.PydanticTemplateModel` templates to override them. The given directory will be
1171
+ searched for matching templates, and use the default templates as a fallback
1150
1172
  if an override is not found
1151
1173
 
1152
1174
  Available templates to override:
@@ -1,5 +1,6 @@
1
+ import sys
1
2
  from importlib.util import find_spec
2
- from typing import Any, ClassVar, Dict, Generator, List, Literal, Optional, Union
3
+ from typing import Any, ClassVar, Dict, Generator, List, Literal, Optional, Tuple, Union, get_args
3
4
 
4
5
  from jinja2 import Environment, PackageLoader
5
6
  from pydantic import BaseModel, Field, field_validator
@@ -28,6 +29,14 @@ else:
28
29
  return f
29
30
 
30
31
 
32
+ IMPORT_GROUPS = Literal["future", "stdlib", "thirdparty", "local", "conditional"]
33
+ """
34
+ See :attr:`.Import.group` and :attr:`.Imports.sort`
35
+
36
+ Order of this literal is used in sort and therefore not arbitrary.
37
+ """
38
+
39
+
31
40
  class PydanticTemplateModel(TemplateModel):
32
41
  """
33
42
  Metaclass to render pydantic models with jinja templates.
@@ -292,6 +301,28 @@ class Import(PydanticTemplateModel):
292
301
  Used primarily in split schema generation, see :func:`.pydanticgen.generate_split` for example usage.
293
302
  """
294
303
 
304
+ @computed_field
305
+ def group(self) -> IMPORT_GROUPS:
306
+ """
307
+ Import group used when sorting
308
+
309
+ * ``future`` - from `__future__` import...
310
+ * ``stdlib`` - ... the standard library
311
+ * ``thirdparty`` - other dependencies not in the standard library
312
+ * ``local`` - relative imports (eg. from split generation)
313
+ * ``conditional`` - a :class:`.ConditionalImport`
314
+ """
315
+ if self.module == "__future__":
316
+ return "future"
317
+ elif sys.version_info.minor >= 10 and self.module in sys.stdlib_module_names:
318
+ return "stdlib"
319
+ elif sys.version_info.minor < 10 and self.module in _some_stdlib_module_names:
320
+ return "stdlib"
321
+ elif self.module.startswith("."):
322
+ return "local"
323
+ else:
324
+ return "thirdparty"
325
+
295
326
  def merge(self, other: "Import") -> List["Import"]:
296
327
  """
297
328
  Merge one import with another, see :meth:`.Imports` for an example.
@@ -346,6 +377,16 @@ class Import(PydanticTemplateModel):
346
377
  # one is a module, the other imports objects, keep both
347
378
  return [self, other]
348
379
 
380
+ def sort(self) -> None:
381
+ """
382
+ Sort imported objects
383
+
384
+ * First by whether the first letter is capitalized or not,
385
+ * Then alphabetically (by object name rather than alias)
386
+ """
387
+ if self.objects:
388
+ self.objects = sorted(self.objects, key=lambda obj: (obj.name[0].islower(), obj.name))
389
+
349
390
 
350
391
  class ConditionalImport(Import):
351
392
  """
@@ -391,6 +432,17 @@ class ConditionalImport(Import):
391
432
  condition: str
392
433
  alternative: Import
393
434
 
435
+ @computed_field
436
+ def group(self) -> Literal["conditional"]:
437
+ return "conditional"
438
+
439
+ def sort(self) -> None:
440
+ """
441
+ :meth:`.Import.sort` called for self and :attr:`.alternative`
442
+ """
443
+ super(ConditionalImport, self).sort()
444
+ self.alternative.sort()
445
+
394
446
 
395
447
  class Imports(PydanticTemplateModel):
396
448
  """
@@ -427,6 +479,10 @@ class Imports(PydanticTemplateModel):
427
479
  template: ClassVar[str] = "imports.py.jinja"
428
480
 
429
481
  imports: List[Union[Import, ConditionalImport]] = Field(default_factory=list)
482
+ group_order: Tuple[str, ...] = get_args(IMPORT_GROUPS)
483
+ """Order in which to sort imports by their :attr:`.Import.group`"""
484
+ render_sorted: bool = True
485
+ """When rendering, render in sorted groups"""
430
486
 
431
487
  @classmethod
432
488
  def _merge(
@@ -484,13 +540,17 @@ class Imports(PydanticTemplateModel):
484
540
  break
485
541
 
486
542
  # SPECIAL CASE - __future__ annotations must happen at the top of a file
543
+ # sort here outside of sort method because our imports are invalid without it,
544
+ # where calling ``sort`` should be optional.
487
545
  imports = sorted(imports, key=lambda i: i.module == "__future__", reverse=True)
488
546
  return imports
489
547
 
490
548
  def __add__(self, other: Union[Import, "Imports", List[Import]]) -> "Imports":
491
549
  imports = self.imports.copy()
492
550
  imports = self._merge(imports, other)
493
- return Imports.model_construct(imports=imports)
551
+ return Imports.model_construct(
552
+ imports=imports, **{k: getattr(self, k, None) for k in self.model_fields if k != "imports"}
553
+ )
494
554
 
495
555
  def __len__(self) -> int:
496
556
  return len(self.imports)
@@ -552,6 +612,36 @@ class Imports(PydanticTemplateModel):
552
612
  merged_imports = cls._merge(merged_imports, i)
553
613
  return merged_imports
554
614
 
615
+ @computed_field
616
+ def import_groups(self) -> List[IMPORT_GROUPS]:
617
+ """
618
+ List of what group each import belongs to
619
+ """
620
+ return [i.group for i in self.imports]
621
+
622
+ def sort(self) -> None:
623
+ """
624
+ Sort imports recursively, mimicking isort:
625
+
626
+ * First by :attr:`.Import.group` according to :attr:`.Imports.group_order`
627
+ * Then by whether the :class:`.Import` has any objects
628
+ (``import module`` comes before ``from module import name``)
629
+ * Then alphabetically by module name
630
+ """
631
+
632
+ def _sort_key(i: Import) -> Tuple[int, int, str]:
633
+ return (self.group_order.index(i.group), int(i.objects is not None), i.module)
634
+
635
+ imports = sorted(self.imports, key=_sort_key)
636
+ for i in imports:
637
+ i.sort()
638
+ self.imports = imports
639
+
640
+ def render(self, environment: Optional[Environment] = None, black: bool = False) -> str:
641
+ if self.render_sorted:
642
+ self.sort()
643
+ return super(Imports, self).render(environment=environment, black=black)
644
+
555
645
 
556
646
  class PydanticModule(PydanticTemplateModel):
557
647
  """
@@ -565,7 +655,7 @@ class PydanticModule(PydanticTemplateModel):
565
655
  version: Optional[str] = None
566
656
  base_model: PydanticBaseModel = PydanticBaseModel()
567
657
  injected_classes: Optional[List[str]] = None
568
- python_imports: List[Union[Import, ConditionalImport]] = Field(default_factory=list)
658
+ python_imports: Union[Imports, List[Union[Import, ConditionalImport]]] = Imports()
569
659
  enums: Dict[str, PydanticEnum] = Field(default_factory=dict)
570
660
  classes: Dict[str, PydanticClass] = Field(default_factory=dict)
571
661
  meta: Optional[Dict[str, Any]] = None
@@ -573,6 +663,21 @@ class PydanticModule(PydanticTemplateModel):
573
663
  Metadata for the schema to be included in a linkml_meta module-level instance of LinkMLMeta
574
664
  """
575
665
 
666
+ @field_validator("python_imports", mode="after")
667
+ @classmethod
668
+ def cast_imports(cls, imports: Union[Imports, List[Union[Import, ConditionalImport]]]) -> Imports:
669
+ if isinstance(imports, list):
670
+ imports = Imports(imports=imports)
671
+ return imports
672
+
576
673
  @computed_field
577
674
  def class_names(self) -> List[str]:
578
675
  return [c.name for c in self.classes.values()]
676
+
677
+
678
+ _some_stdlib_module_names = {"copy", "datetime", "decimal", "enum", "inspect", "os", "re", "sys", "typing"}
679
+ """
680
+ sys.stdlib_module_names is only present in 3.10 and later
681
+ so we make a cheap copy of the stdlib modules that we commonly use here,
682
+ but this should be removed whenever support for 3.9 is dropped.
683
+ """
@@ -20,12 +20,20 @@ from {{ module }} import (
20
20
  {%- endif %}
21
21
  {%- endif %}
22
22
  {% endmacro %}
23
+ {#- For when used with Import model -#}
23
24
  {%- if module %}
24
25
  {{ import_(module, alias, objects) }}
25
26
  {% endif -%}
26
27
  {#- For when used with Imports container -#}
27
28
  {%- if imports -%}
28
- {%- for i in imports -%}
29
- {{ i }}
30
- {%- endfor -%}
29
+ {%- if render_sorted -%}
30
+ {% for i in range(imports | length) %}
31
+ {{ imports[i] }}
32
+ {%- if not loop.last and import_groups[i] != import_groups[i+1] %}{{ '\n' }}{% endif -%}
33
+ {% endfor %}
34
+ {%- else -%}
35
+ {%- for import in imports -%}
36
+ {{ import }}
37
+ {%- endfor -%}
38
+ {%- endif -%}
31
39
  {% endif -%}
@@ -1,6 +1,4 @@
1
- {% for import in python_imports %}
2
- {{ import }}
3
- {%- endfor -%}
1
+ {{ python_imports }}
4
2
 
5
3
  metamodel_version = "{{metamodel_version}}"
6
4
  version = "{{version if version else None}}"
@@ -3,9 +3,9 @@
3
3
  pattern=re.compile(r"{{pattern}}")
4
4
  if isinstance(v,list):
5
5
  for element in v:
6
- if not pattern.match(element):
6
+ if isinstance(v, str) and not pattern.match(element):
7
7
  raise ValueError(f"Invalid {{name}} format: {element}")
8
8
  elif isinstance(v,str):
9
9
  if not pattern.match(v):
10
10
  raise ValueError(f"Invalid {{name}} format: {v}")
11
- return v
11
+ return v
@@ -0,0 +1 @@
1
+ __all__ = ["python_ifabsent_processor"]
@@ -0,0 +1,92 @@
1
+ from linkml_runtime.linkml_model import (
2
+ ClassDefinition,
3
+ EnumDefinitionName,
4
+ SlotDefinition,
5
+ )
6
+
7
+ from linkml.generators.common.ifabsent_processor import IfAbsentProcessor
8
+
9
+
10
+ class PythonIfAbsentProcessor(IfAbsentProcessor):
11
+ UNIMPLEMENTED_DEFAULT_VALUES = ["class_curie", "class_uri", "slot_uri", "slot_curie", "default_range", "default_ns"]
12
+
13
+ def map_custom_default_values(self, default_value: str, slot: SlotDefinition, cls: ClassDefinition) -> (bool, str):
14
+ if default_value in self.UNIMPLEMENTED_DEFAULT_VALUES:
15
+ return True, None
16
+
17
+ if default_value == "bnode":
18
+ return True, "bnode()"
19
+
20
+ return False, None
21
+
22
+ def map_string_default_value(self, default_value: str, slot: SlotDefinition, cls: ClassDefinition):
23
+ return self._strval(default_value)
24
+
25
+ def map_boolean_true_default_value(self, slot: SlotDefinition, cls: ClassDefinition):
26
+ return "True"
27
+
28
+ def map_boolean_false_default_value(self, slot: SlotDefinition, cls: ClassDefinition):
29
+ return "False"
30
+
31
+ def map_integer_default_value(self, default_value: str, slot: SlotDefinition, cls: ClassDefinition):
32
+ return default_value
33
+
34
+ def map_float_default_value(self, default_value: str, slot: SlotDefinition, cls: ClassDefinition):
35
+ return default_value
36
+
37
+ def map_double_default_value(self, default_value: str, slot: SlotDefinition, cls: ClassDefinition):
38
+ return default_value
39
+
40
+ def map_decimal_default_value(self, default_value: str, slot: SlotDefinition, cls: ClassDefinition):
41
+ return default_value
42
+
43
+ def map_time_default_value(self, hour: str, minutes: str, seconds: str, slot: SlotDefinition, cls: ClassDefinition):
44
+ return f"time({int(hour)}, {int(minutes)}, {int(seconds)})"
45
+
46
+ def map_date_default_value(self, year: str, month: str, day: str, slot: SlotDefinition, cls: ClassDefinition):
47
+ return f"date({int(year)}, {int(month)}, {int(day)})"
48
+
49
+ def map_datetime_default_value(
50
+ self,
51
+ year: str,
52
+ month: str,
53
+ day: str,
54
+ hour: str,
55
+ minutes: str,
56
+ seconds: str,
57
+ slot: SlotDefinition,
58
+ cls: ClassDefinition,
59
+ ):
60
+ return f"datetime({int(year)}, {int(month)}, {int(day)}, " f"{int(hour)}, {int(minutes)}, {int(seconds)})"
61
+
62
+ def map_uri_or_curie_default_value(self, default_value: str, slot: SlotDefinition, cls: ClassDefinition):
63
+ return self._uri_for(default_value)
64
+
65
+ def map_curie_default_value(self, default_value: str, slot: SlotDefinition, cls: ClassDefinition):
66
+ return self._uri_for(default_value)
67
+
68
+ def map_uri_default_value(self, default_value: str, slot: SlotDefinition, cls: ClassDefinition):
69
+ return self._uri_for(default_value)
70
+
71
+ def map_enum_default_value(
72
+ self, enum_name: EnumDefinitionName, permissible_value_name: str, slot: SlotDefinition, cls: ClassDefinition
73
+ ):
74
+ return f"{enum_name}.{permissible_value_name}"
75
+
76
+ def map_nc_name_default_value(self, default_value: str, slot: SlotDefinition, cls: ClassDefinition):
77
+ raise NotImplementedError()
78
+
79
+ def map_object_identifier_default_value(self, default_value: str, slot: SlotDefinition, cls: ClassDefinition):
80
+ raise NotImplementedError()
81
+
82
+ def map_node_identifier_default_value(self, default_value: str, slot: SlotDefinition, cls: ClassDefinition):
83
+ raise NotImplementedError()
84
+
85
+ def map_json_pointer_default_value(self, default_value: str, slot: SlotDefinition, cls: ClassDefinition):
86
+ raise NotImplementedError()
87
+
88
+ def map_json_path_default_value(self, default_value: str, slot: SlotDefinition, cls: ClassDefinition):
89
+ raise NotImplementedError()
90
+
91
+ def map_sparql_path_default_value(self, default_value: str, slot: SlotDefinition, cls: ClassDefinition):
92
+ raise NotImplementedError()