Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion documentation/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ New features

Infrastructure / Support
----------------------
* Upgraded dependencies [see `PR #2215 <https://www.github.com/FlexMeasures/flexmeasures/pull/2215>`_]
* Upgraded dependencies [see `PR #1485 <https://www.github.com/FlexMeasures/flexmeasures/pull/1485>`_ and `PR #2215 <https://www.github.com/FlexMeasures/flexmeasures/pull/2215>`_]

Bugfixes
-----------
Expand Down
2 changes: 1 addition & 1 deletion flexmeasures/api/common/schemas/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def load_current(cls):
return current_user.account if not current_user.is_anonymous else None


class UserIdField(fields.Integer, MarshmallowClickMixin):
class UserIdField(MarshmallowClickMixin, fields.Integer):
"""
Field that represents a user ID. It deserializes from the user id to a user instance.
"""
Expand Down
34 changes: 34 additions & 0 deletions flexmeasures/cli/tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import sys
import pytest
import click

from datetime import datetime
from pytz import utc

from flexmeasures.cli import is_running as cli_is_running
from flexmeasures.cli.utils import DeprecatedOption, DeprecatedOptionsCommand
from click.testing import CliRunner


def test_cli_is_running(app, monkeypatch):
Expand Down Expand Up @@ -111,3 +114,34 @@ def test_get_unique_sensor_names(app, db, add_asset_with_children):
]

assert list(aliases.values()) == expected_aliases


def test_deprecated_options_command_allows_non_deprecated_option():
@click.command(cls=DeprecatedOptionsCommand)
@click.option("--name", cls=DeprecatedOption)
def cmd(name):
click.echo(name)

result = CliRunner().invoke(cmd, ["--name", "foo"])

assert result.exit_code == 0
assert result.output == "foo\n"


def test_deprecated_options_command_warns_for_deprecated_alias():
@click.command(cls=DeprecatedOptionsCommand)
@click.option(
"--name",
"--old-name",
cls=DeprecatedOption,
deprecated=["--old-name"],
preferred="--name",
)
def cmd(name):
click.echo(name)

result = CliRunner().invoke(cmd, ["--old-name", "foo"])

assert result.exit_code == 0
assert "Option '--old-name' will be replaced by '--name'." in result.output
assert result.output.endswith("foo\n")
12 changes: 10 additions & 2 deletions flexmeasures/cli/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,15 @@ class DeprecatedOption(click.Option):
"""

def __init__(self, *args, **kwargs):
self.deprecated = kwargs.pop("deprecated", ())
deprecated = kwargs.pop("deprecated", ())
# Keep our aliases in a separate attribute to avoid colliding with Click's
# own `deprecated` option argument (introduced in Click 8.2+).
if isinstance(deprecated, (list, tuple, set)):
self.deprecated_options = tuple(deprecated)
elif isinstance(deprecated, str):
self.deprecated_options = (deprecated,)
else:
self.deprecated_options = ()
self.preferred = kwargs.pop("preferred", args[0][-1])
super(DeprecatedOption, self).__init__(*args, **kwargs)

Expand Down Expand Up @@ -76,7 +84,7 @@ def make_process(an_option):
"""Construct a closure to the parser option processor"""

orig_process = an_option.process
deprecated = getattr(an_option.obj, "deprecated", None)
deprecated = getattr(an_option.obj, "deprecated_options", None)
preferred = getattr(an_option.obj, "preferred", None)
msg = "Expected `deprecated` value for `{}`"
assert deprecated is not None, msg.format(an_option.obj.name)
Expand Down
2 changes: 1 addition & 1 deletion flexmeasures/data/schemas/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def validate_logo_url(self, value, **kwargs):
raise FMValidationError(str(e))


class AccountIdField(fields.Int, MarshmallowClickMixin):
class AccountIdField(MarshmallowClickMixin, fields.Int):
"""Field that deserializes to an Account and serializes back to an integer."""

@with_appcontext_if_needed()
Expand Down
2 changes: 1 addition & 1 deletion flexmeasures/data/schemas/sources.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
)


class DataSourceIdField(fields.Int, MarshmallowClickMixin):
class DataSourceIdField(MarshmallowClickMixin, fields.Int):
"""Field that deserializes to a DataSource and serializes back to an integer."""

@with_appcontext_if_needed()
Expand Down
10 changes: 9 additions & 1 deletion flexmeasures/data/schemas/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from flexmeasures.utils.unit_utils import to_preferred, ur


class MarshmallowClickMixin(click.ParamType):
class MarshmallowClickMixin:
def __init__(self, *args, **kwargs):

metadata_keys = ["description", "example"]
Expand All @@ -21,6 +21,7 @@ def __init__(self, *args, **kwargs):

super().__init__(*args, **kwargs)
self.name = self.__class__.__name__
self.__name__ = self.name

def get_metavar(self, param, **kwargs):
return self.__class__.__name__
Expand All @@ -31,6 +32,13 @@ def convert(self, value, param, ctx, **kwargs):
except ma.exceptions.ValidationError as e:
raise click.exceptions.BadParameter(e, ctx=ctx, param=param)

def __call__(self, value):
"""Support click.FuncParamType by behaving like a conversion callable."""
try:
return self.deserialize(value)
except ma.exceptions.ValidationError as e:
raise ValueError(e) from e


class FMValidationError(ma.exceptions.ValidationError):
"""
Expand Down
3 changes: 1 addition & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@ dependencies = [
"bcrypt==4.3.0", # see https://github.com/SeitaBV/flexmeasures-cloudinfra/issues/283
"pytz>=2025.2",
"isodate>=0.7.2",
# see https://github.com/FlexMeasures/flexmeasures/issues/1485
"click<8.2.0",
"click>=8.2.0",
"click-default-group>=1.2.4",
"email-validator>=2.3.0",
"rq>=2.6.1",
Expand Down
8 changes: 4 additions & 4 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading