linkml 1.6.4__py3-none-any.whl → 1.6.5__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.
- linkml/generators/excelgen.py +75 -73
- linkml/generators/pydanticgen.py +42 -1
- linkml/generators/pythongen.py +9 -2
- linkml/utils/generator.py +25 -8
- linkml/utils/schemaloader.py +1 -1
- {linkml-1.6.4.dist-info → linkml-1.6.5.dist-info}/METADATA +1 -1
- {linkml-1.6.4.dist-info → linkml-1.6.5.dist-info}/RECORD +10 -10
- {linkml-1.6.4.dist-info → linkml-1.6.5.dist-info}/LICENSE +0 -0
- {linkml-1.6.4.dist-info → linkml-1.6.5.dist-info}/WHEEL +0 -0
- {linkml-1.6.4.dist-info → linkml-1.6.5.dist-info}/entry_points.txt +0 -0
linkml/generators/excelgen.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import logging
|
2
|
-
import
|
3
|
-
from
|
2
|
+
from dataclasses import dataclass, field
|
3
|
+
from pathlib import Path
|
4
4
|
from typing import List
|
5
5
|
|
6
6
|
import click
|
@@ -8,78 +8,80 @@ from linkml_runtime.utils.schemaview import SchemaView
|
|
8
8
|
from openpyxl import Workbook
|
9
9
|
from openpyxl.utils import get_column_letter
|
10
10
|
from openpyxl.worksheet.datavalidation import DataValidation
|
11
|
-
from openpyxl.worksheet.worksheet import Worksheet
|
12
11
|
|
13
12
|
from linkml._version import __version__
|
14
13
|
from linkml.utils.generator import Generator, shared_arguments
|
15
|
-
from linkml.utils.helpers import convert_to_snake_case
|
16
14
|
|
17
15
|
|
18
16
|
@dataclass
|
19
17
|
class ExcelGenerator(Generator):
|
20
18
|
# ClassVars
|
21
|
-
generatorname =
|
19
|
+
generatorname = Path(__file__).name
|
22
20
|
generatorversion = "0.1.1"
|
23
21
|
valid_formats = ["xlsx"]
|
24
22
|
uses_schemaloader = False
|
25
23
|
requires_metamodel = False
|
26
24
|
|
25
|
+
split_workbook_by_class: bool = field(default_factory=lambda: False)
|
26
|
+
|
27
27
|
def __post_init__(self) -> None:
|
28
28
|
super().__post_init__()
|
29
29
|
self.logger = logging.getLogger(__name__)
|
30
30
|
self.schemaview = SchemaView(self.schema)
|
31
31
|
|
32
|
-
def create_workbook(self,
|
32
|
+
def create_workbook(self, workbook_path: Path) -> Workbook:
|
33
33
|
"""
|
34
34
|
Creates an Excel workbook using the openpyxl library and returns it.
|
35
35
|
|
36
|
-
:param
|
36
|
+
:param workbook_path: Path of the workbook to be created.
|
37
37
|
:return: An openpyxl Workbook object representing the newly created workbook.
|
38
38
|
"""
|
39
39
|
workbook = Workbook()
|
40
|
-
workbook.
|
40
|
+
workbook.save(workbook_path)
|
41
41
|
return workbook
|
42
42
|
|
43
|
-
def
|
44
|
-
"""
|
45
|
-
Returns the name of the given workbook.
|
46
|
-
|
47
|
-
:param workbook: The workbook whose name should be returned.
|
48
|
-
:return: Name of the workbook.
|
49
|
-
"""
|
50
|
-
return workbook.title
|
51
|
-
|
52
|
-
def remove_worksheet_by_name(self, workbook: Workbook, worksheet_name: str) -> None:
|
53
|
-
"""
|
54
|
-
Remove worksheet from workbook by name.
|
55
|
-
"""
|
56
|
-
worksheet = workbook[worksheet_name]
|
57
|
-
workbook.remove(worksheet)
|
58
|
-
|
59
|
-
def create_worksheet(self, workbook: Workbook, worksheet_name: str) -> Worksheet:
|
43
|
+
def create_workbook_and_worksheets(self, output_path: Path, classes: List[str]) -> None:
|
60
44
|
"""
|
61
|
-
Creates
|
45
|
+
Creates a workbook with worksheets for each class.
|
62
46
|
|
63
|
-
:param
|
64
|
-
:param
|
47
|
+
:param output_path: The path where the workbook should be created.
|
48
|
+
:param classes: List of class names for which worksheets should be created.
|
65
49
|
"""
|
66
|
-
|
67
|
-
|
68
|
-
|
50
|
+
workbook = self.create_workbook(output_path)
|
51
|
+
workbook.remove(workbook.active)
|
52
|
+
sv = self.schemaview
|
69
53
|
|
70
|
-
|
54
|
+
for cls_name in classes:
|
55
|
+
cls = sv.get_class(class_name=cls_name, imports=self.mergeimports)
|
56
|
+
if not cls.mixin and not cls.abstract:
|
57
|
+
workbook.create_sheet(cls_name)
|
71
58
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
59
|
+
# Add columns to the worksheet for the current class
|
60
|
+
slots = [s.name for s in sv.class_induced_slots(cls_name, self.mergeimports)]
|
61
|
+
self.add_columns_to_worksheet(workbook, cls_name, slots)
|
62
|
+
workbook.save(output_path)
|
76
63
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
64
|
+
# Add enum validation for columns with enum types
|
65
|
+
enum_list = list(sv.all_enums(imports=self.mergeimports).keys())
|
66
|
+
for s in sv.class_induced_slots(cls_name, self.mergeimports):
|
67
|
+
if s.range in enum_list:
|
68
|
+
pv_list = list(sv.get_enum(s.range).permissible_values.keys())
|
69
|
+
|
70
|
+
# Check if the total length of permissible values is <= 255 characters
|
71
|
+
enum_length = sum(len(value) for value in pv_list)
|
72
|
+
if enum_length <= 255:
|
73
|
+
self.column_enum_validation(workbook, cls_name, s.name, pv_list)
|
74
|
+
else:
|
75
|
+
self.logger.warning(
|
76
|
+
f"'{s.range}' has permissible values with total "
|
77
|
+
"length > 255 characters. Dropdowns may not work properly "
|
78
|
+
f"in {output_path}"
|
79
|
+
)
|
80
|
+
workbook.save(output_path)
|
81
|
+
|
82
|
+
workbook.save(output_path)
|
83
|
+
if self.split_workbook_by_class:
|
84
|
+
self.logger.info(f"The Excel workbooks have been written to {output_path}")
|
83
85
|
|
84
86
|
def add_columns_to_worksheet(self, workbook: Workbook, worksheet_name: str, sheet_headings: List[str]) -> None:
|
85
87
|
"""
|
@@ -96,10 +98,6 @@ class ExcelGenerator(Generator):
|
|
96
98
|
for i, heading in enumerate(sheet_headings):
|
97
99
|
worksheet.cell(row=1, column=i + 1, value=heading)
|
98
100
|
|
99
|
-
# Save the changes to the workbook
|
100
|
-
workbook_name = self.get_workbook_name(workbook)
|
101
|
-
workbook.save(workbook_name)
|
102
|
-
|
103
101
|
def column_enum_validation(
|
104
102
|
self,
|
105
103
|
workbook: Workbook,
|
@@ -129,48 +127,52 @@ class ExcelGenerator(Generator):
|
|
129
127
|
|
130
128
|
dv.add(f"{column_letter}2:{column_letter}1048576")
|
131
129
|
|
132
|
-
workbook_name = self.get_workbook_name(workbook)
|
133
|
-
workbook.save(workbook_name)
|
134
|
-
|
135
130
|
def serialize(self, **kwargs) -> str:
|
136
|
-
|
137
|
-
|
138
|
-
|
131
|
+
sv = self.schemaview
|
132
|
+
classes_to_process = [
|
133
|
+
cls_name
|
134
|
+
for cls_name, cls in sv.all_classes(imports=self.mergeimports).items()
|
135
|
+
if not cls.mixin and not cls.abstract
|
136
|
+
]
|
139
137
|
|
140
|
-
|
141
|
-
|
142
|
-
|
138
|
+
if self.split_workbook_by_class:
|
139
|
+
output_path = Path(self.schema.name + "_worksheets") if not self.output else Path(self.output)
|
140
|
+
output_path = output_path.absolute()
|
143
141
|
|
144
|
-
|
145
|
-
|
146
|
-
if not cls.mixin and not cls.abstract:
|
147
|
-
slots = [s.name for s in sv.class_induced_slots(cls_name, imports=self.mergeimports)]
|
148
|
-
self.add_columns_to_worksheet(workbook, cls_name, slots)
|
142
|
+
if not output_path.is_dir():
|
143
|
+
output_path.mkdir(parents=True, exist_ok=True)
|
149
144
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
for
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
145
|
+
for cls_name in classes_to_process:
|
146
|
+
cls_output_path = output_path.joinpath(f"{cls_name}.xlsx")
|
147
|
+
self.create_workbook_and_worksheets(cls_output_path, [cls_name])
|
148
|
+
self.logger.info(f"The Excel workbook for class '{cls_name}' has been written to {cls_output_path}")
|
149
|
+
else:
|
150
|
+
output_path = Path(self.schema.name + ".xlsx") if not self.output else Path(self.output)
|
151
|
+
output_path = output_path.absolute()
|
152
|
+
|
153
|
+
self.create_workbook_and_worksheets(output_path, classes_to_process)
|
154
|
+
|
155
|
+
self.logger.info(f"The Excel workbook has been written to {output_path}")
|
160
156
|
|
161
157
|
|
162
158
|
@shared_arguments(ExcelGenerator)
|
163
159
|
@click.command()
|
160
|
+
@click.option(
|
161
|
+
"--split-workbook-by-class",
|
162
|
+
is_flag=True,
|
163
|
+
default=False,
|
164
|
+
help="""Split model into separate Excel workbooks/files, one for each class""",
|
165
|
+
)
|
164
166
|
@click.option(
|
165
167
|
"-o",
|
166
168
|
"--output",
|
167
169
|
type=click.Path(),
|
168
|
-
help="""Name of Excel spreadsheet to be created""",
|
170
|
+
help="""Name of Excel spreadsheet to be created, or name of directory to create split workbooks in""",
|
169
171
|
)
|
170
172
|
@click.version_option(__version__, "-V", "--version")
|
171
|
-
def cli(yamlfile, **kwargs):
|
173
|
+
def cli(yamlfile, split_workbook_by_class, **kwargs):
|
172
174
|
"""Generate Excel representation of a LinkML model"""
|
173
|
-
ExcelGenerator(yamlfile, **kwargs).serialize(**kwargs)
|
175
|
+
ExcelGenerator(yamlfile, split_workbook_by_class=split_workbook_by_class, **kwargs).serialize(**kwargs)
|
174
176
|
|
175
177
|
|
176
178
|
if __name__ == "__main__":
|
linkml/generators/pydanticgen.py
CHANGED
@@ -108,7 +108,46 @@ class {{ e.name }}(str{% if e['values'] %}, Enum{% endif %}):
|
|
108
108
|
{% endfor %}
|
109
109
|
"""
|
110
110
|
### CLASSES ###
|
111
|
-
|
111
|
+
if pydantic_ver == "1":
|
112
|
+
template += """
|
113
|
+
{%- for c in schema.classes.values() %}
|
114
|
+
class {{ c.name }}
|
115
|
+
{%- if class_isa_plus_mixins[c.name] -%}
|
116
|
+
({{class_isa_plus_mixins[c.name]|join(', ')}})
|
117
|
+
{%- else -%}
|
118
|
+
(ConfiguredBaseModel)
|
119
|
+
{%- endif -%}
|
120
|
+
:
|
121
|
+
{% if c.description -%}
|
122
|
+
\"\"\"
|
123
|
+
{{ c.description }}
|
124
|
+
\"\"\"
|
125
|
+
{%- endif %}
|
126
|
+
{% for attr in c.attributes.values() if c.attributes -%}
|
127
|
+
{{attr.name}}: {{ attr.annotations['python_range'].value }} = Field(
|
128
|
+
{%- if predefined_slot_values[c.name][attr.name] -%}
|
129
|
+
{{ predefined_slot_values[c.name][attr.name] }}
|
130
|
+
{%- elif (attr.required or attr.identifier or attr.key) -%}
|
131
|
+
...
|
132
|
+
{%- else -%}
|
133
|
+
None
|
134
|
+
{%- endif -%}
|
135
|
+
{%- if attr.title != None %}, title="{{attr.title}}"{% endif -%}
|
136
|
+
{%- if attr.description %}, description=\"\"\"{{attr.description}}\"\"\"{% endif -%}
|
137
|
+
{%- if attr.pattern %}, regex=\"{{attr.pattern}}\"{% endif -%}
|
138
|
+
{%- if attr.equals_number != None %}, le={{attr.equals_number}}, ge={{attr.equals_number}}
|
139
|
+
{%- else -%}
|
140
|
+
{%- if attr.minimum_value != None %}, ge={{attr.minimum_value}}{% endif -%}
|
141
|
+
{%- if attr.maximum_value != None %}, le={{attr.maximum_value}}{% endif -%}
|
142
|
+
{%- endif -%}
|
143
|
+
)
|
144
|
+
{% else -%}
|
145
|
+
None
|
146
|
+
{% endfor %}
|
147
|
+
{% endfor %}
|
148
|
+
"""
|
149
|
+
elif pydantic_ver == "2":
|
150
|
+
template += """
|
112
151
|
{%- for c in schema.classes.values() %}
|
113
152
|
class {{ c.name }}
|
114
153
|
{%- if class_isa_plus_mixins[c.name] -%}
|
@@ -133,6 +172,7 @@ class {{ c.name }}
|
|
133
172
|
{%- endif -%}
|
134
173
|
{%- if attr.title != None %}, title="{{attr.title}}"{% endif -%}
|
135
174
|
{%- if attr.description %}, description=\"\"\"{{attr.description}}\"\"\"{% endif -%}
|
175
|
+
{%- if attr.pattern %}, pattern=\"{{attr.pattern}}\"{% endif -%}
|
136
176
|
{%- if attr.equals_number != None %}, le={{attr.equals_number}}, ge={{attr.equals_number}}
|
137
177
|
{%- else -%}
|
138
178
|
{%- if attr.minimum_value != None %}, ge={{attr.minimum_value}}{% endif -%}
|
@@ -144,6 +184,7 @@ class {{ c.name }}
|
|
144
184
|
{% endfor %}
|
145
185
|
{% endfor %}
|
146
186
|
"""
|
187
|
+
|
147
188
|
### FWD REFS / REBUILD MODEL ###
|
148
189
|
if pydantic_ver == "1":
|
149
190
|
template += """
|
linkml/generators/pythongen.py
CHANGED
@@ -509,6 +509,7 @@ dataclasses._init_fn = dataclasses_init_fn_with_kwargs
|
|
509
509
|
initializers += [self.gen_class_variable(cls, slot, False) for slot in slot_variables]
|
510
510
|
|
511
511
|
# Followed by everything else
|
512
|
+
|
512
513
|
slot_variables = self._slot_iter(cls, lambda slot: not slot.required and slot in domain_slots)
|
513
514
|
initializers += [self.gen_class_variable(cls, slot, False) for slot in slot_variables]
|
514
515
|
|
@@ -604,7 +605,7 @@ dataclasses._init_fn = dataclasses_init_fn_with_kwargs
|
|
604
605
|
|
605
606
|
def class_reference_type(self, slot: SlotDefinition, cls: Optional[ClassDefinition]) -> Tuple[str, str, str]:
|
606
607
|
"""
|
607
|
-
Return the type of
|
608
|
+
Return the type of slot referencing a class
|
608
609
|
|
609
610
|
:param slot: slot to be typed
|
610
611
|
:param cls: owning class. Used for generating key references
|
@@ -734,6 +735,12 @@ dataclasses._init_fn = dataclasses_init_fn_with_kwargs
|
|
734
735
|
return typ_name
|
735
736
|
|
736
737
|
def gen_constructor(self, cls: ClassDefinition) -> Optional[str]:
|
738
|
+
"""
|
739
|
+
Generate python constructor for class
|
740
|
+
|
741
|
+
:param cls: class to generate constructor for
|
742
|
+
:return: python constructor
|
743
|
+
"""
|
737
744
|
rlines: List[str] = []
|
738
745
|
designators = [x for x in self.domain_slots(cls) if x.designates_type]
|
739
746
|
if len(designators) > 0:
|
@@ -845,7 +852,7 @@ dataclasses._init_fn = dataclasses_init_fn_with_kwargs
|
|
845
852
|
elif slot.inlined:
|
846
853
|
slot_range_cls = self.schema.classes[slot.range]
|
847
854
|
identifier = self.class_identifier(slot_range_cls)
|
848
|
-
# If we don't have an identifier and we are expecting to be inlined first class elements
|
855
|
+
# If we don't have an identifier, and we are expecting to be inlined first class elements
|
849
856
|
# (inlined_as_list is not True), we will use the first required field as the key.
|
850
857
|
# Note that this may not always work, but the workaround is straight forward -- set inlined_as_list to
|
851
858
|
# True
|
linkml/utils/generator.py
CHANGED
@@ -223,7 +223,7 @@ class Generator(metaclass=abc.ABCMeta):
|
|
223
223
|
else:
|
224
224
|
if isinstance(schema, SchemaDefinition):
|
225
225
|
# schemaloader based methods require schemas to have been created via SchemaLoader,
|
226
|
-
# which prepopulates some fields (e.g definition_url). If the schema has not been processed through the
|
226
|
+
# which prepopulates some fields (e.g. definition_url). If the schema has not been processed through the
|
227
227
|
# loader, then roundtrip
|
228
228
|
if any(c for c in schema.classes.values() if not c.definition_uri):
|
229
229
|
schema = yaml_dumper.dumps(schema)
|
@@ -339,11 +339,11 @@ class Generator(metaclass=abc.ABCMeta):
|
|
339
339
|
|
340
340
|
def visit_class_slot(self, cls: ClassDefinition, aliased_slot_name: str, slot: SlotDefinition) -> None:
|
341
341
|
"""Visited for each slot in a class. If class level visit_all_slots is true, this is visited once
|
342
|
-
for any class that is inherited (class itself, is_a, mixin, apply_to). Otherwise just the own slots.
|
342
|
+
for any class that is inherited (class itself, is_a, mixin, apply_to). Otherwise, just the own slots.
|
343
343
|
|
344
344
|
@param cls: containing class
|
345
345
|
@param aliased_slot_name: Aliased slot name. May not be unique across all class slots
|
346
|
-
@param slot:
|
346
|
+
@param slot: being visited
|
347
347
|
"""
|
348
348
|
...
|
349
349
|
|
@@ -758,11 +758,28 @@ class Generator(metaclass=abc.ABCMeta):
|
|
758
758
|
# TODO: add lru cache once we get identity into the classes
|
759
759
|
def domain_slots(self, cls: ClassDefinition) -> List[SlotDefinition]:
|
760
760
|
"""Return all slots in the class definition that are owned by the class"""
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
761
|
+
domain_slots = []
|
762
|
+
for slot_name in cls.slots:
|
763
|
+
slot = self.schema.slots[slot_name]
|
764
|
+
|
765
|
+
# add any mixin ancestors here so that slots will be distributed to descendents correctly via mixin
|
766
|
+
# hierarchy.
|
767
|
+
mixin_ancestors = []
|
768
|
+
if cls.mixins:
|
769
|
+
for mixin in cls.mixins:
|
770
|
+
for ancestor in self.schemaview.class_ancestors(mixin, mixins=False):
|
771
|
+
if ancestor not in mixin_ancestors:
|
772
|
+
mixin_ancestors.append(ancestor)
|
773
|
+
|
774
|
+
for mixin_ancestor in mixin_ancestors:
|
775
|
+
if mixin_ancestor not in cls.mixins:
|
776
|
+
cls.mixins.append(mixin_ancestor)
|
777
|
+
|
778
|
+
# Check if the class is in the domain of the slot or if any of its mixins are in the domain
|
779
|
+
if cls.name in slot.domain_of or (set(cls.mixins).intersection(slot.domain_of)):
|
780
|
+
domain_slots.append(slot)
|
781
|
+
|
782
|
+
return domain_slots
|
766
783
|
|
767
784
|
def add_mappings(self, defn: Definition) -> None:
|
768
785
|
"""
|
linkml/utils/schemaloader.py
CHANGED
@@ -691,7 +691,7 @@ class SchemaLoader:
|
|
691
691
|
cls.is_a,
|
692
692
|
)
|
693
693
|
for mixin in cls.mixins:
|
694
|
-
# Note that apply_to has
|
694
|
+
# Note that apply_to has been injected as a faux mixin, so it gets covered here
|
695
695
|
if mixin in self.schema.classes:
|
696
696
|
self.merge_class(self.schema.classes[mixin], merged_classes)
|
697
697
|
merge_classes(self.schema, cls, self.schema.classes[mixin], True)
|
@@ -19,7 +19,7 @@ linkml/generators/docgen/type.md.jinja2,sha256=QmCMJZrFwP33eHkggBVtypbyrxTb-XZn9
|
|
19
19
|
linkml/generators/docgen.py,sha256=zsLzbXN2t9pafQubEnb7QshufMKBMqUWjdLE1OyFyq8,33296
|
20
20
|
linkml/generators/dotgen.py,sha256=CnbVY6CO1OMuiYXYnvxgNN2IW1mtOQW-J-QnwZlXkUI,5012
|
21
21
|
linkml/generators/erdiagramgen.py,sha256=Gu-_nhLuEPTsYYaoV6tNS1V6cZ2dNJdm6YwxC0VGl7g,10315
|
22
|
-
linkml/generators/excelgen.py,sha256=
|
22
|
+
linkml/generators/excelgen.py,sha256=ClzWs3wO-QjH2XzzQVUsGF2n6fnoozmXopxPYDEJyPs,7232
|
23
23
|
linkml/generators/golanggen.py,sha256=Dnl7dhmb1AIK3Is7KRaUbxPd3kBTjWuspFqardiBTJ8,5751
|
24
24
|
linkml/generators/golrgen.py,sha256=tIsbsr4SM9HxeK7TCUwnq-GdSKZ_qW5f7fybg_aqCZE,3436
|
25
25
|
linkml/generators/graphqlgen.py,sha256=6qZpI0rwg3ypsv_KrLVzXgdsJfR8LNPqgMwaRwzwnDs,2151
|
@@ -39,8 +39,8 @@ linkml/generators/plantumlgen.py,sha256=Vs__5x9ioiT4IBTbvZUpgT8MsYJ0amfBL64MB_nm
|
|
39
39
|
linkml/generators/prefixmapgen.py,sha256=JJ7hgzuqKVfFZrbDV76Dk8dR2NHsmpp-eNUAspXkfwA,4626
|
40
40
|
linkml/generators/projectgen.py,sha256=EVgS5bDzFTm3WAuMg3lC3rzdcaW-hgpq99qZA4nksSY,9544
|
41
41
|
linkml/generators/protogen.py,sha256=9YfxBZkQdBWwsUbstxEUR4xRWNuAKSfz9zXPhgIYePU,2328
|
42
|
-
linkml/generators/pydanticgen.py,sha256=
|
43
|
-
linkml/generators/pythongen.py,sha256=
|
42
|
+
linkml/generators/pydanticgen.py,sha256=rH__R3Pt7TKQzG2DBo1R5OehQG3FaBMCjXBzZlAWMqw,23742
|
43
|
+
linkml/generators/pythongen.py,sha256=7XNlOpScOOpxpo9Q_sasDOZFYaKifbXWQL-OKczpkfY,52327
|
44
44
|
linkml/generators/rdfgen.py,sha256=LxzYBaFEkV7rlf54nWv_6H6AGcWMRXwkaeVXq9VYEc8,2693
|
45
45
|
linkml/generators/shaclgen.py,sha256=KxNmDZW2ciCuSqUhJ65TxLTjF8jME1FmN5SaWJCuW9k,8662
|
46
46
|
linkml/generators/shexgen.py,sha256=Awtn5SyjS-TUcVCwMdT0F7hNO4K8VcSCYBaFru45Mwg,8994
|
@@ -86,7 +86,7 @@ linkml/utils/converter.py,sha256=rdhCI7Tsjddr3o1rVBfMq5gQubk_GE6fqlBBmyxI5_M,627
|
|
86
86
|
linkml/utils/datautils.py,sha256=2XWM9LBSVp8v3SwIZECrX3SjDUYzdnP-syjp6YdL89E,3734
|
87
87
|
linkml/utils/datavalidator.py,sha256=kBdWaVi8IZT1bOwEJgJYx-wZAb_PTBObB9nHpYORfKA,472
|
88
88
|
linkml/utils/execute_tutorial.py,sha256=T4kHTSyz3ItJGEUZxVjR-3yLVKnOr5Ix4NMGE47-IuE,6912
|
89
|
-
linkml/utils/generator.py,sha256=
|
89
|
+
linkml/utils/generator.py,sha256=dW9kfVL-7an0ieXR5HLe8bqOyEgDGAoIzdLOu_TFQhc,39101
|
90
90
|
linkml/utils/helpers.py,sha256=yR8n4zFA5wPcYC7xzRuNF3wO16vG80v6j7DM3qTNmIc,447
|
91
91
|
linkml/utils/ifabsent_functions.py,sha256=FZwceqwlq81lMPDsdNfSHhtzDXSf8F4cbbhRdnDzjss,5765
|
92
92
|
linkml/utils/logictools.py,sha256=GSmBiobC49TcQjE08RtXEE3JwJEOV7eEREio25uJiFs,21184
|
@@ -94,7 +94,7 @@ linkml/utils/mergeutils.py,sha256=QVm2iQB4v_L2rSvPBsPe9C865R03BgV3TzlPoTTTwWQ,90
|
|
94
94
|
linkml/utils/rawloader.py,sha256=QB7Rdvy4o4ZJEWBWa2_2xzz2TOh_6Oe4slvUn8IBVIc,4329
|
95
95
|
linkml/utils/schema_builder.py,sha256=WLSit3J4lTifaFLLWTwjqIRiTru1pqvTIUuC1TrxS6Y,9902
|
96
96
|
linkml/utils/schema_fixer.py,sha256=rjwJB5ukfrgc0Z-j3mKSNzRMkHPp_k_zFKaFNIPeIv8,15086
|
97
|
-
linkml/utils/schemaloader.py,sha256=
|
97
|
+
linkml/utils/schemaloader.py,sha256=bBSTqimMDTFH2FcKtRz99dKNJzV_myPsZSkIFp_6-A0,46421
|
98
98
|
linkml/utils/schemasynopsis.py,sha256=6NKa89bkZfZQE9QM0St-6xQcrsHPkYmBgnnWnlgAcQ4,18455
|
99
99
|
linkml/utils/sqlutils.py,sha256=86XeEbfY0Dk-EObw4q5-dxyzSeBtmIhjqqyDcR8ALS0,16591
|
100
100
|
linkml/utils/typereferences.py,sha256=8Yfuz9-HAwOPoJLbIcO_sY9zf32hvPRzGeSOzECfMWA,2232
|
@@ -123,8 +123,8 @@ linkml/workspaces/datamodel/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMp
|
|
123
123
|
linkml/workspaces/datamodel/workspaces.py,sha256=4HdkqweGNfMPqnB1_Onc9DcTfkhoagTRcqruh08nRoI,14905
|
124
124
|
linkml/workspaces/datamodel/workspaces.yaml,sha256=EjVrwPpeRZqJRjuGyyDRxxFzuv55SiLIXPBRUG6HStU,4233
|
125
125
|
linkml/workspaces/example_runner.py,sha256=hblnsZVntuwFO4vqcwl_K5XH6jxb52xCtvdc7Sfq_Yc,11452
|
126
|
-
linkml-1.6.
|
127
|
-
linkml-1.6.
|
128
|
-
linkml-1.6.
|
129
|
-
linkml-1.6.
|
130
|
-
linkml-1.6.
|
126
|
+
linkml-1.6.5.dist-info/WHEEL,sha256=vVCvjcmxuUltf8cYhJ0sJMRDLr1XsPuxEId8YDzbyCY,88
|
127
|
+
linkml-1.6.5.dist-info/LICENSE,sha256=kORMoywK6j9_iy0UvLR-a80P1Rvc9AOM4gsKlUNZABg,535
|
128
|
+
linkml-1.6.5.dist-info/METADATA,sha256=dB0BnsijpuHie4nRiNeQ2N5mLQrr0pCu_6msKi2eWZo,3496
|
129
|
+
linkml-1.6.5.dist-info/entry_points.txt,sha256=za8r49Z5gcz3rAYTZLbxw5EPZr1rGuxSe1uiRUpf8R0,2143
|
130
|
+
linkml-1.6.5.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|