From c74f239e49d24368c5f51ce0432cee22f3a5d0dc Mon Sep 17 00:00:00 2001
From: Markus Scheidgen <markus.scheidgen@gmail.com>
Date: Tue, 14 Jul 2020 13:42:53 +0200
Subject: [PATCH] Added the remaining datamodel packages to the overall
 public/common environment and metainfo browser. #376

---
 examples/access_metainfo.py                   | 15 ++++---
 gui/src/components/Markdown.js                |  2 +-
 .../metaInfoBrowser/DefinitionCard.js         |  2 +-
 nomad/datamodel/datamodel.py                  | 11 +++--
 nomad/datamodel/dft.py                        |  2 +-
 nomad/datamodel/ems.py                        |  2 +-
 nomad/datamodel/encyclopedia.py               | 12 +++--
 nomad/datamodel/metainfo/__init__.py          |  6 +++
 nomad/metainfo/legacy.py                      | 45 ++++++++++++++-----
 9 files changed, 70 insertions(+), 27 deletions(-)

diff --git a/examples/access_metainfo.py b/examples/access_metainfo.py
index b3d9b8e12e..1d632c3a01 100644
--- a/examples/access_metainfo.py
+++ b/examples/access_metainfo.py
@@ -49,7 +49,7 @@ from nomad.datamodel.metainfo import m_env  # noqa, contains all common, public,
 from vaspparser.metainfo import m_env as vasp_m_env  # noqa, contains also the vasp specific definitions
 print(m_env.packages)
 # Resolve definition by name
-print(m_env.resolve_definition('atom_labels', metainfo.Quantity))
+print(m_env.resolve_definitions('number_of_atoms', metainfo.Quantity))
 # Traverse all definitions:
 for definition in m_env.m_all_contents():
     print(definition)
@@ -64,18 +64,14 @@ quantity = public.section_system.atom_labels
 for dim in quantity.shape:
     if isinstance(dim, str):
         section = quantity.m_parent
-        print('%s[%s]: %s' % (quantity.name, dim, m_env.resolve_definition(dim, metainfo.Quantity)))
+        print('%s[%s]: %s' % (quantity.name, dim, m_env.resolve_definitions(dim, metainfo.Quantity)))
 
 # All quantities used as dimensions in a package:
 for definition in public.m_package.m_all_contents():
     if definition.m_def == metainfo.Quantity.m_def:
         for dim in definition.shape:
             if isinstance(dim, str) and '..' not in dim:
-                try:
-                    print('%s[%s]: %s' % (quantity.name, dim, m_env.resolve_definition(dim, metainfo.Quantity)))
-                except KeyError:
-                    # metainfo is still not perfect
-                    print('does not exist: ' + dim)
+                print('%s[%s]: %s' % (quantity.name, dim, m_env.resolve_definitions(dim, metainfo.Quantity)))
 
 
 # Categories are special classes, similar to sections and they Python definition is a
@@ -90,3 +86,8 @@ print(public.m_package.category_definitions)
 print(public.m_package.section_definitions)
 # Access the categories of a metainfo definition, e.g. quantity
 print(public.section_single_configuration_calculation.energy_total.categories)
+
+
+print(m_env.resolve_definition('EntryMetadata', metainfo.Section).all_quantities)
+print(m_env.resolve_definition('Bulk', metainfo.Section).all_quantities)
+print(m_env.resolve_definition('OptimadeEntry', metainfo.Section).all_quantities)
\ No newline at end of file
diff --git a/gui/src/components/Markdown.js b/gui/src/components/Markdown.js
index c5618f0133..26f68dcccb 100644
--- a/gui/src/components/Markdown.js
+++ b/gui/src/components/Markdown.js
@@ -217,7 +217,7 @@ function Markdown(props) {
   return (
     <Typography variant="body1"
       className={classes.root}
-      dangerouslySetInnerHTML={{__html: marked(content)}}
+      dangerouslySetInnerHTML={{__html: marked(content || '')}}
     />
   )
 }
diff --git a/gui/src/components/metaInfoBrowser/DefinitionCard.js b/gui/src/components/metaInfoBrowser/DefinitionCard.js
index a60ad1d81c..7e1b77e48b 100644
--- a/gui/src/components/metaInfoBrowser/DefinitionCard.js
+++ b/gui/src/components/metaInfoBrowser/DefinitionCard.js
@@ -127,7 +127,7 @@ class DefinitionCardUnstyled extends React.Component {
   }
 
   renderDescription(description) {
-    description = description.replace(/[^([A-Za-z0-9](([A-Za-z0-9]+_)+[A-Za-z0-9]+)[^)[A-Za-z0-9]/g, '`$1`')
+    description = (description || '').replace(/[^([A-Za-z0-9](([A-Za-z0-9]+_)+[A-Za-z0-9]+)[^)[A-Za-z0-9]/g, '`$1`')
     return (
       <Markdown>{description}</Markdown>
     )
diff --git a/nomad/datamodel/datamodel.py b/nomad/datamodel/datamodel.py
index 1ef6454988..c7c0e22044 100644
--- a/nomad/datamodel/datamodel.py
+++ b/nomad/datamodel/datamodel.py
@@ -26,9 +26,14 @@ from nomad.metainfo.mongoengine_extension import Mongo, MongoDocument
 
 from .dft import DFTMetadata
 from .ems import EMSMetadata
-from .encyclopedia import EncyclopediaMetadata
-from .metainfo.public import section_run
-from .metainfo.general_experimental import section_experiment
+
+# This is usually defined automatically when the first metainfo definition is evaluated, but
+# due to the next imports requireing the m_package already, this would be too late.
+m_package = metainfo.Package()
+
+from .encyclopedia import EncyclopediaMetadata  # noqa
+from .metainfo.public import section_run  # noqa
+from .metainfo.general_experimental import section_experiment  # noqa
 
 
 def _only_atoms(atoms):
diff --git a/nomad/datamodel/dft.py b/nomad/datamodel/dft.py
index 5e5ae809bf..623d155899 100644
--- a/nomad/datamodel/dft.py
+++ b/nomad/datamodel/dft.py
@@ -19,7 +19,7 @@ DFT specific metadata
 import re
 
 from nomad import config, utils
-from nomad.metainfo import MSection, Section, Quantity, MEnum, SubSection
+from nomad.metainfo import MSection, Section, Quantity, MEnum, SubSection, Package
 from nomad.metainfo.search_extension import Search
 
 from .common import get_optional_backend_value
diff --git a/nomad/datamodel/ems.py b/nomad/datamodel/ems.py
index 89a8422bbe..0db370d554 100644
--- a/nomad/datamodel/ems.py
+++ b/nomad/datamodel/ems.py
@@ -17,7 +17,7 @@ Experimental material science specific metadata
 '''
 
 from nomad import config
-from nomad.metainfo import Quantity, MSection, Section, Datetime
+from nomad.metainfo import Quantity, MSection, Section, Datetime, Package
 from nomad.metainfo.search_extension import Search
 
 from .common import get_optional_backend_value
diff --git a/nomad/datamodel/encyclopedia.py b/nomad/datamodel/encyclopedia.py
index d8e77f19c8..a031a4d177 100644
--- a/nomad/datamodel/encyclopedia.py
+++ b/nomad/datamodel/encyclopedia.py
@@ -1,9 +1,15 @@
 import numpy as np
-from nomad.metainfo import MSection, Section, SubSection, Quantity, MEnum, Reference
-from nomad.datamodel.metainfo.public import section_k_band, section_dos, section_thermodynamical_properties
-from nomad.metainfo.search_extension import Search
 from elasticsearch_dsl import Text, Keyword
 
+from nomad.metainfo import MSection, Section, SubSection, Quantity, MEnum, Reference, Package
+from nomad.metainfo.search_extension import Search
+
+# This is usally defined automatically when the first metainfo definition is evaluated, but
+# due to the next imports requireing the m_package already, this would be too late.
+m_package = Package()
+
+from .metainfo.public import section_k_band, section_dos, section_thermodynamical_properties  # noqa
+
 
 class WyckoffVariables(MSection):
     m_def = Section(
diff --git a/nomad/datamodel/metainfo/__init__.py b/nomad/datamodel/metainfo/__init__.py
index ca3964e994..08f5e9f84a 100644
--- a/nomad/datamodel/metainfo/__init__.py
+++ b/nomad/datamodel/metainfo/__init__.py
@@ -9,3 +9,9 @@ m_env = LegacyMetainfoEnvironment()
 m_env.m_add_sub_section(Environment.packages, sys.modules['nomad.datamodel.metainfo.common'].m_package)  # type: ignore
 m_env.m_add_sub_section(Environment.packages, sys.modules['nomad.datamodel.metainfo.public'].m_package)  # type: ignore
 m_env.m_add_sub_section(Environment.packages, sys.modules['nomad.datamodel.metainfo.general'].m_package)  # type: ignore
+
+m_env.m_add_sub_section(Environment.packages, sys.modules['nomad.datamodel.datamodel'].m_package)  # type: ignore
+m_env.m_add_sub_section(Environment.packages, sys.modules['nomad.datamodel.dft'].m_package)  # type: ignore
+m_env.m_add_sub_section(Environment.packages, sys.modules['nomad.datamodel.ems'].m_package)  # type: ignore
+m_env.m_add_sub_section(Environment.packages, sys.modules['nomad.datamodel.encyclopedia'].m_package)  # type: ignore
+m_env.m_add_sub_section(Environment.packages, sys.modules['nomad.datamodel.optimade'].m_package)  # type: ignore
diff --git a/nomad/metainfo/legacy.py b/nomad/metainfo/legacy.py
index 113eb0b6a2..57b50bc011 100644
--- a/nomad/metainfo/legacy.py
+++ b/nomad/metainfo/legacy.py
@@ -54,6 +54,13 @@ class LegacyPackage(LegacyDefinition):
         self.python_path = python_path
 
 
+def def_name(definition):
+    try:
+        return definition.a_legacy.name
+    except AttributeError:
+        return definition.name
+
+
 def normalize_name(name: str):
     return name.replace('.', '_').replace('-', '_')
 
@@ -100,25 +107,42 @@ class LegacyMetainfoEnvironment(Environment):
 
     legacy_package_name = Quantity(type=str)
 
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        self.__section_to_sub_section_name = None
+
+    @property
+    def section_to_sub_section_name(self) -> Dict[str, str]:
+        if self.__section_to_sub_section_name is not None:
+            return self.__section_to_sub_section_name
+
+        self.__section_to_sub_section_name = dict()
+        for definition in self.m_all_contents():
+            if definition.m_def == SubSection.m_def:
+                self.__section_to_sub_section_name[definition.sub_section.name] = definition.name
+
+        return self.__section_to_sub_section_name
+
     def legacy_info(self, definition: Definition, *args, **kwargs) -> InfoKindEl:
         ''' Creates a legacy metainfo object for the given definition. '''
         super_names: List[str] = list()
         result: Dict[str, Any] = dict(
-            name=definition.a_legacy.name,
+            name=def_name(definition),
             description=definition.description,
             superNames=super_names)
 
         for category in definition.categories:
-            super_names.append(category.a_legacy.name)
+            super_names.append(def_name(category))
 
         if isinstance(definition, Section):
+            sub_section_name = self.section_to_sub_section_name.get(definition.name, definition.name)
             result['kindStr'] = 'type_section'
             result['repeats'] = any(
                 sub_section.repeats
-                for sub_section in self.resolve_definitions(definition.name, SubSection))
+                for sub_section in self.resolve_definitions(sub_section_name, SubSection))
 
-            for sub_section in self.resolve_definitions(definition.name, SubSection):
-                super_names.append(sub_section.m_parent_as(Definition).a_legacy.name)
+            for sub_section in self.resolve_definitions(sub_section_name, SubSection):
+                super_names.append(def_name(sub_section.m_parent_as(Definition)))
 
         elif isinstance(definition, Quantity):
             result['kindStr'] = 'type_document_content'
@@ -135,7 +159,7 @@ class LegacyMetainfoEnvironment(Environment):
             elif isinstance(definition.type, Reference):
                 dtype_str = 'r'
                 result['referencedSections'] = [
-                    definition.type.target_section_def.m_resolved().a_legacy.name]
+                    def_name(definition.type.target_section_def.m_resolved())]
             elif isinstance(definition.type, MEnum):
                 dtype_str = 'C'
             elif type(definition.type) == np.dtype:
@@ -143,12 +167,13 @@ class LegacyMetainfoEnvironment(Environment):
             elif definition.type == Any:
                 dtype_str = 'D'
             else:
-                raise TypeError(
-                    'Unsupported quantity type %s in %s.' % (definition.type, definition))
+                dtype_str = str(definition.type)
+                # raise TypeError(
+                #     'Unsupported quantity type %s in %s.' % (definition.type, definition))
             result['dtypeStr'] = dtype_str
             if definition.unit is not None:
                 result['units'] = str(definition.unit)
-            super_names.append(definition.m_parent_as(Definition).a_legacy.name)
+            super_names.append(def_name(definition.m_parent_as(Definition)))
 
         elif isinstance(definition, Category):
             result['kindStr'] = 'type_abstract_document_content'
@@ -215,7 +240,7 @@ class LegacyMetainfoEnvironment(Environment):
             'type': 'nomad_meta_info_1_0',
             'description': description,
             'dependencies': [
-                {'relativePath': dependency.a_legacy.name}
+                {'relativePath': def_name(dependency)}
                 for dependency in dependencies],
             'metaInfos': definitions
         }
-- 
GitLab