Skip to content

Commit

Permalink
Type hints: Remove all Optionals in favour of "| None" notation (made…
Browse files Browse the repository at this point in the history
… possible by Python 3.8)
  • Loading branch information
cyberw committed Oct 12, 2023
1 parent 0ee097f commit cc98d60
Show file tree
Hide file tree
Showing 13 changed files with 72 additions and 76 deletions.
4 changes: 2 additions & 2 deletions locust/argument_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import platform
import sys
import textwrap
from typing import Dict, List, NamedTuple, Optional, Any
from typing import Dict, List, NamedTuple, Any
import configargparse

import locust
Expand Down Expand Up @@ -625,7 +625,7 @@ class UIExtraArgOptions(NamedTuple):
default_value: str
is_secret: bool
help_text: str
choices: Optional[List[str]] = None
choices: List[str] | None = None


def ui_extra_args_dict(args=None) -> Dict[str, Dict[str, Any]]:
Expand Down
2 changes: 1 addition & 1 deletion locust/clients.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import re
import time
from contextlib import contextmanager
from typing import Generator, Optional
from typing import Generator
from urllib.parse import urlparse, urlunparse

import requests
Expand Down
44 changes: 22 additions & 22 deletions locust/contrib/fasthttp.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from ssl import SSLError
import time
import traceback
from typing import Callable, Optional, Tuple, Dict, Any, Generator, cast
from typing import Callable, Tuple, Dict, Any, Generator, cast

from http.cookiejar import CookieJar

Expand Down Expand Up @@ -78,10 +78,10 @@ def __init__(
self,
environment: Environment,
base_url: str,
user: Optional[User],
user: User | None,
insecure=True,
client_pool: Optional[HTTPClientPool] = None,
ssl_context_factory: Optional[Callable] = None,
client_pool: HTTPClientPool | None = None,
ssl_context_factory: Callable | None = None,
**kwargs,
):
self.environment = environment
Expand Down Expand Up @@ -312,18 +312,18 @@ class FastHttpUser(User):
insecure: bool = True
"""Parameter passed to FastHttpSession. Default True, meaning no SSL verification."""

default_headers: Optional[dict] = None
default_headers: dict | None = None
"""Parameter passed to FastHttpSession. Adds the listed headers to every request."""

concurrency: int = 10
"""Parameter passed to FastHttpSession. Describes number of concurrent requests allowed by the FastHttpSession. Default 10.
Note that setting this value has no effect when custom client_pool was given, and you need to spawn a your own gevent pool
to use it (as Users only have one greenlet). See test_fasthttp.py / test_client_pool_concurrency for an example."""

client_pool: Optional[HTTPClientPool] = None
client_pool: HTTPClientPool | None = None
"""HTTP client pool to use. If not given, a new pool is created per single user."""

ssl_context_factory: Optional[Callable] = None
ssl_context_factory: Callable | None = None
"""A callable that return a SSLContext for overriding the default context created by the FastHttpSession."""

abstract = True
Expand Down Expand Up @@ -361,7 +361,7 @@ def __init__(self, environment):

@contextmanager
def rest(
self, method, url, headers: Optional[dict] = None, **kwargs
self, method, url, headers: dict | None = None, **kwargs
) -> Generator[RestResponseContextManager, None, None]:
"""
A wrapper for self.client.request that:
Expand Down Expand Up @@ -424,36 +424,36 @@ def rest_(self, method, url, name=None, **kwargs) -> Generator[RestResponseConte


class FastRequest(CompatRequest):
payload: Optional[str] = None
payload: str | None = None

@property
def body(self) -> Optional[str]:
def body(self) -> str | None:
return self.payload


class FastResponse(CompatResponse):
headers: Optional[Headers] = None
headers: Headers | None = None
"""Dict like object containing the response headers"""

_response: Optional[HTTPSocketPoolResponse] = None
_response: HTTPSocketPoolResponse | None = None

encoding: Optional[str] = None
encoding: str | None = None
"""In some cases setting the encoding explicitly is needed. If so, do it before calling .text"""

request: Optional[FastRequest] = None
request: FastRequest | None = None

def __init__(
self,
ghc_response: HTTPSocketPoolResponse,
request: Optional[FastRequest] = None,
sent_request: Optional[str] = None,
request: FastRequest | None = None,
sent_request: str | None = None,
):
super().__init__(ghc_response, request, sent_request)

self.request = request

@property
def text(self) -> Optional[str]:
def text(self) -> str | None:
"""
Returns the text content of the response as a decoded string
"""
Expand All @@ -467,7 +467,7 @@ def text(self) -> Optional[str]:
return str(self.content, self.encoding, errors="replace")

@property
def url(self) -> Optional[str]:
def url(self) -> str | None:
"""
Get "response" URL, which is the same as the request URL. This is a small deviation from HttpSession, which gets the final (possibly redirected) URL.
"""
Expand Down Expand Up @@ -517,11 +517,11 @@ class ErrorResponse:
that doesn't have a real Response object attached. E.g. a socket error or similar
"""

headers: Optional[Headers] = None
headers: Headers | None = None
content = None
status_code = 0
error: Optional[Exception] = None
text: Optional[str] = None
error: Exception | None = None
text: str | None = None
request: CompatRequest

def __init__(self, url: str, request: CompatRequest):
Expand All @@ -537,7 +537,7 @@ class LocustUserAgent(UserAgent):
request_type = FastRequest
valid_response_codes = frozenset([200, 201, 202, 203, 204, 205, 206, 207, 208, 226, 301, 302, 303, 307])

def __init__(self, client_pool: Optional[HTTPClientPool] = None, **kwargs):
def __init__(self, client_pool: HTTPClientPool | None = None, **kwargs):
super().__init__(**kwargs)

if client_pool is not None:
Expand Down
4 changes: 2 additions & 2 deletions locust/debug.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import inspect
import locust
from locust import User, argument_parser
from typing import Type, Optional
from typing import Type
from locust.env import Environment
from locust.exception import CatchResponseError, RescheduleTask

Expand Down Expand Up @@ -93,7 +93,7 @@ def on_request(
print()


_env: Optional[Environment] = None # minimal Environment for debugging
_env: Environment | None = None # minimal Environment for debugging


def run_single_user(
Expand Down
10 changes: 5 additions & 5 deletions locust/dispatch.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import time
from collections.abc import Iterator
from operator import attrgetter
from typing import Dict, Generator, List, TYPE_CHECKING, Optional, Tuple, Type, Set
from typing import Dict, Generator, List, TYPE_CHECKING, Tuple, Type, Set

import gevent

Expand Down Expand Up @@ -164,7 +164,7 @@ def _dispatcher(self) -> Generator[Dict[str, Dict[str, int]], None, None]:

self._dispatch_in_progress = False

def new_dispatch(self, target_user_count: int, spawn_rate: float, user_classes: Optional[List] = None) -> None:
def new_dispatch(self, target_user_count: int, spawn_rate: float, user_classes: List | None = None) -> None:
"""
Initialize a new dispatch cycle.
Expand Down Expand Up @@ -319,7 +319,7 @@ def _get_user_current_count(self, user: str) -> int:
def _distribute_users(
self, target_user_count: int
) -> Tuple[
Dict[str, Dict[str, int]], Generator[Optional[str], None, None], itertools.cycle, List[Tuple["WorkerNode", str]]
Dict[str, Dict[str, int]], Generator[str | None, None, None], itertools.cycle, List[Tuple["WorkerNode", str]]
]:
"""
This function might take some time to complete if the `target_user_count` is a big number. A big number
Expand Down Expand Up @@ -349,7 +349,7 @@ def _distribute_users(

return users_on_workers, user_gen, worker_gen, active_users

def _user_gen(self) -> Generator[Optional[str], None, None]:
def _user_gen(self) -> Generator[str | None, None, None]:
"""
This method generates users according to their weights using
a smooth weighted round-robin algorithm implemented by https://github.com/linnik/roundrobin.
Expand Down Expand Up @@ -403,7 +403,7 @@ def infinite_cycle_gen(users: List[Tuple[Type[User], int]]) -> itertools.cycle:
current_fixed_users_count = {u: self._get_user_current_count(u) for u in fixed_users}
spawned_classes: Set[str] = set()
while len(spawned_classes) != len(fixed_users):
user_name: Optional[str] = next(cycle_fixed_gen)
user_name: str | None = next(cycle_fixed_gen)
if not user_name:
break

Expand Down
31 changes: 15 additions & 16 deletions locust/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
List,
Type,
TypeVar,
Optional,
)

from configargparse import Namespace
Expand All @@ -27,27 +26,27 @@ class Environment:
def __init__(
self,
*,
user_classes: Optional[List[Type[User]]] = None,
shape_class: Optional[LoadTestShape] = None,
tags: Optional[List[str]] = None,
user_classes: List[Type[User]] | None = None,
shape_class: LoadTestShape | None = None,
tags: List[str] | None = None,
locustfile: str = None,
exclude_tags: Optional[List[str]] = None,
exclude_tags: List[str] | None = None,
events: Events = None,
host: str = None,
reset_stats=False,
stop_timeout: Optional[float] = None,
stop_timeout: float | None = None,
catch_exceptions=True,
parsed_options: Optional[Namespace] = None,
available_user_classes: Optional[Dict[str, User]] = None,
available_shape_classes: Optional[Dict[str, LoadTestShape]] = None,
parsed_options: Namespace | None = None,
available_user_classes: Dict[str, User] | None = None,
available_shape_classes: Dict[str, LoadTestShape] | None = None,
):
self.runner: Optional[Runner] = None
self.runner: Runner | None = None
"""Reference to the :class:`Runner <locust.runners.Runner>` instance"""

self.web_ui: Optional[WebUI] = None
self.web_ui: WebUI | None = None
"""Reference to the WebUI instance"""

self.process_exit_code: Optional[int] = None
self.process_exit_code: int | None = None
"""
If set it'll be the exit code of the Locust process
"""
Expand Down Expand Up @@ -159,10 +158,10 @@ def create_web_ui(
self,
host="",
port=8089,
auth_credentials: Optional[str] = None,
tls_cert: Optional[str] = None,
tls_key: Optional[str] = None,
stats_csv_writer: Optional[StatsCSV] = None,
auth_credentials: str | None = None,
tls_cert: str | None = None,
tls_key: str | None = None,
stats_csv_writer: StatsCSV | None = None,
delayed_start=False,
userclass_picker_is_active=False,
modern_ui=False,
Expand Down
27 changes: 13 additions & 14 deletions locust/runners.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
NoReturn,
ValuesView,
Set,
Optional,
Tuple,
Type,
Any,
Expand Down Expand Up @@ -104,9 +103,9 @@ def __init__(self, environment: "Environment") -> None:
self.user_greenlets = Group()
self.greenlet = Group()
self.state = STATE_INIT
self.spawning_greenlet: Optional[gevent.Greenlet] = None
self.shape_greenlet: Optional[gevent.Greenlet] = None
self.shape_last_tick: Tuple[int, float] | Tuple[int, float, Optional[List[Type[User]]]] | None = None
self.spawning_greenlet: gevent.Greenlet | None = None
self.shape_greenlet: gevent.Greenlet | None = None
self.shape_last_tick: Tuple[int, float] | Tuple[int, float, List[Type[User]] | None] | None = None
self.current_cpu_usage: int = 0
self.cpu_warning_emitted: bool = False
self.worker_cpu_warning_emitted: bool = False
Expand All @@ -121,7 +120,7 @@ def __init__(self, environment: "Environment") -> None:
self.target_user_count: int = 0
self.custom_messages: Dict[str, Callable] = {}

self._users_dispatcher: Optional[UsersDispatcher] = None
self._users_dispatcher: UsersDispatcher | None = None

# set up event listeners for recording requests
def on_request(request_type, name, response_time, response_length, exception=None, **_kwargs):
Expand Down Expand Up @@ -311,7 +310,7 @@ def monitor_cpu_and_memory(self) -> NoReturn:

@abstractmethod
def start(
self, user_count: int, spawn_rate: float, wait: bool = False, user_classes: Optional[List[Type[User]]] = None
self, user_count: int, spawn_rate: float, wait: bool = False, user_classes: List[Type[User]] | None = None
) -> None:
...

Expand Down Expand Up @@ -531,7 +530,7 @@ def _start(self, user_count: int, spawn_rate: float, wait: bool = False, user_cl
self.environment.events.spawning_complete.fire(user_count=sum(self.target_user_classes_count.values()))

def start(
self, user_count: int, spawn_rate: float, wait: bool = False, user_classes: Optional[List[Type[User]]] = None
self, user_count: int, spawn_rate: float, wait: bool = False, user_classes: List[Type[User]] | None = None
) -> None:
if spawn_rate > 100:
logger.warning(
Expand All @@ -551,7 +550,7 @@ def stop(self) -> None:
return
super().stop()

def send_message(self, msg_type: str, data: Optional[Any] = None) -> None:
def send_message(self, msg_type: str, data: Any | None = None) -> None:
"""
Emulates internodal messaging by calling registered listeners
Expand Down Expand Up @@ -672,7 +671,7 @@ def __init__(self, environment, master_bind_host, master_bind_port):
else:
raise

self._users_dispatcher: Optional[UsersDispatcher] = None
self._users_dispatcher: UsersDispatcher | None = None

self.greenlet.spawn(self.heartbeat_worker).link_exception(greenlet_exception_handler)
self.greenlet.spawn(self.client_listener).link_exception(greenlet_exception_handler)
Expand Down Expand Up @@ -722,7 +721,7 @@ def cpu_log_warning(self) -> bool:
return warning_emitted

def start(
self, user_count: int, spawn_rate: float, wait=False, user_classes: Optional[List[Type[User]]] = None
self, user_count: int, spawn_rate: float, wait=False, user_classes: List[Type[User]] | None = None
) -> None:
self.spawning_completed = False

Expand Down Expand Up @@ -1123,7 +1122,7 @@ def reported_user_classes_count(self) -> Dict[str, int]:
reported_user_classes_count[name] += count
return reported_user_classes_count

def send_message(self, msg_type: str, data: Optional[Dict[str, Any]] = None, client_id: Optional[str] = None):
def send_message(self, msg_type: str, data: Dict[str, Any] | None = None, client_id: str | None = None):
"""
Sends a message to attached worker node(s)
Expand Down Expand Up @@ -1168,7 +1167,7 @@ def __init__(self, environment: "Environment", master_host: str, master_port: in
self.master_host = master_host
self.master_port = master_port
self.worker_cpu_warning_emitted = False
self._users_dispatcher: Optional[UsersDispatcher] = None
self._users_dispatcher: UsersDispatcher | None = None
self.client = rpc.Client(master_host, master_port, self.client_id)
self.greenlet.spawn(self.worker).link_exception(greenlet_exception_handler)
self.connect_to_master()
Expand Down Expand Up @@ -1210,7 +1209,7 @@ def on_user_error(user_instance: User, exception: Exception, tb: TracebackType)
self.environment.events.user_error.add_listener(on_user_error)

def start(
self, user_count: int, spawn_rate: float, wait: bool = False, user_classes: Optional[List[Type[User]]] = None
self, user_count: int, spawn_rate: float, wait: bool = False, user_classes: List[Type[User]] | None = None
) -> None:
raise NotImplementedError("use start_worker")

Expand Down Expand Up @@ -1355,7 +1354,7 @@ def stats_reporter(self) -> NoReturn:
logger.error(f"Temporary connection lost to master server: {e}, will retry later.")
gevent.sleep(WORKER_REPORT_INTERVAL)

def send_message(self, msg_type: str, data: Optional[Dict[str, Any]] = None) -> None:
def send_message(self, msg_type: str, data: Dict[str, Any] | None = None) -> None:
"""
Sends a message to master node
Expand Down
Loading

0 comments on commit cc98d60

Please sign in to comment.