Skip to main content

ewx-public Package

The ewx-public package provides the public API for writing custom rules on the Energyworx platform. By installing this package locally, you get type hints, IDE autocompletion, and the ability to develop and test rules outside the platform.

For installation, see the ewx-public package page. For local development setup (writing rules, unit-testing locally, uploading to the platform), see Local Rule Development.

Pin ewx-public to the version that matches the platform release you target — for platform release YY.MM the package version is YY.M.0 (e.g. platform 26.03 ships ewx-public==26.3.0). See Versioning for details.

Migrating from the Legacy Packages

ewx-public replaces the older energyworx_public and energyworx packages that were previously used for rule development. The main changes are:

Legacy importNew import (ewx-public)
from energyworx.rules.base_rule import AbstractRulefrom ewx_public.flow_rule import FlowRule
from energyworx_public.rule import AbstractTransformRulefrom ewx_public.transform_rule import TransformRule
from energyworx.domain import RuleResultfrom ewx_public.rule_result import RuleResult
from energyworx_public.domain import FlowCancelExceptionfrom ewx_public.exceptions import FlowCancelException
from energyworx_public.domain import FlowStopExceptionfrom ewx_public.exceptions import FlowStopException
from energyworx.enum import ... (enums such as DatasourceType, UnitType, TagType)from ewx_public.enums import ...
from energyworx.domain import ... (models such as Datasource, Channel, Tag, TimesliceGroup)from ewx_public.domain.models import ...
StandardUtils.<helper>(...) (utility class)Standalone functions in ewx_public.standard_utils, e.g. from ewx_public.standard_utils import parse_date
from energyworx_public import standard_test_utils as stufrom ewx_public.testing import standard_test_utils as stu (see Series generators below)
Backwards compatibility

The legacy imports (energyworx_public and energyworx) continue to work on the platform. You do not need to update existing rules. However, for new rules we recommend using ewx-public as it provides better type hints and IDE support.

Not part of the public API

Some symbols from the legacy energyworx / std-grid internal libraries have no ewx-public equivalent because they were never part of the public rule-authoring API:

  • StandardUtils was a class in the internal libraries. ewx-public exposes the equivalent helpers as standalone functions in ewx_public.standard_utils (there is no StandardUtils class) — call them directly.
  • SEQUENCE_ID_SEPARATOR was an internal constant equal to the literal ":". It is not exported by ewx-public; if you relied on it, define the literal in your own code.
  • standard_constants / StandardConstants belonged to the internal standard-rules library and are not shipped in ewx-public. Rules that referenced them need to be reworked per-constant rather than via a drop-in import.
  • Tag.tag_links and Tag.is_active_scd were fields on the legacy energyworx.domain.Tag and have no equivalent on the ewx_public Tag. They are absent from the model and from to_dict() output, so expected dictionaries carried over from std-grid need those keys removed. See Rule framework functions for the current structure.

What's Included

The package provides the base classes and models needed to write custom rules:

ClassImportPurpose
FlowRulefrom ewx_public.flow_rule import FlowRuleBase class for flow rules (replaces AbstractRule)
TransformRulefrom ewx_public.transform_rule import TransformRuleBase class for transform rules (replaces AbstractTransformRule)
RuleResultfrom ewx_public.rule_result import RuleResultRequired return type for flow rule apply methods
FlowCancelExceptionfrom ewx_public.exceptions import FlowCancelExceptionCancel a flow execution
FlowStopExceptionfrom ewx_public.exceptions import FlowStopExceptionStop a flow execution

Domain models such as Datasource, Channel, Tag, TimesliceGroup, FlowConfiguration, and ChannelClassifier are also available under ewx_public.domain.models.

For details on rule structure, available methods, and design patterns, see the other pages in this section.

Testing Module (ewx_public.testing)

Availability

The ewx_public.testing subpackage is available from platform release 26.05 onwards (package version ewx-public==26.5.0). Pin to that version or later to use the testing utilities described below.

The ewx_public.testing subpackage provides everything needed to unit-test custom rules locally, without the Energyworx platform. A single pip install ewx-public includes both the rule base classes and the testing utilities.

from ewx_public.testing import make_testable, make_datasource, make_timeseries_df
from ewx_public.testing import assert_timeseries_stored

Core API

Function / ClassImportPurpose
make_testable(RuleClass, ...)from ewx_public.testing import make_testableWrap any FlowRule subclass for local testing
TestableFlowRulefrom ewx_public.testing import TestableFlowRuleThe concrete FlowRule used under the hood by make_testable

Factory Functions

Create test objects with sensible defaults — all keyword-only with auto-incrementing IDs:

FunctionCreates
make_datasource(id=, channels=, tags=, timezone=)Datasource
make_channel(name=, classifier=)Channel
make_tag(tag=, properties=)Tag (includes a default property)
make_tag_property(key=, value=)TagProperty
make_timeseries_df(columns=, start=, periods=, freq=, timezone=)pd.DataFrame with DatetimeIndex
make_namespace(id=, name=)Namespace (for rules accessing self.namespace)
make_flow_configuration(id=, name=)FlowConfiguration
make_channel_classifier(name=)ChannelClassifier
make_timeslice_group(name=)TimesliceGroup
reset_factory_counters()Resets auto-incrementing IDs for deterministic tests

Assertion Helpers

Check rule side effects with descriptive error messages. The count parameter: None = at least one, 0 = none, integer = exact count.

FunctionChecks
assert_timeseries_stored(rule, channel_id=, datasource_id=, count=)store_timeseries() calls
assert_annotations_stored(rule, channel_id=, count=)store_annotations() calls
assert_tags_added(rule, datasource_id=, tag_name=, count=)add_tags() calls
assert_channel_renamed(rule, channel_classifier=, name=, datasource_id=, count=)set_channel_name() calls
assert_trigger_sent(rule, trigger_type=, count=)trigger_flow() / publish_to_custom_pubsub_topic() calls
assert_email_sent(rule, to_email=, cc_email=, subject_contains=, severity=, count=)send_email() calls
assert_task_created(rule, title_contains=, count=)create_task() calls
assert_counter_value(rule, counter_name, expected_value)Counter values
assert_logged(rule, level=, message_contains=, count=)Log messages

Stubs and Utilities

Class / FunctionPurpose
InMemoryBackendStores all rule side effects in plain dicts/lists. Accessible via rule.backend. Email link placeholders that failed to resolve are collected on rule.backend.link_problems.
CapturingLoggerDefault logger — records messages for assertion via .infos, .warnings, .errors
InMemoryTimeseriesServiceBacks self.timeseries_service — seed data with rule.backend.add_timeseries()
InMemoryDatasourceServiceBacks self.datasource_service — seed with rule.backend.add_datasource()
NullObjectDefault for self.services / self.trigger_service — absorbs any attribute access
raising(exc_type, message)Returns a callable that raises the given exception when called

Series generators

ewx_public.testing also ships the standard_test_utils helpers for building synthetic input series in rule tests — the same generators that were previously only available in the legacy energyworx_public.standard_test_utils. Import the module (aliased as stu) or the functions directly:

from ewx_public.testing import standard_test_utils as stu
# or: from ewx_public.testing import create_sinusoidal_series
Availability

The series generators are available from ewx-public 26.8.0 onwards, and have been backported to recent 26.05, 26.06 and 26.07 patch releases.

FunctionCreates
create_monotonic_series(start_date, freq=, periods=, ...)A monotonically increasing pd.Series (e.g. register readings)
create_sinusoidal_series(start_date, freq=, periods=, ...)A sinusoidal pd.Series
create_seasonal_series(start_year, n_years=, yearly=, weekly=, daily=)A pd.Series with yearly / weekly / daily seasonality
create_register_channels(n, name_maker=, **kwargs)An iterator of (name, pd.Series) register channels
create_index_for_timeseries(start_date, end_date, periods, freq, at_start)A pd.DatetimeIndex for a timeseries
annotate_series(ds, annotation_rules_csl, perc_of_annotations=)A pd.DataFrame of the series plus annotation columns

For a complete guide with examples, see Unit Testing Rules: A Practical Guide.