diff --git a/.flake8 b/.flake8 deleted file mode 100644 index 8f8cdc3..0000000 --- a/.flake8 +++ /dev/null @@ -1,2 +0,0 @@ -[flake8] -ignore = E501,E203 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4550298..3616bea 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,22 +3,22 @@ name: CI on: push: branches: - - main + - main pull_request: branches: - - main + - main jobs: build: runs-on: ubuntu-latest strategy: matrix: python-version: - - '3.8' - - '3.9' - - '3.10' - - '3.11' - - 'pypy-3.8' - - 'pypy-3.9' + - "3.8" + - "3.9" + - "3.10" + - "3.11" + - "pypy-3.8" + - "pypy-3.9" fail-fast: false name: Test on Python ${{ matrix.python-version }} steps: diff --git a/Makefile b/Makefile index 64032ab..9c66978 100644 --- a/Makefile +++ b/Makefile @@ -25,9 +25,10 @@ test: build docs: build $(BIN)/tox -e docs -$(BIN)/black: - $(BIN)/pip install black +$(BIN)/ruff: + $(BIN)/pip install ruff + +ruff: $(BIN)/ruff + $(BIN)/ruff check setup.py molotov/ + $(BIN)/ruff format setup.py molotov/*.py -black: $(BIN)/black - $(BIN)/black setup.py molotov/ - $(BIN)/flake8 molotov/ diff --git a/docs/source/conf.py b/docs/source/conf.py index 5d2a980..7422c88 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -31,31 +31,32 @@ # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = ['sphinxarg.ext', 'sphinx.ext.autodoc'] +extensions = ["sphinxarg.ext", "sphinx.ext.autodoc"] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # # source_suffix = ['.rst', '.md'] -source_suffix = '.rst' +source_suffix = ".rst" # The master toctree document. -master_doc = 'index' +master_doc = "index" # General information about the project. -project = 'Molotov' -copyright = '2017, Tarek Ziadé' -author = 'Tarek Ziadé' +project = "Molotov" +copyright = "2017, Tarek Ziadé" +author = "Tarek Ziadé" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -import molotov +import molotov # noqa + release = version = molotov.__version__ # The language for content autogenerated by Sphinx. Refer to documentation @@ -63,7 +64,7 @@ # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. -language = 'en' +language = "en" # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. @@ -71,7 +72,7 @@ exclude_patterns = [] # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' +pygments_style = "sphinx" # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = False @@ -82,34 +83,36 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'alabaster' -highlight_language = 'python3' +html_theme = "alabaster" +highlight_language = "python3" # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # html_theme_options = { - 'logo': 'logo.png', - 'description': 'Load Testing Tool', - 'github_user': 'tarekziade', - 'github_repo': 'molotov', - 'github_button': True, - 'github_type': 'star', - 'github_banner': True, - 'travis_button': False, - 'pre_bg': '#FFF6E5', - 'note_bg': '#E5ECD1', - 'note_border': '#BFCF8C', - 'body_text': '#482C0A', - 'sidebar_text': '#49443E', - 'sidebar_header': '#4B4032', + "logo": "logo.png", + "description": "Load Testing Tool", + "github_user": "tarekziade", + "github_repo": "molotov", + "github_button": True, + "github_type": "star", + "github_banner": True, + "travis_button": False, + "pre_bg": "#FFF6E5", + "note_bg": "#E5ECD1", + "note_border": "#BFCF8C", + "body_text": "#482C0A", + "sidebar_text": "#49443E", + "sidebar_header": "#4B4032", } html_sidebars = { - '**': [ - 'about.html', 'navigation.html', 'searchbox.html', + "**": [ + "about.html", + "navigation.html", + "searchbox.html", ] } @@ -117,13 +120,13 @@ # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ["_static"] # -- Options for HTMLHelp output ------------------------------------------ # Output file base name for HTML help builder. -htmlhelp_basename = 'Molotovdoc' +htmlhelp_basename = "Molotovdoc" # -- Options for LaTeX output --------------------------------------------- @@ -132,15 +135,12 @@ # The paper size ('letterpaper' or 'a4paper'). # # 'papersize': 'letterpaper', - # The font size ('10pt', '11pt' or '12pt'). # # 'pointsize': '10pt', - # Additional stuff for the LaTeX preamble. # # 'preamble': '', - # Latex figure (float) alignment # # 'figure_align': 'htbp', @@ -150,8 +150,7 @@ # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, 'Molotov.tex', 'Molotov Documentation', - 'Tarek Ziadé', 'manual'), + (master_doc, "Molotov.tex", "Molotov Documentation", "Tarek Ziadé", "manual"), ] @@ -159,10 +158,7 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, 'molotov', 'Molotov Documentation', - [author], 1) -] +man_pages = [(master_doc, "molotov", "Molotov Documentation", [author], 1)] # -- Options for Texinfo output ------------------------------------------- @@ -171,10 +167,13 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'Molotov', 'Molotov Documentation', - author, 'Molotov', 'One line description of project.', - 'Miscellaneous'), + ( + master_doc, + "Molotov", + "Molotov Documentation", + author, + "Molotov", + "One line description of project.", + "Miscellaneous", + ), ] - - - diff --git a/molotov/api.py b/molotov/api.py index 357aaa1..5a0ac26 100644 --- a/molotov/api.py +++ b/molotov/api.py @@ -1,7 +1,6 @@ -import random -import functools import asyncio - +import functools +import random _SCENARIO = {} diff --git a/molotov/dummy.py b/molotov/dummy.py index baa9d42..5eb357e 100644 --- a/molotov/dummy.py +++ b/molotov/dummy.py @@ -1,9 +1,10 @@ """ Molotov-based test. """ -import molotov import random from time import sleep +import molotov + @molotov.global_setup() def starting(args): diff --git a/molotov/quickstart/__init__.py b/molotov/quickstart/__init__.py index 35e21e8..04a5e34 100644 --- a/molotov/quickstart/__init__.py +++ b/molotov/quickstart/__init__.py @@ -1,9 +1,9 @@ -import sys -import shutil -import os import argparse -from molotov import __version__ +import os +import shutil +import sys +from molotov import __version__ _DEFAULTS = {"target_dir": "."} _PREFIX = "> " diff --git a/molotov/quickstart/loadtest.py b/molotov/quickstart/loadtest.py index a963c09..fa0cd10 100644 --- a/molotov/quickstart/loadtest.py +++ b/molotov/quickstart/loadtest.py @@ -1,8 +1,8 @@ """ Molotov-based test. """ import json -from molotov import scenario, setup, global_setup, teardown, global_teardown +from molotov import global_setup, global_teardown, scenario, setup, teardown # This is the service you want to load test _API = "http://localhost:8080" diff --git a/molotov/run.py b/molotov/run.py index f644a0e..9d5b59f 100644 --- a/molotov/run.py +++ b/molotov/run.py @@ -1,17 +1,15 @@ -import os -import sys import argparse +import os import platform - +import sys from importlib import import_module -from importlib.util import spec_from_file_location, module_from_spec +from importlib.util import module_from_spec, spec_from_file_location -from molotov.runner import Runner -from molotov.api import get_scenarios, get_scenario from molotov import __version__ -from molotov.util import expand_options, OptionError, printable_error +from molotov.api import get_scenario, get_scenarios +from molotov.runner import Runner from molotov.ui.console import Console - +from molotov.util import OptionError, expand_options, printable_error PYPY = platform.python_implementation() == "PyPy" @@ -43,9 +41,7 @@ def _parser(): help="Name of a single scenario to run once.", ) - parser.add_argument( - "--config", default=None, type=str, help="Point to a JSON config file." - ) + parser.add_argument("--config", default=None, type=str, help="Point to a JSON config file.") parser.add_argument( "--version", @@ -66,31 +62,18 @@ def _parser(): "--verbose", action="count", default=0, - help=( - "Verbosity level. -v will display " - "tracebacks. -vv requests and responses." - ), + help=("Verbosity level. -v will display " "tracebacks. -vv requests and responses."), ) - parser.add_argument( - "-w", "--workers", help="Number of workers", type=int, default=1 - ) + parser.add_argument("-w", "--workers", help="Number of workers", type=int, default=1) - parser.add_argument( - "--ramp-up", help="Ramp-up time in seconds", type=float, default=0.0 - ) + parser.add_argument("--ramp-up", help="Ramp-up time in seconds", type=float, default=0.0) - parser.add_argument( - "--sizing", help="Autosizing", action="store_true", default=False - ) + parser.add_argument("--sizing", help="Autosizing", action="store_true", default=False) - parser.add_argument( - "--sizing-tolerance", help="Sizing tolerance", type=float, default=5.0 - ) + parser.add_argument("--sizing-tolerance", help="Sizing tolerance", type=float, default=5.0) - parser.add_argument( - "--delay", help="Delay between each worker run", type=float, default=0.0 - ) + parser.add_argument("--delay", help="Delay between each worker run", type=float, default=0.0) parser.add_argument( "--console-update", @@ -99,21 +82,13 @@ def _parser(): default=0.2, ) - parser.add_argument( - "-p", "--processes", help="Number of processes", type=int, default=1 - ) + parser.add_argument("-p", "--processes", help="Number of processes", type=int, default=1) - parser.add_argument( - "-d", "--duration", help="Duration in seconds", type=int, default=86400 - ) + parser.add_argument("-d", "--duration", help="Duration in seconds", type=int, default=86400) - parser.add_argument( - "-r", "--max-runs", help="Maximum runs per worker", type=int, default=None - ) + parser.add_argument("-r", "--max-runs", help="Maximum runs per worker", type=int, default=None) - parser.add_argument( - "-q", "--quiet", action="store_true", default=False, help="Quiet" - ) + parser.add_argument("-q", "--quiet", action="store_true", default=False, help="Quiet") parser.add_argument( "-x", @@ -139,9 +114,7 @@ def _parser(): help="Use simple console for feedback", ) - parser.add_argument( - "--statsd", help="Activates statsd", action="store_true", default=False - ) + parser.add_argument("--statsd", help="Activates statsd", action="store_true", default=False) parser.add_argument( "--statsd-address", @@ -150,9 +123,7 @@ def _parser(): default="udp://localhost:8125", ) - parser.add_argument( - "--uvloop", help="Use uvloop", default=False, action="store_true" - ) + parser.add_argument("--uvloop", help="Use uvloop", default=False, action="store_true") parser.add_argument( "--use-extension", @@ -298,9 +269,7 @@ def run(args, stream=None): if args.single_mode: if get_scenario(args.single_mode) is None: - direct_print( - stream, "Can't find %r in registered scenarii" % args.single_mode - ) + direct_print(stream, "Can't find %r in registered scenarii" % args.single_mode) sys.exit(1) res = Runner(args)() diff --git a/molotov/runner.py b/molotov/runner.py index 5b3c1d2..5f021e2 100644 --- a/molotov/runner.py +++ b/molotov/runner.py @@ -1,19 +1,20 @@ -import signal import asyncio +import functools import os +import signal + import multiprocess -import functools from molotov.api import get_fixture from molotov.listeners import EventSender -from molotov.stats import get_statsd_client from molotov.shared import Counters, Tasks +from molotov.stats import get_statsd_client from molotov.util import ( cancellable_sleep, - stop, + event_loop, is_stopped, set_timer, - event_loop, + stop, ) from molotov.worker import Worker @@ -95,7 +96,7 @@ def _launch_processes(self): if not args.quiet: self.console.print("Forking %d processes" % args.processes) jobs = [] - for i in range(args.processes): + for _i in range(args.processes): p = multiprocess.Process(target=self._process) jobs.append(p) p.start() @@ -205,9 +206,7 @@ def _stop(*args): self.loop.run_until_complete(gathered) finally: if self.statsd is not None and not self.statsd.disconnected: - self.loop.run_until_complete( - self._tasks.ensure_future(self.statsd.close()) - ) + self.loop.run_until_complete(self._tasks.ensure_future(self.statsd.close())) self.loop.run_until_complete(self._tasks.cancel_all()) self.loop.close() diff --git a/molotov/session.py b/molotov/session.py index bf46d3c..d72ac2d 100644 --- a/molotov/session.py +++ b/molotov/session.py @@ -1,13 +1,12 @@ -from time import perf_counter import socket -from types import SimpleNamespace from collections import namedtuple +from time import perf_counter +from types import SimpleNamespace -from aiohttp.client import ClientSession, ClientRequest, ClientResponse from aiohttp import TCPConnector, TraceConfig +from aiohttp.client import ClientRequest, ClientResponse, ClientSession -from molotov.listeners import StdoutListener, EventSender - +from molotov.listeners import EventSender, StdoutListener _HOST = socket.gethostname() @@ -37,11 +36,7 @@ def __init__(self, loop, console, verbose, statsd): self.verbose = verbose self.eventer = EventSender( console, - [ - StdoutListener( - verbose=self.verbose, console=self.console, loop=self.loop - ) - ], + [StdoutListener(verbose=self.verbose, console=self.console, loop=self.loop)], ) self.on_request_start.append(self._request_start) self.on_request_end.append(self._request_end) @@ -49,9 +44,7 @@ def __init__(self, loop, console, verbose, statsd): self.context.statsd = statsd def _trace_config_ctx_factory(self, trace_request_ctx): - return SimpleNamespace( - trace_request_ctx=trace_request_ctx, context=self.context - ) + return SimpleNamespace(trace_request_ctx=trace_request_ctx, context=self.context) def add_listener(self, listener): return self.eventer.add_listener(listener) @@ -103,7 +96,7 @@ def get_session(loop, console, verbose=0, statsd=None, **kw): response_class=LoggedClientResponse, connector=connector, trace_configs=[trace_config], - **kw + **kw, ) return session diff --git a/molotov/shared/tasks.py b/molotov/shared/tasks.py index f190c54..38ee5fa 100644 --- a/molotov/shared/tasks.py +++ b/molotov/shared/tasks.py @@ -1,5 +1,5 @@ -import os import asyncio +import os from collections import defaultdict from collections.abc import MutableSequence from contextlib import suppress diff --git a/molotov/slave.py b/molotov/slave.py index 0963494..40a0221 100644 --- a/molotov/slave.py +++ b/molotov/slave.py @@ -1,15 +1,17 @@ +import argparse import json import os -import sys -import argparse -from subprocess import check_call -import tempfile import shutil import site +import sys +import tempfile +from subprocess import check_call + import pkg_resources from molotov import __version__ -from molotov.run import main as run, _parser +from molotov.run import _parser +from molotov.run import main as run def clone_repo(github): @@ -73,13 +75,9 @@ def main(): "--virtualenv", type=str, default="virtualenv", help="Virtualenv executable." ) - parser.add_argument( - "--python", type=str, default=sys.executable, help="Python executable." - ) + parser.add_argument("--python", type=str, default=sys.executable, help="Python executable.") - parser.add_argument( - "--directory", type=str, default=None, help="Directory to run into." - ) + parser.add_argument("--directory", type=str, default=None, help="Directory to run into.") parser.add_argument( "--config", @@ -122,9 +120,7 @@ def main(): # load deps into sys.path pyver = "%d.%d" % (sys.version_info.major, sys.version_info.minor) - site_pkg = os.path.join( - args.directory, "venv", "lib", "python" + pyver, "site-packages" - ) + site_pkg = os.path.join(args.directory, "venv", "lib", "python" + pyver, "site-packages") site.addsitedir(site_pkg) pkg_resources.working_set.add_entry(site_pkg) diff --git a/molotov/stats.py b/molotov/stats.py index 8f69372..3f1f8f0 100644 --- a/molotov/stats.py +++ b/molotov/stats.py @@ -1,4 +1,5 @@ from urllib.parse import urlparse + from aiodogstatsd import Client diff --git a/molotov/tests/example.py b/molotov/tests/example.py index db3e358..07d2e7d 100644 --- a/molotov/tests/example.py +++ b/molotov/tests/example.py @@ -9,16 +9,16 @@ """ import json + from molotov import ( - scenario, - setup, + get_context, global_setup, global_teardown, + scenario, + setup, teardown, - get_context, ) - _API = "http://localhost:8080" _HEADERS = {} diff --git a/molotov/tests/example2.py b/molotov/tests/example2.py index 747d745..2a9e8f2 100644 --- a/molotov/tests/example2.py +++ b/molotov/tests/example2.py @@ -5,7 +5,6 @@ """ from molotov import scenario - _API = "http://localhost:8080" diff --git a/molotov/tests/example3.py b/molotov/tests/example3.py index 94b3c44..0002f0a 100644 --- a/molotov/tests/example3.py +++ b/molotov/tests/example3.py @@ -1,4 +1,4 @@ -from molotov import scenario, global_setup +from molotov import global_setup, scenario @global_setup() diff --git a/molotov/tests/example6.py b/molotov/tests/example6.py index bb25c1d..3dbce7d 100644 --- a/molotov/tests/example6.py +++ b/molotov/tests/example6.py @@ -4,9 +4,9 @@ the average response time. """ -import molotov import time +import molotov _T = {} diff --git a/molotov/tests/example7.py b/molotov/tests/example7.py index f43885b..80766b0 100644 --- a/molotov/tests/example7.py +++ b/molotov/tests/example7.py @@ -3,9 +3,9 @@ This Molotov script uses events to display concurrency info """ -import molotov import time +import molotov concurs = [] # [(timestamp, worker count)] diff --git a/molotov/tests/example8.py b/molotov/tests/example8.py index 1c0519e..1f171b0 100644 --- a/molotov/tests/example8.py +++ b/molotov/tests/example8.py @@ -4,9 +4,10 @@ """ import json -import molotov import time +import molotov + _T = {} diff --git a/molotov/tests/example9.py b/molotov/tests/example9.py index b081c2a..28bc8d5 100644 --- a/molotov/tests/example9.py +++ b/molotov/tests/example9.py @@ -1,9 +1,10 @@ """ Molotov scripts can import modules from the same dir """ -from molotov import scenario from mylib import get_url +from molotov import scenario + @scenario(weight=1) async def my_scenario(session): diff --git a/molotov/tests/statsd.py b/molotov/tests/statsd.py index 1d36d9a..589bd0b 100644 --- a/molotov/tests/statsd.py +++ b/molotov/tests/statsd.py @@ -1,8 +1,9 @@ -import multiprocess import asyncio -import signal import functools import os +import signal + +import multiprocess def debug(data): diff --git a/molotov/tests/support.py b/molotov/tests/support.py index 3e61563..8233dda 100644 --- a/molotov/tests/support.py +++ b/molotov/tests/support.py @@ -1,29 +1,29 @@ -import sys -import signal -import os import asyncio -import unittest -import time -from contextlib import contextmanager import functools +import http.server +import os +import signal +import socketserver +import sys +import time +import unittest from collections import namedtuple +from contextlib import contextmanager from http.client import HTTPConnection from io import StringIO -import http.server -import socketserver -import pytest from unittest.mock import patch import multiprocess +import pytest from aiohttp.client_reqrep import URL from multidict import CIMultiDict -from molotov.api import _SCENARIO, _FIXTURES + from molotov import util +from molotov.api import _FIXTURES, _SCENARIO from molotov.run import PYPY from molotov.session import LoggedClientRequest, LoggedClientResponse -from molotov.ui.console import Console from molotov.shared.counter import Counters - +from molotov.ui.console import Console HERE = os.path.dirname(__file__) diff --git a/molotov/tests/test_api.py b/molotov/tests/test_api.py index a3d7de8..0044aad 100644 --- a/molotov/tests/test_api.py +++ b/molotov/tests/test_api.py @@ -1,4 +1,4 @@ -from molotov.api import pick_scenario, scenario, get_scenarios, setup +from molotov.api import get_scenarios, pick_scenario, scenario, setup from molotov.tests.support import TestLoop, async_test diff --git a/molotov/tests/test_console.py b/molotov/tests/test_console.py index dc7a306..1dae1de 100644 --- a/molotov/tests/test_console.py +++ b/molotov/tests/test_console.py @@ -1,13 +1,13 @@ -import unittest import asyncio -import sys import os import re +import sys +import unittest + import multiprocess +from molotov.tests.support import catch_output, dedicatedloop from molotov.ui.console import Console -from molotov.tests.support import dedicatedloop, catch_output - OUTPUT = """\ one @@ -27,7 +27,7 @@ def run_worker(input): _PROC.append(os.getpid()) _CONSOLE.print("hello") try: - 3 + "" + 3 + "" # noqa except Exception: _CONSOLE.print_error("meh") @@ -61,7 +61,7 @@ async def add_lines(): console.print("two") console.print("3") try: - 1 + "e" + 1 + "e" # noqa except Exception as e: console.print_error(e) console.print_error(e, sys.exc_info()[2]) diff --git a/molotov/tests/test_fmwk.py b/molotov/tests/test_fmwk.py index 322eb06..fc1fe67 100644 --- a/molotov/tests/test_fmwk.py +++ b/molotov/tests/test_fmwk.py @@ -1,30 +1,30 @@ +import asyncio import os import signal -import asyncio -from molotov.session import get_session -from molotov.runner import Runner -from molotov.worker import Worker -from molotov.util import get_var, set_var, json_request, request, stop_reason from molotov.api import ( - scenario, - setup, + events, global_setup, - teardown, global_teardown, + scenario, + scenario_picker, + setup, setup_session, + teardown, teardown_session, - scenario_picker, - events, ) +from molotov.runner import Runner +from molotov.session import get_session from molotov.tests.support import ( TestLoop, async_test, - dedicatedloop, catch_sleep, coserver, + dedicatedloop, patch_errors, ) +from molotov.util import get_var, json_request, request, set_var, stop_reason +from molotov.worker import Worker class TestFmwk(TestLoop): diff --git a/molotov/tests/test_quickstart.py b/molotov/tests/test_quickstart.py index f31f61c..5432de8 100644 --- a/molotov/tests/test_quickstart.py +++ b/molotov/tests/test_quickstart.py @@ -1,9 +1,9 @@ -import tempfile -import shutil import os +import shutil +import tempfile -from molotov import quickstart, __version__, run -from molotov.tests.support import set_args, TestLoop, dedicatedloop +from molotov import __version__, quickstart, run +from molotov.tests.support import TestLoop, dedicatedloop, set_args class TestQuickStart(TestLoop): diff --git a/molotov/tests/test_run.py b/molotov/tests/test_run.py index 0517d59..27461c4 100644 --- a/molotov/tests/test_run.py +++ b/molotov/tests/test_run.py @@ -1,36 +1,35 @@ -import unittest -import time -import random -import os -import signal import asyncio -from unittest.mock import patch +import io +import json +import os +import random import re +import signal +import time +import unittest from collections import defaultdict -import json -import io +from unittest.mock import patch import aiohttp -from molotov.api import scenario, global_setup +from molotov import __version__ +from molotov.api import global_setup, scenario +from molotov.run import main, run +from molotov.session import get_context +from molotov.shared.counter import Counters +from molotov.tests.statsd import run_server, stop_server from molotov.tests.support import ( TestLoop, + catch_sleep, + co_catch_output, coserver, dedicatedloop, + dedicatedloop_noclose, + only_pypy, set_args, skip_pypy, - only_pypy, - catch_sleep, - dedicatedloop_noclose, - co_catch_output, ) -from molotov.tests.statsd import run_server, stop_server -from molotov.run import run, main -from molotov.shared.counter import Counters -from molotov.util import request, json_request, set_timer -from molotov.session import get_context -from molotov import __version__ - +from molotov.util import json_request, request, set_timer _HERE = os.path.dirname(__file__) _CONFIG = os.path.join(_HERE, "molotov.json") @@ -107,7 +106,7 @@ async def here_one(session): async def here_two(session): statsd = get_context(session).statsd if statsd is not None: - for i in range(10): + for _i in range(10): statsd.increment("user.online") await asyncio.sleep(0) @@ -233,7 +232,7 @@ async def here_three(session): def test_fail_mode_fail(self): @scenario(weight=10) async def here_three(session): - assert False + raise AssertionError() stdout, stderr, rc = self._test_molotov( "-x", diff --git a/molotov/tests/test_session.py b/molotov/tests/test_session.py index 787a549..6b1064f 100644 --- a/molotov/tests/test_session.py +++ b/molotov/tests/test_session.py @@ -1,13 +1,21 @@ import gzip +from unittest.mock import patch + from aiohttp.client_reqrep import ClientRequest from yarl import URL -from unittest.mock import patch -from molotov.listeners import BaseListener import molotov.session +from molotov.listeners import BaseListener from molotov.session import get_eventer -from molotov.tests.support import coserver, Response, Request -from molotov.tests.support import TestLoop, async_test, patch_print, patch_errors +from molotov.tests.support import ( + Request, + Response, + TestLoop, + async_test, + coserver, + patch_errors, + patch_print, +) class TestLoggedClientSession(TestLoop): diff --git a/molotov/tests/test_sharedcounter.py b/molotov/tests/test_sharedcounter.py index 605a90d..1bd732c 100644 --- a/molotov/tests/test_sharedcounter.py +++ b/molotov/tests/test_sharedcounter.py @@ -1,8 +1,9 @@ import os import unittest + import multiprocess -from molotov.shared.counter import Counters, Counter +from molotov.shared.counter import Counter, Counters # pre-forked variable _DATA = Counters("test") @@ -39,7 +40,7 @@ def _t(): self.assertRaises(NotImplementedError, _t) def _c(): - Counter("ok") != 6.3 + Counter("ok") != 6.3 # noqa self.assertRaises(TypeError, _c) diff --git a/molotov/tests/test_slave.py b/molotov/tests/test_slave.py index 9469349..521e72f 100644 --- a/molotov/tests/test_slave.py +++ b/molotov/tests/test_slave.py @@ -1,15 +1,15 @@ import os -import pytest -from unittest import mock -import tempfile import subprocess -from shutil import copytree, copyfile +import tempfile +from shutil import copyfile, copytree +from unittest import mock + +import pytest from molotov import __version__ from molotov.slave import main from molotov.tests.support import TestLoop, dedicatedloop, set_args - _REPO = "https://github.com/loads/molotov" NO_INTERNET = os.environ.get("NO_INTERNET") is not None ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")) diff --git a/molotov/tests/test_util.py b/molotov/tests/test_util.py index d60a357..e80cc8e 100644 --- a/molotov/tests/test_util.py +++ b/molotov/tests/test_util.py @@ -1,10 +1,10 @@ -from io import StringIO -from tempfile import mkstemp import json -import unittest import os -from molotov.util import expand_options, OptionError, set_var, get_var, _VARS +import unittest +from io import StringIO +from tempfile import mkstemp +from molotov.util import _VARS, OptionError, expand_options, get_var, set_var _HERE = os.path.dirname(__file__) config = os.path.join(_HERE, "..", "..", "molotov.json") diff --git a/molotov/ui/app.py b/molotov/ui/app.py index fa06996..690642b 100644 --- a/molotov/ui/app.py +++ b/molotov/ui/app.py @@ -1,8 +1,9 @@ import asyncio -import sys -import shutil import io +import shutil +import sys +from prompt_toolkit import HTML from prompt_toolkit.application import Application from prompt_toolkit.layout import ( FormattedTextControl, @@ -11,17 +12,15 @@ VSplit, Window, ) -from prompt_toolkit import HTML from molotov import __version__ from molotov.ui.controllers import ( - TerminalController, - SimpleController, RunStatus, + SimpleController, + TerminalController, create_key_bindings, ) - TITLE = HTML( f"Molotov v{__version__} ~ Happy Breaking 🥛🔨 ~ Ctrl+C to abort" ) diff --git a/molotov/ui/console.py b/molotov/ui/console.py index 6313b8e..131533f 100644 --- a/molotov/ui/console.py +++ b/molotov/ui/console.py @@ -1,7 +1,7 @@ import os -from molotov.util import printable_error from molotov.ui.app import MolotovApp +from molotov.util import printable_error class Console: diff --git a/molotov/ui/controllers.py b/molotov/ui/controllers.py index 92a6dc5..49c44a2 100644 --- a/molotov/ui/controllers.py +++ b/molotov/ui/controllers.py @@ -1,10 +1,10 @@ -import multiprocess -import queue import os +import queue import signal from datetime import datetime import humanize +import multiprocess from prompt_toolkit import HTML from prompt_toolkit.formatted_text import to_formatted_text from prompt_toolkit.key_binding import KeyBindings diff --git a/molotov/util.py b/molotov/util.py index 459851d..bfcbd98 100644 --- a/molotov/util.py +++ b/molotov/util.py @@ -1,16 +1,15 @@ -from io import StringIO -import traceback -import sys +import asyncio import functools import json import os -import asyncio -import time +import sys import threading +import time +import traceback +from io import StringIO from aiohttp import ClientSession, __version__ - _DNS_CACHE = {} _STOP = False _STOP_WHY = [] @@ -69,8 +68,8 @@ def expand_options(config, scenario, args): if not isinstance(config, str): try: config = json.loads(config.read()) - except Exception: - raise OptionError("Can't parse %r" % config) + except Exception as err: + raise OptionError("Can't parse %r" % config) from err else: if not os.path.exists(config): raise OptionError("Can't find %r" % config) @@ -78,8 +77,8 @@ def expand_options(config, scenario, args): with open(config) as f: try: config = json.loads(f.read()) - except ValueError: - raise OptionError("Can't parse %r" % config) + except ValueError as err: + raise OptionError("Can't parse %r" % config) from err if "molotov" not in config: raise OptionError("Bad config -- no molotov key") @@ -161,9 +160,7 @@ def request(endpoint, verb="GET", session_options=None, **options): def json_request(endpoint, verb="GET", session_options=None, **options): """Like :func:`molotov.request` but extracts json from the response.""" - req = functools.partial( - _request, endpoint, verb, session_options, json=True, **options - ) + req = functools.partial(_request, endpoint, verb, session_options, json=True, **options) return _run_in_fresh_loop(req) diff --git a/molotov/worker.py b/molotov/worker.py index 4bb6b8d..0f924aa 100644 --- a/molotov/worker.py +++ b/molotov/worker.py @@ -1,10 +1,10 @@ import asyncio from inspect import isgenerator +from molotov.api import get_fixture, get_scenario, next_scenario, pick_scenario from molotov.listeners import EventSender -from molotov.session import get_session, get_context -from molotov.api import get_fixture, pick_scenario, get_scenario, next_scenario -from molotov.util import cancellable_sleep, is_stopped, set_timer, get_timer, stop, now +from molotov.session import get_context, get_session +from molotov.util import cancellable_sleep, get_timer, is_stopped, now, set_timer, stop class FixtureError(Exception): @@ -74,7 +74,7 @@ async def setup(self): options = await self._setup(self.wid, self.args) except Exception as e: self.console.print_error(e) - raise FixtureError(str(e)) + raise FixtureError(str(e)) from e if options is None: options = {} @@ -92,7 +92,7 @@ async def session_setup(self, session): await self._session_setup(self.wid, session) except Exception as e: self.console.print_error(e) - raise FixtureError(str(e)) + raise FixtureError(str(e)) from e async def session_teardown(self, session): if self._session_teardown is None: @@ -133,9 +133,7 @@ async def _run(self): self.print("Setting up session") - async with get_session( - self.loop, self.console, verbose, self.statsd, **options - ) as session: + async with get_session(self.loop, self.console, verbose, self.statsd, **options) as session: await asyncio.sleep(0) get_context(session).args = self.args get_context(session).worker_id = self.wid diff --git a/ruff.toml b/ruff.toml new file mode 100644 index 0000000..a885855 --- /dev/null +++ b/ruff.toml @@ -0,0 +1,8 @@ +select = ["E4", "E7", "E9", "F", "B", "Q", "I"] + +exclude = [ + ".git", + "bin", +] + +line-length = 100 diff --git a/setup.py b/setup.py index 8f2e9dc..b1ae99b 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,6 @@ import sys -from setuptools import setup, find_packages + +from setuptools import find_packages, setup if sys.version_info < (3, 8): raise ValueError("Requires Python 3.8 or superior") diff --git a/tox.ini b/tox.ini index dea7900..41c8b03 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] downloadcache = {toxworkdir}/cache/ -envlist = py312,py311,py310,py39,py38,flake8,docs,pypy3 +envlist = py312,py311,py310,py39,py38,ruff,docs,pypy3 [testenv:py310] passenv = @@ -33,10 +33,12 @@ deps = -rtox-pypy-requirements.txt commands = pytest --random-order-bucket=global -sv molotov/tests -[testenv:flake8] -commands = flake8 molotov +[testenv:ruff] +commands = + ruff check setup.py molotov + ruf format setup.py molotov/*.py deps = - flake8 + ruff [testenv:docs] deps =