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
@@ -2,7 +2,7 @@ import abc
2
2
  import re
3
3
  import unicodedata
4
4
  from dataclasses import dataclass, field
5
- from typing import Dict, List, Optional
5
+ from typing import Optional
6
6
 
7
7
  from linkml_runtime.linkml_model.meta import (
8
8
  ClassDefinition,
@@ -32,8 +32,8 @@ class OODocument:
32
32
  name: SAFE_NAME
33
33
  package: PACKAGE = None
34
34
  source_schema: SchemaDefinition = None
35
- classes: List["OOClass"] = field(default_factory=lambda: [])
36
- imports: List[str] = field(default_factory=lambda: [])
35
+ classes: list["OOClass"] = field(default_factory=lambda: [])
36
+ imports: list[str] = field(default_factory=lambda: [])
37
37
 
38
38
 
39
39
  @dataclass
@@ -45,7 +45,7 @@ class OOField:
45
45
  name: SAFE_NAME
46
46
  range: TYPE_EXPRESSION = None
47
47
  default_value: str = None
48
- annotations: List[ANNOTATION] = field(default_factory=lambda: [])
48
+ annotations: list[ANNOTATION] = field(default_factory=lambda: [])
49
49
  source_slot: SlotDefinition = field(default_factory=lambda: [])
50
50
 
51
51
 
@@ -61,10 +61,10 @@ class OOClass:
61
61
  is_a: Optional[SAFE_NAME] = None
62
62
  mixin: Optional[bool] = None
63
63
  abstract: Optional[bool] = None
64
- mixins: List[SAFE_NAME] = field(default_factory=lambda: [])
65
- fields: List[OOField] = field(default_factory=lambda: [])
66
- all_fields: List[OOField] = field(default_factory=lambda: [])
67
- annotations: List[ANNOTATION] = field(default_factory=lambda: [])
64
+ mixins: list[SAFE_NAME] = field(default_factory=lambda: [])
65
+ fields: list[OOField] = field(default_factory=lambda: [])
66
+ all_fields: list[OOField] = field(default_factory=lambda: [])
67
+ annotations: list[ANNOTATION] = field(default_factory=lambda: [])
68
68
  package: PACKAGE = None
69
69
  source_class: ClassDefinition = None
70
70
 
@@ -135,7 +135,7 @@ class OOCodeGenerator(Generator):
135
135
 
136
136
  return safe_label
137
137
 
138
- def generate_enums(self, all_enums: Dict[EnumDefinitionName, EnumDefinition]) -> Dict:
138
+ def generate_enums(self, all_enums: dict[EnumDefinitionName, EnumDefinition]) -> dict:
139
139
  # TODO: make an explicit class to represent how an enum is passed to the template
140
140
  enums = {}
141
141
  for enum_name, enum_original in all_enums.items():
@@ -161,7 +161,7 @@ class OOCodeGenerator(Generator):
161
161
 
162
162
  return enums
163
163
 
164
- def create_documents(self) -> List[OODocument]:
164
+ def create_documents(self) -> list[OODocument]:
165
165
  """
166
166
  Currently hardcoded for java-style
167
167
  :return:
@@ -3,10 +3,11 @@
3
3
  import logging
4
4
  import os
5
5
  from collections import defaultdict
6
+ from collections.abc import Mapping
6
7
  from copy import copy
7
8
  from dataclasses import dataclass, field
8
9
  from enum import Enum, unique
9
- from typing import Any, List, Mapping, Optional, Set, Tuple, Union
10
+ from typing import Any, Optional, Union
10
11
 
11
12
  import click
12
13
  import rdflib
@@ -117,7 +118,7 @@ class OwlSchemaGenerator(Generator):
117
118
  metadata_profile: MetadataProfile = None
118
119
  """Deprecated - use metadata_profiles."""
119
120
 
120
- metadata_profiles: List[MetadataProfile] = field(default_factory=lambda: [])
121
+ metadata_profiles: list[MetadataProfile] = field(default_factory=lambda: [])
121
122
  """By default, use the linkml metadata profile,
122
123
  this allows for overrides."""
123
124
 
@@ -151,10 +152,10 @@ class OwlSchemaGenerator(Generator):
151
152
 
152
153
  default_permissible_value_type: Union[str, URIRef] = field(default_factory=lambda: OWL.Class)
153
154
 
154
- slot_is_literal_map: Mapping[str, Set[bool]] = field(default_factory=lambda: defaultdict(set))
155
+ slot_is_literal_map: Mapping[str, set[bool]] = field(default_factory=lambda: defaultdict(set))
155
156
  """DEPRECATED: use node_owltypes"""
156
157
 
157
- node_owltypes: Mapping[Union[BNode, URIRef], Set[OWL_TYPE]] = field(default_factory=lambda: defaultdict(set))
158
+ node_owltypes: Mapping[Union[BNode, URIRef], set[OWL_TYPE]] = field(default_factory=lambda: defaultdict(set))
158
159
  """rdfs:Datatype, owl:Thing"""
159
160
 
160
161
  simplify: bool = True
@@ -425,7 +426,7 @@ class OwlSchemaGenerator(Generator):
425
426
  else:
426
427
  self.graph.add((subject_expr, RDFS.subClassOf, superclass_expr))
427
428
 
428
- def get_own_slots(self, cls: Union[ClassDefinition, AnonymousClassExpression]) -> List[SlotDefinition]:
429
+ def get_own_slots(self, cls: Union[ClassDefinition, AnonymousClassExpression]) -> list[SlotDefinition]:
429
430
  """
430
431
  Get the slots that are defined on a class, excluding those that are inherited.
431
432
 
@@ -561,7 +562,7 @@ class OwlSchemaGenerator(Generator):
561
562
  self,
562
563
  slot: Union[SlotDefinition, AnonymousSlotExpression],
563
564
  owning_class: Optional[Union[ClassDefinition, AnonymousClassExpression]] = None,
564
- ) -> Set[URIRef]:
565
+ ) -> set[URIRef]:
565
566
  """
566
567
  Determine the OWL types of a named slot or slot expression
567
568
 
@@ -594,7 +595,7 @@ class OwlSchemaGenerator(Generator):
594
595
  cls: Optional[Union[ClassDefinition, AnonymousClassExpression]],
595
596
  slot: Union[SlotDefinition, AnonymousSlotExpression],
596
597
  main_slot: SlotDefinition = None,
597
- owl_types: Set[OWL_TYPE] = None,
598
+ owl_types: set[OWL_TYPE] = None,
598
599
  ) -> Optional[Union[BNode, URIRef]]:
599
600
  """
600
601
  Take a ClassExpression and SlotExpression combination and transform to a node.
@@ -685,7 +686,7 @@ class OwlSchemaGenerator(Generator):
685
686
  self,
686
687
  element: Union[SlotDefinition, AnonymousSlotExpression, TypeDefinition, AnonymousTypeExpression],
687
688
  is_literal: Optional[bool] = None,
688
- ) -> Tuple[List[BNode], Set[OWL_TYPE]]:
689
+ ) -> tuple[list[BNode], set[OWL_TYPE]]:
689
690
  owl_types = set()
690
691
  owl_exprs = []
691
692
  graph = self.graph
@@ -978,7 +979,7 @@ class OwlSchemaGenerator(Generator):
978
979
  subject: Union[URIRef, BNode],
979
980
  condition: AnonymousClassExpression,
980
981
  cls: ClassDefinition,
981
- ) -> List[BNode]:
982
+ ) -> list[BNode]:
982
983
  for slot_name, expr in condition.slot_conditions.items():
983
984
  var = self._swrl_var(slot_name)
984
985
  if expr.maximum_value is not None:
@@ -996,7 +997,7 @@ class OwlSchemaGenerator(Generator):
996
997
  return True
997
998
  return profile in self.metadata_profiles or profile == self.metadata_profile
998
999
 
999
- def _get_owltypes(self, current: Set[OWL_TYPE], exprs: List[Union[BNode, URIRef]]) -> Set[OWL_TYPE]:
1000
+ def _get_owltypes(self, current: set[OWL_TYPE], exprs: list[Union[BNode, URIRef]]) -> set[OWL_TYPE]:
1000
1001
  """
1001
1002
  Gets the OWL types of specified expressions plus current owl types.
1002
1003
 
@@ -1076,7 +1077,7 @@ class OwlSchemaGenerator(Generator):
1076
1077
  return URIRef("https://w3id.org/linkml/" + name)
1077
1078
 
1078
1079
  def _complement_of_union_of(
1079
- self, exprs: List[Union[BNode, URIRef]], owl_types: Set[OWL_TYPE] = None, **kwargs
1080
+ self, exprs: list[Union[BNode, URIRef]], owl_types: set[OWL_TYPE] = None, **kwargs
1080
1081
  ) -> Optional[Union[BNode, URIRef]]:
1081
1082
  if not exprs:
1082
1083
  raise ValueError("Must pass at least one")
@@ -1092,16 +1093,16 @@ class OwlSchemaGenerator(Generator):
1092
1093
 
1093
1094
  return neg_expr
1094
1095
 
1095
- def _intersection_of(self, exprs: List[Union[BNode, URIRef]], **kwargs) -> Optional[Union[BNode, URIRef]]:
1096
+ def _intersection_of(self, exprs: list[Union[BNode, URIRef]], **kwargs) -> Optional[Union[BNode, URIRef]]:
1096
1097
  return self._boolean_expression(exprs, OWL.intersectionOf, **kwargs)
1097
1098
 
1098
- def _union_of(self, exprs: List[Union[BNode, URIRef]], **kwargs) -> Optional[Union[BNode, URIRef]]:
1099
+ def _union_of(self, exprs: list[Union[BNode, URIRef]], **kwargs) -> Optional[Union[BNode, URIRef]]:
1099
1100
  return self._boolean_expression(exprs, OWL.unionOf, **kwargs)
1100
1101
 
1101
- def _object_one_of(self, exprs: List[Union[BNode, URIRef]], **kwargs) -> Optional[Union[BNode, URIRef]]:
1102
+ def _object_one_of(self, exprs: list[Union[BNode, URIRef]], **kwargs) -> Optional[Union[BNode, URIRef]]:
1102
1103
  return self._boolean_expression(exprs, OWL.oneOf, **kwargs)
1103
1104
 
1104
- def _exactly_one_of(self, exprs: List[Union[BNode, URIRef]]) -> Optional[Union[BNode, URIRef]]:
1105
+ def _exactly_one_of(self, exprs: list[Union[BNode, URIRef]]) -> Optional[Union[BNode, URIRef]]:
1105
1106
  if not exprs:
1106
1107
  raise ValueError("Must pass at least one")
1107
1108
  if len(exprs) == 1:
@@ -1113,7 +1114,7 @@ class OwlSchemaGenerator(Generator):
1113
1114
  sub_exprs.append(self._intersection_of([x, neg_expr]))
1114
1115
  return self._union_of(sub_exprs)
1115
1116
 
1116
- def _datatype_restriction(self, datatype: URIRef, facets: List[Union[BNode, URIRef]]) -> BNode:
1117
+ def _datatype_restriction(self, datatype: URIRef, facets: list[Union[BNode, URIRef]]) -> BNode:
1117
1118
  node = BNode()
1118
1119
  graph = self.graph
1119
1120
  graph.add((node, RDF.type, RDFS.Datatype))
@@ -1132,10 +1133,10 @@ class OwlSchemaGenerator(Generator):
1132
1133
 
1133
1134
  def _boolean_expression(
1134
1135
  self,
1135
- exprs: List[Union[BNode, URIRef, Literal]],
1136
+ exprs: list[Union[BNode, URIRef, Literal]],
1136
1137
  predicate: URIRef,
1137
1138
  node: Optional[URIRef] = None,
1138
- owl_types: Set[OWL_TYPE] = None,
1139
+ owl_types: set[OWL_TYPE] = None,
1139
1140
  ) -> Optional[Union[BNode, URIRef]]:
1140
1141
  graph = self.graph
1141
1142
  if [x for x in exprs if x is None]:
@@ -8,7 +8,7 @@ import base64
8
8
  import os
9
9
  import zlib
10
10
  from dataclasses import dataclass
11
- from typing import Callable, List, Optional, Set, cast
11
+ from typing import Callable, Optional, cast
12
12
 
13
13
  import click
14
14
  import requests
@@ -38,15 +38,15 @@ class PlantumlGenerator(Generator):
38
38
  valid_formats = ["puml", "plantuml", "png", "pdf", "jpg", "json", "svg"]
39
39
  visit_all_class_slots = False
40
40
 
41
- referenced: Optional[Set[ClassDefinitionName]] = None # List of classes that have to be emitted
42
- generated: Optional[Set[ClassDefinitionName]] = None # List of classes that have been emitted
43
- class_generated: Optional[Set[ClassDefinitionName]] = None # Class definitions that have been emitted
44
- associations_generated: Optional[Set[ClassDefinitionName]] = None # Classes with associations generated
45
- focus_classes: Optional[Set[ClassDefinitionName]] = None # Classes to be completely filled
46
- gen_classes: Optional[Set[ClassDefinitionName]] = None # Classes to be generated
41
+ referenced: Optional[set[ClassDefinitionName]] = None # List of classes that have to be emitted
42
+ generated: Optional[set[ClassDefinitionName]] = None # List of classes that have been emitted
43
+ class_generated: Optional[set[ClassDefinitionName]] = None # Class definitions that have been emitted
44
+ associations_generated: Optional[set[ClassDefinitionName]] = None # Classes with associations generated
45
+ focus_classes: Optional[set[ClassDefinitionName]] = None # Classes to be completely filled
46
+ gen_classes: Optional[set[ClassDefinitionName]] = None # Classes to be generated
47
47
  output_file_name: Optional[str] = None # Location of output file if directory used
48
48
 
49
- classes: Set[ClassDefinitionName] = None
49
+ classes: set[ClassDefinitionName] = None
50
50
  directory: Optional[str] = None
51
51
  kroki_server: Optional[str] = "https://kroki.io"
52
52
  tooltips_flag: bool = False
@@ -54,7 +54,7 @@ class PlantumlGenerator(Generator):
54
54
 
55
55
  def visit_schema(
56
56
  self,
57
- classes: Set[ClassDefinitionName] = None,
57
+ classes: set[ClassDefinitionName] = None,
58
58
  directory: Optional[str] = None,
59
59
  **_,
60
60
  ) -> Optional[str]:
@@ -76,7 +76,7 @@ class PlantumlGenerator(Generator):
76
76
  self.gen_classes = self.synopsis.roots.classrefs
77
77
  self.referenced = self.gen_classes
78
78
  self.generated = set()
79
- plantumlclassdef: List[str] = []
79
+ plantumlclassdef: list[str] = []
80
80
  while self.referenced.difference(self.generated):
81
81
  cn = sorted(list(self.referenced.difference(self.generated)), reverse=True)[0]
82
82
  self.generated.add(cn)
@@ -127,7 +127,7 @@ class PlantumlGenerator(Generator):
127
127
  @param cn:
128
128
  @return:
129
129
  """
130
- slot_defs: List[str] = []
130
+ slot_defs: list[str] = []
131
131
  if cn not in self.class_generated and (not self.focus_classes or cn in self.focus_classes):
132
132
  cls = self.schema.classes[cn]
133
133
  for slot in self.filtered_cls_slots(cn, all_slots=True, filtr=lambda s: s.range not in self.schema.classes):
@@ -168,8 +168,8 @@ class PlantumlGenerator(Generator):
168
168
  @return: PLANTUML representation of the association
169
169
  """
170
170
 
171
- classes: List[str] = []
172
- assocs: List[str] = []
171
+ classes: list[str] = []
172
+ assocs: list[str] = []
173
173
  if cn not in self.associations_generated and (not self.focus_classes or cn in self.focus_classes):
174
174
  cls = self.schema.classes[cn]
175
175
 
@@ -271,7 +271,7 @@ class PlantumlGenerator(Generator):
271
271
  if cn not in self.class_generated:
272
272
  classes.append(self.add_class(cn))
273
273
  assocs.append('"' + cls.is_a + '" ' + plantuml_is_a + ' "' + cn + '"')
274
- entries: List[str] = []
274
+ entries: list[str] = []
275
275
  entries.extend(classes)
276
276
  entries.extend(assocs)
277
277
  return entries
@@ -294,7 +294,7 @@ class PlantumlGenerator(Generator):
294
294
  cn: ClassDefinitionName,
295
295
  all_slots: bool = True,
296
296
  filtr: Callable[[SlotDefinition], bool] = None,
297
- ) -> List[SlotDefinition]:
297
+ ) -> list[SlotDefinition]:
298
298
  """Return the set of slots associated with the class that meet the filter criteria. Slots will be returned
299
299
  in defining order, with class slots returned last
300
300
 
@@ -5,7 +5,7 @@ Generate JSON-LD contexts
5
5
 
6
6
  import os
7
7
  from dataclasses import dataclass, field
8
- from typing import Dict, Optional, Set, Union
8
+ from typing import Optional, Union
9
9
 
10
10
  import click
11
11
  from jsonasobj2 import JsonObj, as_json
@@ -30,10 +30,10 @@ class PrefixGenerator(Generator):
30
30
  uses_schemaloader = True
31
31
 
32
32
  # ObjectVars
33
- emit_prefixes: Set[str] = field(default_factory=lambda: set())
33
+ emit_prefixes: set[str] = field(default_factory=lambda: set())
34
34
  default_ns: str = None
35
- context_body: Dict = field(default_factory=lambda: dict())
36
- slot_class_maps: Dict = field(default_factory=lambda: dict())
35
+ context_body: dict = field(default_factory=lambda: dict())
36
+ slot_class_maps: dict = field(default_factory=lambda: dict())
37
37
  base: Optional[Union[str, Namespace]] = None
38
38
 
39
39
  def __post_init__(self):
@@ -74,7 +74,7 @@ class PrefixGenerator(Generator):
74
74
  context[k] = v
75
75
 
76
76
  if self.format == "tsv":
77
- mapping: Dict = {} # prefix to IRI mapping
77
+ mapping: dict = {} # prefix to IRI mapping
78
78
  for prefix in sorted(self.emit_prefixes):
79
79
  mapping[prefix] = self.namespaces[prefix]
80
80
 
@@ -4,7 +4,7 @@ from collections import defaultdict
4
4
  from dataclasses import dataclass, field
5
5
  from functools import lru_cache
6
6
  from pathlib import Path
7
- from typing import Any, Dict, List, Tuple, Type
7
+ from typing import Any
8
8
 
9
9
  import click
10
10
  import yaml
@@ -30,9 +30,9 @@ logger = logging.getLogger(__name__)
30
30
 
31
31
  PATH_FSTRING = str
32
32
  GENERATOR_NAME = str
33
- ARG_DICT = Dict[str, Any]
34
- CONFIG_TUPLE = Tuple[Type[Generator], PATH_FSTRING, ARG_DICT]
35
- GEN_MAP: Dict[GENERATOR_NAME, CONFIG_TUPLE]
33
+ ARG_DICT = dict[str, Any]
34
+ CONFIG_TUPLE = tuple[type[Generator], PATH_FSTRING, ARG_DICT]
35
+ GEN_MAP: dict[GENERATOR_NAME, CONFIG_TUPLE]
36
36
  GEN_MAP = {
37
37
  "graphql": (GraphqlGenerator, "graphql/{name}.graphql", {}),
38
38
  "jsonldcontext": (ContextGenerator, "jsonld/{name}.context.jsonld", {}),
@@ -63,7 +63,7 @@ GEN_MAP = {
63
63
  }
64
64
 
65
65
 
66
- @lru_cache()
66
+ @lru_cache
67
67
  def get_local_imports(schema_path: str, dir: str):
68
68
  logger.info(f"GETTING IMPORTS = {schema_path}")
69
69
  all_imports = [schema_path]
@@ -85,9 +85,9 @@ class ProjectConfiguration:
85
85
  """
86
86
 
87
87
  directory: str = "tmp"
88
- generator_args: Dict[GENERATOR_NAME, ARG_DICT] = field(default_factory=lambda: defaultdict(dict))
89
- includes: List[str] = None
90
- excludes: List[str] = None
88
+ generator_args: dict[GENERATOR_NAME, ARG_DICT] = field(default_factory=lambda: defaultdict(dict))
89
+ includes: list[str] = None
90
+ excludes: list[str] = None
91
91
  mergeimports: bool = None
92
92
 
93
93
 
@@ -188,8 +188,8 @@ class ProjectGenerator:
188
188
  def cli(
189
189
  yamlfile,
190
190
  dir,
191
- exclude: List[str],
192
- include: List[str],
191
+ exclude: list[str],
192
+ include: list[str],
193
193
  config_file,
194
194
  mergeimports,
195
195
  generator_arguments: str,
@@ -3,10 +3,7 @@ from abc import ABC, abstractmethod
3
3
  from enum import Enum
4
4
  from typing import (
5
5
  ClassVar,
6
- Iterable,
7
- List,
8
6
  Optional,
9
- Type,
10
7
  TypeVar,
11
8
  Union,
12
9
  )
@@ -40,14 +37,13 @@ class ArrayRepresentation(Enum):
40
37
  _BOUNDED_ARRAY_FIELDS = ("exact_number_dimensions", "minimum_number_dimensions", "maximum_number_dimensions")
41
38
 
42
39
  _T = TypeVar("_T")
43
- AnyShapeArray = TypeAliasType("AnyShapeArray", Iterable[Union[_T, Iterable["AnyShapeArray[_T]"]]], type_params=(_T,))
40
+ AnyShapeArray = TypeAliasType("AnyShapeArray", list[Union[_T, "AnyShapeArray[_T]"]], type_params=(_T,))
44
41
 
45
42
  _AnyShapeArrayImports = (
46
43
  Imports()
47
44
  + Import(
48
45
  module="typing",
49
46
  objects=[
50
- ObjectImport(name="Iterable"),
51
47
  ObjectImport(name="TypeVar"),
52
48
  ObjectImport(name="Union"),
53
49
  ],
@@ -64,7 +60,7 @@ _AnyShapeArrayImports = (
64
60
  _AnyShapeArrayInjects = [
65
61
  '_T = TypeVar("_T")',
66
62
  """AnyShapeArray = TypeAliasType(
67
- "AnyShapeArray", Iterable[Union[_T, Iterable["AnyShapeArray[_T]"]]], type_params=(_T,)
63
+ "AnyShapeArray", list[Union[_T, "AnyShapeArray[_T]"]], type_params=(_T,)
68
64
  )""",
69
65
  ]
70
66
 
@@ -161,11 +157,9 @@ class ArrayValidator:
161
157
  """
162
158
  if array.minimum_number_dimensions is not None and array.maximum_number_dimensions is None and array.dimensions:
163
159
  raise ValidationError(
164
- (
165
- "Cannot specify a minimum_number_dimensions while maximum is None while using labeled dimensions - "
166
- "either use exact_number_dimensions > len(dimensions) for extra parameterized dimensions or set "
167
- "maximum_number_dimensions explicitly to False for unbounded dimensions"
168
- )
160
+ "Cannot specify a minimum_number_dimensions while maximum is None while using labeled dimensions - "
161
+ "either use exact_number_dimensions > len(dimensions) for extra parameterized dimensions or set "
162
+ "maximum_number_dimensions explicitly to False for unbounded dimensions"
169
163
  )
170
164
 
171
165
  @staticmethod
@@ -256,7 +250,7 @@ class ArrayRangeGenerator(ABC):
256
250
  return any([getattr(self.array, arr_field, None) is not None for arr_field in _BOUNDED_ARRAY_FIELDS])
257
251
 
258
252
  @classmethod
259
- def get_generator(cls, repr: ArrayRepresentation) -> Type["ArrayRangeGenerator"]:
253
+ def get_generator(cls, repr: ArrayRepresentation) -> type["ArrayRangeGenerator"]:
260
254
  """Get the generator class for a given array representation"""
261
255
  for subclass in cls.__subclasses__():
262
256
  if repr in (subclass.REPR, subclass.REPR.value):
@@ -293,7 +287,7 @@ class ListOfListsArray(ArrayRangeGenerator):
293
287
 
294
288
  @staticmethod
295
289
  def _list_of_lists(dimensions: int, dtype: str) -> str:
296
- return ("List[" * dimensions) + dtype + ("]" * dimensions)
290
+ return ("list[" * dimensions) + dtype + ("]" * dimensions)
297
291
 
298
292
  @staticmethod
299
293
  def _parameterized_dimension(dimension: DimensionExpression, dtype: str) -> RangeResult:
@@ -306,7 +300,7 @@ class ListOfListsArray(ArrayRangeGenerator):
306
300
  dmax = dimension.maximum_cardinality
307
301
  else:
308
302
  # TODO: handle labels for labeled but unshaped arrays
309
- return RangeResult(range="List[" + dtype + "]")
303
+ return RangeResult(range="list[" + dtype + "]")
310
304
 
311
305
  items = []
312
306
  if dmin is not None:
@@ -341,7 +335,7 @@ class ListOfListsArray(ArrayRangeGenerator):
341
335
 
342
336
  def _bounded_dimensions(self, array: ArrayExpression) -> RangeResult:
343
337
  """
344
- A nested series of ``List[]`` ranges with :attr:`.dtype` at the center.
338
+ A nested series of ``list[]`` ranges with :attr:`.dtype` at the center.
345
339
 
346
340
  When an array expression allows for a range of dimensions, each set of ``List`` s is joined by a ``Union`` .
347
341
  """
@@ -357,13 +351,13 @@ class ListOfListsArray(ArrayRangeGenerator):
357
351
  ):
358
352
  return self._any_shape()
359
353
  elif array.maximum_number_dimensions:
360
- # e.g., if min = 2, max = 3, range = Union[List[List[dtype]], List[List[List[dtype]]]]
354
+ # e.g., if min = 2, max = 3, range = Union[list[list[dtype]], list[list[list[dtype]]]]
361
355
  min_dims = array.minimum_number_dimensions if array.minimum_number_dimensions is not None else 1
362
356
  ranges = [self._list_of_lists(i, self.dtype) for i in range(min_dims, array.maximum_number_dimensions + 1)]
363
357
  return RangeResult(range="Union[" + ", ".join(ranges) + "]")
364
358
  else:
365
359
  # min specified with no max
366
- # e.g., if min = 3, range = List[List[AnyShapeArray[dtype]]]
360
+ # e.g., if min = 3, range = list[list[AnyShapeArray[dtype]]]
367
361
  return RangeResult(
368
362
  range=self._list_of_lists(array.minimum_number_dimensions - 1, self._any_shape().range),
369
363
  injected_classes=_AnyShapeArrayInjects,
@@ -415,7 +409,7 @@ class ListOfListsArray(ArrayRangeGenerator):
415
409
 
416
410
  if array.minimum_number_dimensions:
417
411
  # some minimum anonymous dimensions but unlimited max dimensions
418
- # e.g., if min = 3, len(dim) = 2, then res.range = List[Union[AnyShapeArray[dtype], dtype]]
412
+ # e.g., if min = 3, len(dim) = 2, then res.range = list[Union[AnyShapeArray[dtype], dtype]]
419
413
  # res.range will be wrapped with the 2 labeled dimensions later
420
414
  res.range = self._list_of_lists(array.minimum_number_dimensions - len(array.dimensions), res.range)
421
415
 
@@ -433,13 +427,13 @@ class ListOfListsArray(ArrayRangeGenerator):
433
427
 
434
428
  # Wrap inner dimension with labeled dimension
435
429
  # e.g., if dimensions = [{min_card: 3}, {min_card: 2}]
436
- # and res.range = List[Union[AnyShapeArray[dtype], dtype]]
430
+ # and res.range = list[Union[AnyShapeArray[dtype], dtype]]
437
431
  # (min 3 dims, no max dims)
438
432
  # then the final range = conlist(
439
433
  # min_length=3,
440
434
  # item_type=conlist(
441
435
  # min_length=2,
442
- # item_type=List[Union[AnyShapeArray[dtype], dtype]]
436
+ # item_type=list[Union[AnyShapeArray[dtype], dtype]]
443
437
  # )
444
438
  # )
445
439
  for dim in reversed(array.dimensions):
@@ -473,7 +467,7 @@ class NumpydanticArray(ArrayRangeGenerator):
473
467
  return result
474
468
 
475
469
  @staticmethod
476
- def ndarray_annotation(shape: Optional[List[Union[int, str]]] = None, dtype: Optional[str] = None) -> str:
470
+ def ndarray_annotation(shape: Optional[list[Union[int, str]]] = None, dtype: Optional[str] = None) -> str:
477
471
  """
478
472
  Make a stringified :class:`numpydantic.NDArray` annotation for a given shape
479
473
  and dtype.
@@ -1,5 +1,5 @@
1
1
  from pathlib import Path
2
- from typing import List, Optional, Type, TypeVar, Union
2
+ from typing import Optional, TypeVar, Union
3
3
 
4
4
  from linkml.generators.common.build import (
5
5
  BuildResult,
@@ -24,8 +24,8 @@ class PydanticBuildResult(BuildResult):
24
24
  BuildResult parent class for pydantic generator
25
25
  """
26
26
 
27
- imports: Optional[Union[List[Import], Imports]] = None
28
- injected_classes: Optional[List[Union[str, Type]]] = None
27
+ imports: Optional[Union[list[Import], Imports]] = None
28
+ injected_classes: Optional[list[Union[str, type]]] = None
29
29
 
30
30
  def merge(self, other: T) -> T:
31
31
  """
@@ -92,7 +92,7 @@ class RangeResult(PydanticBuildResult, RangeResult_):
92
92
  Returns:
93
93
  :class:`.SlotResult`
94
94
  """
95
- res = super(RangeResult, self).merge(other)
95
+ res = super().merge(other)
96
96
  # Replace with other's annotation
97
97
  res.range = other.range
98
98
  if other.field_extras is not None:
@@ -4,7 +4,7 @@ Classes to inject in generated pydantic models
4
4
 
5
5
  LinkMLMeta = """
6
6
  class LinkMLMeta(RootModel):
7
- root: Dict[str, Any] = {}
7
+ root: dict[str, Any] = {}
8
8
  model_config = ConfigDict(frozen=True)
9
9
 
10
10
  def __getattr__(self, key:str):