You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

101 lines
3.1 KiB
Python

import server.models.models
from server.models.models import Jsonifiable
from neomodel import StructuredNode, StringProperty, RelationshipManager, \
UniqueIdProperty, DateProperty, StructuredRel, DateTimeProperty, StructuredRel, \
Property, RelationshipDefinition
import json
from typing import Type, Tuple, Dict, List, Optional, Generator
def constructor(cls: Type[StructuredNode]) -> str:
return 'constructor(json) {\n' + \
f' super(json)\n' + \
' }'
def get_set_attr(name, attr) -> str:
if RelationshipDefinition in attr.__class__.__mro__:
return f"""
get_{name}() {{
return this._get_relation('{name}')
}}
link_{name}(ref) {{
return this._link_relation('{name}', ref)
}}
unlink_{name}(ref) {{
return this._unlink_relation('{name}', ref)
}}
"""
else:
return f"""
get_{name}() {{
return this.json.{name}
}}
""" + f"""
set_{name}(new_val) {{
this._set('{name}', new_val)
}}
""" if name != 'uid' else ''
def all_attrs(cls):
return '\n'.join([ get_set_attr(name, val) for name, val in get_relevant_attributes(cls)])
def js_representation(cls: Type[StructuredNode]) -> str:
props, rels = get_properties_and_relations(cls)
return f"""models.{cls.__name__} = class {cls.__name__} extends StructuredNode {{
{constructor(cls)}
{all_attrs(cls)}
}}
StructuredNode.registerClassDefinition(models.{cls.__name__}, {json.dumps(props)}, {json.dumps(rels)})
"""
def get_relevant_attributes(cls: Type[StructuredNode]) -> Generator[None, Tuple[str, Property], None]:
for name, value in vars(cls).items():
if name[0] == '_' or name[0].isupper() and not isinstance(value, (RelationshipDefinition, Property)):
continue
yield name, value
def get_properties_and_relations(cls) -> Tuple[Dict[str, dict], Dict[str, dict]]:
props = dict()
rels = dict()
for name, value in get_relevant_attributes(cls):
if isinstance(value, RelationshipDefinition):
target_cls = value._raw_class.__name__ if not isinstance(value._raw_class, str) else value._raw_class
rels[name] = {
'field': name,
'target': target_cls,
'cardinality': value.manager.__name__
}
elif isinstance(value, Property):
props[name] = {
'field': name,
'type': value.__class__.__name__,
'required': value.required
}
return props, rels
if __name__ == '__main__':
reps = list()
reps.append("// This file was generated by running js_conversion.py\n" +
"// It converts the neomodel declaration of this element into js classes.\n" +
"(() => {\nconst models = window.models || {}")
for name, cls in vars(server.models.models).items():
if hasattr(cls, '__mro__') and StructuredNode in cls.__mro__ and StructuredNode != cls.__mro__[0]:
reps.append(js_representation(cls))
reps.append('window.models = models;\n})()')
print('\n\n\n'.join(reps))