linkml 1.8.1__py3-none-any.whl → 1.8.3__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 (78) hide show
  1. linkml/cli/__init__.py +0 -0
  2. linkml/cli/__main__.py +4 -0
  3. linkml/cli/main.py +130 -0
  4. linkml/generators/common/build.py +105 -0
  5. linkml/generators/common/ifabsent_processor.py +286 -0
  6. linkml/generators/common/lifecycle.py +124 -0
  7. linkml/generators/common/template.py +89 -0
  8. linkml/generators/csvgen.py +1 -1
  9. linkml/generators/docgen/slot.md.jinja2 +4 -0
  10. linkml/generators/docgen.py +1 -1
  11. linkml/generators/dotgen.py +1 -1
  12. linkml/generators/erdiagramgen.py +1 -1
  13. linkml/generators/excelgen.py +1 -1
  14. linkml/generators/golanggen.py +1 -1
  15. linkml/generators/golrgen.py +1 -1
  16. linkml/generators/graphqlgen.py +1 -1
  17. linkml/generators/javagen.py +1 -1
  18. linkml/generators/jsonldcontextgen.py +4 -5
  19. linkml/generators/jsonldgen.py +1 -1
  20. linkml/generators/jsonschemagen.py +69 -22
  21. linkml/generators/linkmlgen.py +1 -1
  22. linkml/generators/markdowngen.py +1 -1
  23. linkml/generators/namespacegen.py +1 -1
  24. linkml/generators/oocodegen.py +2 -1
  25. linkml/generators/owlgen.py +1 -1
  26. linkml/generators/plantumlgen.py +1 -1
  27. linkml/generators/prefixmapgen.py +1 -1
  28. linkml/generators/projectgen.py +1 -1
  29. linkml/generators/protogen.py +1 -1
  30. linkml/generators/pydanticgen/__init__.py +8 -3
  31. linkml/generators/pydanticgen/array.py +114 -194
  32. linkml/generators/pydanticgen/build.py +64 -25
  33. linkml/generators/pydanticgen/includes.py +1 -31
  34. linkml/generators/pydanticgen/pydanticgen.py +621 -276
  35. linkml/generators/pydanticgen/template.py +152 -184
  36. linkml/generators/pydanticgen/templates/attribute.py.jinja +9 -7
  37. linkml/generators/pydanticgen/templates/base_model.py.jinja +0 -13
  38. linkml/generators/pydanticgen/templates/class.py.jinja +2 -2
  39. linkml/generators/pydanticgen/templates/footer.py.jinja +2 -10
  40. linkml/generators/pydanticgen/templates/module.py.jinja +2 -2
  41. linkml/generators/pydanticgen/templates/validator.py.jinja +0 -4
  42. linkml/generators/python/__init__.py +1 -0
  43. linkml/generators/python/python_ifabsent_processor.py +92 -0
  44. linkml/generators/pythongen.py +19 -23
  45. linkml/generators/rdfgen.py +1 -1
  46. linkml/generators/shacl/__init__.py +1 -3
  47. linkml/generators/shacl/shacl_data_type.py +1 -1
  48. linkml/generators/shacl/shacl_ifabsent_processor.py +89 -0
  49. linkml/generators/shaclgen.py +11 -5
  50. linkml/generators/shexgen.py +1 -1
  51. linkml/generators/sparqlgen.py +1 -1
  52. linkml/generators/sqlalchemygen.py +1 -1
  53. linkml/generators/sqltablegen.py +1 -1
  54. linkml/generators/sssomgen.py +1 -1
  55. linkml/generators/summarygen.py +1 -1
  56. linkml/generators/terminusdbgen.py +7 -4
  57. linkml/generators/typescriptgen.py +1 -1
  58. linkml/generators/yamlgen.py +1 -1
  59. linkml/generators/yumlgen.py +1 -1
  60. linkml/linter/cli.py +1 -1
  61. linkml/transformers/logical_model_transformer.py +117 -18
  62. linkml/utils/converter.py +1 -1
  63. linkml/utils/execute_tutorial.py +2 -0
  64. linkml/utils/logictools.py +142 -29
  65. linkml/utils/schema_builder.py +7 -6
  66. linkml/utils/schema_fixer.py +1 -1
  67. linkml/utils/sqlutils.py +1 -1
  68. linkml/validator/cli.py +4 -1
  69. linkml/validators/jsonschemavalidator.py +1 -1
  70. linkml/validators/sparqlvalidator.py +1 -1
  71. linkml/workspaces/example_runner.py +1 -1
  72. {linkml-1.8.1.dist-info → linkml-1.8.3.dist-info}/METADATA +2 -2
  73. {linkml-1.8.1.dist-info → linkml-1.8.3.dist-info}/RECORD +76 -68
  74. {linkml-1.8.1.dist-info → linkml-1.8.3.dist-info}/entry_points.txt +1 -1
  75. linkml/generators/shacl/ifabsent_processor.py +0 -59
  76. linkml/utils/ifabsent_functions.py +0 -138
  77. {linkml-1.8.1.dist-info → linkml-1.8.3.dist-info}/LICENSE +0 -0
  78. {linkml-1.8.1.dist-info → linkml-1.8.3.dist-info}/WHEEL +0 -0
@@ -0,0 +1,89 @@
1
+ """
2
+ Base classes for jinja template handling classes.
3
+
4
+ See :mod:`.linkml.generators.pydanticgen.template` for example implementation
5
+ """
6
+
7
+ from copy import copy
8
+ from typing import Any, ClassVar, Dict, List, Optional, Union
9
+
10
+ from jinja2 import Environment
11
+ from pydantic import BaseModel
12
+
13
+
14
+ class TemplateModel(BaseModel):
15
+ """
16
+ Metaclass to render model results with jinja templates.
17
+
18
+ Each subclass needs to declare a :class:`typing.ClassVar` for a
19
+ jinja template within the `templates` directory.
20
+
21
+ Templates are written expecting each of the other TemplateModels
22
+ to already be rendered to strings - ie. rather than the ``class.py.jinja``
23
+ template receiving a full :class:`.PydanticAttribute` object or dictionary,
24
+ it receives it having already been rendered to a string. See the :meth:`.render` method.
25
+ """
26
+
27
+ template: ClassVar[str]
28
+ _environment: ClassVar[Environment]
29
+
30
+ meta_exclude: ClassVar[List[str]] = None
31
+
32
+ def render(self, environment: Optional[Environment] = None, **kwargs) -> str:
33
+ """
34
+ Recursively render a template model to a string.
35
+
36
+ For each field in the model, recurse through, rendering each :class:`.TemplateModel`
37
+ using the template set in :attr:`.TemplateModel.template` , but preserving the structure
38
+ of lists and dictionaries. Regular :class:`.BaseModel` s are rendered to dictionaries.
39
+ Any other value is passed through unchanged.
40
+
41
+ Args:
42
+ environment (:class:`jinja2.Environment`): Template environment - see :meth:`.environment`
43
+ """
44
+ if environment is None:
45
+ environment = TemplateModel.environment()
46
+
47
+ fields = {**self.model_fields, **self.model_computed_fields}
48
+
49
+ data = {k: _render(getattr(self, k, None), environment) for k in fields}
50
+ template = environment.get_template(self.template)
51
+ rendered = template.render(**data)
52
+ return rendered
53
+
54
+ @classmethod
55
+ def environment(cls) -> Environment:
56
+ """
57
+ Default environment for Template models.
58
+ uses a :class:`jinja2.PackageLoader` for the templates directory within this module
59
+ with the ``trim_blocks`` and ``lstrip_blocks`` parameters set to ``True`` so that the
60
+ default templates could be written in a more readable way.
61
+ """
62
+ return copy(cls._environment)
63
+
64
+ @classmethod
65
+ def exclude_from_meta(cls: "TemplateModel") -> List[str]:
66
+ """
67
+ Attributes in the source definition to exclude from linkml_meta
68
+ """
69
+ ret = [*cls.model_fields.keys()]
70
+ if cls.meta_exclude is not None:
71
+ ret = ret + cls.meta_exclude
72
+ return ret
73
+
74
+
75
+ def _render(
76
+ item: Union[TemplateModel, Any, List[Union[Any, TemplateModel]], Dict[str, Union[Any, TemplateModel]]],
77
+ environment: Environment,
78
+ ) -> Union[str, List[str], Dict[str, str]]:
79
+ if isinstance(item, TemplateModel):
80
+ return item.render(environment)
81
+ elif isinstance(item, list):
82
+ return [_render(i, environment) for i in item]
83
+ elif isinstance(item, dict):
84
+ return {k: _render(v, environment) for k, v in item.items()}
85
+ elif isinstance(item, BaseModel):
86
+ fields = item.model_fields
87
+ return {k: _render(getattr(item, k, None), environment) for k in fields.keys()}
88
+ else:
89
+ return item
@@ -95,7 +95,7 @@ class CsvGenerator(Generator):
95
95
 
96
96
 
97
97
  @shared_arguments(CsvGenerator)
98
- @click.command()
98
+ @click.command(name="csv")
99
99
  @click.version_option(__version__, "-V", "--version")
100
100
  @click.option("--root", "-r", multiple=True, help="Class(es) to transform")
101
101
  def cli(yamlfile, root=None, **args):
@@ -34,6 +34,10 @@ _{{ element_description_line }}_
34
34
  {% endfor %}
35
35
  {% endif %}
36
36
 
37
+ {% if element.abstract %}
38
+ * __NOTE__: this is an abstract slot and should not be populated directly
39
+ {% endif %}
40
+
37
41
  URI: {{ gen.uri_link(element) }}
38
42
 
39
43
 
@@ -978,7 +978,7 @@ YAML, and including it when necessary but not by default (e.g. in documentation
978
978
  """,
979
979
  )
980
980
  @click.version_option(__version__, "-V", "--version")
981
- @click.command()
981
+ @click.command(name="doc")
982
982
  def cli(
983
983
  yamlfile,
984
984
  directory,
@@ -136,7 +136,7 @@ class DotGenerator(Generator):
136
136
 
137
137
 
138
138
  @shared_arguments(DotGenerator)
139
- @click.command()
139
+ @click.command(name="graphviz")
140
140
  @click.option(
141
141
  "--directory",
142
142
  "-d",
@@ -312,7 +312,7 @@ class ERDiagramGenerator(Generator):
312
312
  @click.option("--classes", "-c", multiple=True, help="List of classes to serialize")
313
313
  @click.option("--include-upstream", is_flag=True, help="Include upstream classes")
314
314
  @click.version_option(__version__, "-V", "--version")
315
- @click.command()
315
+ @click.command(name="erdiagram")
316
316
  def cli(
317
317
  yamlfile,
318
318
  classes: List[str],
@@ -167,7 +167,7 @@ class ExcelGenerator(Generator):
167
167
 
168
168
 
169
169
  @shared_arguments(ExcelGenerator)
170
- @click.command()
170
+ @click.command(name="excel")
171
171
  @click.option(
172
172
  "--split-workbook-by-class",
173
173
  is_flag=True,
@@ -189,7 +189,7 @@ class GolangGenerator(Generator):
189
189
 
190
190
  @shared_arguments(GolangGenerator)
191
191
  @click.version_option(__version__, "-V", "--version")
192
- @click.command()
192
+ @click.command(name="golang")
193
193
  def cli(yamlfile, **args):
194
194
  """Generate Golang types
195
195
 
@@ -101,7 +101,7 @@ class GolrSchemaGenerator(Generator):
101
101
 
102
102
 
103
103
  @shared_arguments(GolrSchemaGenerator)
104
- @click.command()
104
+ @click.command(name="golr-views")
105
105
  @click.option("--dir", "-d", default="golr-views", show_default=True, help="Output directory")
106
106
  @click.version_option(__version__, "-V", "--version")
107
107
  def cli(yamlfile, dir=None, **args):
@@ -52,7 +52,7 @@ class GraphqlGenerator(Generator):
52
52
 
53
53
 
54
54
  @shared_arguments(GraphqlGenerator)
55
- @click.command()
55
+ @click.command(name="graphql")
56
56
  @click.version_option(__version__, "-V", "--version")
57
57
  def cli(yamlfile, **args):
58
58
  """Generate graphql representation of a LinkML model"""
@@ -146,7 +146,7 @@ class JavaGenerator(OOCodeGenerator):
146
146
  help="Optional Java 17 record implementation",
147
147
  )
148
148
  @click.version_option(__version__, "-V", "--version")
149
- @click.command()
149
+ @click.command(name="java")
150
150
  def cli(
151
151
  yamlfile,
152
152
  output_directory=None,
@@ -18,11 +18,9 @@ from rdflib import SKOS, XSD, Namespace
18
18
  from linkml._version import __version__
19
19
  from linkml.utils.generator import Generator, shared_arguments
20
20
 
21
- URI_RANGES = (XSD.anyURI, SHEX.nonliteral, SHEX.bnode, SHEX.iri)
22
-
21
+ URI_RANGES = (SHEX.nonliteral, SHEX.bnode, SHEX.iri)
23
22
 
24
23
  ENUM_CONTEXT = {
25
- "@vocab": "@null",
26
24
  "text": "skos:notation",
27
25
  "description": "skos:prefLabel",
28
26
  "meaning": "@id",
@@ -99,7 +97,7 @@ class ContextGenerator(Generator):
99
97
  comments.generation_date = self.schema.generation_date
100
98
  comments.source = self.schema.source_file
101
99
  context.comments = comments
102
- context_content = {}
100
+ context_content = {"xsd": "http://www.w3.org/2001/XMLSchema#"}
103
101
  if base:
104
102
  base = str(base)
105
103
  if "://" not in base:
@@ -193,6 +191,7 @@ class ContextGenerator(Generator):
193
191
  elif not uri_prefix or is_default_namespace:
194
192
  definition["@id"] = uri_suffix
195
193
  else:
194
+
196
195
  definition["@id"] = (uri_prefix + ":" + uri_suffix) if uri_prefix else uri
197
196
 
198
197
  if uri_prefix and not is_default_namespace:
@@ -203,7 +202,7 @@ class ContextGenerator(Generator):
203
202
 
204
203
 
205
204
  @shared_arguments(ContextGenerator)
206
- @click.command()
205
+ @click.command(name="jsonld-context")
207
206
  @click.option("--base", help="Base URI for model")
208
207
  @click.option(
209
208
  "--prefixes/--no-prefixes",
@@ -192,7 +192,7 @@ class JSONLDGenerator(Generator):
192
192
 
193
193
 
194
194
  @shared_arguments(JSONLDGenerator)
195
- @click.command()
195
+ @click.command(name="jsonld")
196
196
  @click.option(
197
197
  "--context",
198
198
  multiple=True,
@@ -126,7 +126,13 @@ class JsonSchema(dict):
126
126
 
127
127
  @property
128
128
  def is_array(self):
129
- return self.get("type") == "array"
129
+ typ = self.get("type", False)
130
+ if isinstance(typ, str):
131
+ return typ == "array"
132
+ elif isinstance(typ, list):
133
+ return "array" in typ
134
+ else:
135
+ return False
130
136
 
131
137
  @property
132
138
  def is_object(self):
@@ -136,7 +142,7 @@ class JsonSchema(dict):
136
142
  return json.dumps(self, **kwargs)
137
143
 
138
144
  @classmethod
139
- def ref_for(cls, class_name: Union[str, List[str]], identifier_optional: bool = False):
145
+ def ref_for(cls, class_name: Union[str, List[str]], identifier_optional: bool = False, required: bool = True):
140
146
  def _ref(class_name):
141
147
  def_name = camelcase(class_name)
142
148
  def_suffix = cls.OPTIONAL_IDENTIFIER_SUFFIX if identifier_optional else ""
@@ -144,15 +150,27 @@ class JsonSchema(dict):
144
150
 
145
151
  if isinstance(class_name, list):
146
152
  if len(class_name) == 1:
147
- return _ref(class_name[0])
153
+ ref = _ref(class_name[0])
148
154
  else:
149
- return JsonSchema({"anyOf": [_ref(name) for name in class_name]})
155
+ ref = JsonSchema({"anyOf": [_ref(name) for name in class_name]})
150
156
  else:
151
- return _ref(class_name)
157
+ ref = _ref(class_name)
158
+
159
+ if not required:
160
+ if "anyOf" in ref:
161
+ ref["anyOf"].append({"type": "null"})
162
+ else:
163
+ ref = JsonSchema({"anyOf": [ref, {"type": "null"}]})
164
+ return ref
152
165
 
153
166
  @classmethod
154
- def array_of(cls, subschema: "JsonSchema") -> "JsonSchema":
155
- schema = {"type": "array", "items": subschema}
167
+ def array_of(cls, subschema: "JsonSchema", required: bool = True) -> "JsonSchema":
168
+ if required:
169
+ typ = "array"
170
+ else:
171
+ typ = ["array", "null"]
172
+
173
+ schema = {"type": typ, "items": subschema}
156
174
 
157
175
  return JsonSchema(schema)
158
176
 
@@ -199,6 +217,9 @@ class JsonSchemaGenerator(Generator):
199
217
 
200
218
  top_level_schema: JsonSchema = None
201
219
 
220
+ include_null: bool = True
221
+ """Whether to include a "null" type in optional slots"""
222
+
202
223
  def __post_init__(self):
203
224
  if self.topClass:
204
225
  logging.warning("topClass is deprecated - use top_class")
@@ -315,7 +336,7 @@ class JsonSchemaGenerator(Generator):
315
336
 
316
337
  subschema = JsonSchema()
317
338
  for slot in cls.slot_conditions.values():
318
- prop = self.get_subschema_for_slot(slot, omit_type=True)
339
+ prop = self.get_subschema_for_slot(slot, omit_type=True, include_null=False)
319
340
  value_required = False
320
341
  value_disallowed = False
321
342
  if slot.value_presence:
@@ -433,11 +454,17 @@ class JsonSchemaGenerator(Generator):
433
454
  constraints.add_keyword("maximum", slot.maximum_value)
434
455
  constraints.add_keyword("const", slot.equals_string)
435
456
  constraints.add_keyword("const", slot.equals_number)
457
+ if slot.equals_string_in:
458
+ constraints.add_keyword("enum", slot.equals_string_in)
436
459
  return constraints
437
460
 
438
461
  def get_subschema_for_slot(
439
- self, slot: Union[SlotDefinition, AnonymousSlotExpression], omit_type: bool = False
462
+ self, slot: Union[SlotDefinition, AnonymousSlotExpression], omit_type: bool = False, include_null: bool = True
440
463
  ) -> JsonSchema:
464
+ """
465
+ Args:
466
+ include_null: Include ``type: null`` when generating ranges that are not required
467
+ """
441
468
  prop = JsonSchema()
442
469
  if isinstance(slot, SlotDefinition) and slot.array:
443
470
  # TODO: this is currently too lax, in that it will validate ANY array.
@@ -448,9 +475,10 @@ class JsonSchemaGenerator(Generator):
448
475
  "additionalProperties": True,
449
476
  }
450
477
  )
451
- return JsonSchema.array_of(prop)
478
+ return JsonSchema.array_of(prop, required=slot.required)
452
479
  slot_is_multivalued = "multivalued" in slot and slot.multivalued
453
480
  slot_is_inlined = self.schemaview.is_inlined(slot)
481
+ slot_is_boolean = any([slot.any_of, slot.all_of, slot.exactly_one_of, slot.none_of])
454
482
  if not omit_type:
455
483
  typ, fmt, reference = self.get_type_info_for_slot_subschema(slot)
456
484
  if slot_is_inlined:
@@ -471,7 +499,9 @@ class JsonSchemaGenerator(Generator):
471
499
  # If the range can be collected as a simple dict, then we can also accept the value
472
500
  # of that simple dict directly.
473
501
  if range_simple_dict_value_slot is not None:
474
- additionalProps.append(self.get_subschema_for_slot(range_simple_dict_value_slot))
502
+ additionalProps.append(
503
+ self.get_subschema_for_slot(range_simple_dict_value_slot, include_null=False)
504
+ )
475
505
 
476
506
  # If the range has no required slots, then null is acceptable
477
507
  if len(range_required_slots) == 0:
@@ -483,12 +513,17 @@ class JsonSchemaGenerator(Generator):
483
513
  additionalProps = additionalProps[0]
484
514
  else:
485
515
  additionalProps = JsonSchema({"anyOf": additionalProps})
486
- prop = JsonSchema({"type": "object", "additionalProperties": additionalProps})
516
+ if slot.required or not include_null:
517
+ typ = "object"
518
+ else:
519
+ typ = ["object", "null"]
520
+ prop = JsonSchema({"type": typ, "additionalProperties": additionalProps})
487
521
  self.top_level_schema.add_lax_def(reference, self.aliased_slot_name(range_id_slot))
488
522
  else:
489
- prop = JsonSchema.array_of(JsonSchema.ref_for(reference))
523
+ prop = JsonSchema.array_of(JsonSchema.ref_for(reference), required=slot.required)
490
524
  else:
491
- prop = JsonSchema.ref_for(reference)
525
+ prop = JsonSchema.ref_for(reference, required=slot.required or not include_null)
526
+
492
527
  else:
493
528
  if reference is not None:
494
529
  prop = JsonSchema.ref_for(reference)
@@ -498,7 +533,12 @@ class JsonSchemaGenerator(Generator):
498
533
  prop = JsonSchema({"type": typ, "format": fmt})
499
534
 
500
535
  if slot_is_multivalued:
501
- prop = JsonSchema.array_of(prop)
536
+ prop = JsonSchema.array_of(prop, required=slot.required)
537
+ else:
538
+ # handle optionals - bools like any_of, etc. below as they call this method recursively
539
+ if not slot.required and not slot_is_boolean and include_null:
540
+ if "type" in prop:
541
+ prop["type"] = [prop["type"], "null"]
502
542
 
503
543
  prop.add_keyword("description", slot.description)
504
544
  if self.title_from == "title" and slot.title:
@@ -524,22 +564,29 @@ class JsonSchemaGenerator(Generator):
524
564
 
525
565
  bool_subschema = JsonSchema()
526
566
  if slot.any_of is not None and len(slot.any_of) > 0:
527
- bool_subschema["anyOf"] = [self.get_subschema_for_slot(s) for s in slot.any_of]
567
+ bool_subschema["anyOf"] = [self.get_subschema_for_slot(s, include_null=False) for s in slot.any_of]
568
+ if not slot.required and not prop.is_array and include_null:
569
+ bool_subschema["anyOf"].append({"type": "null"})
528
570
 
529
571
  if slot.all_of is not None and len(slot.all_of) > 0:
530
- bool_subschema["allOf"] = [self.get_subschema_for_slot(s) for s in slot.all_of]
572
+ bool_subschema["allOf"] = [self.get_subschema_for_slot(s, include_null=False) for s in slot.all_of]
531
573
 
532
574
  if slot.exactly_one_of is not None and len(slot.exactly_one_of) > 0:
533
- bool_subschema["oneOf"] = [self.get_subschema_for_slot(s) for s in slot.exactly_one_of]
575
+ bool_subschema["oneOf"] = [self.get_subschema_for_slot(s, include_null=False) for s in slot.exactly_one_of]
534
576
 
535
577
  if slot.none_of is not None and len(slot.none_of) > 0:
536
- bool_subschema["not"] = {"anyOf": [self.get_subschema_for_slot(s) for s in slot.none_of]}
578
+ bool_subschema["not"] = {
579
+ "anyOf": [self.get_subschema_for_slot(s, include_null=False) for s in slot.none_of]
580
+ }
537
581
 
538
582
  if bool_subschema:
539
583
  if prop.is_array:
540
584
  if "items" not in prop:
541
585
  prop["items"] = {}
542
- prop["type"] = "array"
586
+ if slot.required or not include_null:
587
+ prop["type"] = "array"
588
+ else:
589
+ prop["type"] = ["array", "null"]
543
590
  prop["items"].update(bool_subschema)
544
591
  else:
545
592
  prop.update(bool_subschema)
@@ -554,7 +601,7 @@ class JsonSchemaGenerator(Generator):
554
601
  value_disallowed = slot.value_presence == PresenceEnum(PresenceEnum.ABSENT)
555
602
 
556
603
  aliased_slot_name = self.aliased_slot_name(slot)
557
- prop = self.get_subschema_for_slot(slot)
604
+ prop = self.get_subschema_for_slot(slot, include_null=self.include_null)
558
605
  subschema.add_property(
559
606
  aliased_slot_name, prop, value_required=value_required, value_disallowed=value_disallowed
560
607
  )
@@ -625,7 +672,7 @@ class JsonSchemaGenerator(Generator):
625
672
 
626
673
 
627
674
  @shared_arguments(JsonSchemaGenerator)
628
- @click.command()
675
+ @click.command(name="json-schema")
629
676
  @click.option(
630
677
  "-i",
631
678
  "--inline",
@@ -97,7 +97,7 @@ class LinkmlGenerator(Generator):
97
97
  help="Name of JSON or YAML file to be created",
98
98
  )
99
99
  @click.version_option(__version__, "-V", "--version")
100
- @click.command()
100
+ @click.command(name="linkml")
101
101
  def cli(
102
102
  yamlfile,
103
103
  materialize_attributes: bool,
@@ -789,7 +789,7 @@ def pad_heading(text: str) -> str:
789
789
 
790
790
 
791
791
  @shared_arguments(MarkdownGenerator)
792
- @click.command()
792
+ @click.command(name="markdown")
793
793
  @click.option("--dir", "-d", required=True, help="Output directory")
794
794
  @click.option("--classes", "-c", multiple=True, help="Class(es) to emit")
795
795
  @click.option("--map-fields", "-M", multiple=True, help="Map metamodel fields, e.g. slot=field")
@@ -195,7 +195,7 @@ def curie(identifier) -> str:
195
195
 
196
196
  @shared_arguments(NamespaceGenerator)
197
197
  @click.version_option(__version__, "-V", "--version")
198
- @click.command()
198
+ @click.command(name="namespaces")
199
199
  def cli(yamlfile, **args):
200
200
  """Generate a namespace manager for all of the prefixes represented in a LinkML model"""
201
201
  print(NamespaceGenerator(yamlfile, **args).serialize(**args))
@@ -76,6 +76,7 @@ class OOCodeGenerator(Generator):
76
76
  visit_all_class_slots = False
77
77
  uses_schemaloader = False
78
78
  requires_metamodel = False
79
+ schemaview: SchemaView = None
79
80
 
80
81
  template_file: str = None
81
82
  """Path to template"""
@@ -84,7 +85,7 @@ class OOCodeGenerator(Generator):
84
85
 
85
86
  def __post_init__(self):
86
87
  # TODO: consider moving up a level
87
- self.schemaview = SchemaView(self.schema)
88
+ self.schemaview: SchemaView = SchemaView(self.schema)
88
89
  super().__post_init__()
89
90
 
90
91
  @abc.abstractmethod
@@ -1271,7 +1271,7 @@ class OwlSchemaGenerator(Generator):
1271
1271
 
1272
1272
 
1273
1273
  @shared_arguments(OwlSchemaGenerator)
1274
- @click.command()
1274
+ @click.command(name="owl")
1275
1275
  @click.option("-o", "--output", help="Output file name")
1276
1276
  @click.option(
1277
1277
  "--metadata-profile",
@@ -339,7 +339,7 @@ class PlantumlGenerator(Generator):
339
339
 
340
340
 
341
341
  @shared_arguments(PlantumlGenerator)
342
- @click.command()
342
+ @click.command(name="plantuml")
343
343
  @click.option("--classes", "-c", multiple=True, help="Class(es) to emit")
344
344
  @click.option(
345
345
  "--directory",
@@ -112,7 +112,7 @@ class PrefixGenerator(Generator):
112
112
 
113
113
 
114
114
  @shared_arguments(PrefixGenerator)
115
- @click.command()
115
+ @click.command(name="prefix-map")
116
116
  @click.option("--base", help="Base URI for model")
117
117
  @click.option("--output", "-o", help="Output file path")
118
118
  @click.version_option(__version__, "-V", "--version")
@@ -159,7 +159,7 @@ class ProjectGenerator:
159
159
  gen.serialize(**serialize_args)
160
160
 
161
161
 
162
- @click.command()
162
+ @click.command(name="project")
163
163
  @click.option(
164
164
  "--dir",
165
165
  "-d",
@@ -69,7 +69,7 @@ class ProtoGenerator(Generator):
69
69
 
70
70
  @shared_arguments(ProtoGenerator)
71
71
  @click.version_option(__version__, "-V", "--version")
72
- @click.command()
72
+ @click.command(name="proto")
73
73
  def cli(yamlfile, **args):
74
74
  """Generate proto representation of LinkML model"""
75
75
  print(ProtoGenerator(yamlfile, **args).serialize(**args))
@@ -1,4 +1,9 @@
1
- from linkml.generators.pydanticgen.pydanticgen import DEFAULT_IMPORTS, MetadataMode, PydanticGenerator, cli
1
+ from linkml.generators.pydanticgen.pydanticgen import (
2
+ DEFAULT_IMPORTS,
3
+ MetadataMode,
4
+ PydanticGenerator,
5
+ cli,
6
+ )
2
7
  from linkml.generators.pydanticgen.template import (
3
8
  ConditionalImport,
4
9
  Import,
@@ -8,8 +13,8 @@ from linkml.generators.pydanticgen.template import (
8
13
  PydanticClass,
9
14
  PydanticEnum,
10
15
  PydanticModule,
16
+ PydanticTemplateModel,
11
17
  PydanticValidator,
12
- TemplateModel,
13
18
  )
14
19
 
15
20
  __all__ = [
@@ -26,5 +31,5 @@ __all__ = [
26
31
  "PydanticGenerator",
27
32
  "PydanticModule",
28
33
  "PydanticValidator",
29
- "TemplateModel",
34
+ "PydanticTemplateModel",
30
35
  ]