diff --git a/src/firebolt/async_db/_types.py b/src/firebolt/async_db/_types.py index ca9d9156c92..060424898d9 100644 --- a/src/firebolt/async_db/_types.py +++ b/src/firebolt/async_db/_types.py @@ -46,18 +46,18 @@ def parse_datetime(date_string: str) -> datetime: # type: ignore def DateFromTicks(t: int) -> date: - """Convert ticks to date for firebolt db.""" + """Convert `ticks` to `date` for Firebolt DB.""" return datetime.fromtimestamp(t).date() def Time(hour: int, minute: int, second: int) -> None: - """Unsupported: construct time for firebolt db.""" - raise NotSupportedError("time is not supported by Firebolt") + """Unsupported: Construct `time`, for Firebolt DB.""" + raise NotSupportedError("The time construct is not supported by Firebolt") def TimeFromTicks(t: int) -> None: - """Unsupported: convert ticks to time for firebolt db.""" - raise NotSupportedError("time is not supported by Firebolt") + """Unsupported: Convert `ticks` to `time` for Firebolt DB.""" + raise NotSupportedError("The time construct is not supported by Firebolt") Timestamp = datetime @@ -65,7 +65,7 @@ def TimeFromTicks(t: int) -> None: def Binary(value: str) -> str: - """Convert string to binary for firebolt db, does nothing.""" + """Convert string to binary for Firebolt DB does nothing.""" return value @@ -89,7 +89,7 @@ def Binary(value: str) -> str: class ARRAY: - """Class for holding information about array column type in firebolt db.""" + """Class for holding `array` column type information in Firebolt DB.""" _prefix = "Array(" @@ -109,7 +109,7 @@ def __eq__(self, other: object) -> bool: class DECIMAL: - """Class for holding imformation about decimal value in firebolt db.""" + """Class for holding `decimal` value information in Firebolt DB.""" _prefix = "Decimal(" @@ -127,7 +127,7 @@ def __eq__(self, other: object) -> bool: class DATETIME64: - """Class for holding imformation about datetime64 value in firebolt db.""" + """Class for holding `datetime64` value information in Firebolt DB.""" _prefix = "DateTime64(" @@ -147,7 +147,7 @@ def __eq__(self, other: object) -> bool: class _InternalType(Enum): - """Enum of all internal firebolt types except for array.""" + """Enum of all internal Firebolt types, except for `array`.""" # INT, INTEGER Int8 = "Int8" @@ -182,7 +182,7 @@ class _InternalType(Enum): @cached_property def python_type(self) -> type: - """Convert internal type to python type.""" + """Convert internal type to Python type.""" types = { _InternalType.Int8: int, _InternalType.UInt8: int, @@ -205,7 +205,7 @@ def python_type(self) -> type: def parse_type(raw_type: str) -> Union[type, ARRAY, DECIMAL, DATETIME64]: - """Parse typename, provided by query metadata into python type.""" + """Parse typename provided by query metadata into Python type.""" if not isinstance(raw_type, str): raise DataError(f"Invalid typename {str(raw_type)}: str expected") # Handle arrays @@ -244,7 +244,7 @@ def parse_value( value: RawColType, ctype: Union[type, ARRAY, DECIMAL, DATETIME64], ) -> ColType: - """Provided raw value and python type, parses first into python value.""" + """Provided raw value, and Python type; parses first into Python value.""" if value is None: return None if ctype in (int, str, float): @@ -276,7 +276,7 @@ def parse_value( def format_value(value: ParameterType) -> str: - """For python value to be used in a SQL query""" + """For Python value to be used in a SQL query.""" if isinstance(value, bool): return str(int(value)) if isinstance(value, (int, float, Decimal)): @@ -299,7 +299,7 @@ def format_value(value: ParameterType) -> str: def format_statement(statement: Statement, parameters: Sequence[ParameterType]) -> str: """ - Substitute placeholders in a sqlparse statement with provided values. + Substitute placeholders in a `sqlparse` statement with provided values. """ idx = 0 @@ -336,7 +336,10 @@ def process_token(token: Token) -> Token: def statement_to_set(statement: Statement) -> Optional[SetParameter]: - """Try to parse statement as a SET command. Return None if it's not a SET command""" + """ + Try to parse `statement` as a `SET` command. + Return `None` if it's not a `SET` command. + """ # Filter out meaningless tokens like Punctuation and Whitespaces tokens = [ token @@ -370,9 +373,8 @@ def split_format_sql( query: str, parameters: Sequence[Sequence[ParameterType]] ) -> List[Union[str, SetParameter]]: """ - Split a query into separate statement, and format it with parameters - if it's a single statement - Trying to format a multi-statement query would result in NotSupportedError + Multi-statement query formatting will result in `NotSupportedError`. + Instead, split a query into a separate statement and format with parameters. """ statements = parse_sql(query) if not statements: diff --git a/src/firebolt/async_db/connection.py b/src/firebolt/async_db/connection.py index 1e0f4e10486..9c802e40d3f 100644 --- a/src/firebolt/async_db/connection.py +++ b/src/firebolt/async_db/connection.py @@ -30,8 +30,9 @@ DEFAULT_TIMEOUT_SECONDS: int = 5 KEEPALIVE_FLAG: int = 1 KEEPIDLE_RATE: int = 60 # seconds -AUTH_CREDENTIALS_DEPRECATION_MESSAGE = """ Passing connection credentials directly to `connect` function is deprecated. - Please consider passing Auth object instead. +AUTH_CREDENTIALS_DEPRECATION_MESSAGE = """ Passing connection credentials + directly to the `connect` function is deprecated. + Pass the `Auth` object instead. Examples: >>> from firebolt.client.auth import UsernamePassword >>> ... @@ -128,29 +129,29 @@ def _get_auth( access_token: Optional[str], use_token_cache: bool, ) -> Auth: - """Create Auth class based on provided credentials. + """Create `Auth` class based on provided credentials. - If access_token is provided, it's used for Auth creation. - Username and password are used otherwise. + If `access_token` is provided, it's used for `Auth` creation. + Otherwise, username/password are used. Returns: - Auth: auth object + Auth: `auth object` Raises: - ConfigurationError: Invalid combination of credentials provided + `ConfigurationError`: Invalid combination of credentials provided """ if not access_token: if not username or not password: raise ConfigurationError( "Neither username/password nor access_token are provided. Provide one" - " to authenticate" + " to authenticate." ) return UsernamePassword(username, password, use_token_cache) if username or password: raise ConfigurationError( - "Either username/password and access_token are provided. Provide only one" - " to authenticate" + "Username/password and access_token are both provided. Provide only one" + " to authenticate." ) return Token(access_token) @@ -172,24 +173,24 @@ async def connect_inner( """Connect to Firebolt database. Args: - database (str): Name of the database to connect - username (Optional[str]): User name to use for authentication (Deprecated) - password (Optional[str]): Password to use for authentication (Deprecated) - access_token (Optional[str]): Authentication token to use insead of + `database` (str): Name of the database to connect + `username` (Optional[str]): User name to use for authentication (Deprecated) + `password` (Optional[str]): Password to use for authentication (Deprecated) + `access_token` (Optional[str]): Authentication token to use instead of credentials (Deprecated) - auth (Auth)L Authentication object - engine_name (Optional[str]): The name of the engine to connect to - engine_url (Optional[str]): The engine endpoint to use - account_name (Optional[str]): For customers with multiple accounts; - if None uses default. - api_endpoint (str): Firebolt API endpoint. Used for authentication. - use_token_cache (bool): Cached authentication token in filesystem. + `auth` (Auth)L Authentication object. + `engine_name` (Optional[str]): Name of the engine to connect to + `engine_url` (Optional[str]): The engine endpoint to use + `account_name` (Optional[str]): For customers with multiple accounts; + if none, default is used + `api_endpoint` (str): Firebolt API endpoint. Used for authentication + `use_token_cache` (bool): Cached authentication token in filesystem Default: True - additional_parameters (Optional[Dict]): Dictionary of less widely-used - arguments for connection. + `additional_parameters` (Optional[Dict]): Dictionary of less widely-used + arguments for connection Note: - Providing both `engine_name` and `engine_url` would result in an error. + Providing both `engine_name` and `engine_url` will result in an error """ # These parameters are optional in function signature @@ -251,11 +252,12 @@ async def connect_inner( class OverriddenHttpBackend(AutoBackend): """ - This class is a short-term solution for TCP keep-alive issue: + `OverriddenHttpBackend` is a short-term solution for the TCP + connection idle timeout issue described in the following article: https://docs.aws.amazon.com/elasticloadbalancing/latest/network/network-load-balancers.html#connection-idle-timeout - Since httpx creates a connection right before executing a request - backend has to be overridden in order to set the socket KEEPALIVE - and KEEPIDLE settings. + Since httpx creates a connection right before executing a request, the + backend must be overridden to set the socket to `KEEPALIVE` + and `KEEPIDLE` settings. """ async def connect_tcp( @@ -330,7 +332,7 @@ def _cursor(self, **kwargs: Any) -> BaseCursor: """ if self.closed: - raise ConnectionClosedError("Unable to create cursor: connection closed") + raise ConnectionClosedError("Unable to create cursor: connection closed.") c = self.cursor_class(self._client, self, **kwargs) self._cursors.append(c) @@ -354,7 +356,7 @@ async def _aclose(self) -> None: @property def closed(self) -> bool: - """True if connection is closed, False otherwise.""" + """`True if connection is closed; False otherwise.""" return self._is_closed def _remove_cursor(self, cursor: Cursor) -> None: @@ -365,28 +367,28 @@ def _remove_cursor(self, cursor: Cursor) -> None: pass def commit(self) -> None: - """Does nothing since Firebolt doesn't have transactions""" + """Does nothing since Firebolt doesn't have transactions.""" if self.closed: - raise ConnectionClosedError("Unable to commit: connection closed") + raise ConnectionClosedError("Unable to commit: Connection closed.") class Connection(BaseConnection): """ - Firebolt asyncronous database connection class. Implements `PEP 249`_. + Firebolt asynchronous database connection class. Implements `PEP 249`_. Args: - engine_url: Firebolt database engine REST API url - database: Firebolt database name - username: Firebolt account username - password: Firebolt account password - api_endpoint: Optional. Firebolt API endpoint. Used for authentication. - connector_versions: Optional. Tuple of connector name and version or - list of tuples of your connector stack. Useful for tracking custom + `engine_url`: Firebolt database engine REST API url + `database`: Firebolt database name + `username`: Firebolt account username + `password`: Firebolt account password + `api_endpoint`: Optional. Firebolt API endpoint used for authentication + `connector_versions`: Optional. Tuple of connector name and version, or + a list of tuples of your connector stack. Useful for tracking custom connector usage. Note: - Firebolt currenly doesn't support transactions + Firebolt does not support transactions, so commit and rollback methods are not implemented. .. _PEP 249: @@ -406,7 +408,7 @@ def cursor(self) -> Cursor: # Context manager support async def __aenter__(self) -> Connection: if self.closed: - raise ConnectionClosedError("Connection is already closed") + raise ConnectionClosedError("Connection is already closed.") return self async def __aexit__( diff --git a/src/firebolt/async_db/cursor.py b/src/firebolt/async_db/cursor.py index b3d68eaf1e3..597f5df3370 100644 --- a/src/firebolt/async_db/cursor.py +++ b/src/firebolt/async_db/cursor.py @@ -63,7 +63,7 @@ class CursorState(Enum): class Statistics(BaseModel): """ - Class for query execution statistics + Class for query execution statistics. """ elapsed: float @@ -152,7 +152,7 @@ def __del__(self) -> None: @check_not_closed def description(self) -> Optional[List[Column]]: """ - Provides information about a single result row of a query + Provides information about a single result row of a query. Attributes: * ``name`` @@ -168,7 +168,7 @@ def description(self) -> Optional[List[Column]]: @property # type: ignore @check_not_closed def statistics(self) -> Optional[Statistics]: - """Query execution statistics returned by the backend""" + """Query execution statistics returned by the backend.""" return self._statistics @property # type: ignore @@ -210,8 +210,8 @@ def nextset(self) -> Optional[bool]: """ Skip to the next available set, discarding any remaining rows from the current set. - Returns True if operation was successful, - None if there are no more sets to retrive + Returns True if operation was successful; + None if there are no more sets to retrive. """ return self._pop_next_set() @@ -338,14 +338,14 @@ async def _do_execute( if set_parameters is not None: logger.warning( "Passing set parameters as an argument is deprecated. Please run " - "a query 'SET = '" + "a query 'SET = '." ) try: if parameters and skip_parsing: logger.warning( "Query formatting parameters are provided with skip_parsing." - " They will be ignored" + " They will be ignored." ) # Allow users to manually skip parsing for performance improvement @@ -416,7 +416,7 @@ async def execute( with values provided in `parameters`. Values are formatted to be properly recognized by database and to exclude SQL injection. Multi-statement queries: multiple statements, provided in a single query - and separated by semicolon are executed separatelly and sequentially. + and separated by semicolon, are executed separatelly and sequentially. To switch to next statement result, `nextset` method should be used. SET statements: to provide additional query execution parameters, execute `SET param=value` statement before it. All parameters are stored in @@ -427,15 +427,15 @@ async def execute( query (str): SQL query to execute parameters (Optional[Sequence[ParameterType]]): A sequence of substitution parameters. Used to replace '?' placeholders inside a query with - actual values + actual values. set_parameters (Optional[Dict]): List of set parameters to execute - a query with. DEPRECATED: Use SET SQL statements instead + a query with. DEPRECATED: Use SET SQL statements instead. skip_parsing (bool): Flag to disable query parsing. This will - disable parameterized, multi-statement and SET queries, - while improving performance + disable parameterized, multi-statement, and SET queries, + while improving performance. Returns: - int: Query row count + int: Query row count. """ params_list = [parameters] if parameters else [] await self._do_execute(query, params_list, set_parameters, skip_parsing) @@ -451,19 +451,19 @@ async def executemany( as multiple statements sequentially. Supported features: - Parameterized queries: placeholder characters ('?') are substituted + Parameterized queries: Placeholder characters ('?') are substituted with values provided in `parameters`. Values are formatted to be properly recognized by database and to exclude SQL injection. - Multi-statement queries: multiple statements, provided in a single query - and separated by semicolon are executed separatelly and sequentially. - To switch to next statement result, `nextset` method should be used. - SET statements: to provide additional query execution parameters, execute + Multi-statement queries: Multiple statements, provided in a single query + and separated by semicolon, are executed separately and sequentially. + To switch to next statement result, use `nextset` method. + SET statements: To provide additional query execution parameters, execute `SET param=value` statement before it. All parameters are stored in cursor object until it's closed. They can also be removed with `flush_parameters` method call. Args: - query (str): SQL query to execute + query (str): SQL query to execute. parameters_seq (Sequence[Sequence[ParameterType]]): A sequence of substitution parameter sets. Used to replace '?' placeholders inside a query with actual values from each set in a sequence. Resulting queries @@ -476,7 +476,7 @@ async def executemany( return self.rowcount def _parse_row(self, row: List[RawColType]) -> List[ColType]: - """Parse a single data row based on query column types""" + """Parse a single data row based on query column types.""" assert len(row) == len(self.description) return [ parse_value(col, self.description[i].type_code) for i, col in enumerate(row) @@ -486,7 +486,7 @@ def _get_next_range(self, size: int) -> Tuple[int, int]: cleandoc( """ Return range of next rows of size (if possible), - and update _idx to point to the end of this range + and update _idx to point to the end of this range. """ ) @@ -514,7 +514,7 @@ def fetchone(self) -> Optional[List[ColType]]: @check_query_executed def fetchmany(self, size: Optional[int] = None) -> List[List[ColType]]: """ - Fetch the next set of rows of a query result, + Fetch the next set of rows of a query result; cursor.arraysize is default size. """ size = size if size is not None else self.arraysize @@ -553,16 +553,16 @@ def __exit__( class Cursor(BaseCursor): """ - Class, responsible for executing asyncio queries to Firebolt Database. - Should not be created directly, + Executes asyncio queries to Firebolt Database. + Should not be created directly; use :py:func:`connection.cursor ` Args: - description: information about a single result row - rowcount: the number of rows produced by last query - closed: True if connection is closed, False otherwise + description: Information about a single result row. + rowcount: The number of rows produced by last query. + closed: True if connection is closed; False otherwise. arraysize: Read/Write, specifies the number of rows to fetch at a time - with the :py:func:`fetchmany` method + with the :py:func:`fetchmany` method. """ @@ -593,27 +593,27 @@ async def executemany( return await super().executemany(query, parameters_seq) """ Prepare and execute a database query against all parameter - sequences provided + sequences provided. """ @wraps(BaseCursor.fetchone) async def fetchone(self) -> Optional[List[ColType]]: async with self._async_query_lock.reader: return super().fetchone() - """Fetch the next row of a query result set""" + """Fetch the next row of a query result set.""" @wraps(BaseCursor.fetchmany) async def fetchmany(self, size: Optional[int] = None) -> List[List[ColType]]: async with self._async_query_lock.reader: return super().fetchmany(size) - """fetch the next set of rows of a query result, - size is cursor.arraysize by default""" + """Fetch the next set of rows of a query result; + size is cursor.arraysize by default.""" @wraps(BaseCursor.fetchall) async def fetchall(self) -> List[List[ColType]]: async with self._async_query_lock.reader: return super().fetchall() - """Fetch all remaining rows of a query result""" + """Fetch all remaining rows of a query result.""" @wraps(BaseCursor.nextset) async def nextset(self) -> None: diff --git a/src/firebolt/async_db/util.py b/src/firebolt/async_db/util.py index b39e95d9975..50dfdafdbe4 100644 --- a/src/firebolt/async_db/util.py +++ b/src/firebolt/async_db/util.py @@ -11,7 +11,7 @@ async def is_db_available(connection: Connection, database_name: str) -> bool: - """Verify if the database exists""" + """Verify if the database exists.""" resp = await _filter_request( connection, DATABASES_URL, {"filter.name_contains": database_name} ) @@ -19,7 +19,7 @@ async def is_db_available(connection: Connection, database_name: str) -> bool: async def is_engine_running(connection: Connection, engine_url: str) -> bool: - """Verify if the engine is running""" + """Verify if the engine is running.""" # Url is not always guaranteed to be of this structure # but for the sake of error check this is sufficient engine_name = URL(engine_url).host.split(".")[0] diff --git a/src/firebolt/client/auth/base.py b/src/firebolt/client/auth/base.py index d111c4ace67..75d6b29d816 100644 --- a/src/firebolt/client/auth/base.py +++ b/src/firebolt/client/auth/base.py @@ -18,7 +18,7 @@ class Auth(HttpxAuth): Updates all http requests with bearer token authorization header Args: - use_token_cache (bool): True if token should be cached in filesystem, + use_token_cache (bool): True if token should be cached in filesystem; False otherwise """ @@ -66,7 +66,7 @@ def expired(self) -> bool: def _token_storage(self) -> Optional[TokenSecureStorage]: """Token filesystem cache storage. - This is evaluated lazily, only if caching is enabled + This is evaluated lazily, only if caching is enabled. Returns: Optional[TokenSecureStorage]: Token filesystem cache storage if any @@ -74,19 +74,19 @@ def _token_storage(self) -> Optional[TokenSecureStorage]: return None def _get_cached_token(self) -> Optional[str]: - """If caching enabled, get token from filesystem cache. + """If caching is enabled, get token from filesystem cache. - If caching is disabled, None is returned + If caching is disabled, None is returned. Returns: - Optional[str]: Token if any and if caching is enabled, None otherwise + Optional[str]: Token if any, and if caching is enabled; None otherwise """ if not self._use_token_cache or not self._token_storage: return None return self._token_storage.get_cached_token() def _cache_token(self) -> None: - """If caching enabled, cache token to filesystem.""" + """If caching isenabled, cache token to filesystem.""" if not self._use_token_cache or not self._token_storage: return # Only cache if token and expiration are retrieved diff --git a/src/firebolt/client/auth/token.py b/src/firebolt/client/auth/token.py index 533e78b4050..01864a1cc09 100644 --- a/src/firebolt/client/auth/token.py +++ b/src/firebolt/client/auth/token.py @@ -7,10 +7,10 @@ class Token(Auth): - """Token authentication class for Firebolt database. + """Token authentication class for Firebolt Database. Uses provided token for authentication. Doesn't cache token and doesn't - refresh it on expiration + refresh it on expiration. Args: token (str): Authorization token diff --git a/src/firebolt/client/auth/username_password.py b/src/firebolt/client/auth/username_password.py index 191306c0e77..f7b49adbe27 100644 --- a/src/firebolt/client/auth/username_password.py +++ b/src/firebolt/client/auth/username_password.py @@ -12,15 +12,15 @@ class UsernamePassword(Auth): - """Username/Password authentication class for Firebolt database. + """Username/Password authentication class for Firebolt Database. Gets authentication token using - provided credentials and updates it when it expires + provided credentials and updates it when it expires. Args: username (str): Username password (str): Password - use_token_cache (bool): True if token should be cached in filesystem, + use_token_cache (bool): True if token should be cached in filesystem; False otherwise Attributes: diff --git a/src/firebolt/client/client.py b/src/firebolt/client/client.py index 569c4998a35..7e9df64d349 100644 --- a/src/firebolt/client/client.py +++ b/src/firebolt/client/client.py @@ -83,10 +83,10 @@ class Client(FireboltClientMixin, HttpxClient): @cached_property def account_id(self) -> str: - """User account id. + """User account ID. - If account_name was provided during Client construction, returns it's id. - Gets default account otherwise + If account_name was provided during Client construction, returns its ID; + gets default account otherwise. Returns: str: Account ID @@ -118,17 +118,17 @@ def _send_handling_redirects( class AsyncClient(FireboltClientMixin, HttpxAsyncClient): """An HTTP client, based on httpx.AsyncClient. - Asyncronously handles authentication for Firebolt database. - Authentication can be passed through auth keyword as a tuple or as a - FireboltAuth instance + Asynchronously handles authentication for Firebolt database. + Authentication can be passed through auth keyword as a tuple, or as a + FireboltAuth instance. """ @async_cached_property async def account_id(self) -> str: """User account id. - If account_name was provided during AsyncClient construction, returns it's id. - Gets default account otherwise + If account_name was provided during AsyncClient construction, returns its ID; + gets default account otherwise. Returns: str: Account ID diff --git a/src/firebolt/client/resource_manager_hooks.py b/src/firebolt/client/resource_manager_hooks.py index d47f20e6fbb..6cbbc99d9c6 100644 --- a/src/firebolt/client/resource_manager_hooks.py +++ b/src/firebolt/client/resource_manager_hooks.py @@ -39,8 +39,8 @@ def log_response(response: Response) -> None: def raise_on_4xx_5xx(response: Response) -> None: """Raise an error on HTTP response with error return code. - Hook for an HTTP client - If an error is message is found raise as an ApiError + Hook for an HTTP client. + If an error message is found, raise as an ApiError. Args: response (Response): Response to check for error code diff --git a/src/firebolt/common/settings.py b/src/firebolt/common/settings.py index c7b67d3055c..77a75164827 100644 --- a/src/firebolt/common/settings.py +++ b/src/firebolt/common/settings.py @@ -7,7 +7,7 @@ logger = logging.getLogger(__name__) AUTH_CREDENTIALS_DEPRECATION_MESSAGE = """ Passing connection credentials directly in Settings is deprecated. - Please consider passing Auth object instead. + Use Auth object instead. Examples: >>> from firebolt.client.auth import UsernamePassword >>> ... @@ -24,11 +24,11 @@ class Settings(BaseSettings): Attributes: user (Optional[str]): User name password (Optional[str]): User password - access_token (Optional[str]): Access token to use for authentication. + access_token (Optional[str]): Access token to use for authentication Mutually exclusive with user and password - account_name (Optional[str]): Account name. + account_name (Optional[str]): Account name Default user account is used if none provided - server (Optional[str]): Environment api endpoint (Advanced). + server (Optional[str]): Environment api endpoint (Advanced) Default api endpoint is used if none provided default_region (str): Default region for provisioning """ @@ -71,7 +71,7 @@ def mutual_exclusive_with_creds(cls, values: dict) -> dict: ) if sum(params_present) == 0: raise ValueError( - "Provide at least one of auth, user/password or access_token" + "Provide at least one of auth, user/password or access_token." ) if sum(params_present) > 1: raise ValueError("Provide only one of auth, user/password or access_token") diff --git a/src/firebolt/model/__init__.py b/src/firebolt/model/__init__.py index 94019755c47..83992de4b6e 100644 --- a/src/firebolt/model/__init__.py +++ b/src/firebolt/model/__init__.py @@ -11,14 +11,14 @@ class Config: def jsonable_dict(self, *args: Any, **kwargs: Any) -> dict: """ - Generate a dictionary representation of the service that is contains serialized - primitive types, and is therefore json-ready. + Generate a dictionary representation of the service that contains serialized + primitive types, and is therefore JSON-ready. - This could be replaced with something native, once this issue is resolved: + This could be replaced with something native once this issue is resolved: https://github.com/samuelcolvin/pydantic/issues/1409 - This function is intended to improve the compatibility with httpx, which - expects to take in a dictionary of primitives as input to the json parameter + This function is intended to improve the compatibility with HTTPX, which + expects to take in a dictionary of primitives as input to the JSON parameter of its request function. See: https://www.python-httpx.org/api/#helper-functions """ return json.loads(self.json(*args, **kwargs)) diff --git a/src/firebolt/model/binding.py b/src/firebolt/model/binding.py index e60da5a1ebc..26407d44a78 100644 --- a/src/firebolt/model/binding.py +++ b/src/firebolt/model/binding.py @@ -15,7 +15,7 @@ class BindingKey(BaseModel): class Binding(FireboltBaseModel): - """A Binding between an Engine and a Database""" + """A binding between an engine and a database.""" binding_key: BindingKey = Field(alias="id") is_default_engine: bool = Field(alias="engine_is_default") diff --git a/src/firebolt/model/engine.py b/src/firebolt/model/engine.py index 20fd1895776..c2894a48562 100644 --- a/src/firebolt/model/engine.py +++ b/src/firebolt/model/engine.py @@ -50,9 +50,9 @@ def wait(seconds: int, timeout_time: float, error_message: str, verbose: bool) - class EngineSettings(FireboltBaseModel): """ - Engine Settings. + Engine settings. - See Also: :py:class:`EngineRevisionSpecification + See also: :py:class:`EngineRevisionSpecification ` which also contains engine configuration. """ @@ -105,7 +105,7 @@ class FieldMask(FireboltBaseModel): class Engine(FireboltBaseModel): """ - A Firebolt engine. Responsible for performing work (queries, data ingestion). + A Firebolt engine. Responsible for performing work (queries, ingestion). Engines are configured in :py:class:`Settings ` @@ -162,7 +162,7 @@ def database(self) -> Optional[Database]: ) def get_latest(self) -> Engine: - """Get an up-to-date instance of the Engine from Firebolt.""" + """Get an up-to-date instance of the engine from Firebolt.""" return self._service.get(id_=self.engine_id) def attach_to_database( @@ -172,7 +172,7 @@ def attach_to_database( Attach this engine to a database. Args: - database: Database to which the engine will be attached. + database: Database to which the engine will be attached is_default_engine: Whether this engine should be used as default for this database. Only one engine can be set as default for a single database. @@ -184,7 +184,7 @@ def attach_to_database( @check_attached_to_database def get_connection(self) -> Connection: - """Get a connection to the attached database, for running queries. + """Get a connection to the attached database for running queries. Returns: Connection: engine connection instance @@ -211,16 +211,16 @@ def start( Args: wait_for_startup: If True, wait for startup to complete. - If false, return immediately after requesting startup. + If False, return immediately after requesting startup. wait_timeout_seconds: Number of seconds to wait for startup to complete - before raising a TimeoutError. + before raising a TimeoutError verbose: - If True, print dots periodically while waiting for engine startup. - If false, do not print any dots. + If True, print dots periodically while waiting for engine start. + If False, do not print any dots. Returns: - The updated Engine from Firebolt. + The updated engine from Firebolt. """ timeout_time = time.time() + wait_timeout_seconds @@ -332,12 +332,12 @@ def update( use_spot: Optional[bool] = None, ) -> Engine: """ - update the engine, and returns an updated version of the engine, all parameters - could be set to None, this would keep the old engine parameter value + Updates the engine and returns an updated version of the engine. If all + parameters are set to None, old engine parameter values remain. """ class _EngineUpdateRequest(FireboltBaseModel): - """Helper model for sending Engine update requests.""" + """Helper model for sending engine update requests.""" account_id: str desired_revision: Optional[EngineRevision] @@ -428,13 +428,13 @@ def restart( Args: wait_for_startup: If True, wait for startup to complete. - If false, return immediately after requesting startup. + If False, return immediately after requesting startup. wait_timeout_seconds: Number of seconds to wait for startup to complete before raising a TimeoutError. Returns: - The updated Engine from Firebolt. + The updated engine from Firebolt. """ timeout_time = time.time() + wait_timeout_seconds @@ -459,7 +459,7 @@ def restart( return engine def delete(self) -> Engine: - """Delete an Engine from Firebolt.""" + """Delete an engine from Firebolt.""" response = self._service.client.delete( url=ACCOUNT_ENGINE_URL.format( account_id=self._service.account_id, engine_id=self.engine_id @@ -482,7 +482,7 @@ def _send_engine_request(self, url: str) -> Engine: class _EngineCreateRequest(FireboltBaseModel): - """Helper model for sending Engine create requests.""" + """Helper model for sending engine create requests.""" account_id: str engine: Engine diff --git a/src/firebolt/model/engine_revision.py b/src/firebolt/model/engine_revision.py index 640a470cc09..30792eca6b3 100644 --- a/src/firebolt/model/engine_revision.py +++ b/src/firebolt/model/engine_revision.py @@ -17,9 +17,9 @@ class EngineRevisionKey(FireboltBaseModel): class EngineRevisionSpecification(FireboltBaseModel): """ - An EngineRevision Specification. + An EngineRevision specification. - Notably, it determines which instance types and how many of them its Engine gets. + Determines which instance types and how many of them its engine gets. See Also: :py:class:`Settings `, @@ -39,8 +39,8 @@ class EngineRevisionSpecification(FireboltBaseModel): class EngineRevision(FireboltBaseModel): """ - A Firebolt Engine revision, - which contains a Specification (instance types, counts). + A Firebolt engine revision, + which contains a specification (instance types, counts). As engines are updated with new settings, revisions are created. """ diff --git a/src/firebolt/service/binding.py b/src/firebolt/service/binding.py index 19935191ea4..f8e09d625cc 100644 --- a/src/firebolt/service/binding.py +++ b/src/firebolt/service/binding.py @@ -17,7 +17,7 @@ class BindingService(BaseService): def get_by_key(self, binding_key: BindingKey) -> Binding: - """Get a binding by it's BindingKey""" + """Get a binding by its BindingKey""" response = self.client.get( url=ACCOUNT_DATABASE_BINDING_URL.format( account_id=binding_key.account_id, @@ -50,7 +50,7 @@ def get_many( If None, do not filter on this parameter. Returns: - List of bindings matching the filter parameters. + List of bindings matching the filter parameters """ response = self.client.get( @@ -67,7 +67,7 @@ def get_many( return [Binding.parse_obj(i["node"]) for i in response.json()["edges"]] def get_database_bound_to_engine(self, engine: Engine) -> Optional[Database]: - """Get the Database to which an engine is bound, if any.""" + """Get the database to which an engine is bound, if any.""" try: binding = self.get_many(engine_id=engine.engine_id)[0] except IndexError: diff --git a/src/firebolt/service/database.py b/src/firebolt/service/database.py index 2c1e4f48270..32efd35199b 100644 --- a/src/firebolt/service/database.py +++ b/src/firebolt/service/database.py @@ -17,7 +17,7 @@ class DatabaseService(BaseService): def get(self, id_: str) -> Database: - """Get a Database from Firebolt by its id.""" + """Get a Database from Firebolt by its ID.""" response = self.client.get( url=ACCOUNT_DATABASE_URL.format(account_id=self.account_id, database_id=id_) @@ -27,13 +27,13 @@ def get(self, id_: str) -> Database: ) def get_by_name(self, name: str) -> Database: - """Get a Database from Firebolt by its name.""" + """Get a database from Firebolt by its name.""" database_id = self.get_id_by_name(name=name) return self.get(id_=database_id) def get_id_by_name(self, name: str) -> str: - """Get a Database id from Firebolt by its name.""" + """Get a database ID from Firebolt by its name.""" response = self.client.get( url=ACCOUNT_DATABASE_BY_NAME_URL.format(account_id=self.account_id), @@ -53,15 +53,15 @@ def get_many( Get a list of databases on Firebolt. Args: - name_contains: Filter for databases with a name containing this substring. - attached_engine_name_eq: Filter for databases by an exact engine name. + name_contains: Filter for databases with a name containing this substring + attached_engine_name_eq: Filter for databases by an exact engine name attached_engine_name_contains: Filter for databases by engines with a - name containing this substring. + name containing this substring order_by: Method by which to order the results. - See :py:class:`firebolt.service.types.DatabaseOrder`. + See :py:class:`firebolt.service.types.DatabaseOrder` Returns: - A list of databases matching the filters. + A list of databases matching the filters """ if isinstance(order_by, str): @@ -92,15 +92,15 @@ def create( Create a new Database on Firebolt. Args: - name: Name of the database. - region: Region name in which to create the database. + name: Name of the database + region: Region name in which to create the database Returns: - The newly created Database. + The newly created database """ class _DatabaseCreateRequest(FireboltBaseModel): - """Helper model for sending Database creation requests.""" + """Helper model for sending database creation requests.""" account_id: str database: Database diff --git a/src/firebolt/service/engine.py b/src/firebolt/service/engine.py index 31a26b479e7..9f8b921df19 100644 --- a/src/firebolt/service/engine.py +++ b/src/firebolt/service/engine.py @@ -23,7 +23,7 @@ class EngineService(BaseService): def get(self, id_: str) -> Engine: - """Get an Engine from Firebolt by its id.""" + """Get an engine from Firebolt by its ID.""" response = self.client.get( url=ACCOUNT_ENGINE_URL.format(account_id=self.account_id, engine_id=id_), @@ -32,7 +32,7 @@ def get(self, id_: str) -> Engine: return Engine.parse_obj_with_service(obj=engine_entry, engine_service=self) def get_by_ids(self, ids: List[str]) -> List[Engine]: - """Get multiple Engines from Firebolt by their ids.""" + """Get multiple engines from Firebolt by ID.""" response = self.client.post( url=ENGINES_BY_IDS_URL, json={ @@ -48,7 +48,7 @@ def get_by_ids(self, ids: List[str]) -> List[Engine]: ] def get_by_name(self, name: str) -> Engine: - """Get an Engine from Firebolt by its name.""" + """Get an engine from Firebolt by its name.""" response = self.client.get( url=ACCOUNT_ENGINE_BY_NAME_URL.format(account_id=self.account_id), @@ -69,14 +69,14 @@ def get_many( Get a list of engines on Firebolt. Args: - name_contains: Filter for engines with a name containing this substring. - current_status_eq: Filter for engines with this status. - current_status_not_eq: Filter for engines that do not have this status. - region_eq: Filter for engines by region. - order_by: Method by which to order the results. See [EngineOrder]. + name_contains: Filter for engines with a name containing this substring + current_status_eq: Filter for engines with this status + current_status_not_eq: Filter for engines that do not have this status + region_eq: Filter for engines by region + order_by: Method by which to order the results. See [EngineOrder] Returns: - A list of engines matching the filters. + A list of engines matching the filters """ if isinstance(order_by, str): @@ -119,30 +119,30 @@ def create( revision_spec_kwargs: Dict[str, Any] = {}, ) -> Engine: """ - Create a new Engine. + Create a new engine. Args: - name: An identifier that specifies the name of the engine. - region: The AWS region in which the engine runs. + name: An identifier that specifies the name of the engine + region: The AWS region in which the engine runs engine_type: The engine type. GENERAL_PURPOSE or DATA_ANALYTICS scale: The number of compute instances on the engine. The scale can be any int from 1 to 128. - spec: Firebolt instance type. If not set will default to + spec: Firebolt instance type. If not set, will default to the cheapest instance. auto_stop: The amount of time (in minutes) - after which the engine automatically stops. - warmup: The warmup method that should be used. + after which the engine automatically stops + warmup: The warmup method that should be used: - `MINIMAL` - On-demand loading (both indexes and tables' data). + `MINIMAL` - On-demand loading (both indexes and tables' data) - `PRELOAD_INDEXES` - Load indexes only. + `PRELOAD_INDEXES` - Load indexes only `PRELOAD_ALL_DATA` - Full data auto-load - (both indexes and table data - full warmup). - description: A short description of the engine's purpose. + (both indexes and table data - full warmup) + description: A short description of the engine's purpose Returns: - Engine with the specified settings. + Engine with the specified settings """ logger.info(f"Creating Engine (name={name})") @@ -202,11 +202,11 @@ def _send_create_engine( Create a new Engine on Firebolt from the local Engine object. Args: - engine: The Engine to create. - engine_revision: EngineRevision to use for configuring the Engine. + engine: The engine to create + engine_revision: EngineRevision to use for configuring the engine Returns: - The newly created engine. + The newly created engine """ response = self.client.post( diff --git a/src/firebolt/service/engine_revision.py b/src/firebolt/service/engine_revision.py index fa59275b204..b79964d62b1 100644 --- a/src/firebolt/service/engine_revision.py +++ b/src/firebolt/service/engine_revision.py @@ -22,7 +22,7 @@ def get_by_key(self, key: EngineRevisionKey) -> EngineRevision: Fetch an EngineRevision from Firebolt by its key. Args: - key: Key of the desired EngineRevision. + key: Key of the desired EngineRevision Returns: The requested EngineRevision diff --git a/src/firebolt/service/instance_type.py b/src/firebolt/service/instance_type.py index 5661f003da6..47a3ea26d45 100644 --- a/src/firebolt/service/instance_type.py +++ b/src/firebolt/service/instance_type.py @@ -8,7 +8,7 @@ class InstanceTypeLookup(NamedTuple): - """Helper tuple for looking up instance types by names""" + """Helper tuple for looking up instance types by names.""" region_name: str instance_type_name: str @@ -93,13 +93,13 @@ def get_by_name( Get an instance type by name. Args: - instance_type_name: Name of the instance (eg. "i3.4xlarge"). + instance_type_name: Name of the instance (eg. "i3.4xlarge") region_name: Name of the AWS region from which to get the instance. If not provided, use the default region name from the client. Returns: - The requested instance type. + The requested instance type """ # Will raise an error if neither set diff --git a/src/firebolt/service/manager.py b/src/firebolt/service/manager.py index 378f7c41ae4..e484e0af1b8 100644 --- a/src/firebolt/service/manager.py +++ b/src/firebolt/service/manager.py @@ -22,7 +22,6 @@ class ResourceManager: Also provides listings of: - regions (AWS regions in which engines can run) - - instance types (AWS instance types which engines can use) """ diff --git a/src/firebolt/service/region.py b/src/firebolt/service/region.py index dbfec2d24c1..ff614d56288 100644 --- a/src/firebolt/service/region.py +++ b/src/firebolt/service/region.py @@ -10,17 +10,17 @@ class RegionService(BaseService): def __init__(self, resource_manager: ResourceManager): """ - Service to manage AWS Regions (us-east-1, etc). + Service to manage AWS regions (us-east-1, etc) Args: - resource_manager: Resource manager to use. + resource_manager: Resource manager to use """ super().__init__(resource_manager=resource_manager) @cached_property def regions(self) -> List[Region]: - """List of available AWS Regions on Firebolt.""" + """List of available AWS regions on Firebolt.""" response = self.client.get(url=REGIONS_URL, params={"page.first": 5000}) return [Region.parse_obj(i["node"]) for i in response.json()["edges"]] @@ -39,7 +39,7 @@ def regions_by_key(self) -> Dict[RegionKey, Region]: @cached_property def default_region(self) -> Region: - """Default AWS Region, could be provided from environment.""" + """Default AWS region, could be provided from environment.""" if not self.settings.default_region: raise ValueError( @@ -53,12 +53,12 @@ def get_by_name(self, name: str) -> Region: return self.regions_by_name[name] def get_by_key(self, key: RegionKey) -> Region: - """Get an AWS Region by its key.""" + """Get an AWS region by its key.""" return self.regions_by_key[key] def get_by_id(self, id_: str) -> Region: - """Get an AWS Region by region_id.""" + """Get an AWS region by region_id.""" return self.get_by_key( RegionKey(provider_id=self.resource_manager.provider_id, region_id=id_) diff --git a/src/firebolt/service/types.py b/src/firebolt/service/types.py index b46f6104d49..0ccdaef3573 100644 --- a/src/firebolt/service/types.py +++ b/src/firebolt/service/types.py @@ -36,9 +36,9 @@ class EngineStatus(Enum): """ ENGINE_STATUS_UNSPECIFIED = "ENGINE_STATUS_UNSPECIFIED" - """ Logical record is created, however underlying infrastructure + """ Logical record is created, however, underlying infrastructure is not initialized. - In other words this means that engine is stopped.""" + In other words, this means that engine is stopped.""" ENGINE_STATUS_CREATED = "ENGINE_STATUS_CREATED" """Engine status was created.""" @@ -62,43 +62,43 @@ class EngineStatus(Enum): ENGINE_STATUS_RUNNING_REVISION_STARTING = "ENGINE_STATUS_RUNNING_REVISION_STARTING" """ Engine is initialized, - there are no running engine revision but it's starting.""" + there are no running engine revisions, but it's starting.""" ENGINE_STATUS_RUNNING_REVISION_STARTUP_FAILED = ( "ENGINE_STATUS_RUNNING_REVISION_STARTUP_FAILED" ) - """ Engine is initialized, - initial revision is failed to provision or start.""" + """ Engine is initialized; + initial revision failed to provision or start.""" ENGINE_STATUS_RUNNING_REVISION_SERVING = "ENGINE_STATUS_RUNNING_REVISION_SERVING" """ Engine is ready (serves an engine revision). """ ENGINE_STATUS_RUNNING_REVISION_CHANGING = "ENGINE_STATUS_RUNNING_REVISION_CHANGING" - """ Engine is ready (serves an engine revision), + """ Engine is ready (serves an engine revision); zero-downtime replacement revision is starting.""" ENGINE_STATUS_RUNNING_REVISION_CHANGE_FAILED = ( "ENGINE_STATUS_RUNNING_REVISION_CHANGE_FAILED" ) - """ Engine is ready (serves an engine revision), + """ Engine is ready (serves an engine revision); replacement revision failed to provision or start.""" ENGINE_STATUS_RUNNING_REVISION_RESTARTING = ( "ENGINE_STATUS_RUNNING_REVISION_RESTARTING" ) - """ Engine is initialized, + """ Engine is initialized; replacement of the revision with a downtime is in progress.""" ENGINE_STATUS_RUNNING_REVISION_RESTART_FAILED = ( "ENGINE_STATUS_RUNNING_REVISION_RESTART_FAILED" ) - """ Engine is initialized, + """ Engine is initialized; replacement revision failed to provision or start.""" ENGINE_STATUS_RUNNING_REVISIONS_TERMINATING = ( "ENGINE_STATUS_RUNNING_REVISIONS_TERMINATING" ) - """ Engine is initialized, + """ Engine is initialized; all child revisions are being terminated.""" # Engine termination request was sent. @@ -132,18 +132,18 @@ class EngineStatusSummary(Enum): """ Fully stopped.""" ENGINE_STATUS_SUMMARY_STARTING = "ENGINE_STATUS_SUMMARY_STARTING" - """ Provisioning process is in progress. - We are creating cloud infra for this engine.""" + """ Provisioning process is in progress; + creating cloud infra for this engine.""" ENGINE_STATUS_SUMMARY_STARTING_INITIALIZING = ( "ENGINE_STATUS_SUMMARY_STARTING_INITIALIZING" ) - """ Provisioning process is complete. - We are now waiting for PackDB cluster to initialize and start.""" + """ Provisioning process is complete; + waiting for PackDB cluster to initialize and start.""" ENGINE_STATUS_SUMMARY_RUNNING = "ENGINE_STATUS_SUMMARY_RUNNING" - """ Fully started. - Engine is ready to serve requests.""" + """ Fully started; + engine is ready to serve requests.""" ENGINE_STATUS_SUMMARY_UPGRADING = "ENGINE_STATUS_SUMMARY_UPGRADING" """ Version of the PackDB is changing. @@ -158,7 +158,7 @@ class EngineStatusSummary(Enum): "ENGINE_STATUS_SUMMARY_RESTARTING_INITIALIZING" ) """ Hard restart (full stop/start cycle) is in progress. - Underlying infrastructure is ready, waiting for + Underlying infrastructure is ready. Waiting for PackDB cluster to initialize and start. This status is logically the same as ENGINE_STATUS_SUMMARY_STARTING_INITIALIZING, but used during restart cycle.""" diff --git a/src/firebolt/utils/exception.py b/src/firebolt/utils/exception.py index 359888bfb07..38f7af57964 100644 --- a/src/firebolt/utils/exception.py +++ b/src/firebolt/utils/exception.py @@ -7,23 +7,23 @@ class FireboltEngineError(FireboltError): class EngineNotRunningError(FireboltEngineError): - """Engine, that's being queried, is not running.""" + """Engine that's being queried is not running.""" class NoAttachedDatabaseError(FireboltEngineError): - """Engine, that's being accessed, is not running. + """Engine that's being accessed is not running. Args: - method_name (str): Name of the method, which caused issue + method_name (str): Method that caused the error Attributes: - method_name (str): Name of the method, which caused issue + method_name (str): Method that caused the error """ def __init__(self, method_name: str): super().__init__( f"Unable to call {method_name}: " - "Engine must to be attached to a database first." + "Engine must be attached to a database first." ) self.method_name = method_name @@ -40,10 +40,10 @@ class AccountNotFoundError(FireboltError): """Account with provided name doesn't exist. Args: - account_name (str): Name of account, that wasn't found + account_name (str): Name of account that wasn't found Attributes: - account_name (str): Name of account, that wasn't found + account_name (str): Name of account that wasn't found """ def __init__(self, account_name: str): @@ -52,13 +52,13 @@ def __init__(self, account_name: str): class AttachedEngineInUseError(FireboltDatabaseError): - """Engine is unavailable because it's starting/stopping. + """Engine unavailable because it's starting/stopping. Args: - method_name (str): Name of the method, which caused issue + method_name (str): Method that caused the error Attributes: - method_name (str): Name of the method, which caused issue + method_name (str): Method that caused the error """ def __init__(self, method_name: str): @@ -85,10 +85,10 @@ class CursorClosedError(CursorError): """Cursor operations are unavailable since it's closed. Args: - method_name (str): Name of the method, which caused issue + method_name (str): Method that caused the error Attributes: - method_name (str): Name of the method, which caused issue + method_name (str): Method that caused the error """ def __init__(self, method_name: str): @@ -100,10 +100,10 @@ class QueryNotRunError(CursorError): """Some cursor methods are unavailable before a query is run. Args: - method_name (str): Name of the method, which caused issue + method_name (str): Method that caused the error Attributes: - method_name (str): Name of the method, which caused issue + method_name (str): Method that caused the error """ def __init__(self, method_name: str): @@ -117,11 +117,11 @@ class AuthenticationError(FireboltError): Stores error cause and authentication endpoint. Args: - api_endpoint (str): Environment api endpoint, used for authentication + api_endpoint (str): Environment api endpoint used for authentication cause (str): Reason for authentication failure Attributes: - api_endpoint (str): Environment api endpoint, used for authentication + api_endpoint (str): Environment api endpoint used for authentication cause (str): Reason for authentication failure """ @@ -172,7 +172,7 @@ class DatabaseError(Error): class DataError(DatabaseError): """Data processing error. - Exception raised for errors that are due to problems with the processed data + Exception raised for errors that are due to problems with the processed data, like division by zero, numeric value out of range, etc. """ @@ -181,7 +181,7 @@ class OperationalError(DatabaseError): """Database operating error. Exception raised for errors that are related to the database's operation - and not necessarily under the control of the programmer, e.g. an unexpected + and not necessarily under the control of the programmer, e.g., an unexpected disconnect occurs, the data source name is not found, a transaction could not be processed, a memory allocation error occurred during processing, etc. """ @@ -191,7 +191,7 @@ class IntegrityError(DatabaseError): """Database data integrity error. Exception raised when the relational integrity of the database is affected, - e.g. a foreign key check fails. + e.g., a foreign key check fails. """ @@ -199,14 +199,14 @@ class InternalError(DatabaseError): """Database internal error. Exception raised when the database encounters an internal error, - e.g. the cursor is not valid anymore, the transaction is out of sync, etc. + e.g., the cursor is not valid anymore, the transaction is out of sync, etc. """ class ProgrammingError(DatabaseError): """Database programming error. - Exception raised for programming errors, e.g. table not found or already exists, + Exception raised for programming errors, e.g., table not found or already exists, syntax error in the SQL statement, wrong number of parameters specified, etc. """ @@ -215,7 +215,7 @@ class NotSupportedError(DatabaseError): """Operation not supported. Exception raised in case a method or database API was used which is not supported - by the database, e.g. requesting a .rollback() on a connection that + by the database, e.g., requesting a .rollback() on a connection that does not support transaction or has transactions turned off. """ diff --git a/src/firebolt/utils/token_storage.py b/src/firebolt/utils/token_storage.py index 740a782c61d..131c76f8e43 100644 --- a/src/firebolt/utils/token_storage.py +++ b/src/firebolt/utils/token_storage.py @@ -95,7 +95,7 @@ def get_cached_token(self) -> Optional[str]: """Get decrypted token. If token is not found, cannot be decrypted with username and password, - or is expired - None will be returned + or is expired - None will be returned. Returns: Optional[str]: Decrypted token or None @@ -114,7 +114,7 @@ def cache_token(self, token: str, expiration_ts: int) -> None: """Encrypt and store token in file system. Expiration timestamp is also stored with token in order to later - be ableto check if it's expired + be able to check if it's expired. Args: token (str): Token to store @@ -131,7 +131,7 @@ def cache_token(self, token: str, expiration_ts: int) -> None: class FernetEncrypter: """PBDKF2HMAC based encrypter. - Username and password combination is used as a key + Username and password combination is used as a key. Args: salt (str): Salt value for encryption diff --git a/src/firebolt/utils/util.py b/src/firebolt/utils/util.py index 22ca800fc3d..56c07b07b4f 100644 --- a/src/firebolt/utils/util.py +++ b/src/firebolt/utils/util.py @@ -51,13 +51,13 @@ def prune_dict(d: dict) -> dict: def mixin_for(baseclass: Type[TMix]) -> Type[TMix]: """Define mixin with baseclass typehint. - Should be used as a mixin base class to fix typehints + Should be used as a mixin base class to fix typehints. Args: baseclass (Type[TMix]): Class which mixin will be made for Returns: - Type[TMix]: Mixin type to inherin from + Type[TMix]: Mixin type to inherit from Examples: ``` @@ -85,15 +85,15 @@ def fix_url_schema(url: str) -> str: class AsyncJobThread: - """Thread runner that allows running async tasks syncronously in a separate thread. + """Thread runner that allows running async tasks synchronously in a separate thread. Caches loop to be reused in all threads. - It allows running async functions syncronously inside a running event loop. + It allows running async functions synchronously inside a running event loop. Since nesting loops is not allowed, we create a separate thread for a new event loop Attributes: result (Any): Value, returned by coroutine execution - exception (Optional[BaseException]): If any, exception that occured + exception (Optional[BaseException]): If any, exception that occurred during coroutine execution """ @@ -106,7 +106,7 @@ def _initialize_loop(self) -> None: """Initialize a loop once to use for later execution. Tries to get a running loop. - Creates a new loop if no active one and sets it as active. + Creates a new loop if no active one, and sets it as active. """ if not self._loop: try: @@ -119,8 +119,8 @@ def _initialize_loop(self) -> None: def _run(self, coro: Coroutine) -> None: """Run coroutine in an event loop. - Execution return value is stored into ``result`` field - If an exception occures, it will be caught and stored into ``exception`` field + Execution return value is stored into ``result`` field. + If an exception occurs, it will be caught and stored into ``exception`` field. Args: coro (Coroutine): Coroutine to execute @@ -161,7 +161,7 @@ def async_to_sync(f: Callable, async_job_thread: AsyncJobThread = None) -> Calla (Default value = None) Returns: - Callable: regular function, which can be executed syncronously + Callable: regular function, which can be executed synchronously """ @wraps(f) diff --git a/tests/integration/dbapi/async/test_auth_async.py b/tests/integration/dbapi/async/test_auth_async.py index 76dac742db4..ef7ada44c95 100644 --- a/tests/integration/dbapi/async/test_auth_async.py +++ b/tests/integration/dbapi/async/test_auth_async.py @@ -31,7 +31,7 @@ async def test_refresh_token(connection: Connection) -> None: @mark.asyncio async def test_credentials_invalidation(connection: Connection) -> None: - """Auth raises Authentication Error on credentials invalidation""" + """Auth raises authentication error on credentials invalidation""" with connection.cursor() as c: # Works fine await c.execute("show tables") diff --git a/tests/integration/dbapi/async/test_queries_async.py b/tests/integration/dbapi/async/test_queries_async.py index fbe5ee329ff..d0d96bccc32 100644 --- a/tests/integration/dbapi/async/test_queries_async.py +++ b/tests/integration/dbapi/async/test_queries_async.py @@ -55,7 +55,7 @@ async def test_select( all_types_query_description: List[Column], all_types_query_response: List[ColType], ) -> None: - """Select handles all data types properly""" + """Select handles all data types properly.""" with connection.cursor() as c: assert (await c.execute("set firebolt_use_decimal = 1")) == -1 assert await c.execute(all_types_query) == 1, "Invalid row count returned" @@ -88,7 +88,7 @@ async def test_select( async def test_long_query( connection: Connection, ) -> None: - """AWS ALB TCP timeout set to 350, make sure we handle the keepalive correctly""" + """AWS ALB TCP timeout set to 350; make sure we handle the keepalive correctly.""" with connection.cursor() as c: await c.execute( "SET advanced_mode = 1; SET use_standard_sql = 0;" @@ -107,14 +107,14 @@ async def test_drop_create( """Create and drop table/index queries are handled properly.""" async def test_query(c: Cursor, query: str) -> None: - assert await c.execute(query) == 1, "Invalid row count returned." - assert c.rowcount == 1, "Invalid rowcount value." + assert await c.execute(query) == 1, "Invalid row count returned" + assert c.rowcount == 1, "Invalid rowcount value" assert_deep_eq( c.description, create_drop_description, - "Invalid create table query description.", + "Invalid create table query description", ) - assert len(await c.fetchall()) == 1, "Invalid data returned." + assert len(await c.fetchall()) == 1, "Invalid data returned" """Create table query is handled properly""" with connection.cursor() as c: @@ -173,9 +173,9 @@ async def test_insert(connection: Connection) -> None: """Insert and delete queries are handled properly.""" async def test_empty_query(c: Cursor, query: str) -> None: - assert await c.execute(query) == -1, "Invalid row count returned." - assert c.rowcount == -1, "Invalid rowcount value." - assert c.description is None, "Invalid description." + assert await c.execute(query) == -1, "Invalid row count returned" + assert c.rowcount == -1, "Invalid rowcount value" + assert c.description is None, "Invalid description" with raises(DataError): await c.fetchone() @@ -203,7 +203,7 @@ async def test_empty_query(c: Cursor, query: str) -> None: "SELECT * FROM test_insert_async_tb ORDER BY test_insert_async_tb.id" ) == 1 - ), "Invalid data length in table after insert." + ), "Invalid data length in table after insert" assert_deep_eq( await c.fetchall(), @@ -218,13 +218,13 @@ async def test_empty_query(c: Cursor, query: str) -> None: [1, 2, 3], ], ], - "Invalid data in table after insert.", + "Invalid data in table after insert", ) @mark.asyncio async def test_parameterized_query(connection: Connection) -> None: - """Query parameters are handled properly""" + """Query parameters are handled properly.""" async def test_empty_query(c: Cursor, query: str, params: tuple) -> None: assert await c.execute(query, params) == -1, "Invalid row count returned" diff --git a/tests/integration/dbapi/sync/test_errors.py b/tests/integration/dbapi/sync/test_errors.py index 34130babe8e..1a1a519e418 100644 --- a/tests/integration/dbapi/sync/test_errors.py +++ b/tests/integration/dbapi/sync/test_errors.py @@ -15,7 +15,7 @@ def test_invalid_credentials( engine_url: str, database_name: str, username: str, password: str, api_endpoint: str ) -> None: - """Connection properly reacts to invalid credentials error""" + """Connection properly reacts to invalid credentials error.""" with connect( engine_url=engine_url, database=database_name, @@ -59,7 +59,7 @@ def test_invalid_account( def test_engine_url_not_exists( engine_url: str, database_name: str, username: str, password: str, api_endpoint: str ) -> None: - """Connection properly reacts to invalid engine url error""" + """Connection properly reacts to invalid engine url error.""" with connect( engine_url=engine_url + "_", database=database_name, @@ -78,7 +78,7 @@ def test_engine_name_not_exists( password: str, api_endpoint: str, ) -> None: - """Connection properly reacts to invalid engine name error""" + """Connection properly reacts to invalid engine name error.""" with raises(FireboltEngineError): with connect( engine_name=engine_name + "_________", @@ -97,7 +97,7 @@ def test_engine_stopped( password: str, api_endpoint: str, ) -> None: - """Connection properly reacts to engine not running error""" + """Connection properly reacts to engine not running error.""" with raises(EngineNotRunningError): with connect( engine_url=stopped_engine_url, diff --git a/tests/integration/dbapi/sync/test_queries.py b/tests/integration/dbapi/sync/test_queries.py index 06558bca5ea..85b569feb1b 100644 --- a/tests/integration/dbapi/sync/test_queries.py +++ b/tests/integration/dbapi/sync/test_queries.py @@ -60,7 +60,7 @@ def test_select( all_types_query_description: List[Column], all_types_query_response: List[ColType], ) -> None: - """Select handles all data types properly""" + """Select handles all data types properly.""" with connection.cursor() as c: assert c.execute("set firebolt_use_decimal = 1") == -1 assert c.execute(all_types_query) == 1, "Invalid row count returned" @@ -90,7 +90,7 @@ def test_select( def test_long_query( connection: Connection, ) -> None: - """AWS ALB TCP timeout set to 350, make sure we handle the keepalive correctly""" + """AWS ALB TCP timeout set to 350, make sure we handle the keepalive correctly.""" with connection.cursor() as c: c.execute( "SET advanced_mode = 1; SET use_standard_sql = 0;" @@ -218,7 +218,7 @@ def test_empty_query(c: Cursor, query: str) -> None: def test_parameterized_query(connection: Connection) -> None: - """Query parameters are handled properly""" + """Query parameters are handled properly.""" def test_empty_query(c: Cursor, query: str, params: tuple) -> None: assert c.execute(query, params) == -1, "Invalid row count returned" diff --git a/tests/unit/async_db/test_connection.py b/tests/unit/async_db/test_connection.py index 959a80c60c9..b6a5242ddc5 100644 --- a/tests/unit/async_db/test_connection.py +++ b/tests/unit/async_db/test_connection.py @@ -63,7 +63,7 @@ async def test_cursor_initialized( query_url: str, python_query_data: List[List[ColType]], ) -> None: - """Connection initialised its cursors properly.""" + """Connection initialized its cursors properly.""" httpx_mock.add_callback(auth_callback, url=auth_url) httpx_mock.add_callback(query_callback, url=query_url) diff --git a/tests/unit/async_db/test_cursor.py b/tests/unit/async_db/test_cursor.py index 4f83f7aec7b..f94634acbca 100644 --- a/tests/unit/async_db/test_cursor.py +++ b/tests/unit/async_db/test_cursor.py @@ -29,7 +29,7 @@ async def test_cursor_state( query_url: str, cursor: Cursor, ): - """Cursor state changes depending on the operations performed with it.""" + """Cursor state changes depend on the operations performed with it.""" httpx_mock.add_callback(auth_callback, url=auth_url) httpx_mock.add_callback(query_callback, url=query_url) @@ -57,7 +57,7 @@ def error_query_callback(*args, **kwargs): @mark.asyncio async def test_closed_cursor(cursor: Cursor): - """Most of cursor methods are unavailable for closed cursor.""" + """Most cursor methods are unavailable for closed cursor.""" fields = ("description", "rowcount", "statistics") async_methods = ( ("execute", (cursor,)), @@ -104,7 +104,7 @@ async def test_cursor_no_query( query_url: str, cursor: Cursor, ): - """Some of cursor methods are unavailable until a query is run.""" + """Some cursor methods are unavailable until a query is run.""" async_methods = ( "fetchone", "fetchmany", @@ -156,7 +156,7 @@ async def test_cursor_execute( python_query_description: List[Column], python_query_data: List[List[ColType]], ): - """Cursor is able to execute query, all fields are populated properly.""" + """Cursor is able to execute query; all fields are populated properly.""" for query in ( lambda: cursor.execute("select * from t"), @@ -286,7 +286,7 @@ async def test_cursor_fetchone( query_url: str, cursor: Cursor, ): - """cursor fetchone fetches single row in correct order, if no rows returns None.""" + """cursor fetchone fetches single row in correct order. If no rows, returns None.""" httpx_mock.add_callback(auth_callback, url=auth_url) httpx_mock.add_callback(query_callback, url=query_url) @@ -322,7 +322,7 @@ async def test_cursor_fetchmany( cleandoc( """ Cursor's fetchmany fetches the provided amount of rows, or arraysize by - default. If not enough rows left, returns less or None if there are no rows. + default. If not enough rows left, returns less, or None if there are no rows. """ ) httpx_mock.add_callback(auth_callback, url=auth_url) @@ -365,7 +365,7 @@ async def test_cursor_fetchmany( assert ( len(await cursor.fetchmany()) == 0 - ), "fetchmany should return empty result set when no rows left to fetch" + ), "fetchmany should return empty result set when no rows remain to fetch" httpx_mock.add_callback(insert_query_callback, url=query_url) await cursor.execute("sql") @@ -383,7 +383,7 @@ async def test_cursor_fetchall( query_url: str, cursor: Cursor, ): - """cursor fetchall fetches all rows that left after last query.""" + """cursor fetchall fetches all rows remaining after last query.""" httpx_mock.add_callback(auth_callback, url=auth_url) httpx_mock.add_callback(query_callback, url=query_url) @@ -400,7 +400,7 @@ async def test_cursor_fetchall( assert ( len(await cursor.fetchall()) == 0 - ), "fetchmany should return empty result set when no rows left to fetch" + ), "fetchmany should return empty result set when no rows remain to fetch" httpx_mock.add_callback(insert_query_callback, url=query_url) await cursor.execute("sql") @@ -420,7 +420,7 @@ async def test_set_parameters( cursor: Cursor, set_params: Dict, ): - """Cursor passes provided set parameters to engine""" + """Cursor passes provided set parameters to engine.""" httpx_mock.add_callback(auth_callback, url=auth_url) httpx_mock.add_callback(query_with_params_callback, url=query_with_params_url) await cursor.execute("select 1", set_parameters=set_params) @@ -438,7 +438,7 @@ async def test_cursor_multi_statement( python_query_description: List[Column], python_query_data: List[List[ColType]], ): - """executemany with multiple parameter sets is not supported""" + """executemany with multiple parameter sets is not supported.""" httpx_mock.add_callback(auth_callback, url=auth_url) httpx_mock.add_callback(query_callback, url=query_url) httpx_mock.add_callback(insert_query_callback, url=query_url) @@ -501,7 +501,7 @@ async def test_cursor_set_statements( python_query_description: List[Column], python_query_data: List[List[ColType]], ): - """cursor correctly parses and processes set statements""" + """cursor correctly parses and processes set statements.""" httpx_mock.add_callback(auth_callback, url=auth_url) httpx_mock.add_callback(select_one_query_callback, url=f"{query_url}&a=b") @@ -573,7 +573,7 @@ async def test_cursor_set_parameters_sent( cursor: Cursor, set_params: Dict, ): - """Cursor passes provided set parameters to engine""" + """Cursor passes provided set parameters to engine.""" httpx_mock.add_callback(auth_callback, url=auth_url) params = "" @@ -597,7 +597,7 @@ async def test_cursor_skip_parse( query_callback: Callable, cursor: Cursor, ): - """Cursor doesn't process a query if skip_parsing is provided""" + """Cursor doesn't process a query if skip_parsing is provided.""" httpx_mock.add_callback(auth_callback, url=auth_url) httpx_mock.add_callback(query_callback, url=query_url) diff --git a/tests/unit/async_db/test_module.py b/tests/unit/async_db/test_module.py index 4dda2740658..c0661af0d0c 100644 --- a/tests/unit/async_db/test_module.py +++ b/tests/unit/async_db/test_module.py @@ -2,6 +2,6 @@ def test_has_exceptions(db_api_exceptions): - """Verify async module has top-level dbapi exceptions exposed""" + """Verify async module has top-level dbapi exceptions exposed.""" for ex_name, ex_class in db_api_exceptions.items(): assert issubclass(getattr(firebolt.async_db, ex_name), ex_class) diff --git a/tests/unit/client/test_client.py b/tests/unit/client/test_client.py index bbf403450f8..ea69ebbd8f4 100644 --- a/tests/unit/client/test_client.py +++ b/tests/unit/client/test_client.py @@ -20,7 +20,7 @@ def test_client_retry( ): """ Client retries with new auth token - if first attempt fails with Unauthorized error + if first attempt fails with unauthorized error. """ client = Client(auth=UsernamePassword(test_username, test_password)) diff --git a/tests/unit/client/test_client_async.py b/tests/unit/client/test_client_async.py index 727fd614a6c..f4cf3244795 100644 --- a/tests/unit/client/test_client_async.py +++ b/tests/unit/client/test_client_async.py @@ -21,7 +21,7 @@ async def test_client_retry( ): """ Client retries with new auth token - if first attempt fails with Unauthorized error + if first attempt fails with unauthorized error. """ async with AsyncClient( auth=UsernamePassword(test_username, test_password) diff --git a/tests/unit/common/test_token_storage.py b/tests/unit/common/test_token_storage.py index b0cac9ed738..4e441e877fa 100644 --- a/tests/unit/common/test_token_storage.py +++ b/tests/unit/common/test_token_storage.py @@ -13,7 +13,7 @@ def test_encrypter_happy_path(): """ - Simple encrypt/decrypt using FernetEncrypter + Simple encrypt/decrypt using FernetEncrypter. """ salt = generate_salt() encrypter1 = FernetEncrypter(salt, username="username", password="password") @@ -27,8 +27,8 @@ def test_encrypter_happy_path(): def test_encrypter_wrong_parameter(): """ - Test that decryption only works, if the correct salt, - username and password is provided, otherwise None is returned + Test that decryption only works if the correct salt + username and password is provided; otherwise None is returned. """ salt1 = generate_salt() salt2 = generate_salt() @@ -72,7 +72,7 @@ def test_token_storage_happy_path(fs: FakeFilesystem): @patch("firebolt.utils.token_storage.time", return_value=0) def test_token_storage_wrong_parameter(fs: FakeFilesystem): """ - Test getting token with different username or password + Test getting token with different username or password. """ settings = {"username": "username", "password": "password"} token = "some string to encrypt" @@ -95,7 +95,7 @@ def test_token_storage_wrong_parameter(fs: FakeFilesystem): def test_token_storage_json_broken(fs: FakeFilesystem): """ - Check that the TokenSecureStorage properly handles broken json + Check that the TokenSecureStorage properly handles broken json. """ settings = {"username": "username", "password": "password"} @@ -109,7 +109,7 @@ def test_token_storage_json_broken(fs: FakeFilesystem): @patch("firebolt.utils.token_storage.time", return_value=0) def test_multiple_tokens(fs: FakeFilesystem) -> None: """ - Check that the TokenSecureStorage properly handles multiple tokens hashed + Check that the TokenSecureStorage properly handles multiple tokens hashed. """ settings1 = {"username": "username1", "password": "password1"} settings2 = {"username": "username2", "password": "password2"} @@ -138,7 +138,7 @@ def test_multiple_tokens(fs: FakeFilesystem) -> None: @patch("firebolt.utils.token_storage.time", return_value=0) def test_expired_token(fs: FakeFilesystem) -> None: """ - Check that TokenSecureStorage ignores expired tokens + Check that TokenSecureStorage ignores expired tokens. """ tss = TokenSecureStorage(username="username", password="password") tss.cache_token("token", 0) diff --git a/tests/unit/common/test_util.py b/tests/unit/common/test_util.py index 9a79dbffd1f..cafa968feb2 100644 --- a/tests/unit/common/test_util.py +++ b/tests/unit/common/test_util.py @@ -7,7 +7,7 @@ def test_async_to_sync_happy_path(): - """async_to_sync properly converts coroutine to sync function""" + """async_to_sync properly converts coroutine to sync function.""" class JobMarker(Exception): pass @@ -21,7 +21,7 @@ async def task(): def test_async_to_sync_thread(): - """async_to_sync properly works in threads""" + """async_to_sync works correctly in threads.""" marks = [False] * 3 @@ -35,7 +35,7 @@ async def task(id: int): def test_async_to_sync_after_run(): - """async_to_sync properly runs after asyncio.run""" + """async_to_sync runs correctly after asyncio.run.""" class JobMarker(Exception): pass @@ -54,7 +54,7 @@ async def task(): @mark.asyncio async def test_nested_loops() -> None: - """async_to_sync properly works inside a running loop""" + """async_to_sync works correctly inside a running loop.""" class JobMarker(Exception): pass diff --git a/tests/unit/db/test_connection.py b/tests/unit/db/test_connection.py index f8ce4d34881..f50aae5afdd 100644 --- a/tests/unit/db/test_connection.py +++ b/tests/unit/db/test_connection.py @@ -59,7 +59,7 @@ def test_cursor_initialized( query_url: str, python_query_data: List[List[ColType]], ) -> None: - """Connection initialised its cursors properly.""" + """Connection initialized its cursors properly.""" httpx_mock.add_callback(auth_callback, url=auth_url) httpx_mock.add_callback(query_callback, url=query_url) diff --git a/tests/unit/db/test_cursor.py b/tests/unit/db/test_cursor.py index 528b4bb40bd..0727c18067b 100644 --- a/tests/unit/db/test_cursor.py +++ b/tests/unit/db/test_cursor.py @@ -237,7 +237,7 @@ def test_cursor_fetchone( query_url: str, cursor: Cursor, ): - """cursor fetchone fetches single row in correct order, if no rows returns None.""" + """cursor fetchone fetches single row in correct order; if no rows returns None.""" httpx_mock.add_callback(auth_callback, url=auth_url) httpx_mock.add_callback(query_callback, url=query_url) @@ -272,7 +272,7 @@ def test_cursor_fetchmany( cleandoc( """ Cursor's fetchmany fetches the provided amount of rows, or arraysize by - default. If not enough rows left, returns less or None if there are no rows. + default. If not enough rows left, returns less, or None if there are no rows. """ ) httpx_mock.add_callback(auth_callback, url=auth_url) @@ -368,7 +368,7 @@ def test_set_parameters( cursor: Cursor, set_params: Dict, ): - """Cursor passes provided set parameters to engine""" + """Cursor passes provided set parameters to engine.""" httpx_mock.add_callback(auth_callback, url=auth_url) httpx_mock.add_callback(query_with_params_callback, url=query_with_params_url) cursor.execute("select 1", set_parameters=set_params) @@ -385,7 +385,7 @@ def test_cursor_multi_statement( python_query_description: List[Column], python_query_data: List[List[ColType]], ): - """executemany with multiple parameter sets is not supported""" + """executemany with multiple parameter sets is not supported.""" httpx_mock.add_callback(auth_callback, url=auth_url) httpx_mock.add_callback(query_callback, url=query_url) httpx_mock.add_callback(insert_query_callback, url=query_url) @@ -435,7 +435,7 @@ def test_cursor_set_statements( python_query_description: List[Column], python_query_data: List[List[ColType]], ): - """cursor correctly parses and processes set statements""" + """cursor correctly parses and processes set statements.""" httpx_mock.add_callback(auth_callback, url=auth_url) httpx_mock.add_callback(select_one_query_callback, url=f"{query_url}&a=b") @@ -506,7 +506,7 @@ def test_cursor_set_parameters_sent( cursor: Cursor, set_params: Dict, ): - """Cursor passes provided set parameters to engine""" + """Cursor passes provided set parameters to engine.""" httpx_mock.add_callback(auth_callback, url=auth_url) params = "" @@ -529,7 +529,7 @@ def test_cursor_skip_parse( query_callback: Callable, cursor: Cursor, ): - """Cursor doesn't process a query if skip_parsing is provided""" + """Cursor doesn't process a query if skip_parsing is provided.""" httpx_mock.add_callback(auth_callback, url=auth_url) httpx_mock.add_callback(query_callback, url=query_url) diff --git a/tests/unit/db/test_module.py b/tests/unit/db/test_module.py index 473c0770f49..f10b53884e1 100644 --- a/tests/unit/db/test_module.py +++ b/tests/unit/db/test_module.py @@ -2,6 +2,6 @@ def test_has_exceptions(db_api_exceptions): - """Verify sync module has top-level dbapi exceptions exposed""" + """Verify sync module has top-level dbapi exceptions exposed.""" for ex_name, ex_class in db_api_exceptions.items(): assert issubclass(getattr(firebolt.db, ex_name), ex_class) diff --git a/tests/unit/service/test_resource_manager.py b/tests/unit/service/test_resource_manager.py index 778025cca7a..a76f6f8ba05 100644 --- a/tests/unit/service/test_resource_manager.py +++ b/tests/unit/service/test_resource_manager.py @@ -24,7 +24,7 @@ def test_rm_credentials( provider_url: str, access_token: str, ) -> None: - """Creadentials, that are passed to rm are processed properly.""" + """Credentials, that are passed to rm are processed properly.""" url = "https://url" httpx_mock.add_callback(check_credentials_callback, url=auth_url) @@ -76,7 +76,7 @@ def test_rm_token_cache( provider_url: str, access_token: str, ) -> None: - """Creadentials, that are passed to rm are processed properly.""" + """Credentials, that are passed to rm are processed properly.""" url = "https://url" httpx_mock.add_callback(check_credentials_callback, url=auth_url)