Skip to content

Commit 3e35433

Browse files
committed
Fix warnings introduced by upgrades
Signed-off-by: Beat Buesser <beat.buesser@ibm.com>
1 parent 3ad1538 commit 3e35433

File tree

266 files changed

+3073
-3185
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

266 files changed

+3073
-3185
lines changed

.github/workflows/ci-style-checks.yml

+2-5
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,13 @@ jobs:
4949
run: pycodestyle --ignore=C0330,C0415,E203,E231,W503 --max-line-length=120 art
5050
- name: pylint
5151
if: ${{ always() }}
52-
run: pylint --disable=C0330,C0415,E203,E1136,E0401,E1102 -rn art
52+
run: pylint --fail-under=9.67 art/
5353
- name: mypy
5454
if: ${{ always() }}
5555
run: mypy art
5656
- name: ruff
5757
if: ${{ always() }}
58-
run: |
59-
ruff check art/
60-
ruff check tests/
61-
ruff check examples/
58+
run: ruff check art/ tests/ examples/
6259
- name: black
6360
if: ${{ always() }}
6461
run: |

.pylintrc

+9-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,15 @@ disable=
109109
# We anticipate #3512 where it will become optional
110110
fixme,
111111
consider-using-assignment-expr,
112-
112+
# ART
113+
duplicate-code,
114+
no-member,
115+
import-outside-toplevel,
116+
import-error,
117+
not-callable,
118+
too-many-arguments,
119+
too-many-locals,
120+
unsupported-binary-operation,
113121

114122
[REPORTS]
115123

art/__init__.py

-2
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
# Semantic Version
1616
__version__ = "1.18.1"
1717

18-
# pylint: disable=C0103
19-
2018
LOGGING = {
2119
"version": 1,
2220
"disable_existing_loggers": False,

art/attacks/attack.py

+28-41
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@
1818
"""
1919
This module implements the abstract base classes for all attacks.
2020
"""
21-
from __future__ import absolute_import, division, print_function, unicode_literals
21+
from __future__ import absolute_import, division, print_function, unicode_literals, annotations
2222

2323
import abc
2424
import logging
25-
from typing import Any, Dict, List, Optional, Tuple, Union, TYPE_CHECKING
25+
from typing import Any, TYPE_CHECKING
2626

2727
import numpy as np
2828

@@ -38,17 +38,18 @@
3838

3939
class InputFilter(abc.ABCMeta): # pragma: no cover
4040
"""
41-
Metaclass to ensure that inputs are ndarray for all of the subclass generate and extract calls
41+
Metaclass to ensure that inputs are ndarray for all the subclass generate and extract calls
4242
"""
4343

44-
# pylint: disable=W0613
45-
def __init__(cls, name, bases, clsdict): # pylint: disable=W0231
44+
def __init__(cls, name, bases, clsdict):
4645
"""
4746
This function overrides any existing generate or extract methods with a new method that
4847
ensures the input is an `np.ndarray`. There is an assumption that the input object has implemented
4948
__array__ with np.array calls.
5049
"""
5150

51+
super().__init__()
52+
5253
def make_replacement(fdict, func_name):
5354
"""
5455
This function overrides creates replacement functions dynamically
@@ -94,17 +95,17 @@ class Attack(abc.ABC):
9495
Abstract base class for all attack abstract base classes.
9596
"""
9697

97-
attack_params: List[str] = []
98+
attack_params: list[str] = []
9899
# The _estimator_requirements define the requirements an estimator must satisfy to be used as a target for an
99100
# attack. They should be a tuple of requirements, where each requirement is either a class the estimator must
100101
# inherit from, or a tuple of classes which define a union, i.e. the estimator must inherit from at least one class
101102
# in the requirement tuple.
102-
_estimator_requirements: Optional[Union[Tuple[Any, ...], Tuple[()]]] = None
103+
_estimator_requirements: tuple[Any, ...] | tuple[()] | None = None
103104

104105
def __init__(
105106
self,
106107
estimator,
107-
summary_writer: Union[str, bool, SummaryWriter] = False,
108+
summary_writer: str | bool | SummaryWriter = False,
108109
):
109110
"""
110111
:param estimator: An estimator.
@@ -126,7 +127,7 @@ def __init__(
126127

127128
self._estimator = estimator
128129
self._summary_writer_arg = summary_writer
129-
self._summary_writer: Optional[SummaryWriter] = None
130+
self._summary_writer: SummaryWriter | None = None
130131

131132
if isinstance(summary_writer, SummaryWriter): # pragma: no cover
132133
self._summary_writer = summary_writer
@@ -212,13 +213,13 @@ def __init__(self, **kwargs) -> None:
212213
super().__init__(**kwargs)
213214

214215
@abc.abstractmethod
215-
def generate(self, x: np.ndarray, y: Optional[np.ndarray] = None, **kwargs) -> np.ndarray:
216+
def generate(self, x: np.ndarray, y: np.ndarray | None = None, **kwargs) -> np.ndarray:
216217
"""
217218
Generate adversarial examples and return them as an array. This method should be overridden by all concrete
218219
evasion attack implementations.
219220
220221
:param x: An array with the original inputs to be attacked.
221-
:param y: Correct labels or target labels for `x`, depending if the attack is targeted
222+
:param y: Correct labels or target labels for `x`, depending on if the attack is targeted
222223
or not. This parameter is only used by some of the attacks.
223224
:return: An array holding the adversarial examples.
224225
"""
@@ -241,14 +242,14 @@ class PoisoningAttack(Attack):
241242
Abstract base class for poisoning attack classes
242243
"""
243244

244-
def __init__(self, classifier: Optional["CLASSIFIER_TYPE"]) -> None:
245+
def __init__(self, classifier: "CLASSIFIER_TYPE" | None) -> None:
245246
"""
246247
:param classifier: A trained classifier (or none if no classifier is needed)
247248
"""
248249
super().__init__(classifier)
249250

250251
@abc.abstractmethod
251-
def poison(self, x: np.ndarray, y=Optional[np.ndarray], **kwargs) -> Tuple[np.ndarray, np.ndarray]:
252+
def poison(self, x: np.ndarray, y: np.ndarray | None = None, **kwargs) -> tuple[np.ndarray, np.ndarray]:
252253
"""
253254
Generate poisoning examples and return them as an array. This method should be overridden by all concrete
254255
poisoning attack implementations.
@@ -310,14 +311,8 @@ class PoisoningAttackTransformer(PoisoningAttack):
310311
These attacks have an additional method, `poison_estimator`, that returns the poisoned classifier.
311312
"""
312313

313-
def __init__(self, classifier: Optional["CLASSIFIER_TYPE"]) -> None:
314-
"""
315-
:param classifier: A trained classifier (or none if no classifier is needed)
316-
"""
317-
super().__init__(classifier)
318-
319314
@abc.abstractmethod
320-
def poison(self, x: np.ndarray, y=Optional[np.ndarray], **kwargs) -> Tuple[np.ndarray, np.ndarray]:
315+
def poison(self, x: np.ndarray, y: np.ndarray | None = None, **kwargs) -> tuple[np.ndarray, np.ndarray]:
321316
"""
322317
Generate poisoning examples and return them as an array. This method should be overridden by all concrete
323318
poisoning attack implementations.
@@ -354,16 +349,16 @@ def __init__(self):
354349
@abc.abstractmethod
355350
def poison(
356351
self,
357-
x: Union[np.ndarray, List[np.ndarray]],
358-
y: List[Dict[str, np.ndarray]],
352+
x: np.ndarray | list[np.ndarray],
353+
y: list[dict[str, np.ndarray]],
359354
**kwargs,
360-
) -> Tuple[Union[np.ndarray, List[np.ndarray]], List[Dict[str, np.ndarray]]]:
355+
) -> tuple[np.ndarray | list[np.ndarray], list[dict[str, np.ndarray]]]:
361356
"""
362357
Generate poisoning examples and return them as an array. This method should be overridden by all concrete
363358
poisoning attack implementations.
364359
365360
:param x: An array with the original inputs to be attacked.
366-
:param y: True labels of type `List[Dict[np.ndarray]]`, one dictionary per input image.
361+
:param y: True labels of type `list[dict[np.ndarray]]`, one dictionary per input image.
367362
The keys and values of the dictionary are:
368363
- boxes [N, 4]: the boxes in [x1, y1, x2, y2] format, with 0 <= x1 < x2 <= W and 0 <= y1 < y2 <= H.
369364
- labels [N]: the labels for each image
@@ -385,7 +380,7 @@ def __init__(self):
385380
super().__init__(None) # type: ignore
386381

387382
@abc.abstractmethod
388-
def poison(self, x: np.ndarray, y: Optional[np.ndarray] = None, **kwargs) -> Tuple[np.ndarray, np.ndarray]:
383+
def poison(self, x: np.ndarray, y: np.ndarray | None = None, **kwargs) -> tuple[np.ndarray, np.ndarray]:
389384
"""
390385
Generate poisoning examples and return them as an array. This method should be overridden by all concrete
391386
poisoning attack implementations.
@@ -403,7 +398,7 @@ class PoisoningAttackWhiteBox(PoisoningAttack):
403398
"""
404399

405400
@abc.abstractmethod
406-
def poison(self, x: np.ndarray, y: Optional[np.ndarray] = None, **kwargs) -> Tuple[np.ndarray, np.ndarray]:
401+
def poison(self, x: np.ndarray, y: np.ndarray | None = None, **kwargs) -> tuple[np.ndarray, np.ndarray]:
407402
"""
408403
Generate poisoning examples and return them as an array. This method should be overridden by all concrete
409404
poisoning attack implementations.
@@ -422,7 +417,7 @@ class ExtractionAttack(Attack):
422417
"""
423418

424419
@abc.abstractmethod
425-
def extract(self, x: np.ndarray, y: Optional[np.ndarray] = None, **kwargs) -> "CLASSIFIER_TYPE":
420+
def extract(self, x: np.ndarray, y: np.ndarray | None = None, **kwargs) -> "CLASSIFIER_TYPE":
426421
"""
427422
Extract models and return them as an ART classifier. This method should be overridden by all concrete extraction
428423
attack implementations.
@@ -448,7 +443,7 @@ def __init__(self, estimator):
448443
super().__init__(estimator)
449444

450445
@abc.abstractmethod
451-
def infer(self, x: np.ndarray, y: Optional[np.ndarray] = None, **kwargs) -> np.ndarray:
446+
def infer(self, x: np.ndarray, y: np.ndarray | None = None, **kwargs) -> np.ndarray:
452447
"""
453448
Infer sensitive attributes from the targeted estimator. This method
454449
should be overridden by all concrete inference attack implementations.
@@ -467,7 +462,7 @@ class AttributeInferenceAttack(InferenceAttack):
467462

468463
attack_params = InferenceAttack.attack_params + ["attack_feature"]
469464

470-
def __init__(self, estimator, attack_feature: Union[int, slice] = 0):
465+
def __init__(self, estimator, attack_feature: int | slice = 0):
471466
"""
472467
:param estimator: A trained estimator targeted for inference attack.
473468
:type estimator: :class:`.art.estimators.estimator.BaseEstimator`
@@ -478,7 +473,7 @@ def __init__(self, estimator, attack_feature: Union[int, slice] = 0):
478473
self.attack_feature = get_feature_index(attack_feature)
479474

480475
@abc.abstractmethod
481-
def infer(self, x: np.ndarray, y: Optional[np.ndarray] = None, **kwargs) -> np.ndarray:
476+
def infer(self, x: np.ndarray, y: np.ndarray | None = None, **kwargs) -> np.ndarray:
482477
"""
483478
Infer sensitive attributes from the targeted estimator. This method
484479
should be overridden by all concrete inference attack implementations.
@@ -490,7 +485,7 @@ def infer(self, x: np.ndarray, y: Optional[np.ndarray] = None, **kwargs) -> np.n
490485
raise NotImplementedError
491486

492487
@staticmethod
493-
def _check_attack_feature(attack_feature: Union[int, slice]) -> None:
488+
def _check_attack_feature(attack_feature: int | slice) -> None:
494489
if not isinstance(attack_feature, int) and not isinstance(attack_feature, slice):
495490
raise ValueError("Attack feature must be either an integer or a slice object.")
496491

@@ -506,16 +501,8 @@ class MembershipInferenceAttack(InferenceAttack):
506501
Abstract base class for membership inference attack classes.
507502
"""
508503

509-
def __init__(self, estimator):
510-
"""
511-
:param estimator: A trained estimator targeted for inference attack.
512-
:type estimator: :class:`.art.estimators.estimator.BaseEstimator`
513-
:param attack_feature: The index of the feature to be attacked.
514-
"""
515-
super().__init__(estimator)
516-
517504
@abc.abstractmethod
518-
def infer(self, x: np.ndarray, y: Optional[np.ndarray] = None, **kwargs) -> np.ndarray:
505+
def infer(self, x: np.ndarray, y: np.ndarray | None = None, **kwargs) -> np.ndarray:
519506
"""
520507
Infer membership status of samples from the target estimator. This method
521508
should be overridden by all concrete inference attack implementations.
@@ -552,7 +539,7 @@ def __init__(self, estimator):
552539
super().__init__(estimator)
553540

554541
@abc.abstractmethod
555-
def reconstruct(self, x: np.ndarray, y: Optional[np.ndarray] = None, **kwargs) -> Tuple[np.ndarray, np.ndarray]:
542+
def reconstruct(self, x: np.ndarray, y: np.ndarray | None = None, **kwargs) -> tuple[np.ndarray, np.ndarray]:
556543
"""
557544
Reconstruct the training dataset of and from the targeted estimator. This method
558545
should be overridden by all concrete inference attack implementations.

art/attacks/evasion/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Module providing evasion attacks under a common interface.
33
"""
44

5-
# pylint: disable=C0413
5+
# pylint: disable=wrong-import-position
66
import importlib
77

88
from art.attacks.evasion.adversarial_patch.adversarial_patch import AdversarialPatch

art/attacks/evasion/adversarial_asr.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,10 @@ def __init__(
7272
:param num_iter_decrease_eps: Iterations after which to decrease epsilon if attack succeeds (Paper default: 10).
7373
:param batch_size: Batch size.
7474
"""
75-
# pylint: disable=W0231
75+
# pylint: disable=super-init-not-called
7676

7777
# re-implement init such that inherited methods work
78-
EvasionAttack.__init__(self, estimator=estimator) # pylint: disable=W0233
78+
EvasionAttack.__init__(self, estimator=estimator) # pylint: disable=non-parent-init-called
7979
self.masker = None # type: ignore
8080
self.eps = eps
8181
self.learning_rate_1 = learning_rate

art/attacks/evasion/adversarial_patch/adversarial_patch.py

+8-8
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@
2121
2222
| Paper link: https://arxiv.org/abs/1712.09665
2323
"""
24-
from __future__ import absolute_import, division, print_function, unicode_literals
24+
from __future__ import absolute_import, division, print_function, unicode_literals, annotations
2525

2626
import logging
27-
from typing import Optional, Tuple, Union, TYPE_CHECKING
27+
from typing import TYPE_CHECKING
2828

2929
import numpy as np
3030

@@ -71,7 +71,7 @@ def __init__(
7171
learning_rate: float = 5.0,
7272
max_iter: int = 500,
7373
batch_size: int = 16,
74-
patch_shape: Optional[Tuple[int, int, int]] = None,
74+
patch_shape: tuple[int | int | int] | None = None,
7575
targeted: bool = True,
7676
verbose: bool = True,
7777
):
@@ -98,7 +98,7 @@ def __init__(
9898
if self.estimator.clip_values is None: # pragma: no cover
9999
raise ValueError("Adversarial Patch attack requires a classifier with clip_values.")
100100

101-
self._attack: Union[AdversarialPatchTensorFlowV2, AdversarialPatchPyTorch, AdversarialPatchNumpy]
101+
self._attack: AdversarialPatchTensorFlowV2 | AdversarialPatchPyTorch | AdversarialPatchNumpy
102102
if isinstance(self.estimator, TensorFlowV2Classifier):
103103
self._attack = AdversarialPatchTensorFlowV2(
104104
classifier=classifier,
@@ -145,8 +145,8 @@ def __init__(
145145
self._check_params()
146146

147147
def generate( # type: ignore
148-
self, x: np.ndarray, y: Optional[np.ndarray] = None, **kwargs
149-
) -> Tuple[np.ndarray, np.ndarray]:
148+
self, x: np.ndarray, y: np.ndarray | None = None, **kwargs
149+
) -> tuple[np.ndarray, np.ndarray]:
150150
"""
151151
Generate an adversarial patch and return the patch and its mask in arrays.
152152
@@ -173,7 +173,7 @@ def generate( # type: ignore
173173
return self._attack.generate(x=x, y=y, **kwargs)
174174

175175
def apply_patch(
176-
self, x: np.ndarray, scale: float, patch_external: Optional[np.ndarray] = None, **kwargs
176+
self, x: np.ndarray, scale: float, patch_external: np.ndarray | None = None, **kwargs
177177
) -> np.ndarray:
178178
"""
179179
A function to apply the learned adversarial patch to images or videos.
@@ -185,7 +185,7 @@ def apply_patch(
185185
"""
186186
return self._attack.apply_patch(x, scale, patch_external=patch_external, **kwargs)
187187

188-
def reset_patch(self, initial_patch_value: Optional[Union[float, np.ndarray]]) -> None:
188+
def reset_patch(self, initial_patch_value: float | np.ndarray | None) -> None:
189189
"""
190190
Reset the adversarial patch.
191191

0 commit comments

Comments
 (0)