Skip to content

Component Writing Overview / Tips

Components are the base artifacts of hetida designer. This page describes some options you have which faciliate their development, debugging and testing. Click on headings to reach more detailed documentation for each feature

Logging

Logging should be used as usual with the help of the standard library:

import logging
logger = logging.getLogger(__name__)
# ...
def main(...):
    # ...
    logger.info("Log message")

During execution log messages from inside components emitted this way are captured and returned as part of the execution result. In hetida designer execution result view these log messages are displayed.

Debugging

print(...) and setting breakpoints will not work for debugging, since component code is run remotely.

You can use logging instead as described above for basic debugging purposes. Or you can raise an exception containing relevant debugging information in its message.

Exceptions

There are predefined exception classes that you can use or derive your own exception classes from. These allow to add extra information like an error_code string or integer which then become a part of the execution response and can be handled in structured way by external services.

from hdutils import (
    ComponentException,
    ComponentInputValidationException,
    InsufficientPlottingData,
    IntentionallyAbortedExecution
)

    ...
    raise ComponentException("This makes no sense", error_code=123)
    ...
    raise ComponentInputValidationException(
        "The series must not be empty!",
        error_code="EmptySeries",
        invalid_component_inputs=["series_inpute"]
    )    
    ...
    raise InsufficientPlottingData("Not enough data for plotting.")
    ...
    raise IntentionallyAbortedExecution("Preconditions not fulfilled. Aborting")

Unit Tests

Components can contain unit tests (pytest) directly in their component code, i.e. functions prefixed with test_. Doctests are also supported.

Unit tests can be run from the designer user interface using the "bug" toolbar button at the top of the component editor tab:

Importing other components

It is possible to import other components and use functions / classes etc from them:

from hetdesrun.component.load import import_comp
# refer to other component by its id:
my_other_component = import_comp("abcdef12-4567-890a-bcde-f1234567890a")
func_from_other = my_other_component.func_from_other

# ...
def main(...):
    # ...
    func_from_other(...)
    # ...

You can obtain another component's id by opening its "Edit component details" dialogue (pencil icon) in hetida designer.

If the id is valid, you can hover over it in the code to see its name and version and you can ctrl+click on it to access the imported component.

Note that for releasing, all imported components must also be released.

Note also that import_comp must be called in a global assignment statement for this to work.

Resolving possibly relative time intervals

Especially relevant for component adapter source components for MULTITSFRAME or SERIES:

Add timestampFrom and timestampTo required inputs of type STRING. With the following code they can be provided as absolute timestamps as well as dtexp relative expressions like now - 10min and will be resolved with the execution timestamp as now:

from hetdesrun.dt_utils import resolve_interval

...

def main(...):
    start, end = resolve_interval(timestampFrom, timestampTo)
    # start, end are now utc timezoned datetime objects

Importing/Uploading a component into a hetida designer installation

The home tab has an upload button at its bottom left corner. You can simply paste a component's code in the opened dialog to get it into this designer installation.

Since components are self-contained and their code is / can be made a faithful representation that includes documentation, desired test and release wiring via the broom toolbar button (see next section!), this is the easiest way to share components between installations.

If your component imports other components, you should of course upload them as well.

Special / Generated Parts

Component code contains parts generated by hetide designer:

  • COMPONENT_INFO and main function definition
  • module docstring, if not present, can be obtained from the markdown documentation by pressing the "broom" button. To update it from the documentation you must delete an existing module docstring first.
  • TEST_WIRING_FROM_PY_FILE_IMPORT and RELEASE_WIRING global variables, which define the respective wirings during import from code.

Together these parts can make the component code a complete representation of the component which enables importing faithfully form component code. See special code parts docs to see what can be edited and how.

What should I do before releasing a component?

Recommendations:

  • Consider adding some unit tests
  • Update markdown documentation in documentation tab.
  • Delete current module docstring
  • Press broom toolbar button
  • Copy value of TEST_WIRING_FROM_PY_FILE_IMPORT and paste it as value for RELEASE_WIRING.
  • Ensure name, description, category and version tag are up-to-date, descriptive and meaningful. Prefer semver version tags.
  • Release

Should I use type annotations in component code?

Recommendation is: No.

1st reason: The hetida designer UI does not provide a type checker, so it will not be of much help there.

2nd reason: Components are small, typically self-contained pieces of analytical (i.e. not deep software engineering) code with a relatively clear interface provided by the main function signature and corresponding IO configuration. Component code should be easily readable, understandable by non-software engineers and the barrier to extend them or creating variants should be low.

However you are of course free to add type annotations and even check them externally, e.g. in a "hybrid" working setup using hdctl sync.