From 1825816fc2a032ed8ae032c761109816e63fbf67 Mon Sep 17 00:00:00 2001 From: David Ruiz Falco Date: Fri, 3 Jan 2025 16:41:14 +0100 Subject: [PATCH] ruff --- nuclia_e2e/pyproject.toml | 121 ++-------------------------- nuclia_e2e/tests/conftest.py | 26 +++--- nuclia_e2e/tests/test_kb.py | 21 ++--- nuclia_e2e/tests/test_onboarding.py | 10 +-- 4 files changed, 35 insertions(+), 143 deletions(-) diff --git a/nuclia_e2e/pyproject.toml b/nuclia_e2e/pyproject.toml index f8e1d72..0786972 100644 --- a/nuclia_e2e/pyproject.toml +++ b/nuclia_e2e/pyproject.toml @@ -76,119 +76,14 @@ lint.ignore = [ "ISC002", # multi-line-implicit-string-concatenation () # TODO: Remove these rules from ignore list after fixing them - "PGH004", # Use specific rule codes when using `noqa` - "PT003", # scope=function is implied in `@pytest.fixture()` - "B006", # Do not use mutable data structures for argument defaults" - "BLE001", # Do not catch blind exception: `Exception` - "TRY003", # Avoid specifying long messages outside the exception class - "TRY002", # Create your own exception - "EM102", # Exception must not use an f-string literal, assign to variable first - "PTH", # Ignore path library recommendations - "ERA001", # Found commented-out code - "S113", # Probable use of requests call without timeout - "PLR2004", # Magic value used in comparison, ... - "PLR0913", # Too many arguments ignored - "PLR0915", # Too many statements ignored - "N818", # Exception name - "SIM117", # Use a single `with` statement with multiple contexts instead of nested `with` statements - "FBT001", # Boolean-typed positional argument in function definition" - "FBT002", # Boolean-typed positional argument in function definition" - "PLW0603", # Using the global statement to update `X` is discouraged - "E721", # Do not compare types, use `isinstance()` - "E501", # Line too long - "PLR0912", # Too many branches - "C901", # Code is too complex - "PGH003", # Use specific rule codes when ignoring type issues - "B904", # exceptions things - "RUF012", # Mutable class attributes should be annotated with `typing.ClassVar` - "N805", # First argument of a method should be named `self` - "N802", # Function name `Chat` should be lowercase - "N803", # Argument name `backupCount` should be lowercase - "SLF001", # Private member accessed - "PYI036", - "N801", # Class name `X` should use CapWords convention - "N816", # Variable `X` in global scope should not be mixedCase - "G004", # Logging statement uses f-string - "UP006", # Use `dict` instead of `Dict` for type annotation - "UP035", # `typing.List` is deprecated, use `list` instead - "SIM401", # Use `x.get("y", z)` instead of an `if` block - "PT023", # Use `@pytest.mark.asyncio()` over `@pytest.mark.asyncio` - "F541", # f-string without any placeholders - "PT022", # No teardown in fixture `nats_consumer_factory`, use `return` instead of `yield` - "INP001", # add __init__.py - "RET505", # Unnecessary `else` after `return` statement - "TC002", # Move third-party import `X` into a type-checking block - "SIM115", # Use context handler for opening files - "C408", # Unnecessary `dict` call (rewrite as a literal) - "PT024", # `pytest.mark.asyncio` is unnecessary for fixtures - "C417", # Unnecessary `map` usage - "S104", # Possible binding to all interfaces - "UP026", # `mock` is deprecated, use `unittest.mock` - "UP031", # Use format specifiers instead of percent format - "TRY201", # Use `raise` without specifying exception name - "TRY203", # Remove exception handler; error is immediately re-raised - "B011", # Do not `assert False` (`python -O` removes these calls), raise `AssertionError()` - "PT015", # Assertion always fails, replace with `pytest.fail()` - "E722", # Do not use bare `except` - "SIM300", # Yoda conditions are discouraged, use `data2 == "a response"` instead - "UP032", # Use f-string instead of `format` call - "SIM118", # Use `key not in dict` instead of `key not in dict.keys()` - "PT001", # Use `@pytest.fixture()` over `@pytest.fixture` - "TRY300", # Consider moving this statement to an `else` block - "SIM102", # Use a single `if` statement instead of nested `if` statements - "UP004", # Class `Gnatsd` inherits from `object` - "EM101", # Exception must not use a string literal, assign to variable first - "RUF010", # Use explicit conversion flag - "RSE102", # Unnecessary parentheses on raised exception - "RUF100", # Unused blanket `noqa` directive - "S324", # Probable use of insecure hash functions in `hashlib`: `md5` - "RUF013", # PEP 484 prohibits implicit `Optional` - "SIM108", # Use ternary operator `bucket = self.bucket if self.field is None else self.field.bucket_name` instead of `if`-`else`-block - "S101", # Use of `assert` detected - "RET504", # Unnecessary assignment to `deleted` before `return` statement - "RET506", # Unnecessary `else` after `raise` statement - "TC003", # Move standard library import `concurrent.futures.ThreadPoolExecutor` into a type-checking block - "UP009", # UTF-8 encoding declaration is unnecessary - "S110", # `try`-`except`-`pass` detected, consider logging the exception - "RET503", # Missing explicit `return` at the end of function able to return non-`None` value - "PLW2901", # `for` loop variable `value` overwritten by assignment target - "TID252", # Prefer absolute imports over relative imports - "PLC0414", # Import alias does not rename original package - "S301", # `pickle` and modules that wrap it can be unsafe when used to deserialize untrusted data, possible security issue - "F841", # Local variable `info_account_user_id` is assigned to but never used - "T201", #`print` found - "UP007", # Use `X | Y` for type annotations - "PLR1714", # Consider merging multiple comparisons - "B007", # Loop control variable `idx` not used within loop body - "SIM110", # Use `return any(scope in conn.auth.scopes for scope in scopes)` instead of `for` loop - "W291", # Trailing whitespace - "SIM113", # Use `enumerate()` for index variable `count` in `for` loop - "RET502", # Do not implicitly `return None` in function able to return non-`None` value - "UP030", # Use implicit references for positional format fields - "RUF015", # Prefer `next(iter(mock_aiohttp.requests.values()))` over single element slice - "SIM114", # Combine `if` branches using logical `or` operator - "PT018", # Assertion should be broken down into multiple parts - "RUF005", # Consider `[key, *values, str(int(time.time() // ttl))]` instead of concatenation - "UP039", # Unnecessary parentheses after class definition - "C416", # Unnecessary `list` comprehension (rewrite using `list()`) - "S105", # Possible hardcoded password assigned to: "TOKEN" - "PLR0911", # Too many return statements (7 > 6) - "B009", # Do not call `getattr` with a constant attribute value. - "PT017", # Found assertion on exception `r` in `except` block, use `pytest.raises()` instead - "TC001", # Move application import `stashify_idp.authorizer.db.IDPRegionalDatabaseUtility` into a type-checking block - "C401", # Unnecessary generator (rewrite as a `set` comprehension) - "UP015", # Unnecessary open mode parameters - "B023", # Function definition does not bind loop variable `assets` - "C403", # Unnecessary `list` comprehension (rewrite as a `set` comprehension) - "C419", # Unnecessary list comprehension - "PLR0402", # [*] Use `from nuclia_accounting import tables` in lieu of alias - "RUF002", # Docstring contains ambiguous `’` (RIGHT SINGLE QUOTATION MARK). Did you mean ``` (GRAVE ACCENT)? - "N806", # Variable `rolloverAt` in function should be lowercase - "PLR0402", # [*] Use `from nuclia_external_auth import oauth` in lieu of alias - "B026", # Star-arg unpacking after a keyword argument is strongly discouraged - "PLR1711", # Useless `return` statement at end of function - "SIM910", # Use `dict.get()` without default value - "F601", # Dictionary key literal `"resources_processed"` repeated + "ERA001", + "PLR2004", + "T201", + "BLE001", + "PT004", + "RET504", + "SIM102", + "B007", ] exclude = [ diff --git a/nuclia_e2e/tests/conftest.py b/nuclia_e2e/tests/conftest.py index 8bc9f77..8d62cf7 100644 --- a/nuclia_e2e/tests/conftest.py +++ b/nuclia_e2e/tests/conftest.py @@ -6,6 +6,7 @@ from nuclia.data import get_auth from nuclia.data import get_config from nuclia.sdk.kbs import NucliaKBS +from nuclia_e2e.tests.data import TEST_ACCOUNT_SLUG import aiohttp import asyncio @@ -19,12 +20,10 @@ import string import tempfile -from .data import TEST_ACCOUNT_SLUG - TEST_ENV = os.environ.get("TEST_ENV") -# All tests that needs some existing account will use the one configured in the global "permanent_account_slug" -# with some predefined user credentials without expiration: +# All tests that needs some existing account will use the one configured in +# the global "permanent_account_slug" with some predefined user credentials without expiration: # "permanent_account_owner_pat": PAT token for `testing_sdk@nuclia.com` on the suitable account CLUSTERS_CONFIG = { @@ -136,7 +135,8 @@ async def send_onboard_inquiry(self, data): async def create_account(self, slug): if not self.access_token: - raise ValueError("Access token is not set. Please provide an access token.") + msg = "Access token is not set. Please provide an access token." + raise ValueError(msg) url = f"{self.base_url}/api/v1/accounts" async with self.session.post( url, json={"slug": slug, "title": slug}, headers=self.auth_headers @@ -168,7 +168,7 @@ def global_api(aiohttp_session): ) -@pytest.fixture(scope="function") +@pytest.fixture() def global_api_config(): global_config = CLUSTERS_CONFIG[TEST_ENV]["global"] nuclia.BASE = global_config["base_url"] @@ -182,7 +182,6 @@ def global_api_config(): @pytest.fixture( - scope="function", params=[pytest.param(zone, id=zone["name"]) for zone in CLUSTERS_CONFIG[TEST_ENV]["zones"]], ) def regional_api_config(request, global_api_config): @@ -194,7 +193,7 @@ def regional_api_config(request, global_api_config): config.set_default_account(global_api_config["permanent_account_slug"]) config.set_default_zone(zone_config["zone_slug"]) zone_config["test_kb_slug"] = "{test_kb_slug}-{name}".format(**zone_config) - yield zone_config + return zone_config class EmailUtil: @@ -261,7 +260,7 @@ async def get_last_email_body(self, test_address): async def wait_for_email_signup_link(self, email_address, max_wait_time=20): print(f"waiting 10 seconds for signup email at {email_address}") signup_url = None - for i in range(max_wait_time): + for _ in range(max_wait_time): print("still waiting...") await asyncio.sleep(1) body = await self.get_last_email_body(email_address) @@ -276,11 +275,10 @@ async def wait_for_email_signup_link(self, email_address, max_wait_time=20): @pytest.fixture(scope="session") def email_util(): - util = EmailUtil("carles@nuclia.com", "oynpctapnzwqjxol") - return util + return EmailUtil("carles@nuclia.com", "oynpctapnzwqjxol") -@pytest.fixture(scope="function") +@pytest.fixture() async def cleanup_test_account(global_api: GlobalAPI): await global_api.manager.delete_account(TEST_ACCOUNT_SLUG) @@ -289,7 +287,7 @@ async def cleanup_test_account(global_api: GlobalAPI): await global_api.manager.delete_account(TEST_ACCOUNT_SLUG) -@pytest.fixture(scope="function") +@pytest.fixture() async def clean_kb_test(request, regional_api_config): kbs = NucliaKBS() try: @@ -297,5 +295,3 @@ async def clean_kb_test(request, regional_api_config): except ValueError: # Raised by sdk when kb not found pass - - yield diff --git a/nuclia_e2e/tests/test_kb.py b/nuclia_e2e/tests/test_kb.py index cae193e..dc1578a 100644 --- a/nuclia_e2e/tests/test_kb.py +++ b/nuclia_e2e/tests/test_kb.py @@ -1,3 +1,4 @@ +from collections.abc import Coroutine from datetime import datetime from datetime import timedelta from datetime import timezone @@ -23,7 +24,6 @@ from pathlib import Path from time import monotonic from typing import Any -from typing import Coroutine import asyncio import backoff @@ -189,7 +189,8 @@ async def condition() -> tuple[bool, Any]: continue for fc in res.computedmetadata.field_classifications: if fc.field.field_type.name == "GENERIC": - # in case only generic fields are found, result won't be ever trur and condition will fail. + # in case only generic fields are found, + # result won't be ever true and condition will fail. continue # heuristic, but si@pytest.mark.asynciomple enough for now, @@ -310,13 +311,13 @@ async def condition() -> tuple[bool, Any]: partial( kb.logs.query, type=EventType.CHAT, - query=ActivityLogsChatQuery(year_month="{dt.year}-{dt.month}".format(dt=now), filters={}), + query=ActivityLogsChatQuery(year_month=f"{now.year}-{now.month}", filters={}), ) ) if len(logs.data) >= 2: # as the asks may be retried more than once (because some times rephrase doesn't always work) - # we need to check the last logs. The way the tests are setup if we reach here is because we validated - # that we got the expected results on ask, so the log should match this reasoning. + # we need to check the last logs. The way the tests are setup if we reach here is because we + # validated that we got the expected results on ask, so the log should match this reasoning. if logs.data[-2].question == "why cocoa prices high?" and logs.data[-1].question == "when?": return (True, logs) return (False, None) @@ -331,7 +332,7 @@ async def condition() -> tuple[bool, Any]: partial( kb.logs.query, type=EventType.SEARCH, - query=ActivityLogsSearchQuery(year_month="{dt.year}-{dt.month}".format(dt=now), filters={}), + query=ActivityLogsSearchQuery(year_month=f"{now.year}-{now.month}", filters={}), ) ) assert logs.data[-1].question == "why cocoa prices high?" @@ -346,7 +347,7 @@ async def run_test_kb_deletion(regional_api_config): assert kbid is None -@pytest.mark.asyncio_cooperative +@pytest.mark.asyncio_cooperative() async def test_kb(regional_api_config, clean_kb_test): """ Test a chain of operations that simulates a normal use of a knowledgebox, just concentrated @@ -375,9 +376,9 @@ async def test_kb(regional_api_config, clean_kb_test): # Upload a new resource and validate that is correctly processed and stored in nuclia (await run_test_upload_and_process(regional_api_config),) - # Wait for both labeller task results to be consolidated in nucliadb while we also run semantic search - # and a generative question. This /find and /ask requests are crafted so they trigger all the existing calls - # to predict features + # Wait for both labeller task results to be consolidated in nucliadb while we also run semantic search + # and a generative question. This /find and /ask requests are crafted so they trigger + # all the existing calls to predict features await asyncio.gather( run_test_check_da_labeller_output(regional_api_config), run_test_find(regional_api_config), diff --git a/nuclia_e2e/tests/test_onboarding.py b/nuclia_e2e/tests/test_onboarding.py index 9dbe15b..4ece819 100644 --- a/nuclia_e2e/tests/test_onboarding.py +++ b/nuclia_e2e/tests/test_onboarding.py @@ -1,11 +1,11 @@ +from nuclia_e2e.tests.data import TEST_ACCOUNT_SLUG +from nuclia_e2e.tests.data import TEST_ONBOARD_INQUIRY + import pytest -from .data import TEST_ONBOARD_INQUIRY, TEST_ACCOUNT_SLUG -@pytest.mark.asyncio_cooperative -async def test_onboarding( - request, global_api, email_util, cleanup_test_account, aiohttp_session -): +@pytest.mark.asyncio_cooperative() +async def test_onboarding(request, global_api, email_util, cleanup_test_account, aiohttp_session): # Request signup using a random alias email test_alias_email = email_util.generate_email_address() test_password = "notarealpassword"