Skip to content

refactor(system): add historian.types submodule#28

Merged
cesarcoatl merged 2 commits into8.3from
8.3-feat/system/historian.types
Apr 28, 2026
Merged

refactor(system): add historian.types submodule#28
cesarcoatl merged 2 commits into8.3from
8.3-feat/system/historian.types

Conversation

@cesarcoatl
Copy link
Copy Markdown
Member

@cesarcoatl cesarcoatl commented Apr 28, 2026

Summary by Sourcery

Introduce historian point type helpers and supporting model types while updating Java API dependencies.

New Features:

  • Add system.historian.types module with helpers to create annotation, data, and metadata points for storage in the historian API.

Enhancements:

  • Define historian model data abstractions (points, annotations, metadata, and standard complex point types) and expose them via a new common model data package with corresponding type stubs.
  • Extend system.historian public API stubs to include type helper functions and existing historian operations for improved typing support.

Build:

  • Bump java-api and java-api-stubs dependencies from 17.26.0 to 17.26.5.

@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai Bot commented Apr 28, 2026

Reviewer's Guide

Introduces a new historian.types system-level helper module and corresponding Java historian data model stubs, while bumping the java-api dependency to expose those model types and wiring new system.historian types stubs into the public API surface.

Class diagram for new historian data model types

classDiagram
    class SnapshotCapable {
        +bool isSnapshot()
        +Instant snapshotTime()
        +SnapshotCapable withSnapshot(Instant timestamp)
    }

    class TemporalPoint {
        +int compareTo(TemporalPoint other)
        +QualifiedPath source()
        +Instant timestamp()
        +Any type()
        +Any value()
    }

    class DataPoint {
        +QualityCode quality()
        +Any valueClass()
    }

    class AtomicPoint {
    }

    class Annotation {
        +Annotation(notes, type_, author)
        +str author()
        +str notes()
        +str type()
    }

    class AnnotationPoint {
        +AnnotationPoint(identifier, source, value, startTime, endTime, lastUpdated)
        +static Builder builder()
        +Instant endTime()
        +UUID identifier()
        +Instant lastUpdated()
        +QualifiedPath source()
        +Instant startTime()
        +Instant timestamp()
        +StandardComplexPointType type()
        +Annotation value()
        +AnnotationPoint withSource(QualifiedPath source)
    }

    class AnnotationPoint_Builder {
        +AnnotationPoint_Builder()
        +AnnotationPoint_Builder annotationType(str annotationType)
        +AnnotationPoint_Builder author(str author)
        +AnnotationPoint build()
        +AnnotationPoint_Builder endTime(Instant endTime)
        +AnnotationPoint_Builder identifier(UUID identifier)
        +AnnotationPoint_Builder lastUpdated(Instant lastUpdated)
        +AnnotationPoint_Builder notes(str notes)
        +AnnotationPoint_Builder source(QualifiedPath source)
        +AnnotationPoint_Builder startTime(Instant startTime)
    }

    class MetadataPoint {
        +MetadataPoint(value, quality, timestamp, source)
        +static Builder builder(MetadataPoint metadataPoint)
        +static MetadataPoint empty(QualifiedPath source)
        +QualityCode quality()
        +MetadataPoint withSource(QualifiedPath source)
    }

    class MetadataPoint_Builder {
        +MetadataPoint_Builder()
        +MetadataPoint_Builder addValue(PropertyValue value)
        +MetadataPoint build()
        +MetadataPoint_Builder quality(QualityCode quality)
        +MetadataPoint_Builder source(QualifiedPath source)
        +MetadataPoint_Builder timestamp(Instant timestamp)
        +MetadataPoint_Builder values(PropertySet values)
    }

    class StandardComplexPointType {
        <<enum>>
        +StandardComplexPointType ANNOTATION
        +StandardComplexPointType GENERIC
        +StandardComplexPointType METADATA
        +Class getPointClass()
        +Class getQueryOptionsClass()
        +List~StandardComplexPointType~ values()
    }

    class Record {
    }

    class Enum {
    }

    SnapshotCapable <|-- DataPoint
    TemporalPoint <|-- DataPoint
    DataPoint <|-- AtomicPoint

    Record <|-- Annotation
    Record <|-- AnnotationPoint
    Record <|-- MetadataPoint

    TemporalPoint <|-- MetadataPoint
    Enum <|-- StandardComplexPointType

    AnnotationPoint o-- Annotation
    AnnotationPoint ..> StandardComplexPointType

    AnnotationPoint_Builder --> AnnotationPoint
    MetadataPoint_Builder --> MetadataPoint
Loading

Class diagram for system.historian.types helper API

classDiagram
    class SystemHistorianTypes {
        +AnnotationPoint annotationPoint(str source, Date startTime, Date endTime, str annotationType, str data, str identifier)
        +AtomicPoint dataPoint(str source, object value, Date timestamp, int quality)
        +MetadataPoint metadataPoint(str source, Dict properties, Date timestamp)
    }

    class AnnotationPoint {
    }

    class AtomicPoint {
    }

    class MetadataPoint {
    }

    SystemHistorianTypes ..> AnnotationPoint
    SystemHistorianTypes ..> AtomicPoint
    SystemHistorianTypes ..> MetadataPoint
Loading

File-Level Changes

Change Details Files
Add Python shims and stubs for historian data model types used by new system.historian.types helpers.
  • Create com.inductiveautomation.historian.common.model.data package with SnapshotCapable, TemporalPoint, DataPoint, AtomicPoint, Annotation, AnnotationPoint, MetadataPoint, and StandardComplexPointType placeholder implementations for use from Jython.
  • Add matching type stub file defining full signatures for the historian data model classes, builders, and enums for static type checking.
src/com/inductiveautomation/historian/common/model/data/__init__.py
stubs/stubs/com/inductiveautomation/historian/common/model/data/__init__.pyi
Introduce system.historian.types helper API and its stubs for constructing historian point objects.
  • Add system.historian.types module exposing annotationPoint, dataPoint, and metadataPoint factory functions that will create historian model objects.
  • Define the corresponding .pyi stub for system.historian.types so that scripting docs and type checkers know the exact parameter and return types of the new helpers.
  • Add a system.historian package stub with signatures for browse, query, store, and update functions to complete the historian scripting API surface.
src/system/historian/types.py
stubs/stubs/system/historian/__init__.py
stubs/stubs/system/historian/types.pyi
Update java-api dependency and its stubs to a newer patch version to align with the added historian model types.
  • Bump java-api from 17.26.0 to 17.26.5 in runtime requirements with updated hashes.
  • Bump java-api-stubs from 17.26.0 to 17.26.5 in stubs requirements.
requirements.txt
stubs/requirements.txt

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 4 issues, and left some high level feedback:

  • The new system.historian.types helpers are currently effectively no-ops (annotationPoint ignores all arguments and dataPoint/metadataPoint don’t construct or return anything), which will lead to confusing runtime behavior; either wire these through to the underlying Java APIs or explicitly raise NotImplementedError so misuse fails loudly.
  • In AnnotationPoint.__init__ and MetadataPoint.__init__, the print(...) calls introduce unexpected side effects for what appear to be model/typing shims; consider removing these and, if needed, storing arguments on private attributes instead to keep the module side-effect free.
  • For the builder-style methods on AnnotationPoint.Builder and MetadataPoint.Builder in the runtime module, the bodies are empty pass implementations; aligning them with the stubs by returning self (or raising NotImplementedError) will prevent confusing attribute errors or NoneType issues at runtime.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The new `system.historian.types` helpers are currently effectively no-ops (`annotationPoint` ignores all arguments and `dataPoint`/`metadataPoint` don’t construct or return anything), which will lead to confusing runtime behavior; either wire these through to the underlying Java APIs or explicitly raise `NotImplementedError` so misuse fails loudly.
- In `AnnotationPoint.__init__` and `MetadataPoint.__init__`, the `print(...)` calls introduce unexpected side effects for what appear to be model/typing shims; consider removing these and, if needed, storing arguments on private attributes instead to keep the module side-effect free.
- For the builder-style methods on `AnnotationPoint.Builder` and `MetadataPoint.Builder` in the runtime module, the bodies are empty `pass` implementations; aligning them with the stubs by returning `self` (or raising `NotImplementedError`) will prevent confusing attribute errors or `NoneType` issues at runtime.

## Individual Comments

### Comment 1
<location path="src/com/inductiveautomation/historian/common/model/data/__init__.py" line_range="237" />
<code_context>
+    ):
+        # type: (...) -> None
+        super(MetadataPoint, self).__init__()
+        print(value, quality, timestamp, source)
+
+    @staticmethod
</code_context>
<issue_to_address>
**issue:** MetadataPoint constructor printing has the same runtime/logging concerns as in AnnotationPoint.

As with `AnnotationPoint`, printing all constructor arguments here introduces unexpected side effects and may unnecessarily expose metadata. Since this module is just a shim over the Java types, `__init__` should ideally do nothing (or the bare minimum) and avoid printing/logging entirely.
</issue_to_address>

### Comment 2
<location path="src/system/historian/types.py" line_range="50-51" />
<code_context>
+        An annotation point object that can be passed to
+        system.historian.storeAnnotations.
+    """
+    builder = AnnotationPoint.builder()
+    return builder.build()
+
+
</code_context>
<issue_to_address>
**issue (bug_risk):** annotationPoint ignores all provided arguments, which contradicts the API and docstring.

The function accepts `source`, `startTime`, `endTime`, `annotationType`, `data`, and `identifier`, but none are set on the builder, so the returned `AnnotationPoint` ignores caller input. Please either populate the builder with these values (converting to the appropriate Java types like `QualifiedPath`, `Instant`, and `UUID`) or raise `NotImplementedError` instead of returning an incomplete object.
</issue_to_address>

### Comment 3
<location path="src/system/historian/types.py" line_range="54-63" />
<code_context>
+    return builder.build()
+
+
+def dataPoint(
+    source,  # type: Union[str, unicode]
+    value,  # type: object
+    timestamp=None,  # type: Optional[Date]
+    quality=None,  # type: Optional[int]
+):
+    # type: (...) -> AtomicPoint
+    """Creates a data point that can be stored to a historian.
+
+    Data points represent individual values associated with a historical
+    path, timestamp, and quality.
+
+    Args:
+        source: The historical path where the data point will be stored.
+        value: The value to be stored in the historian.
+        timestamp: The timestamp when the data point was recorded. If
+            omitted, the current time is used. Optional.
+        quality: The quality code of the data point. If omitted, a
+            "good" quality is used. Optional.
+    """
+    pass
+
+
</code_context>
<issue_to_address>
**issue (bug_risk):** dataPoint is declared to return an AtomicPoint but currently does nothing.

The stub and docstring promise an `AtomicPoint`, but the function body is just `pass`, so it always returns `None`. This will cause runtime failures wherever an `AtomicPoint` is expected. Either raise `NotImplementedError` until it’s implemented, or construct and return the appropriate `AtomicPoint` (likely via the Java APIs) to match the declared return type.
</issue_to_address>

### Comment 4
<location path="src/system/historian/types.py" line_range="77-86" />
<code_context>
+    pass
+
+
+def metadataPoint(
+    source,  # type: Union[str, unicode]
+    properties,  # type: Dict[Union[str, unicode], Any]
+    timestamp,  # type: Date
+):
+    # type: (...) -> MetadataPoint
+    """Creates a metadata point that can be stored to a historian.
+
+    Metadata points allow you to store additional properties associated
+    with a historical path at a specific point in time.
+
+    Args:
+        source: The historical path where the metadata point will be
+            stored.
+        properties: A dictionary of properties to be stored as
+            historical metadata.
+        timestamp: The timestamp when the metadata point was recorded.
+
+    Returns:
+        A metadata point object that can be passed to
+        system.historian.storeMetadata.
+    """
</code_context>
<issue_to_address>
**issue (bug_risk):** metadataPoint never constructs or returns a MetadataPoint despite the signature.

Because the body only contains a docstring, this function currently returns `None` despite the `MetadataPoint` return annotation. Please either implement the construction of a `MetadataPoint` or explicitly `raise NotImplementedError` so misuse is caught immediately rather than silently returning `None`.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

):
# type: (...) -> None
super(MetadataPoint, self).__init__()
print(value, quality, timestamp, source)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: MetadataPoint constructor printing has the same runtime/logging concerns as in AnnotationPoint.

As with AnnotationPoint, printing all constructor arguments here introduces unexpected side effects and may unnecessarily expose metadata. Since this module is just a shim over the Java types, __init__ should ideally do nothing (or the bare minimum) and avoid printing/logging entirely.

Comment on lines +50 to +51
builder = AnnotationPoint.builder()
return builder.build()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): annotationPoint ignores all provided arguments, which contradicts the API and docstring.

The function accepts source, startTime, endTime, annotationType, data, and identifier, but none are set on the builder, so the returned AnnotationPoint ignores caller input. Please either populate the builder with these values (converting to the appropriate Java types like QualifiedPath, Instant, and UUID) or raise NotImplementedError instead of returning an incomplete object.

Comment on lines +54 to +63
def dataPoint(
source, # type: Union[str, unicode]
value, # type: object
timestamp=None, # type: Optional[Date]
quality=None, # type: Optional[int]
):
# type: (...) -> AtomicPoint
"""Creates a data point that can be stored to a historian.

Data points represent individual values associated with a historical
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): dataPoint is declared to return an AtomicPoint but currently does nothing.

The stub and docstring promise an AtomicPoint, but the function body is just pass, so it always returns None. This will cause runtime failures wherever an AtomicPoint is expected. Either raise NotImplementedError until it’s implemented, or construct and return the appropriate AtomicPoint (likely via the Java APIs) to match the declared return type.

Comment on lines +77 to +86
def metadataPoint(
source, # type: Union[str, unicode]
properties, # type: Dict[Union[str, unicode], Any]
timestamp, # type: Date
):
# type: (...) -> MetadataPoint
"""Creates a metadata point that can be stored to a historian.

Metadata points allow you to store additional properties associated
with a historical path at a specific point in time.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): metadataPoint never constructs or returns a MetadataPoint despite the signature.

Because the body only contains a docstring, this function currently returns None despite the MetadataPoint return annotation. Please either implement the construction of a MetadataPoint or explicitly raise NotImplementedError so misuse is caught immediately rather than silently returning None.

@cesarcoatl cesarcoatl merged commit b37ed00 into 8.3 Apr 28, 2026
5 checks passed
@cesarcoatl cesarcoatl deleted the 8.3-feat/system/historian.types branch April 28, 2026 04:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant