fix imports being inside the any_of range, more manual inspection before finishing for the night

This commit is contained in:
sneakers-the-rat 2024-07-24 22:47:06 -07:00
parent 781b667952
commit af11bb61ec
Signed by untrusted user who does not match committer: jonny
GPG key ID: 6DCB96EF1E4D232D
4 changed files with 47 additions and 7 deletions

View file

@ -11,6 +11,8 @@ NWB schema translation
Cleanup
- [ ] Update pydantic generator
- [ ] Restore regressions from stripping the generator
- [x] Make any_of with array ranges work
- [ ] PR upstream `equals_string` and `ifabsent` (if existing PR doesnt fix)
- [ ] Use the class rather than a string in _get_class_slot_range_origin:
```
or inlined_as_list
@ -43,6 +45,9 @@ Important things that are not implemented yet!
Remove monkeypatches/overrides once PRs are closed
- [ ] https://github.com/linkml/linkml-runtime/pull/330
Tests
- [ ] Ensure schemas and pydantic modules in repos are up to date
## Docs TODOs
```{todolist}

View file

@ -246,7 +246,6 @@ class ClassAdapter(Adapter):
ifabsent=f"string({name})",
equals_string=equals_string,
range="string",
identifier=True,
)
else:
name_slot = SlotDefinition(name="name", required=True, range="string", identifier=True)

View file

@ -30,6 +30,7 @@ The `serialize` method:
import inspect
import pdb
import re
import sys
import warnings
from copy import copy
@ -40,7 +41,8 @@ from typing import ClassVar, Dict, List, Optional, Tuple, Type, Union
from linkml.generators import PydanticGenerator
from linkml.generators.pydanticgen.build import SlotResult
from linkml.generators.pydanticgen.array import ArrayRepresentation
from linkml.generators.pydanticgen.array import ArrayRepresentation, NumpydanticArray
from linkml.generators.pydanticgen.template import PydanticModule
from linkml_runtime.linkml_model.meta import (
Annotation,
AnonymousSlotExpression,
@ -61,6 +63,8 @@ from pydantic import BaseModel
from nwb_linkml.maps import flat_to_nptyping
from nwb_linkml.maps.naming import module_case, version_module_case
OPTIONAL_PATTERN = re.compile(r'Optional\[([\w\.]*)\]')
@dataclass
class NWBPydanticGenerator(PydanticGenerator):
@ -86,7 +90,7 @@ class NWBPydanticGenerator(PydanticGenerator):
gen_slots: bool = True
skip_meta: ClassVar[Tuple[str]] = ('domain_of',)
skip_meta: ClassVar[Tuple[str]] = ('domain_of','alias')
def _check_anyof(
self, s: SlotDefinition, sn: SlotDefinitionName, sv: SchemaView
@ -111,18 +115,42 @@ class NWBPydanticGenerator(PydanticGenerator):
if not base_range_subsumes_any_of:
raise ValueError("Slot cannot have both range and any_of defined")
def before_generate_schema(self):
pass
def after_generate_slot(self, slot: SlotResult, sv: SchemaView) -> SlotResult:
"""
- strip unwanted metadata
- generate range with any_of
"""
for key in self.skip_meta:
if key in slot.attribute.meta:
del slot.attribute.meta[key]
# make array ranges in any_of
if 'any_of' in slot.attribute.meta:
any_ofs = slot.attribute.meta['any_of']
if all(['array' in expr for expr in any_ofs]):
ranges = []
is_optional = False
for expr in any_ofs:
# remove optional from inner type
pyrange = slot.attribute.range
is_optional = OPTIONAL_PATTERN.match(pyrange)
if is_optional:
pyrange = is_optional.groups()[0]
range_generator = NumpydanticArray(ArrayExpression(**expr['array']), pyrange)
ranges.append(range_generator.make().range)
slot.attribute.range = 'Union[' + ', '.join(ranges) + ']'
if is_optional:
slot.attribute.range = 'Optional[' + slot.attribute.range + ']'
del slot.attribute.meta['any_of']
return slot
def before_render_template(self, template: PydanticModule, sv: SchemaView) -> PydanticModule:
if 'source_file' in template.meta:
del template.meta['source_file']
def compile_module(
self, module_path: Path = None, module_name: str = "test", **kwargs
) -> ModuleType: # pragma: no cover - replaced with provider

View file

@ -12,7 +12,7 @@ from types import ModuleType
from typing import List, Optional, Type
from linkml_runtime.linkml_model.meta import SchemaDefinition
from linkml.generators.pydanticgen.pydanticgen import SplitMode, _import_to_path
from linkml.generators.pydanticgen.pydanticgen import SplitMode, _import_to_path, _ensure_inits
from pydantic import BaseModel
from nwb_linkml.generators.pydantic import NWBPydanticGenerator
@ -148,7 +148,9 @@ class PydanticProvider(Provider):
force: bool,
**kwargs
) -> List[str]:
# FIXME: This is messy as all fuck, we're just getting it to work again so we can start iterating on the models themselves
res = []
module_paths = []
# first make the namespace file we were given
@ -170,6 +172,7 @@ class PydanticProvider(Provider):
if dump:
with open(ns_file, 'w') as ofile:
ofile.write(serialized)
module_paths.append(ns_file)
else:
with open(ns_file, 'r') as ofile:
serialized = ofile.read()
@ -203,6 +206,7 @@ class PydanticProvider(Provider):
if dump:
with open(import_file, 'w') as ofile:
ofile.write(serialized)
module_paths.append(import_file)
else:
with open(import_file, 'r') as ofile:
@ -210,6 +214,10 @@ class PydanticProvider(Provider):
res.append(serialized)
# make __init__.py files if we generated any files
if len(module_paths) > 0:
_ensure_inits(module_paths)
return res
def _make_inits(self, out_file: Path) -> None: