Skip to content
Closed
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
9f84ad7
add placeholders
MJoshuaB Aug 11, 2024
c81ff56
add new placeholder comments
MJoshuaB Aug 20, 2024
18762be
exploring AST unfinished - minor emergency had to leave
Aug 21, 2024
2238161
identifying some mismatched functions
Aug 28, 2024
46053e6
fine tuning and testing required
Aug 29, 2024
27edb80
minimal tests added
Sep 3, 2024
112173d
Merge pull request #2 from Azure/main
JessicaBell00 Sep 8, 2024
c5ffb91
Merge branch 'Azure:main' into main
JessicaBell00 Sep 10, 2024
7dc03ca
Merge branch 'working-main' into main
JessicaBell00 Sep 12, 2024
18f09e9
Merge pull request #5 from MJoshuaB/main
JessicaBell00 Sep 12, 2024
af098f7
Merge branch 'Azure:main' into working-main
JessicaBell00 Sep 12, 2024
6e53b16
Final Refactor
Sep 17, 2024
80657b4
not running multiple times picking up on different function types
Sep 19, 2024
5b69e7e
Merge branch 'main' into invalid-use-of-@overload
16234397 Sep 19, 2024
a0e5c18
removed code not reached
Sep 24, 2024
bf6936c
Merge remote-tracking branch 'origin/invalid-use-of-@overload' into i…
Sep 24, 2024
3ed8120
Checks at a class level
Sep 24, 2024
ac9921a
Merge branch 'main' into invalid-use-of-@overload
16234397 Sep 24, 2024
4c638df
Looking into different connection_verify assignments
Sep 25, 2024
ab62179
Placeholders added back
16234397 Sep 26, 2024
795c861
Checker base done
Sep 26, 2024
a835da4
Checker, Tests, & Readme done
Sep 29, 2024
efe6ddc
Merge branch 'main' into working-main
MJoshuaB Oct 1, 2024
c50a082
Merge branch 'working-main' into do-not-hardcode-boolean-connection_v…
16234397 Oct 5, 2024
24e9647
Merge pull request #10 from MJoshuaB/do-not-hardcode-boolean-connecti…
16234397 Oct 5, 2024
1f78550
Merge branch 'working-main' into invalid-use-of-@overload
16234397 Oct 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ In the case of a false positive, use the disable command to remove the pylint er
| docstring-keyword-should-match-keyword-only | Docstring keyword arguments and keyword-only method arguments should match. | pylint:disable=docstring-keyword-should-match-keyword-only | [link](https://azure.github.io/azure-sdk/python_documentation.html#docstrings) |
| docstring-type-do-not-use-class | Docstring type is formatted incorrectly. Do not use `:class` in docstring type. | pylint:disable=docstring-type-do-not-use-class | [link](https://sphinx-rtd-tutorial.readthedocs.io/en/latest/docstrings.html) |
| no-typing-import-in-type-check | Do not import typing under TYPE_CHECKING. | pylint:disable=no-typing-import-in-type-check | No Link. |
| invalid-use-of-overload | Do not mix async and synchronous overloads | pylint:disable=invalid-use-of-overload | No Link. |
| do-not-log-raised-errors | Do not log errors at `error` or `warning` level when error is raised in an exception block. | pylint:disable=do-not-log-raised-errors | No Link. |
| do-not-use-legacy-typing | Do not use legacy (<Python 3.8) type hinting comments | pylint:disable=do-not-use-legacy-typing | No Link.
| do-not-import-asyncio | Do not import asyncio directly. | pylint:disable=do-not-import-asyncio | No Link. |
| do-not-import-asyncio | Do not import asyncio directly. | pylint:disable=do-not-import-asyncio | No Link. |
Original file line number Diff line number Diff line change
Expand Up @@ -2807,6 +2807,79 @@ def visit_import(self, node):
pass


class InvalidUseOfOverload(BaseChecker):
"""Rule to check that use of the @overload decorator matches the async/sync nature of the underlying function"""

name = "invalid-use-of-overload"
priority = -1
msgs = {
"C4765": (
"Do not mix async and synchronous overloads",
"invalid-use-of-overload",
"Functions and their overloads must be either all async or all synchronous.",
),
}

def visit_module(self, node):
"""Check that use of the @overload decorator matches the async/sync nature of the underlying function"""
try:
klass = node.parent.parent.parent
except: #For testing purposes
klass = node

# Obtain a list of all functions and function names
functions = []
try:
klass.body
for item in klass.body:
if hasattr(item, 'name'):
functions.append(item)

# Dictionary of lists of all functions by name
overloadedfunctions = {}
for item in functions:
if item.name in overloadedfunctions:
overloadedfunctions[item.name].append(item)
else:
overloadedfunctions[item.name] = [item]


# Loop through the overloaded functions and check they are the same type
for funct in overloadedfunctions.values():
if len(funct) > 1: # only need to check if there is more than 1 function with the same name
function_is_async = None

for item in funct:
if function_is_async is None:
function_is_async = self.is_function_async(item)

else:
if function_is_async != self.is_function_async(item):
self.add_message(
msgid=f"invalid-use-of-overload",
node=item,
confidence=None,
)
except:
pass


def is_function_async(self, node):
try:
str(node.__class__).index("Async")
return True
except:
if node.returns is None:
return False
try:
if node.returns.value.name == "Awaitable":
return True
else:
return False
except:
return False


class DoNotUseLegacyTyping(BaseChecker):

""" Rule to check that we aren't using legacy typing using comments. """
Expand Down Expand Up @@ -2865,8 +2938,6 @@ def visit_import(self, node):
)




# if a linter is registered in this function then it will be checked with pylint
def register(linter):
linter.register_checker(ClientsDoNotUseStaticMethods(linter))
Expand Down Expand Up @@ -2900,6 +2971,7 @@ def register(linter):
linter.register_checker(DoNotImportAsyncio(linter))
linter.register_checker(NoLegacyAzureCoreHttpResponseImport(linter))
linter.register_checker(NoImportTypingFromTypeCheck(linter))
linter.register_checker(InvalidUseOfOverload(linter))
linter.register_checker(DoNotUseLegacyTyping(linter))


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Test file for InvalidUseOfOverload checker

from typing import Awaitable, overload, Union


@overload
def double(a: str) -> Awaitable[int]:
...

@overload
def double(a: int) -> Awaitable[int]:
...

async def double(a: Union[str, int]) -> int:
if isinstance(a, str):
return len(a)*2
return a * 2


@overload
def single(a: str):
...

@overload
def single(a: int):
...

def single(a: Union[str, int]) -> int:
if isinstance(a, str):
return len(a)
return a
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Test file for InvalidUseOfOverload checker - testing what mypy doesn't pick up

from typing import Awaitable, overload, Union


@overload
def double(a: str) -> Awaitable[int]:
...

@overload
def double(a: int):
...

async def double(a: Union[str, int]) -> int:
if isinstance(a, str):
return len(a)*2
return a * 2


@overload
def doubleAgain(a: str):
...

@overload
def doubleAgain(a: int):
...

async def doubleAgain(a: Union[str, int]) -> int:
if isinstance(a, str):
return len(a)*2
return a * 2
Original file line number Diff line number Diff line change
Expand Up @@ -4844,6 +4844,52 @@ def test_allowed_import_else(self):
self.checker.visit_import(imc)
self.checker.visit_importfrom(imd)

class TestInvalidUseOfOverload(pylint.testutils.CheckerTestCase):
"""Test that use of the @overload decorator matches the async/sync nature of the underlying function"""

CHECKER_CLASS = checker.InvalidUseOfOverload

def test_valid_use_overload(self):
file = open(
os.path.join(
TEST_FOLDER, "test_files", "invalid_use_of_overload_acceptable.py"
)
)
node = astroid.parse(file.read())
file.close()
with self.assertNoMessages():
self.checker.visit_module(node)


def test_invalid_use_overload(self):
file = open(
os.path.join(
TEST_FOLDER, "test_files", "invalid_use_of_overload_violation.py"
)
)
node = astroid.parse(file.read())
file.close()
children = list(node.get_children())
with self.assertAddsMessages(
pylint.testutils.MessageTest(
msg_id="invalid-use-of-overload",
line=11,
node=children[2],
col_offset=0,
end_line=11,
end_col_offset=10,
),
pylint.testutils.MessageTest(
msg_id="invalid-use-of-overload",
line=28,
node=children[6],
col_offset=0,
end_line=28,
end_col_offset=21,
),
):
self.checker.visit_module(node)



class TestDoNotImportAsyncio(pylint.testutils.CheckerTestCase):
Expand Down