mirror of
https://github.com/p2p-ld/nwb-linkml.git
synced 2024-11-12 17:54:29 +00:00
fix imports being inside the any_of range, more manual inspection before finishing for the night
This commit is contained in:
parent
781b667952
commit
af11bb61ec
4 changed files with 47 additions and 7 deletions
|
@ -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}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue