linkml 1.9.0rc1__py3-none-any.whl → 1.9.1rc3__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 (82) hide show
  1. linkml/generators/common/build.py +1 -7
  2. linkml/generators/common/ifabsent_processor.py +20 -20
  3. linkml/generators/common/lifecycle.py +2 -1
  4. linkml/generators/common/naming.py +1 -1
  5. linkml/generators/common/template.py +5 -5
  6. linkml/generators/common/type_designators.py +1 -3
  7. linkml/generators/csvgen.py +3 -3
  8. linkml/generators/docgen.py +20 -25
  9. linkml/generators/dotgen.py +4 -4
  10. linkml/generators/erdiagramgen.py +7 -7
  11. linkml/generators/excelgen.py +2 -3
  12. linkml/generators/golanggen.py +2 -2
  13. linkml/generators/golrgen.py +3 -3
  14. linkml/generators/jsonldcontextgen.py +4 -4
  15. linkml/generators/jsonschemagen.py +5 -5
  16. linkml/generators/markdowngen.py +8 -10
  17. linkml/generators/mermaidclassdiagramgen.py +2 -2
  18. linkml/generators/oocodegen.py +10 -10
  19. linkml/generators/owlgen.py +19 -18
  20. linkml/generators/plantumlgen.py +15 -15
  21. linkml/generators/prefixmapgen.py +5 -5
  22. linkml/generators/projectgen.py +10 -10
  23. linkml/generators/pydanticgen/array.py +15 -21
  24. linkml/generators/pydanticgen/build.py +4 -4
  25. linkml/generators/pydanticgen/includes.py +1 -1
  26. linkml/generators/pydanticgen/pydanticgen.py +24 -28
  27. linkml/generators/pydanticgen/template.py +36 -36
  28. linkml/generators/pythongen.py +21 -29
  29. linkml/generators/rdfgen.py +2 -2
  30. linkml/generators/shaclgen.py +9 -9
  31. linkml/generators/shexgen.py +3 -3
  32. linkml/generators/sparqlgen.py +3 -3
  33. linkml/generators/sqlalchemygen.py +2 -2
  34. linkml/generators/terminusdbgen.py +2 -3
  35. linkml/generators/typescriptgen.py +3 -3
  36. linkml/generators/yumlgen.py +13 -13
  37. linkml/linter/cli.py +1 -1
  38. linkml/linter/config/datamodel/config.py +207 -213
  39. linkml/linter/config/datamodel/config.yaml +51 -3
  40. linkml/linter/config/default.yaml +3 -0
  41. linkml/linter/formatters/markdown_formatter.py +2 -2
  42. linkml/linter/linter.py +4 -3
  43. linkml/linter/rules.py +38 -19
  44. linkml/reporting/model.py +11 -15
  45. linkml/transformers/logical_model_transformer.py +9 -8
  46. linkml/transformers/relmodel_transformer.py +6 -6
  47. linkml/transformers/schema_renamer.py +2 -2
  48. linkml/utils/converter.py +1 -1
  49. linkml/utils/deprecation.py +3 -3
  50. linkml/utils/execute_tutorial.py +5 -6
  51. linkml/utils/generator.py +17 -16
  52. linkml/utils/helpers.py +2 -2
  53. linkml/utils/logictools.py +5 -4
  54. linkml/utils/mergeutils.py +51 -5
  55. linkml/utils/schema_builder.py +8 -8
  56. linkml/utils/schema_fixer.py +8 -8
  57. linkml/utils/schemaloader.py +16 -15
  58. linkml/utils/schemasynopsis.py +29 -29
  59. linkml/utils/sqlutils.py +5 -5
  60. linkml/utils/typereferences.py +5 -6
  61. linkml/utils/validation.py +2 -2
  62. linkml/validator/cli.py +7 -6
  63. linkml/validator/loaders/delimited_file_loader.py +2 -1
  64. linkml/validator/loaders/json_loader.py +2 -1
  65. linkml/validator/loaders/loader.py +2 -1
  66. linkml/validator/loaders/passthrough_loader.py +2 -1
  67. linkml/validator/loaders/yaml_loader.py +2 -1
  68. linkml/validator/plugins/jsonschema_validation_plugin.py +2 -1
  69. linkml/validator/plugins/pydantic_validation_plugin.py +2 -1
  70. linkml/validator/plugins/recommended_slots_plugin.py +3 -2
  71. linkml/validator/plugins/shacl_validation_plugin.py +2 -1
  72. linkml/validator/plugins/validation_plugin.py +1 -1
  73. linkml/validator/report.py +3 -3
  74. linkml/validator/validator.py +3 -2
  75. linkml/validators/jsonschemavalidator.py +6 -5
  76. linkml/workspaces/datamodel/workspaces.py +21 -26
  77. linkml/workspaces/example_runner.py +7 -6
  78. {linkml-1.9.0rc1.dist-info → linkml-1.9.1rc3.dist-info}/METADATA +6 -9
  79. {linkml-1.9.0rc1.dist-info → linkml-1.9.1rc3.dist-info}/RECORD +82 -82
  80. {linkml-1.9.0rc1.dist-info → linkml-1.9.1rc3.dist-info}/WHEEL +1 -1
  81. {linkml-1.9.0rc1.dist-info → linkml-1.9.1rc3.dist-info}/LICENSE +0 -0
  82. {linkml-1.9.0rc1.dist-info → linkml-1.9.1rc3.dist-info}/entry_points.txt +0 -0
@@ -8,7 +8,7 @@ from dataclasses import dataclass, field
8
8
  from enum import Enum
9
9
  from pathlib import Path
10
10
  from types import ModuleType
11
- from typing import ClassVar, Dict, List, Literal, Optional, Set, Tuple, Type, TypeVar, Union, overload
11
+ from typing import ClassVar, Literal, Optional, TypeVar, Union, overload
12
12
 
13
13
  import click
14
14
  from jinja2 import ChoiceLoader, Environment, FileSystemLoader, Template
@@ -82,9 +82,7 @@ DEFAULT_IMPORTS = (
82
82
  objects=[
83
83
  ObjectImport(name="Any"),
84
84
  ObjectImport(name="ClassVar"),
85
- ObjectImport(name="List"),
86
85
  ObjectImport(name="Literal"),
87
- ObjectImport(name="Dict"),
88
86
  ObjectImport(name="Optional"),
89
87
  ObjectImport(name="Union"),
90
88
  ],
@@ -183,7 +181,7 @@ class PydanticGenerator(OOCodeGenerator, LifecycleMixin):
183
181
  file_extension = "py"
184
182
 
185
183
  # ObjectVars
186
- array_representations: List[ArrayRepresentation] = field(default_factory=lambda: [ArrayRepresentation.LIST])
184
+ array_representations: list[ArrayRepresentation] = field(default_factory=lambda: [ArrayRepresentation.LIST])
187
185
  black: bool = False
188
186
  """
189
187
  If black is present in the environment, format the serialized code with it
@@ -199,7 +197,7 @@ class PydanticGenerator(OOCodeGenerator, LifecycleMixin):
199
197
  """
200
198
  extra_fields: Literal["allow", "forbid", "ignore"] = "forbid"
201
199
  gen_mixin_inheritance: bool = True
202
- injected_classes: Optional[List[Union[Type, str]]] = None
200
+ injected_classes: Optional[list[Union[type, str]]] = None
203
201
  """
204
202
  A list/tuple of classes to inject into the generated module.
205
203
 
@@ -208,7 +206,7 @@ class PydanticGenerator(OOCodeGenerator, LifecycleMixin):
208
206
  source file (ie. the module they are contained in needs a ``__file__`` attr,
209
207
  see: :func:`inspect.getsource` )
210
208
  """
211
- injected_fields: Optional[List[str]] = None
209
+ injected_fields: Optional[list[str]] = None
212
210
  """
213
211
  A list/tuple of field strings to inject into the base class.
214
212
 
@@ -221,7 +219,7 @@ class PydanticGenerator(OOCodeGenerator, LifecycleMixin):
221
219
  )
222
220
 
223
221
  """
224
- imports: Optional[Union[List[Import], Imports]] = None
222
+ imports: Optional[Union[list[Import], Imports]] = None
225
223
  """
226
224
  Additional imports to inject into generated module.
227
225
 
@@ -353,8 +351,8 @@ class PydanticGenerator(OOCodeGenerator, LifecycleMixin):
353
351
  """Substitute CamelCase and non-word characters with _"""
354
352
 
355
353
  # Private attributes
356
- _predefined_slot_values: Optional[Dict[str, Dict[str, str]]] = None
357
- _class_bases: Optional[Dict[str, List[str]]] = None
354
+ _predefined_slot_values: Optional[dict[str, dict[str, str]]] = None
355
+ _class_bases: Optional[dict[str, list[str]]] = None
358
356
 
359
357
  def __post_init__(self):
360
358
  super().__post_init__()
@@ -372,7 +370,7 @@ class PydanticGenerator(OOCodeGenerator, LifecycleMixin):
372
370
  logger.error(f"Error compiling generated python code: {e}")
373
371
  raise e
374
372
 
375
- def _get_classes(self, sv: SchemaView) -> Tuple[List[ClassDefinition], Optional[List[ClassDefinition]]]:
373
+ def _get_classes(self, sv: SchemaView) -> tuple[list[ClassDefinition], Optional[list[ClassDefinition]]]:
376
374
  all_classes = sv.all_classes(imports=True).values()
377
375
 
378
376
  if self.split:
@@ -384,8 +382,8 @@ class PydanticGenerator(OOCodeGenerator, LifecycleMixin):
384
382
 
385
383
  @staticmethod
386
384
  def sort_classes(
387
- clist: List[ClassDefinition], imported: Optional[List[ClassDefinition]] = None
388
- ) -> List[ClassDefinition]:
385
+ clist: list[ClassDefinition], imported: Optional[list[ClassDefinition]] = None
386
+ ) -> list[ClassDefinition]:
389
387
  """
390
388
  sort classes such that if C is a child of P then C appears after P in the list
391
389
 
@@ -515,7 +513,7 @@ class PydanticGenerator(OOCodeGenerator, LifecycleMixin):
515
513
  else:
516
514
  collection_key = None
517
515
  if slot.inlined is False or collection_key is None or slot.inlined_as_list is True:
518
- result.attribute.range = f"List[{result.attribute.range}]"
516
+ result.attribute.range = f"list[{result.attribute.range}]"
519
517
  else:
520
518
  simple_dict_value = None
521
519
  if len(slot_ranges) == 1:
@@ -525,15 +523,15 @@ class PydanticGenerator(OOCodeGenerator, LifecycleMixin):
525
523
  # so we specify either that identifier or the range itself
526
524
  if simple_dict_value != result.attribute.range:
527
525
  simple_dict_value = f"Union[{simple_dict_value}, {result.attribute.range}]"
528
- result.attribute.range = f"Dict[str, {simple_dict_value}]"
526
+ result.attribute.range = f"dict[str, {simple_dict_value}]"
529
527
  else:
530
- result.attribute.range = f"Dict[{collection_key}, {result.attribute.range}]"
528
+ result.attribute.range = f"dict[{collection_key}, {result.attribute.range}]"
531
529
  if not (slot.required or slot.identifier or slot.key) and not slot.designates_type:
532
530
  result.attribute.range = f"Optional[{result.attribute.range}]"
533
531
  return result
534
532
 
535
533
  @property
536
- def predefined_slot_values(self) -> Dict[str, Dict[str, str]]:
534
+ def predefined_slot_values(self) -> dict[str, dict[str, str]]:
537
535
  """
538
536
  :return: Dictionary of dictionaries with predefined slot values for each class
539
537
  """
@@ -563,7 +561,7 @@ class PydanticGenerator(OOCodeGenerator, LifecycleMixin):
563
561
  return self._predefined_slot_values
564
562
 
565
563
  @property
566
- def class_bases(self) -> Dict[str, List[str]]:
564
+ def class_bases(self) -> dict[str, list[str]]:
567
565
  """
568
566
  Generate the inheritance list for each class from is_a plus mixins
569
567
  :return:
@@ -682,7 +680,7 @@ class PydanticGenerator(OOCodeGenerator, LifecycleMixin):
682
680
 
683
681
  def generate_collection_key(
684
682
  self,
685
- slot_ranges: List[str],
683
+ slot_ranges: list[str],
686
684
  slot_def: SlotDefinition,
687
685
  class_def: ClassDefinition,
688
686
  ) -> Optional[str]:
@@ -697,7 +695,7 @@ class PydanticGenerator(OOCodeGenerator, LifecycleMixin):
697
695
  :param slot_ranges: list of python range values
698
696
  """
699
697
 
700
- collection_keys: Set[str] = set()
698
+ collection_keys: set[str] = set()
701
699
 
702
700
  if slot_ranges is None:
703
701
  return None
@@ -715,7 +713,7 @@ class PydanticGenerator(OOCodeGenerator, LifecycleMixin):
715
713
  return list(collection_keys)[0]
716
714
  return None
717
715
 
718
- def _clean_injected_classes(self, injected_classes: List[Union[str, Type]]) -> Optional[List[str]]:
716
+ def _clean_injected_classes(self, injected_classes: list[Union[str, type]]) -> Optional[list[str]]:
719
717
  """Get source, deduplicate, and dedent injected classes"""
720
718
  if len(injected_classes) == 0:
721
719
  return None
@@ -769,7 +767,7 @@ class PydanticGenerator(OOCodeGenerator, LifecycleMixin):
769
767
  env.loader = loader
770
768
  return env
771
769
 
772
- def get_array_representations_range(self, slot: SlotDefinition, range: str) -> List[SlotResult]:
770
+ def get_array_representations_range(self, slot: SlotDefinition, range: str) -> list[SlotResult]:
773
771
  """
774
772
  Generate the python range for array representations
775
773
  """
@@ -1028,7 +1026,7 @@ class PydanticGenerator(OOCodeGenerator, LifecycleMixin):
1028
1026
  split_context: Optional[dict] = None,
1029
1027
  split_mode: SplitMode = SplitMode.AUTO,
1030
1028
  **kwargs,
1031
- ) -> List[SplitResult]:
1029
+ ) -> list[SplitResult]:
1032
1030
  """
1033
1031
  Generate a schema that imports from other schema as a set of python modules that
1034
1032
  import from one another, rather than generating all imported classes in a single schema.
@@ -1119,7 +1117,7 @@ class PydanticGenerator(OOCodeGenerator, LifecycleMixin):
1119
1117
  return results
1120
1118
 
1121
1119
 
1122
- def _subclasses(cls: Type):
1120
+ def _subclasses(cls: type):
1123
1121
  return set(cls.__subclasses__()).union([s for c in cls.__subclasses__() for s in _subclasses(c)])
1124
1122
 
1125
1123
 
@@ -1137,7 +1135,7 @@ def _import_to_path(module: str) -> Path:
1137
1135
  return Path(*dir_pieces)
1138
1136
 
1139
1137
 
1140
- def _ensure_inits(paths: List[Path]):
1138
+ def _ensure_inits(paths: list[Path]):
1141
1139
  """For a set of paths, find the common root and it and all the subdirectories have an __init__.py"""
1142
1140
  # if there is only one file, there is no relative importing to be done
1143
1141
  if len(paths) <= 1:
@@ -1223,10 +1221,8 @@ def cli(
1223
1221
  """Generate pydantic classes to represent a LinkML model"""
1224
1222
  if template_file is not None:
1225
1223
  raise DeprecationWarning(
1226
- (
1227
- "Passing a single template_file is deprecated. Pass a directory of template files instead. "
1228
- "See help string for --template-dir"
1229
- )
1224
+ "Passing a single template_file is deprecated. Pass a directory of template files instead. "
1225
+ "See help string for --template-dir"
1230
1226
  )
1231
1227
 
1232
1228
  if template_dir is not None:
@@ -1,6 +1,7 @@
1
1
  import sys
2
+ from collections.abc import Generator
2
3
  from importlib.util import find_spec
3
- from typing import Any, ClassVar, Dict, Generator, List, Literal, Optional, Tuple, Union, get_args
4
+ from typing import Any, ClassVar, Literal, Optional, Union, get_args
4
5
 
5
6
  from jinja2 import Environment, PackageLoader
6
7
  from pydantic import BaseModel, Field, field_validator
@@ -74,7 +75,7 @@ class PydanticTemplateModel(TemplateModel):
74
75
  loader=PackageLoader("linkml.generators.pydanticgen", "templates"), trim_blocks=True, lstrip_blocks=True
75
76
  )
76
77
 
77
- meta_exclude: ClassVar[List[str]] = None
78
+ meta_exclude: ClassVar[list[str]] = None
78
79
 
79
80
  def render(self, environment: Optional[Environment] = None, black: bool = False) -> str:
80
81
  """
@@ -125,7 +126,7 @@ class PydanticEnum(PydanticTemplateModel):
125
126
 
126
127
  name: str
127
128
  description: Optional[str] = None
128
- values: Dict[str, EnumValue] = Field(default_factory=dict)
129
+ values: dict[str, EnumValue] = Field(default_factory=dict)
129
130
 
130
131
 
131
132
  class PydanticBaseModel(PydanticTemplateModel):
@@ -141,7 +142,7 @@ class PydanticBaseModel(PydanticTemplateModel):
141
142
  """
142
143
  Sets the ``extra`` model for pydantic models
143
144
  """
144
- fields: Optional[List[str]] = None
145
+ fields: Optional[list[str]] = None
145
146
  """
146
147
  Extra fields that are typically injected into the base model via
147
148
  :attr:`~linkml.generators.pydanticgen.PydanticGenerator.injected_fields`
@@ -166,7 +167,7 @@ class PydanticAttribute(PydanticTemplateModel):
166
167
  """
167
168
 
168
169
  template: ClassVar[str] = "attribute.py.jinja"
169
- meta_exclude: ClassVar[List[str]] = ["from_schema", "owner", "range", "inlined", "inlined_as_list"]
170
+ meta_exclude: ClassVar[list[str]] = ["from_schema", "owner", "range", "inlined", "inlined_as_list"]
170
171
 
171
172
  name: str
172
173
  required: bool = False
@@ -186,7 +187,7 @@ class PydanticAttribute(PydanticTemplateModel):
186
187
  maximum_cardinality: Optional[int] = None
187
188
  multivalued: Optional[bool] = None
188
189
  pattern: Optional[str] = None
189
- meta: Optional[Dict[str, Any]] = None
190
+ meta: Optional[dict[str, Any]] = None
190
191
  """
191
192
  Metadata for the slot to be included in a Field annotation
192
193
  """
@@ -222,29 +223,29 @@ class PydanticClass(PydanticTemplateModel):
222
223
  """
223
224
 
224
225
  template: ClassVar[str] = "class.py.jinja"
225
- meta_exclude: ClassVar[List[str]] = ["slots", "is_a"]
226
+ meta_exclude: ClassVar[list[str]] = ["slots", "is_a"]
226
227
 
227
228
  name: str
228
- bases: Union[List[str], str] = PydanticBaseModel.default_name
229
+ bases: Union[list[str], str] = PydanticBaseModel.default_name
229
230
  description: Optional[str] = None
230
- attributes: Optional[Dict[str, PydanticAttribute]] = None
231
- meta: Optional[Dict[str, Any]] = None
231
+ attributes: Optional[dict[str, PydanticAttribute]] = None
232
+ meta: Optional[dict[str, Any]] = None
232
233
  """
233
234
  Metadata for the class to be included in a linkml_meta class attribute
234
235
  """
235
236
 
236
- def _validators(self) -> Optional[Dict[str, PydanticValidator]]:
237
+ def _validators(self) -> Optional[dict[str, PydanticValidator]]:
237
238
  if self.attributes is None:
238
239
  return None
239
240
 
240
241
  return {k: PydanticValidator(**v.model_dump()) for k, v in self.attributes.items() if v.pattern is not None}
241
242
 
242
243
  @computed_field
243
- def validators(self) -> Optional[Dict[str, PydanticValidator]]:
244
+ def validators(self) -> Optional[dict[str, PydanticValidator]]:
244
245
  return self._validators()
245
246
 
246
247
  @computed_field
247
- def slots(self) -> Optional[Dict[str, PydanticAttribute]]:
248
+ def slots(self) -> Optional[dict[str, PydanticAttribute]]:
248
249
  """alias of attributes"""
249
250
  return self.attributes
250
251
 
@@ -293,7 +294,7 @@ class Import(PydanticTemplateModel):
293
294
  template: ClassVar[str] = "imports.py.jinja"
294
295
  module: str
295
296
  alias: Optional[str] = None
296
- objects: Optional[List[ObjectImport]] = None
297
+ objects: Optional[list[ObjectImport]] = None
297
298
  is_schema: bool = False
298
299
  """
299
300
  Whether or not this ``Import`` is importing another schema imported by the main schema --
@@ -323,7 +324,7 @@ class Import(PydanticTemplateModel):
323
324
  else:
324
325
  return "thirdparty"
325
326
 
326
- def merge(self, other: "Import") -> List["Import"]:
327
+ def merge(self, other: "Import") -> list["Import"]:
327
328
  """
328
329
  Merge one import with another, see :meth:`.Imports` for an example.
329
330
 
@@ -440,7 +441,7 @@ class ConditionalImport(Import):
440
441
  """
441
442
  :meth:`.Import.sort` called for self and :attr:`.alternative`
442
443
  """
443
- super(ConditionalImport, self).sort()
444
+ super().sort()
444
445
  self.alternative.sort()
445
446
 
446
447
 
@@ -478,16 +479,16 @@ class Imports(PydanticTemplateModel):
478
479
 
479
480
  template: ClassVar[str] = "imports.py.jinja"
480
481
 
481
- imports: List[Union[Import, ConditionalImport]] = Field(default_factory=list)
482
- group_order: Tuple[str, ...] = get_args(IMPORT_GROUPS)
482
+ imports: list[Union[Import, ConditionalImport]] = Field(default_factory=list)
483
+ group_order: tuple[str, ...] = get_args(IMPORT_GROUPS)
483
484
  """Order in which to sort imports by their :attr:`.Import.group`"""
484
485
  render_sorted: bool = True
485
486
  """When rendering, render in sorted groups"""
486
487
 
487
488
  @classmethod
488
489
  def _merge(
489
- cls, imports: List[Union[Import, ConditionalImport]], other: Union[Import, "Imports", List[Import]]
490
- ) -> List[Union[Import, ConditionalImport]]:
490
+ cls, imports: list[Union[Import, ConditionalImport]], other: Union[Import, "Imports", list[Import]]
491
+ ) -> list[Union[Import, ConditionalImport]]:
491
492
  """
492
493
  Add a new import to an existing imports list, handling deduplication and flattening.
493
494
 
@@ -545,7 +546,7 @@ class Imports(PydanticTemplateModel):
545
546
  imports = sorted(imports, key=lambda i: i.module == "__future__", reverse=True)
546
547
  return imports
547
548
 
548
- def __add__(self, other: Union[Import, "Imports", List[Import]]) -> "Imports":
549
+ def __add__(self, other: Union[Import, "Imports", list[Import]]) -> "Imports":
549
550
  imports = self.imports.copy()
550
551
  imports = self._merge(imports, other)
551
552
  return Imports.model_construct(
@@ -556,8 +557,7 @@ class Imports(PydanticTemplateModel):
556
557
  return len(self.imports)
557
558
 
558
559
  def __iter__(self) -> Generator[Import, None, None]:
559
- for i in self.imports:
560
- yield i
560
+ yield from self.imports
561
561
 
562
562
  def __getitem__(self, item: Union[int, str]) -> Import:
563
563
  if isinstance(item, int):
@@ -571,7 +571,7 @@ class Imports(PydanticTemplateModel):
571
571
  else:
572
572
  raise TypeError(f"Can only index with an int or a string as the name of the module,\nGot: {type(item)}")
573
573
 
574
- def __contains__(self, item: Union[Import, "Imports", List[Import]]) -> bool:
574
+ def __contains__(self, item: Union[Import, "Imports", list[Import]]) -> bool:
575
575
  """
576
576
  Check if all the objects are imported from the given module(s)
577
577
 
@@ -601,8 +601,8 @@ class Imports(PydanticTemplateModel):
601
601
  @field_validator("imports", mode="after")
602
602
  @classmethod
603
603
  def imports_are_merged(
604
- cls, imports: List[Union[Import, ConditionalImport]]
605
- ) -> List[Union[Import, ConditionalImport]]:
604
+ cls, imports: list[Union[Import, ConditionalImport]]
605
+ ) -> list[Union[Import, ConditionalImport]]:
606
606
  """
607
607
  When creating from a list of imports, construct model as if we have done so by iteratively
608
608
  constructing with __add__ calls
@@ -613,7 +613,7 @@ class Imports(PydanticTemplateModel):
613
613
  return merged_imports
614
614
 
615
615
  @computed_field
616
- def import_groups(self) -> List[IMPORT_GROUPS]:
616
+ def import_groups(self) -> list[IMPORT_GROUPS]:
617
617
  """
618
618
  List of what group each import belongs to
619
619
  """
@@ -629,7 +629,7 @@ class Imports(PydanticTemplateModel):
629
629
  * Then alphabetically by module name
630
630
  """
631
631
 
632
- def _sort_key(i: Import) -> Tuple[int, int, str]:
632
+ def _sort_key(i: Import) -> tuple[int, int, str]:
633
633
  return (self.group_order.index(i.group), int(i.objects is not None), i.module)
634
634
 
635
635
  imports = sorted(self.imports, key=_sort_key)
@@ -640,7 +640,7 @@ class Imports(PydanticTemplateModel):
640
640
  def render(self, environment: Optional[Environment] = None, black: bool = False) -> str:
641
641
  if self.render_sorted:
642
642
  self.sort()
643
- return super(Imports, self).render(environment=environment, black=black)
643
+ return super().render(environment=environment, black=black)
644
644
 
645
645
 
646
646
  class PydanticModule(PydanticTemplateModel):
@@ -654,24 +654,24 @@ class PydanticModule(PydanticTemplateModel):
654
654
  metamodel_version: Optional[str] = None
655
655
  version: Optional[str] = None
656
656
  base_model: PydanticBaseModel = PydanticBaseModel()
657
- injected_classes: Optional[List[str]] = None
658
- python_imports: Union[Imports, List[Union[Import, ConditionalImport]]] = Imports()
659
- enums: Dict[str, PydanticEnum] = Field(default_factory=dict)
660
- classes: Dict[str, PydanticClass] = Field(default_factory=dict)
661
- meta: Optional[Dict[str, Any]] = None
657
+ injected_classes: Optional[list[str]] = None
658
+ python_imports: Union[Imports, list[Union[Import, ConditionalImport]]] = Imports()
659
+ enums: dict[str, PydanticEnum] = Field(default_factory=dict)
660
+ classes: dict[str, PydanticClass] = Field(default_factory=dict)
661
+ meta: Optional[dict[str, Any]] = None
662
662
  """
663
663
  Metadata for the schema to be included in a linkml_meta module-level instance of LinkMLMeta
664
664
  """
665
665
 
666
666
  @field_validator("python_imports", mode="after")
667
667
  @classmethod
668
- def cast_imports(cls, imports: Union[Imports, List[Union[Import, ConditionalImport]]]) -> Imports:
668
+ def cast_imports(cls, imports: Union[Imports, list[Union[Import, ConditionalImport]]]) -> Imports:
669
669
  if isinstance(imports, list):
670
670
  imports = Imports(imports=imports)
671
671
  return imports
672
672
 
673
673
  @computed_field
674
- def class_names(self) -> List[str]:
674
+ def class_names(self) -> list[str]:
675
675
  return [c.name for c in self.classes.values()]
676
676
 
677
677
 
@@ -2,11 +2,12 @@ import keyword
2
2
  import logging
3
3
  import os
4
4
  import re
5
+ from collections.abc import Iterator
5
6
  from copy import copy
6
7
  from dataclasses import dataclass
7
8
  from pathlib import Path
8
9
  from types import ModuleType
9
- from typing import Callable, Dict, Iterator, List, Optional, Set, Tuple, Union
10
+ from typing import Callable, Optional, Union
10
11
 
11
12
  import click
12
13
  from linkml_runtime import SchemaView
@@ -204,12 +205,6 @@ class PythonGenerator(Generator):
204
205
  ObjectImport(name="extended_int"),
205
206
  ],
206
207
  )
207
- + Import(
208
- module="linkml_runtime.utils.dataclass_extensions_376",
209
- objects=[
210
- ObjectImport(name="dataclasses_init_fn_with_kwargs"),
211
- ],
212
- )
213
208
  + Import(
214
209
  module="linkml_runtime.utils.formatutils",
215
210
  objects=[
@@ -265,9 +260,6 @@ class PythonGenerator(Generator):
265
260
  metamodel_version = "{self.schema.metamodel_version}"
266
261
  version = {'"' + self.schema.version + '"' if self.schema.version else None}
267
262
 
268
- # Overwrite dataclasses _init_fn to add **kwargs in __init__
269
- dataclasses._init_fn = dataclasses_init_fn_with_kwargs
270
-
271
263
  # Namespaces
272
264
  {self.gen_namespaces()}
273
265
 
@@ -292,7 +284,7 @@ dataclasses._init_fn = dataclasses_init_fn_with_kwargs
292
284
  list_ents = [f"from {k} import {', '.join(v)}" for k, v in self.gen_import_list().items()]
293
285
  return "\n".join(list_ents)
294
286
 
295
- def gen_import_list(self) -> Dict[str, List[str]]:
287
+ def gen_import_list(self) -> dict[str, list[str]]:
296
288
  """
297
289
  Generate a list of types to import
298
290
 
@@ -302,7 +294,7 @@ dataclasses._init_fn = dataclasses_init_fn_with_kwargs
302
294
  class ImportList:
303
295
  def __init__(self, schema_location: str):
304
296
  self.schema_location = schema_location
305
- self.v: Dict[str, Set[str]] = {}
297
+ self.v: dict[str, set[str]] = {}
306
298
 
307
299
  def add_element(self, e: Element) -> None:
308
300
  if e.imported_from:
@@ -324,7 +316,7 @@ dataclasses._init_fn = dataclasses_init_fn_with_kwargs
324
316
  else:
325
317
  innerself.v.setdefault(". " + path, set()).add(name)
326
318
 
327
- def values(self) -> Dict[str, List[str]]:
319
+ def values(self) -> dict[str, list[str]]:
328
320
  return {k: sorted(self.v[k]) for k in sorted(self.v.keys())}
329
321
 
330
322
  def add_type_ref(typ: TypeDefinition) -> None:
@@ -515,7 +507,7 @@ dataclasses._init_fn = dataclasses_init_fn_with_kwargs
515
507
  if slot.inherited:
516
508
  inherited_slots.append(slot.alias if slot.alias else slotname)
517
509
  inherited_slots_str = ", ".join([f'"{underscore(s)}"' for s in inherited_slots])
518
- return f"\n\t_inherited_slots: ClassVar[List[str]] = [{inherited_slots_str}]\n"
510
+ return f"\n\t_inherited_slots: ClassVar[list[str]] = [{inherited_slots_str}]\n"
519
511
 
520
512
  def gen_class_meta(self, cls: ClassDefinition) -> str:
521
513
  if not self.gen_classvars:
@@ -638,7 +630,7 @@ dataclasses._init_fn = dataclasses_init_fn_with_kwargs
638
630
  slot: SlotDefinition,
639
631
  cls: Optional[ClassDefinition],
640
632
  positional_allowed: bool,
641
- ) -> Tuple[str, Optional[str]]:
633
+ ) -> tuple[str, Optional[str]]:
642
634
  """
643
635
  Return the range type including initializers, etc.
644
636
  Generate a class variable declaration for the supplied slot. Note: the positional_allowed attribute works,
@@ -663,33 +655,33 @@ dataclasses._init_fn = dataclasses_init_fn_with_kwargs
663
655
  if num_elements == 1:
664
656
  if slot.required:
665
657
  return (
666
- f"Union[List[{base_key}], Dict[{base_key}, {range_type}]]",
658
+ f"Union[list[{base_key}], dict[{base_key}, {range_type}]]",
667
659
  dflt,
668
660
  )
669
661
  else:
670
662
  return (
671
- f"Optional[Union[List[{base_key}], Dict[{base_key}, {range_type}]]]",
663
+ f"Optional[Union[list[{base_key}], dict[{base_key}, {range_type}]]]",
672
664
  dflt,
673
665
  )
674
666
  else:
675
667
  if slot.required:
676
668
  return (
677
- f"Union[Dict[{base_key}, {range_type}], List[{range_type}]]",
669
+ f"Union[dict[{base_key}, {range_type}], list[{range_type}]]",
678
670
  dflt,
679
671
  )
680
672
  else:
681
673
  return (
682
- f"Optional[Union[Dict[{base_key}, {range_type}], List[{range_type}]]]",
674
+ f"Optional[Union[dict[{base_key}, {range_type}], list[{range_type}]]]",
683
675
  dflt,
684
676
  )
685
677
 
686
678
  # All other cases
687
679
  if slot.multivalued:
688
680
  if slot.required:
689
- return f"Union[{range_type}, List[{range_type}]]", (None if positional_allowed else "None")
681
+ return f"Union[{range_type}, list[{range_type}]]", (None if positional_allowed else "None")
690
682
  else:
691
683
  return (
692
- f"Optional[Union[{range_type}, List[{range_type}]]]",
684
+ f"Optional[Union[{range_type}, list[{range_type}]]]",
693
685
  "empty_list()",
694
686
  )
695
687
  elif slot.required:
@@ -697,7 +689,7 @@ dataclasses._init_fn = dataclasses_init_fn_with_kwargs
697
689
  else:
698
690
  return f"Optional[{range_type}]", "None"
699
691
 
700
- def class_reference_type(self, slot: SlotDefinition, cls: Optional[ClassDefinition]) -> Tuple[str, str, str]:
692
+ def class_reference_type(self, slot: SlotDefinition, cls: Optional[ClassDefinition]) -> tuple[str, str, str]:
701
693
  """
702
694
  Return the type of slot referencing a class
703
695
 
@@ -719,7 +711,7 @@ dataclasses._init_fn = dataclasses_init_fn_with_kwargs
719
711
  return str(self.gen_class_reference(rangelist)), prox_type, prox_type_name
720
712
 
721
713
  @staticmethod
722
- def gen_class_reference(rangelist: List[str]) -> str:
714
+ def gen_class_reference(rangelist: list[str]) -> str:
723
715
  """
724
716
  Return a basic or a union type depending on the number of elements in range list
725
717
 
@@ -766,7 +758,7 @@ dataclasses._init_fn = dataclasses_init_fn_with_kwargs
766
758
  return (
767
759
  (
768
760
  f"""
769
- def __post_init__(self, *_: List[str], **kwargs: Dict[str, Any]):
761
+ def __post_init__(self, *_: str, **kwargs: Any):
770
762
  {post_inits_line}
771
763
  super().__post_init__(**kwargs)
772
764
  {post_inits_post_super_line}"""
@@ -777,7 +769,7 @@ dataclasses._init_fn = dataclasses_init_fn_with_kwargs
777
769
 
778
770
  # sort classes such that if C is a child of P then C appears after P in the list
779
771
  @staticmethod
780
- def _sort_classes(clist: List[ClassDefinition]) -> List[ClassDefinition]:
772
+ def _sort_classes(clist: list[ClassDefinition]) -> list[ClassDefinition]:
781
773
  clist = list(clist)
782
774
  slist = [] # sorted
783
775
  while len(clist) > 0:
@@ -825,7 +817,7 @@ dataclasses._init_fn = dataclasses_init_fn_with_kwargs
825
817
  :param cls: class to generate constructor for
826
818
  :return: python constructor
827
819
  """
828
- rlines: List[str] = []
820
+ rlines: list[str] = []
829
821
  designators = [x for x in self.domain_slots(cls) if x.designates_type]
830
822
  if len(designators) > 0:
831
823
  descendants = self.schemaview.class_descendants(cls.name)
@@ -880,7 +872,7 @@ dataclasses._init_fn = dataclasses_init_fn_with_kwargs
880
872
 
881
873
  def gen_postinit(self, cls: ClassDefinition, slot: SlotDefinition) -> Optional[str]:
882
874
  """Generate python post init rules for slot in class"""
883
- rlines: List[str] = []
875
+ rlines: list[str] = []
884
876
 
885
877
  if slot.range in self.schema.classes:
886
878
  if self.is_class_unconstrained(self.schema.classes[slot.range]):
@@ -1018,7 +1010,7 @@ dataclasses._init_fn = dataclasses_init_fn_with_kwargs
1018
1010
  if first_hit_only:
1019
1011
  break
1020
1012
 
1021
- def primary_keys_for(self, cls: ClassDefinition) -> List[SlotDefinitionName]:
1013
+ def primary_keys_for(self, cls: ClassDefinition) -> list[SlotDefinitionName]:
1022
1014
  """Return the primary key for cls.
1023
1015
 
1024
1016
  Note: At the moment we return at most one entry. At some point, keys will be expanded to support
@@ -1068,7 +1060,7 @@ dataclasses._init_fn = dataclasses_init_fn_with_kwargs
1068
1060
  return False # Occurs before
1069
1061
  return True
1070
1062
 
1071
- def python_uri_for(self, uriorcurie: Union[str, URIRef]) -> Tuple[str, Optional[str]]:
1063
+ def python_uri_for(self, uriorcurie: Union[str, URIRef]) -> tuple[str, Optional[str]]:
1072
1064
  """Return the python form of uriorcurie
1073
1065
  :param uriorcurie:
1074
1066
  :return: URI and CURIE form
@@ -9,7 +9,7 @@ import os
9
9
  import urllib.parse as urlparse
10
10
  from copy import deepcopy
11
11
  from dataclasses import dataclass
12
- from typing import List, Optional
12
+ from typing import Optional
13
13
 
14
14
  import click
15
15
  from linkml_runtime.linkml_model import SchemaDefinition
@@ -36,7 +36,7 @@ class RDFGenerator(Generator):
36
36
 
37
37
  # ObjectVars
38
38
  emit_metadata: bool = False
39
- context: List[str] = None
39
+ context: list[str] = None
40
40
  original_schema: SchemaDefinition = None
41
41
  """See https://github.com/linkml/linkml/issues/871"""
42
42