Merge pull request #13519 from jmchilton/no_implicit_optional

Disable implicit optional types.
This commit is contained in:
Björn Grüning
2022-03-21 15:11:24 +03:00
committed by GitHub
16 changed files with 126 additions and 34 deletions
+2 -1
View File
@@ -7,6 +7,7 @@ import os
from typing import (
Dict,
List,
Optional,
Type,
TypeVar,
)
@@ -526,7 +527,7 @@ class _UnflattenedMetadataDatasetAssociationSerializer(base.ModelSerializer[T],
# because of that: we need to add a few keys that will use the default serializer
self.serializable_keyset.update(["name", "state", "tool_version", "extension", "visible", "dbkey"])
def _proxy_to_dataset(self, serializer: base.Serializer = None, proxy_key=None):
def _proxy_to_dataset(self, serializer: Optional[base.Serializer] = None, proxy_key: Optional[str] = None):
# dataset associations are (rough) proxies to datasets - access their serializer using this remapping fn
# remapping done by either kwarg key: IOW dataset attr key (e.g. uuid)
# or by kwarg serializer: a function that's passed in (e.g. permissions)
+2 -1
View File
@@ -8,6 +8,7 @@ galaxy-data.
import os
import shutil
import tempfile
from typing import Optional
from galaxy import (
model,
@@ -76,7 +77,7 @@ class GalaxyDataTestApp:
model: GalaxyModelMapping
security_agent: GalaxyRBACAgent
def __init__(self, config: GalaxyDataTestConfig = None, **kwd):
def __init__(self, config: Optional[GalaxyDataTestConfig] = None, **kwd):
config = config or GalaxyDataTestConfig(**kwd)
self.config = config
self.security = config.security
+8 -3
View File
@@ -8,7 +8,10 @@ import shlex
import shutil
import sys
import tempfile
from typing import List
from typing import (
List,
Optional,
)
import packaging.version
@@ -305,7 +308,7 @@ class CondaContext(installable.InstallableContext):
stdout_path = "/dev/null"
return self.exec_command("clean", clean_args, stdout_path=stdout_path)
def exec_search(self, args: List[str], json: bool = False, offline: bool = False, platform: str = None):
def exec_search(self, args: List[str], json: bool = False, offline: bool = False, platform: Optional[str] = None):
"""
Search conda channels for a package
@@ -513,7 +516,9 @@ def cleanup_failed_install(conda_target, conda_context=None):
cleanup_failed_install_of_environment(conda_target.install_environment, conda_context=conda_context)
def best_search_result(conda_target, conda_context: CondaContext, offline: bool = False, platform: str = None):
def best_search_result(
conda_target, conda_context: CondaContext, offline: bool = False, platform: Optional[str] = None
):
"""Find best "conda search" result for specified target.
Return ``None`` if no results match.
+15 -3
View File
@@ -1,4 +1,5 @@
"""This module contains a linting functions for tool tests."""
import typing
from inspect import (
Parameter,
signature,
@@ -118,12 +119,16 @@ def _check_asserts(test_idx, assertions, lint_ctx):
if attrib not in assert_function_sig.parameters:
lint_ctx.error(f"Test {test_idx}: unknown attribute '{attrib}' for '{a.tag}'", node=a)
continue
if assert_function_sig.parameters[attrib].annotation is not Parameter.empty:
annotation = assert_function_sig.parameters[attrib].annotation
annotation = _handle_optionals(annotation)
if annotation is not Parameter.empty:
try:
assert_function_sig.parameters[attrib].annotation(a.attrib[attrib])
annotation(a.attrib[attrib])
except TypeError:
raise Exception(f"Faild to instantiate {attrib} for {assert_function_name}")
except ValueError:
lint_ctx.error(
f"Test {test_idx}: attribute '{attrib}' for '{a.tag}' needs to be '{assert_function_sig.parameters[attrib].annotation.__name__}' got '{a.attrib[attrib]}'",
f"Test {test_idx}: attribute '{attrib}' for '{a.tag}' needs to be '{annotation.__name__}' got '{a.attrib[attrib]}'",
node=a,
)
# check missing required attributes
@@ -141,6 +146,13 @@ def _check_asserts(test_idx, assertions, lint_ctx):
lint_ctx.error(f"Test {test_idx}: '{a.tag}' needs to specify 'n', 'min', or 'max'", node=a)
def _handle_optionals(annotation):
as_dict = annotation.__dict__
if "__origin__" in as_dict and as_dict["__origin__"] == typing.Union:
return as_dict["__args__"][0]
return annotation
def _collect_output_names(tool_xml):
output_data_names = []
output_collection_names = []
@@ -3,6 +3,7 @@ import re
import tarfile
import tempfile
import zipfile
from typing import Optional
from galaxy.util import asbool
from ._util import _assert_presence_number
@@ -55,10 +56,10 @@ def assert_has_archive_member(
verify_assertions_function,
children,
all="false",
n: int = None,
n: Optional[int] = None,
delta: int = 0,
min: int = None,
max: int = None,
min: Optional[int] = None,
max: Optional[int] = None,
negate: bool = False,
):
"""Recursively checks the specified children assertions against the text of
+8 -1
View File
@@ -1,8 +1,15 @@
from typing import Optional
from ._util import _assert_number
def assert_has_size(
output_bytes, value: int = None, delta: int = 0, min: int = None, max: int = None, negate: bool = False
output_bytes,
value: Optional[int] = None,
delta: int = 0,
min: Optional[int] = None,
max: Optional[int] = None,
negate: bool = False,
):
"""
Asserts the specified output has a size of the specified value,
@@ -1,4 +1,5 @@
import re
from typing import Optional
from ._util import _assert_number
@@ -18,7 +19,14 @@ def get_first_line(output, comment):
def assert_has_n_columns(
output, n: int = None, delta: int = 0, min: int = None, max: int = None, sep="\t", comment="", negate: bool = False
output,
n: Optional[int] = None,
delta: int = 0,
min: Optional[int] = None,
max: Optional[int] = None,
sep="\t",
comment="",
negate: bool = False,
):
"""Asserts the tabular output contains n columns. The optional
sep argument specifies the column seperator used to determine the
+37 -5
View File
@@ -1,4 +1,5 @@
import re
from typing import Optional
from ._util import (
_assert_number,
@@ -7,7 +8,13 @@ from ._util import (
def assert_has_text(
output, text, n: int = None, delta: int = 0, min: int = None, max: int = None, negate: bool = False
output,
text,
n: Optional[int] = None,
delta: int = 0,
min: Optional[int] = None,
max: Optional[int] = None,
negate: bool = False,
):
"""Asserts specified output contains the substring specified by
the argument text. The exact number of occurrences can be
@@ -37,7 +44,13 @@ def assert_not_has_text(output, text):
def assert_has_line(
output, line, n: int = None, delta: int = 0, min: int = None, max: int = None, negate: bool = False
output,
line,
n: Optional[int] = None,
delta: int = 0,
min: Optional[int] = None,
max: Optional[int] = None,
negate: bool = False,
):
"""Asserts the specified output contains the line specified by the
argument line. The exact number of occurrences can be optionally
@@ -59,7 +72,14 @@ def assert_has_line(
)
def assert_has_n_lines(output, n: int = None, delta: int = 0, min: int = None, max: int = None, negate: bool = False):
def assert_has_n_lines(
output,
n: Optional[int] = None,
delta: int = 0,
min: Optional[int] = None,
max: Optional[int] = None,
negate: bool = False,
):
"""Asserts the specified output contains ``n`` lines allowing
for a difference in the number of lines (delta)
or relative differebce in the number of lines"""
@@ -78,7 +98,13 @@ def assert_has_n_lines(output, n: int = None, delta: int = 0, min: int = None, m
def assert_has_text_matching(
output, expression, n: int = None, delta: int = 0, min: int = None, max: int = None, negate: bool = False
output,
expression,
n: Optional[int] = None,
delta: int = 0,
min: Optional[int] = None,
max: Optional[int] = None,
negate: bool = False,
):
"""Asserts the specified output contains text matching the
regular expression specified by the argument expression.
@@ -102,7 +128,13 @@ def assert_has_text_matching(
def assert_has_line_matching(
output, expression, n: int = None, delta: int = 0, min: int = None, max: int = None, negate: bool = False
output,
expression,
n: Optional[int] = None,
delta: int = 0,
min: Optional[int] = None,
max: Optional[int] = None,
negate: bool = False,
):
"""Asserts the specified output contains a line matching the
regular expression specified by the argument expression. If n is given
+11 -4
View File
@@ -1,4 +1,5 @@
import re
from typing import Optional
from lxml.etree import XMLSyntaxError
@@ -28,7 +29,13 @@ def assert_has_element_with_path(output, path, negate: bool = False):
def assert_has_n_elements_with_path(
output, path, n: int = None, delta: int = 0, min: int = None, max: int = None, negate: bool = False
output,
path,
n: Optional[int] = None,
delta: int = 0,
min: Optional[int] = None,
max: Optional[int] = None,
negate: bool = False,
):
"""Asserts the specified output has exactly n elements matching the
path specified."""
@@ -74,10 +81,10 @@ def assert_xml_element(
children=None,
attribute=None,
all=False,
n: int = None,
n: Optional[int] = None,
delta: int = 0,
min: int = None,
max: int = None,
min: Optional[int] = None,
max: Optional[int] = None,
negate: bool = False,
):
"""
+7 -1
View File
@@ -11,6 +11,7 @@ import urllib.parse
import zipfile
from json import dumps
from logging import getLogger
from typing import Optional
import requests
from packaging.version import parse as parse_version
@@ -810,7 +811,12 @@ class GalaxyInteractorApi:
return urllib.parse.urljoin(f"{self.api_url}/", path)
def _prepare_request_params(
self, data=None, files=None, as_json: bool = False, params: dict = None, headers: dict = None
self,
data=None,
files=None,
as_json: bool = False,
params: Optional[dict] = None,
headers: Optional[dict] = None,
):
"""Handle some Galaxy conventions and work around requests issues.
@@ -998,7 +998,9 @@ class HistoryContentsController(BaseGalaxyAPIController, UsesLibraryMixinItems,
# return self.hda_manager.serialize_dataset_association_roles(trans, hda)
@expose_api
def update_permissions(self, trans, history_id, history_content_id, payload: Dict[str, Any] = None, **kwd):
def update_permissions(
self, trans, history_id, history_content_id, payload: Optional[Dict[str, Any]] = None, **kwd
):
"""
Set permissions of the given library dataset to the given role ids.
+3 -1
View File
@@ -303,7 +303,9 @@ class LibrariesController(BaseGalaxyAPIController):
return self.service.update(trans, id, update_payload)
@expose_api
def delete(self, trans: ProvidesUserContext, id: EncodedDatabaseIdField, payload: Dict[str, Any] = None, **kwd):
def delete(
self, trans: ProvidesUserContext, id: EncodedDatabaseIdField, payload: Optional[Dict[str, Any]] = None, **kwd
):
"""
* DELETE /api/libraries/{id}
marks the library with the given ``id`` as `deleted` (or removes the `deleted` mark if the `undelete` param is true)
+6 -3
View File
@@ -1,4 +1,7 @@
from typing import List
from typing import (
List,
Optional,
)
from galaxy_test.base.populators import DatasetPopulator
from ._framework import ApiTestCase
@@ -9,7 +12,7 @@ class GroupRolesApiTestCase(ApiTestCase):
super().setUp()
self.dataset_populator = DatasetPopulator(self.galaxy_interactor)
def test_index(self, group_name: str = None):
def test_index(self, group_name: Optional[str] = None):
group_name = group_name or "test-group_roles"
group = self._create_group(group_name)
encoded_group_id = group["id"]
@@ -109,7 +112,7 @@ class GroupRolesApiTestCase(ApiTestCase):
delete_response = self._delete(f"groups/{encoded_group_id}/roles/{encoded_role_id}", admin=True)
self._assert_status_code_is(delete_response, 400)
def _create_group(self, group_name: str, encoded_role_ids: List[str] = None):
def _create_group(self, group_name: str, encoded_role_ids: Optional[List[str]] = None):
if encoded_role_ids is None:
encoded_role_ids = [self.dataset_populator.user_private_role_id()]
role_ids = encoded_role_ids
+6 -3
View File
@@ -1,4 +1,7 @@
from typing import List
from typing import (
List,
Optional,
)
from galaxy_test.base.populators import DatasetPopulator
from ._framework import ApiTestCase
@@ -9,7 +12,7 @@ class GroupUsersApiTestCase(ApiTestCase):
super().setUp()
self.dataset_populator = DatasetPopulator(self.galaxy_interactor)
def test_index(self, group_name: str = None):
def test_index(self, group_name: Optional[str] = None):
group_name = group_name or "test-group_users"
group = self._create_group(group_name)
encoded_group_id = group["id"]
@@ -109,7 +112,7 @@ class GroupUsersApiTestCase(ApiTestCase):
delete_response = self._delete(f"groups/{encoded_group_id}/users/{encoded_user_id}", admin=True)
self._assert_status_code_is(delete_response, 400)
def _create_group(self, group_name: str, encoded_user_ids: List[str] = None):
def _create_group(self, group_name: str, encoded_user_ids: Optional[List[str]] = None):
if encoded_user_ids is None:
encoded_user_ids = [self.dataset_populator.user_id()]
user_ids = encoded_user_ids
+4 -2
View File
@@ -1,3 +1,5 @@
from typing import Optional
from galaxy_test.base.populators import DatasetPopulator
from ._framework import ApiTestCase
@@ -7,7 +9,7 @@ class GroupsApiTestCase(ApiTestCase):
super().setUp()
self.dataset_populator = DatasetPopulator(self.galaxy_interactor)
def test_create_valid(self, group_name: str = None):
def test_create_valid(self, group_name: Optional[str] = None):
payload = self._build_valid_group_payload(group_name)
response = self._post("groups", payload, admin=True, json=True)
self._assert_status_code_is(response, 200)
@@ -102,7 +104,7 @@ class GroupsApiTestCase(ApiTestCase):
if assert_id is not None:
assert group["id"] == assert_id
def _build_valid_group_payload(self, name: str = None):
def _build_valid_group_payload(self, name: Optional[str] = None):
name = name or self.dataset_populator.get_random_name()
user_id = self.dataset_populator.user_id()
role_id = self.dataset_populator.user_private_role_id()
+1 -1
View File
@@ -19,6 +19,7 @@ check_untyped_defs = True
exclude = lib/galaxy/tools/bundled|test/functional
pretty = True
no_implicit_reexport = True
no_implicit_optional = True
[mypy-galaxy.util.oset]
# lots of tricky code in here...
@@ -221,7 +222,6 @@ disallow_untyped_defs = True
disallow_incomplete_defs = True
check_untyped_defs = True
disallow_untyped_decorators = True
no_implicit_optional = True
warn_unused_ignores = True
warn_return_any = True
strict_equality = True