Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

deprecate: resync v0 #432

Merged
merged 11 commits into from
Oct 17, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on:
branches: [main]

env:
PYTHON_VERSION: "3.9"
PYTHON_VERSION: "3.10"

jobs:
lint:
Expand Down Expand Up @@ -36,10 +36,8 @@ jobs:
fail-fast: false
matrix:
python-version:
- "3.9"
# Assume these are covered by 3.12
# - "3.10"
# - "3.11"
- "3.10"
- "3.11"
- "3.12"
steps:
- uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on:
branches: [main]

env:
PYTHON_VERSION: "3.9"
PYTHON_VERSION: "3.10"

jobs:
test_and_release:
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ repos:
- id: codespell

- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: "v0.6.0"
rev: "v0.6.9"
hooks:
- id: ruff
args:
Expand Down
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,13 @@ Changes are grouped as follows
- `Fixed` for any bug fixes.
- `Security` in case of vulnerabilities.

## [0.101.0] - 2024-10-016
nodegard marked this conversation as resolved.
Show resolved Hide resolved
### Removed
* Resync for asset & v0
* Support for python 3.9


## [0.100.0] - 2024-10-014
## [0.100.0] - 2024-10-14
### Added
* Support for triggering Shop using a ShopCase instance
* Tutorial for usage of the generated SDK in relation to Shop
Expand Down
2 changes: 1 addition & 1 deletion cognite/powerops/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.100.0"
__version__ = "0.101.0"
161 changes: 3 additions & 158 deletions cognite/powerops/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,18 @@

import logging
from pathlib import Path
from typing import Annotated, Optional
from typing import Annotated

import typer
from rich.logging import Console, RichHandler

from cognite import powerops
from cognite.powerops.utils.cdf.extraction_pipelines import ExtractionPipelineCreate, RunStatus

for third_party in ["cognite-sdk", "requests", "urllib3", "msal", "requests_oauthlib"]:
third_party_logger = logging.getLogger(third_party)
third_party_logger.setLevel(logging.WARNING)
third_party_logger.propagate = False

MODELS_BY_NAME_SORTED = sorted(powerops.resync.MODELS_BY_NAME)
MODELS_BY_NAME_STR = ", ".join(MODELS_BY_NAME_SORTED)

FORMAT = "%(message)s"
logging.basicConfig(
level=logging.INFO, format=FORMAT, datefmt="[%X]", handlers=[RichHandler(console=Console(stderr=True))]
Expand All @@ -38,172 +34,21 @@ def _version_callback(value: bool):
def common(ctx: typer.Context, version: bool = typer.Option(None, "--version", callback=_version_callback)): ...


@app.command("init", help="Setup necessary data models in CDF for ReSync to run")
def init(
dev: bool = typer.Option(
False,
"--dev",
"-d",
help="Whether the deployment is for development environment. If true,"
"the models views and data models will be deleted and recreated.",
),
dry_run: bool = typer.Option(
False, "--dry-run", help="Whether to run the command as a dry run, meaning no resources will be created."
),
verbose: bool = typer.Option(False, "--verbose", "-v", help="Whether to print verbose output"),
):
client = powerops.PowerOpsClient.from_settings()

powerops.resync.init(client, is_dev=dev, dry_run=dry_run, verbose=verbose)


@app.command("validate", help="Validate the configuration files and timeseries")
def validate(
path: Annotated[Path, typer.Argument(help="Path to configuration files")],
market: Annotated[str, typer.Argument(help="Selected power market")],
verbose: bool = typer.Option(
False, "--verbose", "-v", help="Include valid results in output (specify --format), and enable INFO logs"
),
format: str = typer.Option(default=None, help="The format of the output. Available formats: markdown, json"),
error_code: bool = typer.Option(False, "--error-code", "-e", help="Exit with error code if validation fails"),
):
echo = _setup_echo(verbose, typer.echo)
log.info(f"Running validate on configuration files located in {path}")
validation_results = powerops.resync.validate(path, market)

if format == "markdown":
echo(validation_results.as_markdown(include_valid=verbose))
elif format == "json":
echo(validation_results.as_json(include_valid=verbose))

if error_code and not all(result.valid for result in validation_results.results):
raise typer.Exit(code=1)


@app.command(
"plan",
help="Preview the changes from the configuration files that `powerops apply` would make to the data model in CDF",
)
def plan(
path: Annotated[Path, typer.Argument(help="Path to configuration files")],
market: Annotated[str, typer.Argument(help="Selected power market")],
models: list[str] = typer.Option( # noqa: B008
default=MODELS_BY_NAME_SORTED,
help=f"The models to run the plan. Available models: {MODELS_BY_NAME_STR}",
),
dump_folder: Optional[Path] = typer.Option( # noqa: B008
default=None, help="If present, the local and cdf changes will be dumped to this directory."
),
format: str = typer.Option(default=None, help="The format of the output. Available formats: markdown"),
as_extraction_pipeline_run: bool = typer.Option(
default=False,
help="If true, the command will be registered as an extraction pipeline run. With the configuration"
"fetched from the settings.toml [powerops] section.",
),
verbose: bool = typer.Option(False, "--verbose", "-v", help="Whether to print verbose output"),
):
if dump_folder and not dump_folder.is_dir():
raise typer.BadParameter(f"{dump_folder} is not a directory")

echo = _setup_echo(verbose, typer.echo)
log.info(f"Running plan on configuration files located in {path}")
power = powerops.PowerOpsClient.from_settings()

changes = powerops.resync.plan(path, market, model_names=models, dump_folder=dump_folder, client=power)

if format == "markdown":
echo(changes.as_github_markdown())

if as_extraction_pipeline_run is True:
client = power.cdf

pipeline = ExtractionPipelineCreate(
external_id="resync/plan",
data_set_external_id=power.datasets.monitor_dataset,
dump_truncated_to_file=True,
message_keys_skip=["error"],
truncate_keys_first=["error"],
log_file_prefix="powerops_function_loss",
description="The resync/plan function checks that the configuration files are matching "
"the expected resources in CDF. If there are any differences, the run will report as failed",
).get_or_create(client)

with pipeline.create_pipeline_run(client) as run:
if changes.has_changes("CDF", exclude={"timeseries", "parent_assets", "labels"}):
run.update_data(
RunStatus.FAILURE,
summary=changes.as_markdown_summary(no_headers=True),
error=changes.as_markdown_detailed(),
)
else:
run.update_data(RunStatus.SUCCESS)
echo(f"Extraction pipeline run executed with status: {run.status}")


@app.command("apply", help="Apply the changes from the configuration files to the data model in CDF")
def apply(
path: Annotated[Path, typer.Argument(help="Path to configuration files")],
market: Annotated[str, typer.Argument(help="Selected power market")],
models: list[str] = typer.Option( # noqa: B008
default=MODELS_BY_NAME_SORTED,
help=f"The models to run apply. Available models: {MODELS_BY_NAME_STR}",
),
auto_yes: bool = typer.Option(False, "--yes", "-y", help="Auto confirm all prompts"),
format: str = typer.Option(default=None, help="The format of the output. Available formats: markdown"),
verbose: bool = typer.Option(False, "--verbose", "-v", help="Whether to print verbose output"),
):
echo = _setup_echo(verbose, typer.echo)
client = powerops.PowerOpsClient.from_settings()

logging.info(f"Running apply on configuration files located in {path}")
changed = powerops.resync.apply(path, market, client, model_names=models, auto_yes=auto_yes)
if format == "markdown":
echo(changed.as_github_markdown())


@app.command("destroy", help="Destroy all the data models created by resync and remove all the data.")
def destroy(
models: list[str] = typer.Option( # noqa: B008
default=MODELS_BY_NAME_SORTED,
help=f"The models to destroy. Available models: {MODELS_BY_NAME_STR}",
),
dry_run: bool = typer.Option(
False, "--dry-run", help="Whether to run the command as a dry run, meaning no resources will be destroyed."
),
auto_yes: bool = typer.Option(False, "--yes", "-y", help="Auto confirm all prompts"),
format: str = typer.Option(default=None, help="The format of the output. Available formats: markdown"),
verbose: bool = typer.Option(False, "--verbose", "-v", help="Whether to print verbose output"),
):
echo = _setup_echo(verbose, typer.echo)
client = powerops.PowerOpsClient.from_settings()

destroyed = powerops.resync.destroy(client, model_names=models, auto_yes=auto_yes, dry_run=dry_run)
if format == "markdown":
echo(destroyed.as_github_markdown())


@app.command("plan_v1", help="Plan the changes from the configuration files to the data model in CDF")
def plan_v1(path: Annotated[Path, typer.Argument(help="Path to configuration files")]):
logging.info(f"Running plan on configuration files located in {path}")
powerops.resync.plan_v1(path)
powerops.resync.plan(path)


@app.command("apply_v1", help="Apply the changes from the configuration files to the data model in CDF")
def apply_v1(path: Annotated[Path, typer.Argument(help="Path to configuration files")]):
logging.info(f"Running apply on configuration files located in {path}")
powerops.resync.apply_v1(path)
powerops.resync.apply(path)


def main():
app()


def _setup_echo(verbose: bool, echo_func: Optional[powerops.resync.Echo] = None) -> powerops.resync.Echo:
if not verbose:
logging.disable(logging.INFO) # disable logs for INFO and below

return echo_func or print


if __name__ == "__main__":
main()
3 changes: 2 additions & 1 deletion cognite/powerops/client/shop/data_classes/shop_results.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from __future__ import annotations

import logging
from collections.abc import Callable
from functools import cached_property
from typing import TYPE_CHECKING, Callable, Optional, Union
from typing import TYPE_CHECKING, Optional, Union

import pandas as pd

Expand Down
4 changes: 2 additions & 2 deletions cognite/powerops/client/shop/shop_run_api.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from __future__ import annotations

import datetime
from collections.abc import Sequence
from collections.abc import Callable, Sequence
from concurrent.futures import ThreadPoolExecutor
from typing import Callable, Literal, Optional, Union, overload
from typing import Literal, Optional, Union, overload
from urllib.parse import urlparse

import arrow
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -781,7 +781,9 @@ def get_shape(model: dict, transit_object_type: str, transit_object_name: str) -

# Get shape and time_delay values as Dict[delay,water_percentage]
if "shape_discharge" in gate_or_plant:
shape = dict(zip(gate_or_plant["shape_discharge"]["x"], gate_or_plant["shape_discharge"]["y"]))
shape = dict(
zip(gate_or_plant["shape_discharge"]["x"], gate_or_plant["shape_discharge"]["y"], strict=False)
)
elif "time_delay" in gate_or_plant:
shape = {gate_or_plant["time_delay"]: 1}
else:
Expand Down
18 changes: 2 additions & 16 deletions cognite/powerops/resync/__init__.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,3 @@
from .core import DATAMODEL_ID_TO_RESYNC_NAME, MODELS_BY_NAME, apply, destroy, init, plan, validate
from .core.echo import Echo
from .v1 import apply as apply_v1
from .v1 import plan as plan_v1
from .main import apply, plan

__all__ = [
"plan_v1",
"apply_v1",
"apply",
"plan",
"init",
"destroy",
"validate",
"MODELS_BY_NAME",
"Echo",
"DATAMODEL_ID_TO_RESYNC_NAME",
]
__all__ = ["plan", "apply"]
80 changes: 0 additions & 80 deletions cognite/powerops/resync/config/__init__.py

This file was deleted.

Loading