Commit 576c6779 authored by Markus Scheidgen's avatar Markus Scheidgen
Browse files

Started on converting legacy metainfo to new metainfo.

parent fe681d40
Subproject commit 58d45d16f6d837bce490ac151bbbbba91c0b452d
Subproject commit aee4be7407124f87b0ba99eb7b4af3646b8602e9
from typing import Tuple, Dict, List, Type, TypeVar
import os.path
from nomadcore.local_meta_info import loadJsonFile, InfoKindEl
import nomad_meta_info
from nomad import utils
from nomad.metainfo import Definition, Package, Category, Section, Quantity, SubSection
def load_legacy_metainfo(
package_names: List[str] = None) \
-> Tuple[Dict[str, InfoKindEl], Dict[str, List[InfoKindEl]]]:
""" Loads the old metainfo and returns them by package, and by kind. """
meta_info_path = os.path.normpath(os.path.join(
os.path.dirname(nomad_meta_info.__file__), 'all.nomadmetainfo.json'))
meta_info_env, _ = loadJsonFile(filePath=meta_info_path)
defs: Dict[str, InfoKindEl] = {}
packages: Dict[str, List[InfoKindEl]] = {}
for definition in meta_info_env.infoKindEls():
defs[definition.name] = definition
if package_names is None or definition.package in package_names:
packages.setdefault(definition.package, []).append(definition)
return defs, packages
legacy_defs, legacy_packages = load_legacy_metainfo(['common.nomadmetainfo.json', 'public.nomadmetainfo.json'])
logger = utils.get_logger(__name__)
all_defs: Dict[str, Definition] = dict()
T = TypeVar('T', bound=Definition)
dtype_strs = set()
def convert_package(legacy_definitions: List[InfoKindEl], **kwargs) -> Package:
package = Package(**kwargs)
def flux_box(legacy_name: str, section_cls: Type[T], is_new: bool = False) -> T:
if legacy_def.name in all_defs and is_new:
logger.error(
'double definition in legacy metainfo',
def_name=legacy_def.name, def_type='section')
definition = package.all_definitions.get(legacy_name)
if definition is None:
definition = package.m_create(section_cls, name=legacy_name)
if is_new:
all_defs[legacy_def.name] = definition
return definition
for legacy_def in legacy_definitions:
if legacy_def.kindStr == 'type_abstract_document_content':
definition = flux_box(legacy_def.name, Category, is_new=True)
elif legacy_def.kindStr == 'type_section':
definition = flux_box(legacy_def.name, Section, is_new=True)
elif legacy_def.kindStr in ['type_dimension', 'type_document_content']:
definition = Quantity(name=legacy_def.name, type=int)
# map shape, map type
dtype_strs.add(legacy_def.dtypeStr)
else:
logger.error(
'unknown kindStr', def_name=legacy_def.name, kind_str=legacy_def.kindStr)
# superNames
for legacy_super_name in legacy_def.superNames:
legacy_super_def = legacy_defs.get(legacy_super_name)
if legacy_super_def is None:
logger.error(
'super name does not exist', def_name=legacy_def.name,
super_name=legacy_super_name)
if legacy_super_def.kindStr == 'type_section':
parent_def = flux_box(legacy_super_name, Section)
if isinstance(definition, Section):
parent_def.m_create(
SubSection, name=legacy_def.name, sub_section=definition)
elif isinstance(definition, Quantity):
parent_def.m_add_sub_section(Section.quantities, definition)
elif legacy_super_def.kindStr == 'type_abstract_document_content':
category = flux_box(legacy_super_name, Category)
definition.categories += [category]
else:
logger.error(
'super name is neither section nor category',
def_name=legacy_def.name, super_name=legacy_super_name)
return package
common_pkg = convert_package(
legacy_packages['common.nomadmetainfo.json'] + legacy_packages['public.nomadmetainfo.json'],
name='common')
# print(common_pkg.m_to_json(indent=2))
print(dtype_strs)
......@@ -1621,25 +1621,25 @@ class Section(Definition):
is a method ``on_set`` or ``on_add_sub_section``, it will be added as handler.
section_cls:
A helper property that gives the `section class` as a Python class object.
A helper attribute that gives the `section class` as a Python class object.
all_base_sections:
A helper property that gives direct and indirect base sections.
A helper attribute that gives direct and indirect base sections.
all_properties:
A helper property that gives all properties (sub section and quantity) definitions
A helper attribute that gives all properties (sub section and quantity) definitions
including inherited properties as a dictionary with names and definitions.
all_quantities:
A helper property that gives all quantity definition including inherited ones
A helper attribute that gives all quantity definition including inherited ones
as a dictionary that maps names (strings) to :class:`Quantity`.
all_sub_sections:
A helper property that gives all sub-section definition including inherited ones
A helper attribute that gives all sub-section definition including inherited ones
as a dictionary that maps names (strings) to :class:`SubSection`.
all_sub_sections_by_section:
A helper property that gives all sub-section definition including inherited ones
A helper attribute that gives all sub-section definition including inherited ones
as a dictionary that maps section classes (i.e. Python class objects) to
lists of :class:`SubSection`.
"""
......@@ -1721,11 +1721,19 @@ class Package(Definition):
category_definitions: All `category definitions` in this package as :class:`Category`
objects.
all_definitions: A helper attribute that provides all section definitions
by name.
"""
section_definitions: 'SubSection' = None
category_definitions: 'SubSection' = None
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.all_definitions: Dict[str, 'Section'] = dict()
@staticmethod
def from_module(module_name: str):
module = sys.modules[module_name]
......@@ -1741,6 +1749,10 @@ class Package(Definition):
return pkg
def on_add_sub_section(self, sub_section_def, sub_section):
if sub_section_def in [Package.section_definitions, Package.category_definitions]:
self.all_definitions[sub_section.name] = sub_section
class Category(Definition):
""" Categories allow to organize metainfo definitions (not metainfo data like sections do)
......@@ -1750,7 +1762,7 @@ class Category(Definition):
they form a `is a` relationship.
Args:
definitions: A helper property that gives all definitions that are directly or
definitions: A helper attribute that gives all definitions that are directly or
indirectly in this category.
"""
......
......@@ -152,6 +152,7 @@ class TestM2:
assert example_package.description == 'An example metainfo package.'
assert example_package.m_sub_section_count(Package.section_definitions) == 5
assert example_package.m_sub_section_count(Package.category_definitions) == 1
assert len(example_package.all_definitions) == 6
def test_base_sections(self):
assert Definition.m_def in iter(Section.m_def.base_sections)
......@@ -257,10 +258,12 @@ class TestM1:
def test_children_parent(self):
run = Run()
system = run.m_create(System)
system1 = run.m_create(System)
run.m_create(System)
assert run.systems[0] == system # pylint: disable=E1101
assert run.m_get_sub_section(Run.systems, 0) == system
assert run.systems[0] == system1 # pylint: disable=E1101
assert run.m_get_sub_section(Run.systems, 0) == system1
assert run.m_sub_section_count(Run.systems) == 2
def test_parent_repeats(self):
run = Run()
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment