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 import | New import (ewx-public) |
|---|---|
from energyworx.rules.base_rule import AbstractRule | from ewx_public.flow_rule import FlowRule |
from energyworx_public.rule import AbstractTransformRule | from ewx_public.transform_rule import TransformRule |
from energyworx.domain import RuleResult | from ewx_public.rule_result import RuleResult |
from energyworx_public.domain import FlowCancelException | from ewx_public.exceptions import FlowCancelException |
from energyworx_public.domain import FlowStopException | from 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 stu | from ewx_public.testing import standard_test_utils as stu (see Series generators below) |
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.
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:
StandardUtilswas a class in the internal libraries.ewx-publicexposes the equivalent helpers as standalone functions inewx_public.standard_utils(there is noStandardUtilsclass) — call them directly.SEQUENCE_ID_SEPARATORwas an internal constant equal to the literal":". It is not exported byewx-public; if you relied on it, define the literal in your own code.standard_constants/StandardConstantsbelonged to the internal standard-rules library and are not shipped inewx-public. Rules that referenced them need to be reworked per-constant rather than via a drop-in import.Tag.tag_linksandTag.is_active_scdwere fields on the legacyenergyworx.domain.Tagand have no equivalent on theewx_publicTag. They are absent from the model and fromto_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:
| Class | Import | Purpose |
|---|---|---|
FlowRule | from ewx_public.flow_rule import FlowRule | Base class for flow rules (replaces AbstractRule) |
TransformRule | from ewx_public.transform_rule import TransformRule | Base class for transform rules (replaces AbstractTransformRule) |
RuleResult | from ewx_public.rule_result import RuleResult | Required return type for flow rule apply methods |
FlowCancelException | from ewx_public.exceptions import FlowCancelException | Cancel a flow execution |
FlowStopException | from ewx_public.exceptions import FlowStopException | Stop 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)
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 / Class | Import | Purpose |
|---|---|---|
make_testable(RuleClass, ...) | from ewx_public.testing import make_testable | Wrap any FlowRule subclass for local testing |
TestableFlowRule | from ewx_public.testing import TestableFlowRule | The concrete FlowRule used under the hood by make_testable |
Factory Functions
Create test objects with sensible defaults — all keyword-only with auto-incrementing IDs:
| Function | Creates |
|---|---|
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.
| Function | Checks |
|---|---|
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 / Function | Purpose |
|---|---|
InMemoryBackend | Stores 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. |
CapturingLogger | Default logger — records messages for assertion via .infos, .warnings, .errors |
InMemoryTimeseriesService | Backs self.timeseries_service — seed data with rule.backend.add_timeseries() |
InMemoryDatasourceService | Backs self.datasource_service — seed with rule.backend.add_datasource() |
NullObject | Default 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
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.
| Function | Creates |
|---|---|
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.