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

DM-45209: Fix E721 error and general pyupgrade fixes #111

Merged
merged 8 commits into from
Jul 12, 2024
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
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ repos:
- id: isort
name: isort (python)
- repo: https://github.com/PyCQA/flake8
rev: 7.0.0
rev: 7.1.0
hooks:
- id: flake8
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.4.6
rev: v0.5.1
hooks:
- id: ruff
- repo: https://github.com/numpy/numpydoc
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ select = [
"N", # pep8-naming
"W", # pycodestyle
"D", # pydocstyle
"UP", # pyupgrade
]
extend-select = [
"RUF100", # Warn about unused noqa
Expand Down
7 changes: 4 additions & 3 deletions python/lsst/pex/config/choiceField.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,11 @@ def __init__(self, doc, dtype=None, allowed=None, default=None, optional=True, d
for choice, choiceDoc in self.allowed.items():
if choice is not None and not isinstance(choice, dtype):
raise ValueError(
"ChoiceField's allowed choice %s is of incorrect type %s. Expected %s"
% (choice, _typeStr(choice), _typeStr(dtype))
f"ChoiceField's allowed choice {choice} is of incorrect type "
f"{_typeStr(choice)}. Expected {_typeStr(dtype)}"
)
self.__doc__ += "{}\n {}\n".format(f"``{str(choice)!r}``", choiceDoc)
# Force to a string so that additional quotes are added with !r
self.__doc__ += f"``{str(choice)!r}``\n {choiceDoc}\n"

self.source = getStackFrame()

Expand Down
4 changes: 2 additions & 2 deletions python/lsst/pex/config/comparison.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,12 +156,12 @@
return True
else:
if output is not None:
output("LHS is None for %s" % name)
output(f"LHS is None for {name}")

Check warning on line 159 in python/lsst/pex/config/comparison.py

View check run for this annotation

Codecov / codecov/patch

python/lsst/pex/config/comparison.py#L159

Added line #L159 was not covered by tests
return False
else:
if c2 is None:
if output is not None:
output("RHS is None for %s" % name)
output(f"RHS is None for {name}")

Check warning on line 164 in python/lsst/pex/config/comparison.py

View check run for this annotation

Codecov / codecov/patch

python/lsst/pex/config/comparison.py#L164

Added line #L164 was not covered by tests
return False
if type(c1) is not type(c2):
if output is not None:
Expand Down
57 changes: 22 additions & 35 deletions python/lsst/pex/config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,9 @@
import tempfile
import warnings
from collections.abc import Mapping
from types import GenericAlias
from typing import Any, ForwardRef, Generic, TypeVar, cast, overload

try:
from types import GenericAlias
except ImportError:
# cover python 3.8 usage
GenericAlias = type(Mapping[int, int])

# if YAML is not available that's fine and we simply don't register
# the yaml representer since we know it won't be used.
try:
Expand Down Expand Up @@ -130,7 +125,7 @@
----------
x : object
A value.
dtype : tpye
dtype : type
Data type, such as `float`, `int`, or `str`.

Returns
Expand All @@ -140,7 +135,7 @@
``dtype``. If the cast cannot be performed the original value of
``x`` is returned.
"""
if dtype == float and isinstance(x, int):
if dtype is float and isinstance(x, int):
return float(x)
return x

Expand Down Expand Up @@ -293,16 +288,9 @@

self.configSource = config._source
error = (
"%s '%s' failed validation: %s\n"
"For more information see the Field definition at:\n%s"
" and the Config definition at:\n%s"
% (
self.fieldType.__name__,
self.fullname,
msg,
self.fieldSource.format(),
self.configSource.format(),
)
f"{self.fieldType.__name__} '{self.fullname}' failed validation: {msg}\n"
f"For more information see the Field definition at:\n{self.fieldSource.format()}"
f" and the Config definition at:\n{self.configSource.format()}"
)
super().__init__(error)

Expand Down Expand Up @@ -456,13 +444,8 @@
_typ = ForwardRef(unpackedParams)
# type ignore below because typeshed seems to be wrong. It
# indicates there are only 2 args, as it was in python 3.8, but
# 3.9+ takes 3 args. Attempt in old style and new style to
# work with both.
try:
result = _typ._evaluate(globals(), locals(), set()) # type: ignore
except TypeError:
# python 3.8 path
result = _typ._evaluate(globals(), locals())
# 3.9+ takes 3 args.
result = _typ._evaluate(globals(), locals(), recursive_guard=set()) # type: ignore
timj marked this conversation as resolved.
Show resolved Hide resolved
if result is None:
raise ValueError("Could not deduce type from input")
unpackedParams = cast(type, result)
Expand All @@ -481,7 +464,7 @@
"dtype must either be supplied as an argument or as a type argument to the class"
)
if dtype not in self.supportedTypes:
raise ValueError("Unsupported Field dtype %s" % _typeStr(dtype))
raise ValueError(f"Unsupported Field dtype {_typeStr(dtype)}")

Check warning on line 467 in python/lsst/pex/config/config.py

View check run for this annotation

Codecov / codecov/patch

python/lsst/pex/config/config.py#L467

Added line #L467 was not covered by tests

source = getStackFrame()
self._setup(
Expand Down Expand Up @@ -626,14 +609,12 @@
return

if not isinstance(value, self.dtype):
msg = "Value {} is of incorrect type {}. Expected type {}".format(
value,
_typeStr(value),
_typeStr(self.dtype),
msg = (

Check warning on line 612 in python/lsst/pex/config/config.py

View check run for this annotation

Codecov / codecov/patch

python/lsst/pex/config/config.py#L612

Added line #L612 was not covered by tests
f"Value {value} is of incorrect type {_typeStr(value)}. Expected type {_typeStr(self.dtype)}"
)
raise TypeError(msg)
if self.check is not None and not self.check(value):
msg = "Value %s is not a valid value" % str(value)
msg = f"Value {value} is not a valid value"
raise ValueError(msg)

def _collectImports(self, instance, imports):
Expand Down Expand Up @@ -1384,9 +1365,12 @@
configType = type(self)
typeString = _typeStr(configType)
outfile.write(f"import {configType.__module__}\n")
# We are required to write this on a single line because
Copy link
Member Author

Choose a reason for hiding this comment

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

As a general comment, I have seen people reformat config .py files to make them look neater and I now worry that those will no longer be readable.

# of later regex matching, rather than adopting black style
# formatting.
outfile.write(
f"assert type({root})=={typeString}, 'config is of type %s.%s instead of "
f"{typeString}' % (type({root}).__module__, type({root}).__name__)\n"
f'assert type({root}) is {typeString}, f"config is of type '
f'{{type({root}).__module__}}.{{type({root}).__name__}} instead of {typeString}"\n\n'
)
for imp in sorted(self._imports):
if imp in sys.modules and sys.modules[imp] is not None:
Expand Down Expand Up @@ -1717,12 +1701,15 @@
"""
# standard serialization has the form:
# import config.class
# assert type(config)==config.class.Config, ...
# assert type(config) is config.class.Config, ...
# Older files use "type(config)==" instead.
# We want to parse these two lines so we can get the class itself

# Do a single regex to avoid large string copies when splitting a
# large config into separate lines.
matches = re.search(r"^import ([\w.]+)\nassert .*==(.*?),", config_py)
# The assert regex cannot be greedy because the assert error string
# can include both "," and " is ".
matches = re.search(r"^import ([\w.]+)\nassert type\(\S+\)(?:\s*==\s*| is )(.*?),", config_py)

if not matches:
first_line, second_line, _ = config_py.split("\n", 2)
Expand Down
20 changes: 9 additions & 11 deletions python/lsst/pex/config/configChoiceField.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@
self._set = set()

if setHistory:
self.__history.append(("Set selection to %s" % self, at, label))
self.__history.append((f"Set selection to {self}", at, label))

Check warning on line 87 in python/lsst/pex/config/configChoiceField.py

View check run for this annotation

Codecov / codecov/patch

python/lsst/pex/config/configChoiceField.py#L87

Added line #L87 was not covered by tests

@property
def _config(self) -> Config:
Expand Down Expand Up @@ -114,7 +114,7 @@
# invoke __getitem__ to make sure it's present
self._dict.__getitem__(value, at=at)

self.__history.append(("added %s to selection" % value, at, "selection"))
self.__history.append((f"added {value} to selection", at, "selection"))
self._set.add(value)

def discard(self, value, at=None):
Expand All @@ -137,7 +137,7 @@
if at is None:
at = getCallStack()

self.__history.append(("removed %s from selection" % value, at, "selection"))
self.__history.append((f"removed {value} from selection", at, "selection"))
self._set.discard(value)

def __len__(self):
Expand Down Expand Up @@ -295,7 +295,7 @@
dtype = self.types[k]
except Exception:
raise FieldValidationError(
self._field, self._config, "Unknown key %r in Registry/ConfigChoiceField" % k
self._field, self._config, f"Unknown key {k!r} in Registry/ConfigChoiceField"
)
name = _joinNamePath(self._config._name, self._field.name, k)
if at is None:
Expand All @@ -311,14 +311,12 @@
try:
dtype = self.types[k]
except Exception:
raise FieldValidationError(self._field, self._config, "Unknown key %r" % k)
raise FieldValidationError(self._field, self._config, f"Unknown key {k!r}")

Check warning on line 314 in python/lsst/pex/config/configChoiceField.py

View check run for this annotation

Codecov / codecov/patch

python/lsst/pex/config/configChoiceField.py#L314

Added line #L314 was not covered by tests

if value != dtype and type(value) is not dtype:
msg = "Value {} at key {} is of incorrect type {}. Expected type {}".format(
value,
k,
_typeStr(value),
_typeStr(dtype),
msg = (

Check warning on line 317 in python/lsst/pex/config/configChoiceField.py

View check run for this annotation

Codecov / codecov/patch

python/lsst/pex/config/configChoiceField.py#L317

Added line #L317 was not covered by tests
f"Value {value} at key {k} is of incorrect type {_typeStr(value)}. "
f"Expected type {_typeStr(dtype)}"
)
raise FieldValidationError(self._field, self._config, msg)

Expand Down Expand Up @@ -658,7 +656,7 @@
name = getComparisonName(
_joinNamePath(instance1._name, self.name), _joinNamePath(instance2._name, self.name)
)
if not compareScalars("selection for %s" % name, d1._selection, d2._selection, output=output):
if not compareScalars(f"selection for {name}", d1._selection, d2._selection, output=output):
return False
if d1._selection is None:
return True
Expand Down
24 changes: 10 additions & 14 deletions python/lsst/pex/config/configDictField.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,19 +65,15 @@
# validate keytype
k = _autocast(k, self._field.keytype)
if type(k) is not self._field.keytype:
msg = "Key {!r} is of type {}, expected type {}".format(
k, _typeStr(k), _typeStr(self._field.keytype)
)
msg = f"Key {k!r} is of type {_typeStr(k)}, expected type {_typeStr(self._field.keytype)}"
raise FieldValidationError(self._field, self._config, msg)

# validate itemtype
dtype = self._field.itemtype
if type(x) is not self._field.itemtype and x != self._field.itemtype:
msg = "Value {} at key {!r} is of incorrect type {}. Expected type {}".format(
x,
k,
_typeStr(x),
_typeStr(self._field.itemtype),
msg = (
f"Value {x} at key {k!r} is of incorrect type {_typeStr(x)}. "
f"Expected type {_typeStr(self._field.itemtype)}"
)
raise FieldValidationError(self._field, self._config, msg)

Expand All @@ -91,19 +87,19 @@
else:
self._dict[k] = dtype(__name=name, __at=at, __label=label, **x._storage)
if setHistory:
self.history.append(("Added item at key %s" % k, at, label))
self.history.append((f"Added item at key {k}", at, label))
else:
if x == dtype:
x = dtype()
oldValue.update(__at=at, __label=label, **x._storage)
if setHistory:
self.history.append(("Modified item at key %s" % k, at, label))
self.history.append((f"Modified item at key {k}", at, label))

Check warning on line 96 in python/lsst/pex/config/configDictField.py

View check run for this annotation

Codecov / codecov/patch

python/lsst/pex/config/configDictField.py#L96

Added line #L96 was not covered by tests

def __delitem__(self, k, at=None, label="delitem"):
if at is None:
at = getCallStack()
Dict.__delitem__(self, k, at, label, False)
self.history.append(("Removed item at key %s" % k, at, label))
self.history.append((f"Removed item at key {k}", at, label))

Check warning on line 102 in python/lsst/pex/config/configDictField.py

View check run for this annotation

Codecov / codecov/patch

python/lsst/pex/config/configDictField.py#L102

Added line #L102 was not covered by tests


class ConfigDictField(DictField):
Expand Down Expand Up @@ -190,9 +186,9 @@
deprecated=deprecated,
)
if keytype not in self.supportedTypes:
raise ValueError("'keytype' %s is not a supported type" % _typeStr(keytype))
raise ValueError(f"'keytype' {_typeStr(keytype)} is not a supported type")
elif not issubclass(itemtype, Config):
raise ValueError("'itemtype' %s is not a supported type" % _typeStr(itemtype))
raise ValueError(f"'itemtype' {_typeStr(itemtype)} is not a supported type")
if dictCheck is not None and not hasattr(dictCheck, "__call__"):
raise ValueError("'dictCheck' must be callable")
if itemCheck is not None and not hasattr(itemCheck, "__call__"):
Expand Down Expand Up @@ -293,7 +289,7 @@
name = getComparisonName(
_joinNamePath(instance1._name, self.name), _joinNamePath(instance2._name, self.name)
)
if not compareScalars("keys for %s" % name, set(d1.keys()), set(d2.keys()), output=output):
if not compareScalars(f"keys for {name}", set(d1.keys()), set(d2.keys()), output=output):
return False
equal = True
for k, v1 in d1.items():
Expand Down
10 changes: 3 additions & 7 deletions python/lsst/pex/config/configField.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@

def __init__(self, doc, dtype=None, default=None, check=None, deprecated=None):
if dtype is None or not issubclass(dtype, Config):
raise ValueError("dtype=%s is not a subclass of Config" % _typeStr(dtype))
raise ValueError(f"dtype={_typeStr(dtype)} is not a subclass of Config")

Check warning on line 85 in python/lsst/pex/config/configField.py

View check run for this annotation

Codecov / codecov/patch

python/lsst/pex/config/configField.py#L85

Added line #L85 was not covered by tests
if default is None:
default = dtype
source = getStackFrame()
Expand Down Expand Up @@ -125,11 +125,7 @@
name = _joinNamePath(prefix=instance._name, name=self.name)

if value != self.dtype and type(value) is not self.dtype:
msg = "Value {} is of incorrect type {}. Expected {}".format(
value,
_typeStr(value),
_typeStr(self.dtype),
)
msg = f"Value {value} is of incorrect type {_typeStr(value)}. Expected {_typeStr(self.dtype)}"

Check warning on line 128 in python/lsst/pex/config/configField.py

View check run for this annotation

Codecov / codecov/patch

python/lsst/pex/config/configField.py#L128

Added line #L128 was not covered by tests
raise FieldValidationError(self, instance, msg)

if at is None:
Expand Down Expand Up @@ -276,7 +272,7 @@
value.validate()

if self.check is not None and not self.check(value):
msg = "%s is not a valid value" % str(value)
msg = f"{value} is not a valid value"

Check warning on line 275 in python/lsst/pex/config/configField.py

View check run for this annotation

Codecov / codecov/patch

python/lsst/pex/config/configField.py#L275

Added line #L275 was not covered by tests
raise FieldValidationError(self, instance, msg)

def _compare(self, instance1, instance2, shortcut, rtol, atol, output):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@
label: str = "assigment",
):
if instance._frozen:
msg = "Cannot modify a frozen Config. " "Attempting to set field to value %s" % value
msg = "Cannot modify a frozen Config. " f"Attempting to set field to value {value}"

Check warning on line 318 in python/lsst/pex/config/configurableActions/_configurableActionStructField.py

View check run for this annotation

Codecov / codecov/patch

python/lsst/pex/config/configurableActions/_configurableActionStructField.py#L318

Added line #L318 was not covered by tests
raise FieldValidationError(self, instance, msg)

if at is None:
Expand Down
17 changes: 7 additions & 10 deletions python/lsst/pex/config/configurableField.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,8 +308,8 @@
raise AttributeError("'target' must define attribute 'ConfigClass'")
if not issubclass(ConfigClass, Config):
raise TypeError(
"'ConfigClass' is of incorrect type %s.'ConfigClass' must be a subclass of Config"
% _typeStr(ConfigClass)
f"'ConfigClass' is of incorrect type {_typeStr(ConfigClass)}. "
"'ConfigClass' must be a subclass of Config"
)
if not hasattr(target, "__call__"):
raise ValueError("'target' must be callable")
Expand Down Expand Up @@ -389,10 +389,9 @@
value = oldValue.ConfigClass()
oldValue.update(__at=at, __label=label, **value._storage)
else:
msg = "Value {} is of incorrect type {}. Expected {}".format(
value,
_typeStr(value),
_typeStr(oldValue.ConfigClass),
msg = (

Check warning on line 392 in python/lsst/pex/config/configurableField.py

View check run for this annotation

Codecov / codecov/patch

python/lsst/pex/config/configurableField.py#L392

Added line #L392 was not covered by tests
f"Value {value} is of incorrect type {_typeStr(value)}. "
f"Expected {_typeStr(oldValue.ConfigClass)}"
)
raise FieldValidationError(self, instance, msg)

Expand All @@ -418,9 +417,7 @@
# save target information
ConfigClass = value.ConfigClass
outfile.write(
"{}.retarget(target={}, ConfigClass={})\n\n".format(
fullname, _typeStr(target), _typeStr(ConfigClass)
)
f"{fullname}.retarget(target={_typeStr(target)}, ConfigClass={_typeStr(ConfigClass)})\n\n"
)
# save field values
value._save(outfile)
Expand All @@ -438,7 +435,7 @@
value.validate()

if self.check is not None and not self.check(value):
msg = "%s is not a valid value" % str(value)
msg = f"{value} is not a valid value"

Check warning on line 438 in python/lsst/pex/config/configurableField.py

View check run for this annotation

Codecov / codecov/patch

python/lsst/pex/config/configurableField.py#L438

Added line #L438 was not covered by tests
raise FieldValidationError(self, instance, msg)

def __deepcopy__(self, memo):
Expand Down
Loading
Loading