Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce a database model for annotations and their relationship to assets and sensors. Also add a CLI option to load public holidays and store them as annotations. * Add Annotation db model, including relationships Signed-off-by: F.N. Claessen <felix@seita.nl> * Add representation of Annotation objects Signed-off-by: F.N. Claessen <felix@seita.nl> * Add CLI command to add holidays Signed-off-by: F.N. Claessen <felix@seita.nl> * Add migration Signed-off-by: F.N. Claessen <felix@seita.nl> * One source per country Signed-off-by: F.N. Claessen <felix@seita.nl> * Refactor migration Signed-off-by: F.N. Claessen <felix@seita.nl> * Add annotations_assets table Signed-off-by: F.N. Claessen <felix@seita.nl> * Improve inflection of plural Signed-off-by: F.N. Claessen <felix@seita.nl> * Add a CLI option to relate new holidays annotations to assets Signed-off-by: F.N. Claessen <felix@seita.nl> * Add a CLI option to relate new holidays annotations to all assets of an account Signed-off-by: F.N. Claessen <felix@seita.nl> * Add annotations_sensors table Signed-off-by: F.N. Claessen <felix@seita.nl> * black Signed-off-by: F.N. Claessen <felix@seita.nl> * Fix downgrade Signed-off-by: F.N. Claessen <felix@seita.nl> * Fix table name Signed-off-by: F.N. Claessen <felix@seita.nl> * Add downgrade prompt Signed-off-by: F.N. Claessen <felix@seita.nl> * black Signed-off-by: F.N. Claessen <felix@seita.nl> * Fix docstring Signed-off-by: F.N. Claessen <felix@seita.nl> * Add dependency Signed-off-by: F.N. Claessen <felix@seita.nl> * Update docstring Signed-off-by: F.N. Claessen <felix@seita.nl> * Add missing enum name Signed-off-by: F.N. Claessen <felix@seita.nl> * Clarify use of workalendar registry Signed-off-by: F.N. Claessen <felix@seita.nl> * Use recommended way of setting up UniqueConstraint Signed-off-by: F.N. Claessen <felix@seita.nl> * Fix setup of many-to-many relationships between annotations, generic assets and sensors Signed-off-by: F.N. Claessen <felix@seita.nl> * Refactor loop Signed-off-by: F.N. Claessen <felix@seita.nl> * Log the string representation of the newly created Source object, which print its description instead of just its name Signed-off-by: F.N. Claessen <felix@seita.nl> * flake8 Signed-off-by: F.N. Claessen <felix@seita.nl> * Add changelog warning to upgrade the database Signed-off-by: F.N. Claessen <felix@seita.nl> * Typos Signed-off-by: F.N. Claessen <felix@seita.nl> * Changelog entry Signed-off-by: F.N. Claessen <felix@seita.nl> * Refactor: move new annotation classes to dedicated module Signed-off-by: F.N. Claessen <felix@seita.nl> * Refactor: factor out import statement Signed-off-by: F.N. Claessen <felix@seita.nl>
- Loading branch information
Showing
10 changed files
with
265 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
81 changes: 81 additions & 0 deletions
81
flexmeasures/data/migrations/versions/7f8b8920355f_create_annotation_table.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
"""create annotation table | ||
Revision ID: 7f8b8920355f | ||
Revises: c1d316c60985 | ||
Create Date: 2022-01-29 20:23:29.996133 | ||
""" | ||
from alembic import op | ||
import click | ||
import sqlalchemy as sa | ||
|
||
|
||
# revision identifiers, used by Alembic. | ||
revision = "7f8b8920355f" | ||
down_revision = "c1d316c60985" | ||
branch_labels = None | ||
depends_on = None | ||
|
||
|
||
def upgrade(): | ||
create_annotation_table() | ||
create_annotation_asset_relationship_table() | ||
create_annotation_sensor_relationship_table() | ||
|
||
|
||
def downgrade(): | ||
click.confirm( | ||
"This downgrade drops the tables 'annotations_assets', 'annotations_sensors' and 'annotation'. Continue?", | ||
abort=True, | ||
) | ||
op.drop_table("annotations_assets") | ||
op.drop_table("annotations_sensors") | ||
op.drop_constraint(op.f("annotation_name_key"), "annotation", type_="unique") | ||
op.drop_table("annotation") | ||
op.execute("DROP TYPE annotation_type;") | ||
|
||
|
||
def create_annotation_sensor_relationship_table(): | ||
op.create_table( | ||
"annotations_sensors", | ||
sa.Column("id", sa.Integer(), primary_key=True), | ||
sa.Column("sensor_id", sa.Integer()), | ||
sa.Column("annotation_id", sa.Integer()), | ||
sa.ForeignKeyConstraint(("sensor_id",), ["sensor.id"]), | ||
sa.ForeignKeyConstraint(("annotation_id",), ["annotation.id"]), | ||
) | ||
|
||
|
||
def create_annotation_asset_relationship_table(): | ||
op.create_table( | ||
"annotations_assets", | ||
sa.Column("id", sa.Integer(), primary_key=True), | ||
sa.Column("generic_asset_id", sa.Integer()), | ||
sa.Column("annotation_id", sa.Integer()), | ||
sa.ForeignKeyConstraint(("generic_asset_id",), ["generic_asset.id"]), | ||
sa.ForeignKeyConstraint(("annotation_id",), ["annotation.id"]), | ||
) | ||
|
||
|
||
def create_annotation_table(): | ||
op.create_table( | ||
"annotation", | ||
sa.Column( | ||
"id", sa.Integer(), nullable=False, autoincrement=True, primary_key=True | ||
), | ||
sa.Column("name", sa.String(255), nullable=False), | ||
sa.Column("start", sa.DateTime(timezone=True), nullable=False), | ||
sa.Column("end", sa.DateTime(timezone=True), nullable=False), | ||
sa.Column("source_id", sa.Integer(), nullable=False), | ||
sa.Column( | ||
"type", | ||
sa.Enum("alert", "holiday", "label", name="annotation_type"), | ||
nullable=False, | ||
), | ||
sa.ForeignKeyConstraint(("source_id",), ["data_source.id"]), | ||
) | ||
op.create_unique_constraint( | ||
op.f("annotation_name_key"), | ||
"annotation", | ||
["name", "start", "source_id", "type"], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
from datetime import timedelta | ||
|
||
from flexmeasures.data import db | ||
from flexmeasures.data.models.data_sources import DataSource | ||
|
||
|
||
class Annotation(db.Model): | ||
"""An annotation is a nominal value that applies to a specific time or time span. | ||
Examples of annotation types: | ||
- user annotation: annotation.type == "label" and annotation.source.type == "user" | ||
- unresolved alert: annotation.type == "alert" | ||
- resolved alert: annotation.type == "label" and annotation.source.type == "alerting script" | ||
- organisation holiday: annotation.type == "holiday" and annotation.source.type == "user" | ||
- public holiday: annotation.type == "holiday" and annotation.source.name == "workalendar" | ||
""" | ||
|
||
id = db.Column(db.Integer, nullable=False, autoincrement=True, primary_key=True) | ||
name = db.Column(db.String(255), nullable=False) | ||
start = db.Column(db.DateTime(timezone=True), nullable=False) | ||
end = db.Column(db.DateTime(timezone=True), nullable=False) | ||
source_id = db.Column(db.Integer, db.ForeignKey(DataSource.__tablename__ + ".id")) | ||
source = db.relationship( | ||
"DataSource", | ||
foreign_keys=[source_id], | ||
backref=db.backref("annotations", lazy=True), | ||
) | ||
type = db.Column(db.Enum("alert", "holiday", "label", name="annotation_type")) | ||
__table_args__ = ( | ||
db.UniqueConstraint( | ||
"name", | ||
"start", | ||
"source_id", | ||
"type", | ||
name="annotation_name_key", | ||
), | ||
) | ||
|
||
@property | ||
def duration(self) -> timedelta: | ||
return self.end - self.start | ||
|
||
def __repr__(self) -> str: | ||
return f"<Annotation {self.id}: {self.name} ({self.type}), start: {self.start} end: {self.end}, source: {self.source}>" | ||
|
||
|
||
class GenericAssetAnnotationRelationship(db.Model): | ||
"""Links annotations to generic assets.""" | ||
|
||
__tablename__ = "annotations_assets" | ||
|
||
id = db.Column(db.Integer(), primary_key=True) | ||
generic_asset_id = db.Column(db.Integer, db.ForeignKey("generic_asset.id")) | ||
annotation_id = db.Column(db.Integer, db.ForeignKey("annotation.id")) | ||
|
||
|
||
class SensorAnnotationRelationship(db.Model): | ||
"""Links annotations to sensors.""" | ||
|
||
__tablename__ = "annotations_sensors" | ||
|
||
id = db.Column(db.Integer(), primary_key=True) | ||
sensor_id = db.Column(db.Integer, db.ForeignKey("sensor.id")) | ||
annotation_id = db.Column(db.Integer, db.ForeignKey("annotation.id")) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,7 @@ pint | |
py-moneyed | ||
iso8601 | ||
xlrd | ||
workalendar | ||
inflection | ||
inflect | ||
humanize | ||
|
Oops, something went wrong.