diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2fdb8600f..069bbcf9c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -43,7 +43,7 @@ repos: hooks: - id: isort - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: 'v0.0.257' + rev: 'v0.0.260' hooks: - id: ruff - repo: https://github.com/codespell-project/codespell @@ -61,6 +61,13 @@ repos: - flake8-debugger - flake8-string-format - flake8-typing-imports + - repo: https://github.com/PyCQA/bandit + rev: '1.7.5' + hooks: + - id: bandit + args: ["-c", "pyproject.toml", "--quiet", "--format=custom"] + files: ^dvc/ + additional_dependencies: [".[toml]"] - repo: local hooks: - id: mypy diff --git a/dvc/commands/completion.py b/dvc/commands/completion.py index 8ea5ae31d..9f2182eca 100644 --- a/dvc/commands/completion.py +++ b/dvc/commands/completion.py @@ -15,7 +15,7 @@ class CmdCompletion(CmdBaseNoRepo): shell = self.args.shell parser = self.args.parser - script = shtab.complete(parser, shell=shell, preamble=PREAMBLE) + script = shtab.complete(parser, shell=shell, preamble=PREAMBLE) # nosec B604 ui.write(script, force=True) return 0 diff --git a/dvc/daemon.py b/dvc/daemon.py index ec0716e1c..494b5eda9 100644 --- a/dvc/daemon.py +++ b/dvc/daemon.py @@ -5,7 +5,7 @@ import logging import os import platform import sys -from subprocess import Popen +from subprocess import Popen # nosec B404 from typing import List from dvc.env import DVC_DAEMON @@ -28,12 +28,12 @@ def _popen(cmd, **kwargs) -> Popen: os.path.abspath(os.path.dirname(__file__)), "__main__.py" ) prefix += [main_entrypoint] - return Popen(prefix + cmd, close_fds=True, shell=False, **kwargs) + return Popen(prefix + cmd, close_fds=True, shell=False, **kwargs) # nosec B603 def _spawn_windows(cmd, env): if sys.platform == "win32": - from subprocess import ( + from subprocess import ( # nosec B404 CREATE_NEW_PROCESS_GROUP, CREATE_NO_WINDOW, STARTF_USESHOWWINDOW, diff --git a/dvc/lock.py b/dvc/lock.py index de8929c34..a147ba668 100644 --- a/dvc/lock.py +++ b/dvc/lock.py @@ -187,7 +187,9 @@ class HardlinkLock(flufl.lock.Lock, LockBase): if self._tmp_dir is not None: # Under Windows file path length is limited so we hash it - hasher = hashlib.md5(self._claimfile.encode()) # noqa: S324 + hasher = hashlib.md5( # nosec B324, B303 # noqa: S324 + self._claimfile.encode() + ) filename = hasher.hexdigest() self._claimfile = os.path.join(self._tmp_dir, filename + ".lock") diff --git a/dvc/logger.py b/dvc/logger.py index be532d407..1776d5472 100644 --- a/dvc/logger.py +++ b/dvc/logger.py @@ -146,7 +146,8 @@ class LoggerHandler(logging.StreamHandler): self.emit_pretty_exception(exc, verbose=_is_verbose()) if not _is_verbose(): return - except Exception: # noqa, pylint: disable=broad-except + # pylint: disable-next=broad-except + except Exception: # noqa: BLE001, S110 # nosec B110 pass msg = self.format(record) diff --git a/dvc/parsing/interpolate.py b/dvc/parsing/interpolate.py index f175dfdc2..a423c0a1b 100644 --- a/dvc/parsing/interpolate.py +++ b/dvc/parsing/interpolate.py @@ -73,7 +73,7 @@ def embrace(s: str): def escape_str(value): if os.name == "nt": - from subprocess import list2cmdline + from subprocess import list2cmdline # nosec B404 return list2cmdline([value]) from shlex import quote diff --git a/dvc/repo/__init__.py b/dvc/repo/__init__.py index ac6f28e29..dfd428712 100644 --- a/dvc/repo/__init__.py +++ b/dvc/repo/__init__.py @@ -585,10 +585,10 @@ class Repo: finally: os.umask(umask) - repo_token = hashlib.md5( # noqa: S324 + md5 = hashlib.md5( # noqa: S324 # nosec B324, B303 str((root_dir, getpass.getuser())).encode() - ).hexdigest() - + ) + repo_token = md5.hexdigest() return os.path.join(repos_dir, repo_token) def close(self): diff --git a/dvc/repo/experiments/executor/base.py b/dvc/repo/experiments/executor/base.py index 7f9a21f24..64cb12085 100644 --- a/dvc/repo/experiments/executor/base.py +++ b/dvc/repo/experiments/executor/base.py @@ -1,6 +1,6 @@ import logging import os -import pickle +import pickle # nosec B403 from abc import ABC, abstractmethod from contextlib import contextmanager from dataclasses import asdict, dataclass @@ -361,7 +361,7 @@ class BaseExecutor(ABC): @staticmethod def unpack_repro_args(path): with open(path, "rb") as fobj: - data = pickle.load(fobj) + data = pickle.load(fobj) # noqa: S301 # nosec B301 return data["args"], data["kwargs"] def fetch_exps( diff --git a/dvc/repo/experiments/queue/base.py b/dvc/repo/experiments/queue/base.py index 72913d59d..4f4fb9726 100644 --- a/dvc/repo/experiments/queue/base.py +++ b/dvc/repo/experiments/queue/base.py @@ -496,7 +496,7 @@ class BaseStashQueue(ABC): return msg def _pack_args(self, *args, **kwargs) -> None: - import pickle + import pickle # nosec B403 if os.path.exists(self.args_file) and self.scm.is_tracked(self.args_file): logger.warning( @@ -511,7 +511,7 @@ class BaseStashQueue(ABC): ) with open(self.args_file, "rb") as fobj: try: - data = pickle.load(fobj) + data = pickle.load(fobj) # noqa: S301 # nosec B301 except Exception: # noqa: BLE001, pylint: disable=broad-except data = {} extra = int(data.get("extra", 0)) + 1 diff --git a/dvc/repo/experiments/utils.py b/dvc/repo/experiments/utils.py index c7106caa3..f97b2d68c 100644 --- a/dvc/repo/experiments/utils.py +++ b/dvc/repo/experiments/utils.py @@ -306,8 +306,8 @@ def get_random_exp_name(scm, baseline_rev): ADJECTIVES = ('about', 'above', 'abuzz', 'acerb', 'acold', 'acred', 'added', 'addle', 'adept', 'adult', 'adunc', 'adust', 'afoul', 'after', 'agape', 'agaze', 'agile', 'aging', 'agley', 'aglow', 'ahead', 'ahull', 'aided', 'alary', 'algal', 'alike', 'alive', 'alone', 'aloof', 'alpha', 'amber', 'amiss', 'amort', 'ample', 'amuck', 'angry', 'anile', 'apeak', 'apish', 'arced', 'areal', 'armed', 'aroid', 'ashen', 'aspen', 'astir', 'atilt', 'atrip', 'aulic', 'aural', 'awash', 'awful', 'awing', 'awned', 'axile', 'azoic', 'azure', 'baggy', 'baked', 'balky', 'bally', 'balmy', 'banal', 'bandy', 'bardy', 'bared', 'barer', 'barky', 'basal', 'based', 'baser', 'basic', 'batty', 'bawdy', 'beady', 'beaky', 'beamy', 'beaut', 'beefy', 'beery', 'beige', 'bendy', 'bifid', 'bijou', 'biped', 'birch', 'bitty', 'blame', 'bland', 'blank', 'blear', 'blest', 'blind', 'blond', 'blown', 'blowy', 'bluer', 'bluff', 'blunt', 'boned', 'bonny', 'boozy', 'bored', 'boric', 'bosky', 'bosom', 'bound', 'bovid', 'bowed', 'boxed', 'braky', 'brash', 'brief', 'briny', 'brisk', 'broad', 'broch', 'brood', 'brown', 'brute', 'buggy', 'bulgy', 'bumpy', 'burly', 'burnt', 'burry', 'bushy', 'busty', 'butch', 'buxom', 'cadgy', 'cagey', 'calmy', 'campy', 'canny', 'caped', 'cased', 'catty', 'cauld', 'cedar', 'cered', 'ceric', 'chary', 'cheap', 'cheek', 'chewy', 'chief', 'chill', 'chirk', 'choky', 'cissy', 'civil', 'cleft', 'coaly', 'color', 'comfy', 'comic', 'compo', 'conic', 'couth', 'coxal', 'crack', 'crank', 'crash', 'crass', 'crisp', 'cronk', 'cross', 'crude', 'cruel', 'crumb', 'cured', 'curly', 'curst', 'cushy', 'cutty', 'cynic', 'dated', 'dazed', 'dedal', 'deism', 'diazo', 'dicey', 'dingy', 'direr', 'dirty', 'dishy', 'dizzy', 'dolce', 'doped', 'dopey', 'dormy', 'dorty', 'dosed', 'dotal', 'dotty', 'dowdy', 'dowie', 'downy', 'dozen', 'drawn', 'dread', 'drear', 'dress', 'dried', 'ducky', 'duddy', 'dummy', 'dumpy', 'duple', 'dural', 'dusky', 'dusty', 'dutch', 'dying', 'eager', 'eaten', 'ebony', 'edged', 'eerie', 'eight', 'elder', 'elect', 'elfin', 'elite', 'empty', 'enate', 'enemy', 'epoxy', 'erect', 'ethic', 'every', 'extra', 'faced', 'faery', 'faint', 'famed', 'fancy', 'farci', 'fatal', 'fated', 'fatty', 'fazed', 'felon', 'fenny', 'ferny', 'fetal', 'fetid', 'fewer', 'fiery', 'fifty', 'filar', 'filmy', 'final', 'fined', 'finer', 'finny', 'fired', 'first', 'fishy', 'fixed', 'fizzy', 'flaky', 'flamy', 'flash', 'flawy', 'fleet', 'flory', 'flown', 'fluid', 'fluky', 'flush', 'focal', 'foggy', 'folio', 'forky', 'forte', 'forty', 'found', 'frail', 'frank', 'freed', 'freer', 'fresh', 'fried', 'front', 'frore', 'fuggy', 'funky', 'funny', 'furry', 'fusil', 'fussy', 'fuzzy', 'gabby', 'gamer', 'gamey', 'gamic', 'gammy', 'garni', 'gauge', 'gaunt', 'gauzy', 'gawky', 'gawsy', 'gemmy', 'genal', 'genic', 'ghast', 'gimpy', 'girly', 'glare', 'glary', 'glial', 'glued', 'gluey', 'godly', 'gooey', 'goofy', 'goosy', 'gouty', 'grade', 'grand', 'grapy', 'grave', 'gross', 'group', 'gruff', 'guest', 'gules', 'gulfy', 'gummy', 'gushy', 'gusty', 'gutsy', 'gutta', 'gypsy', 'gyral', 'hadal', 'hammy', 'handy', 'hardy', 'hasty', 'hated', 'hazel', 'heady', 'heapy', 'hefty', 'heigh', 'hempy', 'herby', 'hexed', 'hi-fi', 'hilly', 'hired', 'holey', 'honey', 'hooly', 'hoven', 'huger', 'hulky', 'humid', 'hunky', 'hyoid', 'idled', 'iliac', 'inane', 'incog', 'inert', 'inner', 'inter', 'iodic', 'ionic', 'irate', 'irony', 'itchy', 'jaggy', 'jammy', 'japan', 'jazzy', 'jerky', 'jetty', 'joint', 'jowly', 'juicy', 'jumpy', 'jural', 'kacha', 'kaput', 'kempt', 'keyed', 'kinky', 'known', 'kooky', 'kraal', 'laced', 'laigh', 'lairy', 'lamer', 'lardy', 'larky', 'lated', 'later', 'lathy', 'leady', 'leafy', 'leaky', 'leary', 'least', 'ledgy', 'leery', 'legal', 'leggy', 'lento', 'level', 'licht', 'licit', 'liege', 'light', 'liked', 'liney', 'lippy', 'lived', 'livid', 'loamy', 'loath', 'lobar', 'local', 'loony', 'loose', 'loral', 'losel', 'lousy', 'loved', 'lower', 'lowly', 'lowse', 'loyal', 'lucid', 'lucky', 'lumpy', 'lunar', 'lurid', 'lushy', 'lying', 'lyric', 'macho', 'macro', 'magic', 'major', 'malar', 'mangy', 'manky', 'manly', 'mardy', 'massy', 'mated', 'matte', 'mauve', 'mazed', 'mealy', 'meaty', 'medal', 'melic', 'mesic', 'mesne', 'messy', 'metal', 'miffy', 'milky', 'mined', 'minim', 'minor', 'minus', 'mired', 'mirky', 'misty', 'mixed', 'modal', 'model', 'moire', 'molar', 'moldy', 'moody', 'moony', 'mopey', 'moral', 'mossy', 'mothy', 'motor', 'mousy', 'moved', 'mucid', 'mucky', 'muddy', 'muggy', 'muley', 'mural', 'murky', 'mushy', 'muted', 'muzzy', 'myoid', 'naggy', 'naive', 'naked', 'named', 'nasty', 'natal', 'naval', 'nervy', 'newsy', 'nicer', 'niffy', 'nifty', 'ninth', 'nitty', 'nival', 'noble', 'nodal', 'noisy', 'non-U', 'north', 'nosed', 'noted', 'nowed', 'nubby', 'oaken', 'oared', 'oaten', 'obese', 'ocher', 'ochre', 'often', 'ohmic', 'oiled', 'olden', 'older', 'oleic', 'olive', 'optic', 'ortho', 'osmic', 'other', 'outer', 'ovoid', 'owing', 'owned', 'paced', 'pagan', 'paled', 'paler', 'pally', 'paper', 'pappy', 'parky', 'party', 'pasty', 'pavid', 'pawky', 'peaky', 'pearl', 'peart', 'peaty', 'pedal', 'peppy', 'perdu', 'perky', 'pesky', 'phony', 'piano', 'picky', 'piled', 'piney', 'pious', 'pique', 'pithy', 'platy', 'plump', 'plush', 'podgy', 'potty', 'power', 'prest', 'pricy', 'prima', 'prime', 'print', 'privy', 'prize', 'prone', 'proof', 'prosy', 'proud', 'proxy', 'pseud', 'pucka', 'pudgy', 'puffy', 'pukka', 'pupal', 'purer', 'pursy', 'pushy', 'pyoid', 'quack', 'quare', 'quasi', 'quiet', 'quits', 'rabic', 'rabid', 'radio', 'raked', 'randy', 'rapid', 'rarer', 'raspy', 'rathe', 'ratty', 'ready', 'reedy', 'reeky', 'refer', 'regal', 'riant', 'ridgy', 'right', 'riled', 'rimed', 'rindy', 'risen', 'risky', 'ritzy', 'rival', 'riven', 'robed', 'rocky', 'roily', 'roman', 'rooky', 'ropey', 'round', 'rowdy', 'ruddy', 'ruled', 'rummy', 'runic', 'runny', 'runty', 'rural', 'rusty', 'rutty', 'sable', 'salic', 'sandy', 'sappy', 'sarky', 'sassy', 'sated', 'saved', 'savvy', 'scald', 'scaly', 'scary', 'score', 'scrap', 'sedgy', 'seely', 'seral', 'sewed', 'shaky', 'sharp', 'sheen', 'shier', 'shill', 'shoal', 'shock', 'shoed', 'shore', 'short', 'shyer', 'silky', 'silly', 'silty', 'sixth', 'sixty', 'skint', 'slack', 'slant', 'sleek', 'slier', 'slimy', 'slung', 'small', 'smart', 'smoky', 'snaky', 'sneak', 'snide', 'snowy', 'snuff', 'so-so', 'soapy', 'sober', 'socko', 'solar', 'soled', 'solid', 'sonic', 'sooth', 'sooty', 'soppy', 'sorer', 'sound', 'soupy', 'spent', 'spicy', 'spiky', 'spiny', 'spiry', 'splay', 'split', 'sport', 'spumy', 'squat', 'staid', 'stiff', 'still', 'stoic', 'stone', 'stony', 'store', 'stout', 'straw', 'stray', 'strip', 'stung', 'suave', 'sudsy', 'sulfa', 'sulky', 'sunny', 'super', 'sural', 'surer', 'surfy', 'surgy', 'surly', 'swell', 'swept', 'swish', 'sworn', 'tabby', 'taboo', 'tacit', 'tacky', 'tamed', 'tamer', 'tangy', 'taped', 'tarot', 'tarry', 'tasty', 'tatty', 'taunt', 'tawie', 'teary', 'techy', 'telic', 'tenor', 'tense', 'tenth', 'tenty', 'tepid', 'terse', 'testy', 'third', 'tidal', 'tight', 'tiled', 'timid', 'tinct', 'tined', 'tippy', 'tipsy', 'tonal', 'toned', 'tonic', 'toric', 'total', 'tough', 'toxic', 'trade', 'treed', 'treen', 'trial', 'truer', 'tubal', 'tubby', 'tumid', 'tuned', 'tutti', 'twill', 'typal', 'typed', 'typic', 'umber', 'unapt', 'unbid', 'uncut', 'undue', 'undug', 'unfed', 'unfit', 'union', 'unlet', 'unmet', 'unwed', 'unwet', 'upper', 'upset', 'urban', 'utile', 'uveal', 'vagal', 'valid', 'vapid', 'varus', 'vatic', 'veiny', 'vital', 'vivid', 'vocal', 'vogie', 'volar', 'vying', 'wacky', 'wally', 'waney', 'warty', 'washy', 'waspy', 'waste', 'waugh', 'waxen', 'webby', 'wedgy', 'weeny', 'weepy', 'weest', 'weird', 'welsh', 'wersh', 'whist', 'white', 'whity', 'whole', 'wider', 'wight', 'winey', 'wired', 'wised', 'wiser', 'withy', 'wonky', 'woods', 'woozy', 'world', 'wormy', 'worse', 'worst', 'woven', 'wrath', 'wrier', 'wrong', 'wroth', 'xeric', 'yarer', 'yolky', 'young', 'yucky', 'yummy', 'zesty', 'zingy', 'zinky', 'zippy', 'zonal') # noqa: E501, Q000, N806 # fmt: on while True: - adjective = random.choice(ADJECTIVES) # nosec B311 - noun = random.choice(NOUNS) # nosec B311 + adjective = random.choice(ADJECTIVES) # noqa: S311 # nosec B311 + noun = random.choice(NOUNS) # noqa: S311 # nosec B311 name = f"{adjective}-{noun}" exp_ref = ExpRefInfo(baseline_sha=baseline_rev, name=name) if not scm.get_ref(str(exp_ref)): diff --git a/dvc/repo/index.py b/dvc/repo/index.py index e2d2249d9..95d21e96e 100644 --- a/dvc/repo/index.py +++ b/dvc/repo/index.py @@ -264,7 +264,7 @@ class Index: def check_graph(self) -> None: if not getattr(self.repo, "_skip_graph_checks", False): - self.graph # pylint: disable=pointless-statement + self.graph # noqa: B018, pylint: disable=pointless-statement @property def params(self) -> Iterator["ParamsDependency"]: diff --git a/dvc/stage/monitor.py b/dvc/stage/monitor.py index 4a62e034e..d7aa02e11 100644 --- a/dvc/stage/monitor.py +++ b/dvc/stage/monitor.py @@ -1,7 +1,7 @@ import functools import logging import os -import subprocess +import subprocess # nosec B404 import threading from dataclasses import dataclass from typing import TYPE_CHECKING, Callable, List @@ -96,7 +96,9 @@ class Monitor: def _kill_nt(proc): # windows stages are spawned with shell=True, proc is the shell process # and not the actual stage process - we have to kill the entire tree - subprocess.call(["taskkill", "/F", "/T", "/PID", str(proc.pid)]) + subprocess.call( # nosec B607, B603 + ["taskkill", "/F", "/T", "/PID", str(proc.pid)] + ) @staticmethod def _loop(tasks: List[MonitorTask], done: threading.Event): diff --git a/dvc/stage/run.py b/dvc/stage/run.py index 18d9acfbc..3ae7d12b1 100644 --- a/dvc/stage/run.py +++ b/dvc/stage/run.py @@ -1,7 +1,7 @@ import logging import os import signal -import subprocess +import subprocess # nosec B404 import threading from typing import TYPE_CHECKING, List @@ -86,7 +86,7 @@ def _run(stage: "Stage", executable, cmd, checkpoint_func, **kwargs): exec_cmd = _make_cmd(executable, cmd) try: - p = subprocess.Popen(exec_cmd, **kwargs) + p = subprocess.Popen(exec_cmd, **kwargs) # nosec B603 if main_thread: old_handler = signal.signal(signal.SIGINT, signal.SIG_IGN) diff --git a/dvc/testing/fixtures.py b/dvc/testing/fixtures.py index 7f58ea598..062403348 100644 --- a/dvc/testing/fixtures.py +++ b/dvc/testing/fixtures.py @@ -1,5 +1,5 @@ import os -import subprocess +import subprocess # nosec B404 from typing import Dict, Tuple import pytest @@ -233,14 +233,16 @@ def docker_services( pytest.skip("disabled for Windows on CI") try: - subprocess.check_output("docker ps", stderr=subprocess.STDOUT, shell=True) + subprocess.check_output( # nosec B607, B602 + "docker ps", stderr=subprocess.STDOUT, shell=True + ) except subprocess.CalledProcessError as err: out = (err.output or b"").decode("utf-8") pytest.skip(f"docker is not installed or the daemon is not running: {out}") try: cmd = "docker-compose version" - subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True) + subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True) # nosec except subprocess.CalledProcessError as err: out = (err.output or b"").decode("utf-8") pytest.skip(f"docker-compose is not installed: {out}") diff --git a/dvc/ui/pager.py b/dvc/ui/pager.py index e4c4a038f..03c8cf449 100644 --- a/dvc/ui/pager.py +++ b/dvc/ui/pager.py @@ -59,7 +59,7 @@ def find_pager(): if not pager: pager = os.getenv(PAGER_ENV) if not pager: - if os.system(f"({DEFAULT_PAGER}) 2>{os.devnull}") != 0: + if os.system(f"({DEFAULT_PAGER}) 2>{os.devnull}") != 0: # nosec B605 logger.warning( "Unable to find `less` in the PATH. Check out %s for more info.", format_link("https://man.dvc.org/pipeline/show"), diff --git a/dvc/version.py b/dvc/version.py index d4f3b0faa..98b65d2a0 100644 --- a/dvc/version.py +++ b/dvc/version.py @@ -1,7 +1,7 @@ # pylint: disable=unused-import try: - from ._dvc_version import version as __version__ - from ._dvc_version import version_tuple + from ._dvc_version import version as __version__ # type: ignore[import] + from ._dvc_version import version_tuple # type: ignore[import] except ImportError: __version__ = "UNKNOWN" version_tuple = (0, 0, __version__) # type: ignore[assignment] diff --git a/pyproject.toml b/pyproject.toml index e0ce0cdae..da3f58cfe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -257,9 +257,8 @@ ignored-argument-names = "_.*|args|kwargs" # external flake8 codes that should be preserved external = ["B301", "C901", "E302", "W601"] ignore = ["N818", "S101", "PT004", "PT007", "PT019", "SIM105", "SIM108", "SIM110", "SIM117", "TRY003", "TRY200", "TRY300", "TRY301", "PLR2004", "PLW2901", "RUF005"] -select = ["F", "E", "W", "C90", "N", "UP", "YTT", "S", "BLE", "B", "A", "C4", "T10", "ISC", "ICN", "G", "INP", "PIE", "T20", "PT", "Q", "RET501", "RET504", "SIM", "TID", "TCH", "ARG", "PGH", "PLC", "PLE", "PLR", "PLW", "TRY", "RUF"] +select = ["F", "E", "W", "C90", "N", "UP", "YTT", "S", "BLE", "B", "A", "C4", "T10", "EXE", "ISC", "ICN", "G", "INP", "PIE", "T20", "PT", "Q", "RET501", "RET504", "SIM", "TID", "TCH", "ARG", "PGH", "PLC", "PLE", "PLR", "PLW", "TRY", "RUF"] show-source = true -target-version = "py38" [tool.ruff.flake8-pytest-style] fixture-parentheses = false @@ -290,3 +289,7 @@ ignore-names = ["M", "SCM"] [tool.ruff.pylint] max-args = 10 + +[tool.bandit] +exclude_dirs = ["tests", "scripts"] +skips = ["B101"] diff --git a/tests/unit/remote/test_webhdfs.py b/tests/unit/remote/test_webhdfs.py index 77b3ea039..9d9ccde74 100644 --- a/tests/unit/remote/test_webhdfs.py +++ b/tests/unit/remote/test_webhdfs.py @@ -47,5 +47,5 @@ def test_verify_ssl(dvc, webhdfs_config, monkeypatch, mocker): del webhdfs_config["token"] fs = WebHDFSFileSystem(**webhdfs_config) # ssl verify can't be set until after the file system is instantiated - fs.fs + assert fs.fs assert mock_session.verify == ssl_verify