hermes.model.context
====================

.. py:module:: hermes.model.context


Attributes
----------

.. autoapisummary::

   hermes.model.context._log


Classes
-------

.. autoapisummary::

   hermes.model.context.HermesContext
   hermes.model.context.HermesHarvestContext
   hermes.model.context.CodeMetaContext


Module Contents
---------------

.. py:data:: _log

.. py:class:: HermesContext(project_dir: Optional[pathlib.Path] = None)

   The HermesContext stores the metadata for a certain project.

   As there are different views of the metadata in the different stages,
   some stages use a special subclass of this context:

   - The *harvest* stages uses :class:`HermesHarvestContext`.


   .. py:attribute:: default_timestamp


   .. py:attribute:: hermes_name
      :value: 'hermes'



   .. py:attribute:: hermes_cache_name
      :value: '.hermes'



   .. py:attribute:: hermes_lod_context


   .. py:attribute:: hermes_dir


   .. py:attribute:: _caches


   .. py:attribute:: _data


   .. py:attribute:: _errors
      :value: []



   .. py:attribute:: contexts


   .. py:method:: __getitem__(key: hermes.model.path.ContextPath | str) -> Any

      Access a single entry from the context.

      :param key: The path to the item that should be retrieved.
                  Can be in dotted syntax or as a :class:`ContextPath` instance.
      :return: The value stored under the given key.



   .. py:method:: keys() -> List[hermes.model.path.ContextPath]

      Get all the keys for the data stored in this context.



   .. py:method:: init_cache(*path: str) -> pathlib.Path

      Initialize a cache directory if not present.

      :param path: The (local) path to identify the requested cache.
      :return: The path to the requested cache file.



   .. py:method:: get_cache(*path: str, create: bool = False) -> pathlib.Path

      Retrieve a cache file for a given *path*.

      This method returns an appropriate path to a file but does not make any assertions about the format, encoding,
      or whether the file should be exists.
      However, it is capable to create the enclosing directory (if you specify `create = True`).

      :param path: The (local) path to identify the requested cache.
      :param create: Select whether the directory should be created.
      :return: The path to the requested cache file.



   .. py:method:: update(_key: str, _value: Any, **kwargs: Any)

      Store a new value for a given key to the context.

      :param _key: The key may be a dotted name for a metadata attribute to store.
      :param _value: The value that should be stored for the key.
      :param kwargs: Additional information about the value.
                     This can be used to trace back the original value.
                     If `_ep` is given, it is treated as an entry point name that triggered the update.



   .. py:method:: get_data(data: Optional[dict] = None, path: Optional[hermes.model.path.ContextPath] = None, tags: Optional[dict] = None) -> dict


   .. py:method:: error(ep: importlib.metadata.EntryPoint, error: Exception)

      Add an error that occurred during processing to the error log.

      :param ep: The entry point that produced the error.
      :param error: The exception that was thrown due to the error.



   .. py:method:: purge_caches() -> None

      Delete `.hermes` cache-directory if it exsis.



   .. py:method:: add_context(new_context: tuple) -> None

      Add a new linked data context to the harvest context.

      :param new_context: The new context as tuple (context name, context URI)



.. py:class:: HermesHarvestContext(base: HermesContext, ep: importlib.metadata.EntryPoint, config: dict = None)

   Bases: :py:obj:`HermesContext`


   A specialized context for use in *harvest* stage.

   Each harvester has its own context that is cached to :py:attr:`HermesContext.hermes_dir` `/harvest/EP_NAME`.

   This special context is implemented as a context manager that loads the cached data upon entering the context.
   When the context is left, recorded metadata is stored in a cache file possible errors are propagated to the
   parent context.


   .. py:attribute:: _base


   .. py:attribute:: _ep


   .. py:attribute:: _log


   .. py:method:: load_cache()

      Load the cached data from the :py:attr:`HermesContext.hermes_dir`.



   .. py:method:: store_cache()

      Store the collected data to the :py:attr:`HermesContext.hermes_dir`.



   .. py:method:: __enter__()


   .. py:method:: __exit__(exc_type, exc_val, exc_tb)


   .. py:method:: update(_key: str, _value: Any, **kwargs: Any)

      The updates are added to a list of values.
      A value is only replaced if the `_key` and all `kwargs` match.

      .. code:: python

          # 'value 2' will be added (twice)
          ctx.update('key', 'value 1', spam='eggs')
          ctx.update('key', 'value 2', foo='bar')
          ctx.update('key', 'value 2', foo='bar', spam='eggs')

          # 'value 2' will replace 'value 1'
          ctx.update('key', 'value 1', spam='eggs')
          ctx.update('key', 'value 2', spam='eggs')

      This way, the harvester can fully specify the source and only override values that are from the same origin
      (e.g., if the data changed between two runs).

      See :py:meth:`HermesContext.update` for more information.



   .. py:method:: _update_key_from(_key: hermes.model.path.ContextPath, _value: Any, **kwargs)


   .. py:method:: update_from(data: Dict[str, Any], **kwargs: Any)

      Bulk-update multiple values.

      If the value for a certain key is again a collection, the key will be expanded:

      .. code:: python

          ctx.update_from({'arr': ['foo', 'bar'], 'author': {'name': 'Monty Python', 'email': 'eggs@spam.xxx'}})

      will eventually result in the following calls:

      .. code:: python

          ctx.update('arr[0]', 'foo')
          ctx.update('arr[1]', 'bar')
          ctx.update('author.name', 'Monty Python')
          ctx.update('author.email', 'eggs@spam.xxx')

      :param data: The data that should be updated (as mapping with strings as keys).
      :param kwargs: Additional information about the value (see :py:meth:`HermesContext.update` for details).



   .. py:method:: error(ep: importlib.metadata.EntryPoint, error: Exception)

      See :py:meth:`HermesContext.error`



   .. py:method:: _check_values(path, values)


   .. py:method:: get_data(data: Optional[dict] = None, path: Optional[hermes.model.path.ContextPath] = None, tags: Optional[dict] = None) -> dict

      Retrieve the data from a given path.

      This method can be used to extract data and whole sub-trees from the context.
      If you want a complete copy of the data, you can also call this method without giving a path.

      :param data: Optional a target dictionary where the data is stored. If not given, a new one is created.
      :param path: The path to extract data from.
      :param tags: An optional dictionary to collect the tags that belong to the extracted data.
                   The full path will be used as key for this dictionary.
      :return: The extracted data (i.e., the `data` parameter if it was given).



   .. py:method:: finish()

      Calling this method will lead to further processors not handling the context anymore.



.. py:class:: CodeMetaContext(project_dir: pathlib.Path | None = None)

   Bases: :py:obj:`HermesContext`


   The HermesContext stores the metadata for a certain project.

   As there are different views of the metadata in the different stages,
   some stages use a special subclass of this context:

   - The *harvest* stages uses :class:`HermesHarvestContext`.


   .. py:attribute:: _PRIMARY_ATTR


   .. py:attribute:: _CODEMETA_CONTEXT_URL
      :value: 'https://doi.org/10.5063/schema/codemeta-2.0'



   .. py:attribute:: tags


   .. py:method:: merge_from(other: HermesHarvestContext)


   .. py:method:: merge_contexts_from(other: HermesHarvestContext)

      Merges any linked data contexts from a harvesting context into the instance's set of contexts.

      :param other: The :py:class:`HermesHarvestContext` to merge the linked data contexts from



   .. py:method:: update(_key: hermes.model.path.ContextPath, _value: Any, tags: Dict[str, Dict] | None = None)

      Store a new value for a given key to the context.

      :param _key: The key may be a dotted name for a metadata attribute to store.
      :param _value: The value that should be stored for the key.
      :param kwargs: Additional information about the value.
                     This can be used to trace back the original value.
                     If `_ep` is given, it is treated as an entry point name that triggered the update.



   .. py:method:: find_key(item, other)


   .. py:method:: prepare_codemeta()

      Updates the linked data contexts, where the CodeMeta context is the default context,
      and any additional contexts are named contexts.
      Also sets the type to 'SoftwareSourceCode'.



