Commit afcf9216 authored by Markus Scheidgen's avatar Markus Scheidgen
Browse files

Replaces m_secton with m_def.

parent 34843512
...@@ -29,7 +29,7 @@ quantities: Dict[str, Quantity] = { ...@@ -29,7 +29,7 @@ quantities: Dict[str, Quantity] = {
q.name, es_field='optimade.%s' % q.name, q.name, es_field='optimade.%s' % q.name,
elastic_mapping_type=q.m_annotations['elastic']['type']) elastic_mapping_type=q.m_annotations['elastic']['type'])
for q in OptimadeStructureEntry.m_section.quantities.values() for q in OptimadeStructureEntry.m_def.quantities.values()
if 'elastic' in q.m_annotations} if 'elastic' in q.m_annotations}
quantities['elements'].length_quantity = quantities['nelements'] quantities['elements'].length_quantity = quantities['nelements']
......
...@@ -182,7 +182,7 @@ class DFTCalcWithMetadata(CalcWithMetadata): ...@@ -182,7 +182,7 @@ class DFTCalcWithMetadata(CalcWithMetadata):
self.n_total_energies = n_total_energies self.n_total_energies = n_total_energies
self.n_geometries = n_geometries self.n_geometries = n_geometries
self.optimade = backend.get_mi2_section(optimade.OptimadeStructureEntry.m_section) self.optimade = backend.get_mi2_section(optimade.OptimadeStructureEntry.m_def)
def only_atoms(atoms): def only_atoms(atoms):
......
...@@ -188,7 +188,7 @@ Section object need to support: ...@@ -188,7 +188,7 @@ Section object need to support:
- access to subsection via subsection name - access to subsection via subsection name
- access of properties via property name - access of properties via property name
- array access for repeatable sections - array access for repeatable sections
- navigation to its containing section: `.m_section` - navigation to its containing section: `.m_def`
- allow to create/(re-)open subsections via calling the subsection name as a method: `.system()` - allow to create/(re-)open subsections via calling the subsection name as a method: `.system()`
- close a section so that the underlying resource implementation can potentially remove the section from memory and write it to a database/.hdf5 file - close a section so that the underlying resource implementation can potentially remove the section from memory and write it to a database/.hdf5 file
- the *GraphQL* like access methods with dictionary to specify multiple sub-sections - the *GraphQL* like access methods with dictionary to specify multiple sub-sections
......
...@@ -4,24 +4,24 @@ Some playground to try the API_CONCEPT.md ideas. ...@@ -4,24 +4,24 @@ Some playground to try the API_CONCEPT.md ideas.
class MObject: class MObject:
def __init__(self, m_definition: 'MElementDef', m_section: 'MSection' = None): def __init__(self, m_definition: 'MElementDef', m_def: 'MSection' = None):
self.m_definition = m_definition self.m_definition = m_definition
self.m_section = m_section self.m_def = m_def
@property @property
def m_section(self): def m_def(self):
return self._section return self._section
@m_section.setter @m_def.setter
def m_section(self, m_section: 'MSection'): def m_def(self, m_def: 'MSection'):
self._section = m_section self._section = m_def
# add yourself to the parent section # add yourself to the parent section
if m_section is not None: if m_def is not None:
subsection = m_section.subsections.get(self.m_definition.name) subsection = m_def.subsections.get(self.m_definition.name)
if subsection is None: if subsection is None:
subsection = [] subsection = []
m_section.subsections[self.m_definition.name] = subsection m_def.subsections[self.m_definition.name] = subsection
subsection.append(self) subsection.append(self)
...@@ -42,7 +42,7 @@ class MSection(MObject): ...@@ -42,7 +42,7 @@ class MSection(MObject):
raise KeyError('Section "%s" does not have subsection "%s", available subsections are %s' % (self.m_definition.name, name, '?')) raise KeyError('Section "%s" does not have subsection "%s", available subsections are %s' % (self.m_definition.name, name, '?'))
def constructor(**kwargs): def constructor(**kwargs):
new_section = subsection.impl(m_definition=subsection, m_section=self) new_section = subsection.impl(m_definition=subsection, m_def=self)
for key, value in kwargs.items(): for key, value in kwargs.items():
setattr(new_section, key, value) setattr(new_section, key, value)
...@@ -84,13 +84,13 @@ class MSectionDef(MElementDef): ...@@ -84,13 +84,13 @@ class MSectionDef(MElementDef):
self.impl = impl self.impl = impl
def get_subsection(self, name: str): def get_subsection(self, name: str):
return self.m_section.get_section(name) return self.m_def.get_section(name)
m_section = MSectionDef(m_definition=None, name='section', repeats=True, impl=MSectionDef) m_def = MSectionDef(m_definition=None, name='section', repeats=True, impl=MSectionDef)
m_section.m_definition = m_section m_def.m_definition = m_def
m_element = MSectionDef(m_definition=m_section, name='element', abstract=True, impl=None) m_element = MSectionDef(m_definition=m_def, name='element', abstract=True, impl=None)
m_package = MSectionDef(m_definition=m_section, name='package') m_package = MSectionDef(m_definition=m_def, name='package')
class MPackageDef(MElementDef): class MPackageDef(MElementDef):
...@@ -107,9 +107,9 @@ class MPackageDef(MElementDef): ...@@ -107,9 +107,9 @@ class MPackageDef(MElementDef):
metainfo = MPackageDef(name='metainfo') metainfo = MPackageDef(name='metainfo')
m_element.m_section = metainfo m_element.m_def = metainfo
m_section.m_section = metainfo m_def.m_def = metainfo
m_package.m_section = metainfo m_package.m_def = metainfo
m_property = metainfo.new_section(name='property', repeats=True, extends=m_element, section=m_package) m_property = metainfo.new_section(name='property', repeats=True, extends=m_element, section=m_package)
print(metainfo.subsections['section']) print(metainfo.subsections['section'])
......
...@@ -36,7 +36,7 @@ Here is a simple example that demonstrates the definition of System related quan ...@@ -36,7 +36,7 @@ Here is a simple example that demonstrates the definition of System related quan
system (a.k.a. geometry). system (a.k.a. geometry).
\"\"\" \"\"\"
m_section = Section(repeats=True, parent=Run) m_def = Section(repeats=True, parent=Run)
n_atoms = Quantity( n_atoms = Quantity(
type=int, description=''' type=int, description='''
...@@ -74,10 +74,10 @@ This last statement, will produce the following JSON: ...@@ -74,10 +74,10 @@ This last statement, will produce the following JSON:
.. code-block:: JSON .. code-block:: JSON
{ {
"m_section" = "Run", "m_def" = "Run",
"System": [ "System": [
{ {
"m_section" = "System", "m_def" = "System",
"m_parent_index" = 0, "m_parent_index" = 0,
"n_atoms" = 3, "n_atoms" = 3,
"atom_labels" = [ "atom_labels" = [
...@@ -121,7 +121,7 @@ definitions. ...@@ -121,7 +121,7 @@ definitions.
The following classes can be used to define and structure meta-info data: The following classes can be used to define and structure meta-info data:
- sections are defined by sub-classes :class:`MObject` and using :class:`Section` to - sections are defined by sub-classes :class:`MObject` and using :class:`Section` to
populate the classattribute `m_section` populate the classattribute `m_def`
- quantities are defined by assigning classattributes of a section with :class:`Quantity` - quantities are defined by assigning classattributes of a section with :class:`Quantity`
instances instances
- references (from one section to another) can be defined with quantities that use - references (from one section to another) can be defined with quantities that use
...@@ -196,7 +196,7 @@ class Dimension(DataType): ...@@ -196,7 +196,7 @@ class Dimension(DataType):
if isinstance(value, Section): if isinstance(value, Section):
return return
if isinstance(value, type) and hasattr(value, 'm_section'): if isinstance(value, type) and hasattr(value, 'm_def'):
return return
raise TypeError('%s is not a valid dimension' % str(value)) raise TypeError('%s is not a valid dimension' % str(value))
...@@ -248,7 +248,7 @@ class MObject(metaclass=MObjectMeta): ...@@ -248,7 +248,7 @@ class MObject(metaclass=MObjectMeta):
assert run.m_sub_section(System, system.m_parent_index) == system assert run.m_sub_section(System, system.m_parent_index) == system
Attributes: Attributes:
m_section: The section definition that defines this sections, its possible m_def: The section definition that defines this sections, its possible
sub-sections and quantities. sub-sections and quantities.
m_parent: The parent section instance that this section is a sub-section of. m_parent: The parent section instance that this section is a sub-section of.
m_parent_index: For repeatable sections, parent keep a list of sub-sections for m_parent_index: For repeatable sections, parent keep a list of sub-sections for
...@@ -260,19 +260,19 @@ class MObject(metaclass=MObjectMeta): ...@@ -260,19 +260,19 @@ class MObject(metaclass=MObjectMeta):
if possible. if possible.
""" """
m_section: 'Section' = None m_def: 'Section' = None
def __init__(self, m_section: 'Section' = None, m_parent: 'MObject' = None, _bs: bool = False, **kwargs): def __init__(self, m_def: 'Section' = None, m_parent: 'MObject' = None, _bs: bool = False, **kwargs):
self.m_section: 'Section' = m_section self.m_def: 'Section' = m_def
self.m_parent: 'MObject' = m_parent self.m_parent: 'MObject' = m_parent
self.m_parent_index = -1 self.m_parent_index = -1
cls = self.__class__ cls = self.__class__
if self.m_section is None: if self.m_def is None:
self.m_section = cls.m_section self.m_def = cls.m_def
if cls.m_section is not None: if cls.m_def is not None:
assert self.m_section == cls.m_section, \ assert self.m_def == cls.m_def, \
'Section class and section definition must match' 'Section class and section definition must match'
self.m_annotations: Dict[str, Any] = {} self.m_annotations: Dict[str, Any] = {}
...@@ -296,22 +296,22 @@ class MObject(metaclass=MObjectMeta): ...@@ -296,22 +296,22 @@ class MObject(metaclass=MObjectMeta):
if not all([hasattr(__module__, cls) for cls in ['Quantity', 'Section', 'Package', 'Category', 'sub_section']]): if not all([hasattr(__module__, cls) for cls in ['Quantity', 'Section', 'Package', 'Category', 'sub_section']]):
return return
# ensure that the m_section is defined # ensure that the m_def is defined
m_section = cls.m_section m_def = cls.m_def
if m_section is None and cls != MObject: if m_def is None and cls != MObject:
m_section = Section() m_def = Section()
setattr(cls, 'm_section', m_section) setattr(cls, 'm_def', m_def)
# transfer name and description to m_section # transfer name and description to m_def
m_section.name = cls.__name__ m_def.name = cls.__name__
if cls.__doc__ is not None: if cls.__doc__ is not None:
m_section.description = inspect.cleandoc(cls.__doc__) m_def.description = inspect.cleandoc(cls.__doc__)
m_section.section_cls = cls m_def.section_cls = cls
# add sub_section to parent section # add sub_section to parent section
if m_section.parent is not None: if m_def.parent is not None:
sub_section_name = inflection.underscore(m_section.name) sub_section_name = inflection.underscore(m_def.name)
setattr(m_section.parent.section_cls, sub_section_name, sub_section(m_section)) setattr(m_def.parent.section_cls, sub_section_name, sub_section(m_def))
for name, attr in cls.__dict__.items(): for name, attr in cls.__dict__.items():
# transfer names and descriptions for quantities # transfer names and descriptions for quantities
...@@ -321,18 +321,18 @@ class MObject(metaclass=MObjectMeta): ...@@ -321,18 +321,18 @@ class MObject(metaclass=MObjectMeta):
attr.description = inspect.cleandoc(attr.description) attr.description = inspect.cleandoc(attr.description)
attr.__doc__ = attr.description attr.__doc__ = attr.description
# manual manipulation of m_data due to bootstrapping # manual manipulation of m_data due to bootstrapping
m_section.m_data.setdefault('Quantity', []).append(attr) m_def.m_data.setdefault('Quantity', []).append(attr)
# set names and parent on sub-sections # set names and parent on sub-sections
elif isinstance(attr, sub_section): elif isinstance(attr, sub_section):
attr.section_def.parent = m_section attr.section_def.parent = m_def
if attr.section_def.name is None: if attr.section_def.name is None:
attr.section_def.name = inflection.camelize(name) attr.section_def.name = inflection.camelize(name)
# add section cls' section to the module's package # add section cls' section to the module's package
module_name = cls.__module__ module_name = cls.__module__
pkg = Package.from_module(module_name) pkg = Package.from_module(module_name)
pkg.m_add_sub_section(cls.m_section) pkg.m_add_sub_section(cls.m_def)
@staticmethod @staticmethod
def m_type_check(definition: 'Quantity', value: Any, check_item: bool = False): def m_type_check(definition: 'Quantity', value: Any, check_item: bool = False):
...@@ -353,7 +353,7 @@ class MObject(metaclass=MObjectMeta): ...@@ -353,7 +353,7 @@ class MObject(metaclass=MObjectMeta):
raise TypeError('Value has wrong type.') raise TypeError('Value has wrong type.')
elif isinstance(definition.type, Section): elif isinstance(definition.type, Section):
if not isinstance(value, MObject) or value.m_section != definition.type: if not isinstance(value, MObject) or value.m_def != definition.type:
raise TypeError('The value is not a section of wrong section definition') raise TypeError('The value is not a section of wrong section definition')
else: else:
...@@ -392,14 +392,14 @@ class MObject(metaclass=MObjectMeta): ...@@ -392,14 +392,14 @@ class MObject(metaclass=MObjectMeta):
def _resolve_section(self, definition: SectionDef) -> 'Section': def _resolve_section(self, definition: SectionDef) -> 'Section':
"""Resolves and checks the given section definition. """ """Resolves and checks the given section definition. """
if isinstance(definition, str): if isinstance(definition, str):
section = self.m_section.sub_sections[definition] section = self.m_def.sub_sections[definition]
else: else:
if isinstance(definition, type): if isinstance(definition, type):
section = getattr(definition, 'm_section') section = getattr(definition, 'm_def')
else: else:
section = definition section = definition
if section.name not in self.m_section.sub_sections: if section.name not in self.m_def.sub_sections:
raise KeyError('Not a sub section.') raise KeyError('Not a sub section.')
return section return section
...@@ -468,7 +468,7 @@ class MObject(metaclass=MObjectMeta): ...@@ -468,7 +468,7 @@ class MObject(metaclass=MObjectMeta):
def m_add_sub_section(self, sub_section: MObjectBound) -> MObjectBound: def m_add_sub_section(self, sub_section: MObjectBound) -> MObjectBound:
"""Adds the given section instance as a sub section to this section.""" """Adds the given section instance as a sub section to this section."""
section_def = sub_section.m_section section_def = sub_section.m_def
if section_def.repeats: if section_def.repeats:
m_data_sections = self.m_data.setdefault(section_def.name, []) m_data_sections = self.m_data.setdefault(section_def.name, [])
...@@ -497,17 +497,17 @@ class MObject(metaclass=MObjectMeta): ...@@ -497,17 +497,17 @@ class MObject(metaclass=MObjectMeta):
section_def: 'Section' = self._resolve_section(definition) section_def: 'Section' = self._resolve_section(definition)
section_cls = section_def.section_cls section_cls = section_def.section_cls
section_instance = section_cls(m_section=section_def, m_parent=self, **kwargs) section_instance = section_cls(m_def=section_def, m_parent=self, **kwargs)
return self.m_add_sub_section(section_instance) return self.m_add_sub_section(section_instance)
def __resolve_quantity(self, definition: Union[str, 'Quantity']) -> 'Quantity': def __resolve_quantity(self, definition: Union[str, 'Quantity']) -> 'Quantity':
"""Resolves and checks the given quantity definition. """ """Resolves and checks the given quantity definition. """
if isinstance(definition, str): if isinstance(definition, str):
quantity = self.m_section.quantities[definition] quantity = self.m_def.quantities[definition]
else: else:
if definition.m_parent != self.m_section: if definition.m_parent != self.m_def:
raise KeyError('Quantity is not a quantity of this section.') raise KeyError('Quantity is not a quantity of this section.')
quantity = definition quantity = definition
...@@ -538,7 +538,7 @@ class MObject(metaclass=MObjectMeta): ...@@ -538,7 +538,7 @@ class MObject(metaclass=MObjectMeta):
def m_update(self, **kwargs): def m_update(self, **kwargs):
""" Updates all quantities and sub-sections with the given arguments. """ """ Updates all quantities and sub-sections with the given arguments. """
for name, value in kwargs.items(): for name, value in kwargs.items():
attribute = self.m_section.attributes.get(name, None) attribute = self.m_def.attributes.get(name, None)
if attribute is None: if attribute is None:
raise KeyError('%s is not an attribute of this section' % name) raise KeyError('%s is not an attribute of this section' % name)
...@@ -559,11 +559,11 @@ class MObject(metaclass=MObjectMeta): ...@@ -559,11 +559,11 @@ class MObject(metaclass=MObjectMeta):
"""Returns the data of this section as a json serializeable dictionary. """ """Returns the data of this section as a json serializeable dictionary. """
def items() -> Iterable[Tuple[str, Any]]: def items() -> Iterable[Tuple[str, Any]]:
yield 'm_section', self.m_section.name yield 'm_def', self.m_def.name
if self.m_parent_index != -1: if self.m_parent_index != -1:
yield 'm_parent_index', self.m_parent_index yield 'm_parent_index', self.m_parent_index
for name, sub_section in self.m_section.sub_sections.items(): for name, sub_section in self.m_def.sub_sections.items():
if name not in self.m_data: if name not in self.m_data:
continue continue
...@@ -572,7 +572,7 @@ class MObject(metaclass=MObjectMeta): ...@@ -572,7 +572,7 @@ class MObject(metaclass=MObjectMeta):
else: else:
yield name, self.m_data[name].m_to_dict() yield name, self.m_data[name].m_to_dict()
for name in self.m_section.quantities: for name in self.m_def.quantities:
if name in self.m_data: if name in self.m_data:
value = getattr(self, name) value = getattr(self, name)
if hasattr(value, 'tolist'): if hasattr(value, 'tolist'):
...@@ -583,10 +583,10 @@ class MObject(metaclass=MObjectMeta): ...@@ -583,10 +583,10 @@ class MObject(metaclass=MObjectMeta):
@classmethod @classmethod
def m_from_dict(cls: Type[MObjectBound], dct: Dict[str, Any]) -> MObjectBound: def m_from_dict(cls: Type[MObjectBound], dct: Dict[str, Any]) -> MObjectBound:
section_def = cls.m_section section_def = cls.m_def
# remove m_section and m_parent_index, they set themselves automatically # remove m_def and m_parent_index, they set themselves automatically
assert section_def.name == dct.pop('m_section', None) assert section_def.name == dct.pop('m_def', None)
dct.pop('m_parent_index', -1) dct.pop('m_parent_index', -1)
def items(): def items():
...@@ -632,7 +632,7 @@ class MObject(metaclass=MObjectMeta): ...@@ -632,7 +632,7 @@ class MObject(metaclass=MObjectMeta):
yield value, value, name, self yield value, value, name, self
def __repr__(self): def __repr__(self):
m_section_name = self.m_section.name m_section_name = self.m_def.name
name = '' name = ''
if 'name' in self.m_data: if 'name' in self.m_data:
name = self.m_data['name'] name = self.m_data['name']
...@@ -851,7 +851,7 @@ class Section(Definition): ...@@ -851,7 +851,7 @@ class Section(Definition):
class System(MObject): class System(MObject):
pass pass
System.m_section.add_quantity(Quantity(name='n_atoms', type=int)) System.m_def.add_quantity(Quantity(name='n_atoms', type=int))
This will add the quantity definition to this section definition, This will add the quantity definition to this section definition,
and add the respective Python descriptor as an attribute to this class. and add the respective Python descriptor as an attribute to this class.
...@@ -885,7 +885,7 @@ class sub_section: ...@@ -885,7 +885,7 @@ class sub_section:
def __init__(self, section: SectionDef, **kwargs): def __init__(self, section: SectionDef, **kwargs):
if isinstance(section, type): if isinstance(section, type):
self.section_def = cast(MObject, section).m_section self.section_def = cast(MObject, section).m_def
else: else:
self.section_def = cast(Section, section) self.section_def = cast(Section, section)
...@@ -933,11 +933,11 @@ class Category(Definition): ...@@ -933,11 +933,11 @@ class Category(Definition):
if self in definition.all_categories]) if self in definition.all_categories])
Section.m_section = Section(repeats=True, name='Section', _bs=True) Section.m_def = Section(repeats=True, name='Section', _bs=True)
Section.m_section.m_section = Section.m_section Section.m_def.m_def = Section.m_def
Section.m_section.section_cls = Section Section.m_def.section_cls = Section
Quantity.m_section = Section(repeats=True, parent=Section.m_section, name='Quantity', _bs=True) Quantity.m_def = Section(repeats=True, parent=Section.m_def, name='Quantity', _bs=True)
Definition.name = Quantity( Definition.name = Quantity(
type=str, name='name', _bs=True, description=''' type=str, name='name', _bs=True, description='''
...@@ -952,7 +952,7 @@ Definition.links = Quantity( ...@@ -952,7 +952,7 @@ Definition.links = Quantity(
A list of URLs to external resource that describe this definition. A list of URLs to external resource that describe this definition.
''') ''')
Definition.categories = Quantity( Definition.categories = Quantity(
type=Category.m_section, shape=['0..*'], default=[], name='categories', _bs=True, type=Category.m_def, shape=['0..*'], default=[], name='categories', _bs=True,
description=''' description='''
The categories that this definition belongs to. See :class:`Category`. The categories that this definition belongs to. See :class:`Category`.
''') ''')
...@@ -963,12 +963,12 @@ Section.repeats = Quantity( ...@@ -963,12 +963,12 @@ Section.repeats = Quantity(
Wether instances of this section can occur repeatedly in the parent section. Wether instances of this section can occur repeatedly in the parent section.
''') ''')
Section.parent = Quantity( Section.parent = Quantity(
type=Section.m_section, name='parent', _bs=True, description=''' type=Section.m_def, name='parent', _bs=True, description='''
The section definition of parent sections. Only section instances of this definition The section definition of parent sections. Only section instances of this definition
can contain section instances of this definition. can contain section instances of this definition.
''') ''')
Quantity.m_section.section_cls = Quantity Quantity.m_def.section_cls = Quantity
Quantity.type = Quantity( Quantity.type = Quantity(
type=Union[type, Enum, Section, np.dtype], name='type', _bs=True, description=''' type=Union[type, Enum, Section, np.dtype], name='type', _bs=True, description='''
The type of the quantity. The type of the quantity.
...@@ -1014,18 +1014,17 @@ Quantity.default = Quantity( ...@@ -1014,18 +1014,17 @@ Quantity.default = Quantity(
The default value for this quantity. The default value for this quantity.
''') ''')
Package.m_section = Section(repeats=True, name='Package', _bs=True) Package.m_def = Section(repeats=True, name='Package', _bs=True)
Package.m_section.parent = Package.m_section Package.m_def.parent = Package.m_def
Section.m_section.parent = Package.m_section Section.m_def.parent = Package.m_def
Category.m_section = Section(repeats=True, parent=Package.m_section) Category.m_def = Section(repeats=True, parent=Package.m_def)
Package.__init_section_cls__() Package.__init_section_cls__()
Category.__init_section_cls__() Category.__init_section_cls__()
Section.__init_section_cls__() Section.__init_section_cls__()
Quantity.__init_section_cls__() Quantity.__init_section_cls__()
units = UnitRegistry() units = UnitRegistry()
""" The default pint unit registry that should be used to give units to quantity definitions. """ """ The default pint unit registry that should be used to give units to quantity definitions. """
...@@ -28,7 +28,7 @@ class Optimade(): ...@@ -28,7 +28,7 @@ class Optimade():