Beispiel #1
0
    def write(self,
              file_path: Union[str, pathlib.Path],
              write_level: Optional[enums.WriteLevel] = None) -> None:
        """Write a dataset to file"""
        write_level = (min(enums.get_enum("write_level"))
                       if write_level is None else enums.get_value(
                           "write_level", write_level))
        log.debug(f"Write dataset to {file_path} with {write_level}")

        # Make sure directory exists
        file_path = pathlib.Path(file_path).resolve()
        file_path.parent.mkdir(parents=True, exist_ok=True)

        memo = self._construct_memo()
        with h5py.File(file_path, mode="w") as h5_file:

            # Write each field
            for field_name, field in self._fields.items():
                if field.write_level >= write_level:
                    h5_group = h5_file.create_group(field_name)
                    field.write(h5_group, memo, write_level=write_level)

            # Write meta-information
            self.meta.write(h5_file.create_group("__meta__"))

            # Write information about dataset
            fields = {
                fn: f.fieldtype
                for fn, f in self._fields.items()
                if f.write_level >= write_level
            }
            h5_file.attrs["fields"] = _h5utils.encode_h5attr(fields)
            h5_file.attrs["num_obs"] = self.num_obs
            h5_file.attrs["vars"] = _h5utils.encode_h5attr(self.vars)
            h5_file.attrs["version"] = self.version
Beispiel #2
0
class Logger(abc.ABC):
    """Abstract class that can be specialized to create new loggers"""

    name = "logger"
    log_levels = enums.get_enum("log_level")

    def __init__(self, log_level: Optional[str] = None, prefix: str = ""):
        """Register as an active logger, and set up parameters"""
        _ACTIVE_LOGGERS[self.name] = self

        # Use "warn" as default log level, None used as default parameter to allow for other default behaviours
        log_level = "warn" if log_level is None else log_level

        # Check and set log_level and prefix
        self.log_level = log_level
        self.prefix = prefix

    @property
    def log_level(self) -> LogLevel:
        """Log level as an enum"""
        return self._log_level

    @log_level.setter
    def log_level(self, value: str) -> None:
        """Set log level using string, checks that log level is a valid level"""
        self._log_level = enums.get_value("log_level", value)

    @property
    def prefix(self) -> str:
        """Prefix before log text"""
        return self._prefix

    @prefix.setter
    def prefix(self, value: str) -> None:
        """Set prefix"""
        self._prefix = f"[{value}] " if value else ""

    @classmethod
    def is_level(cls, level: str) -> bool:
        """Checks that level is a valid log level"""
        return enums.has_value("log_level", level)

    @classmethod
    def get_color(cls, level: LogLevel) -> str:
        """Get color string for the given log level"""
        return enums.get_value("log_color", level.name, default="")

    @abc.abstractmethod
    def blank(self) -> None:
        """Log blank line"""

    @abc.abstractmethod
    def log(self, level: LogLevel, log_text: str) -> None:
        """Log text at given level"""

    def __repr__(self):
        """Representation of logger"""
        return f"{type(self).__name__}({self.name!r}, log_level={self.log_level.name!r})"
Beispiel #3
0
    def __init__(self, num_obs, name, val=None, unit=None, write_level=None, multiplier=1, **field_args):
        """Create a new field"""
        self.num_obs = num_obs
        self.name = name
        self._unit = unit
        self._write_level = (
            max(enums.get_enum("write_level")) if write_level is None else enums.get_value("write_level", write_level)
        )

        # Use _post_init to set up the actual data structure
        self.data = None
        self.multiplier = multiplier
        self._post_init(val, **field_args)
Beispiel #4
0
    INFO  [My prefix] Calculating the inverse of a  5x3  matrix

"""
# Standard library imports
import abc
from datetime import datetime
import functools
import pathlib
import sys
from typing import Callable, Optional, Union

# Midgard imports
from midgard.collections import enums

# LogLevel type
LogLevel = enums.get_enum("log_level")

# Overview over active loggers
_ACTIVE_LOGGERS = dict()


#
# Loggers
#
class Logger(abc.ABC):
    """Abstract class that can be specialized to create new loggers"""

    name = "logger"
    log_levels = enums.get_enum("log_level")

    def __init__(self, log_level: Optional[str] = None, prefix: str = ""):
Beispiel #5
0
def test_getting_non_existing_enum():
    """Test that getting a non-existing enum raises appropriate error"""
    with pytest.raises(exceptions.UnknownEnumError):
        enums.get_enum("non_existing")
Beispiel #6
0
def test_getting_known_enum():
    """Test that getting 'my_enum' returns MyEnum"""
    my_enum = enums.get_enum("my_enum")
    assert my_enum is MyEnum
Beispiel #7
0
def test_registering_enum_dont_alter():
    """Test that registering an enum does not alter it"""
    enum_name = "my_new_enum"
    enums.register_enum(enum_name)(NonRegisteredEnum)
    assert enums.get_enum(enum_name) is NonRegisteredEnum