Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[pylint] wrap excepts #9683

Merged
merged 2 commits into from
Jan 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
@@ -1,5 +1,9 @@
# Release History

## 0.5.1 (2025-01-23)

- Bug Fix for connection_verify rule

## 0.5.0 (2025-01-06)

- Added `httpx` as an import flagged by C4749(networking-import-outside-azure-core-transport)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2835,12 +2835,15 @@ class DoNotUseLegacyTyping(BaseChecker):

def visit_functiondef(self, node):
"""Check that we aren't using legacy typing."""
if node.type_comment_args or node.type_comment_returns:
self.add_message(
msgid=f"do-not-use-legacy-typing",
node=node,
confidence=None,
)
try:
if node.type_comment_args or node.type_comment_returns:
self.add_message(
msgid=f"do-not-use-legacy-typing",
node=node,
confidence=None,
)
except:
pass


class DoNotImportAsyncio(BaseChecker):
Expand All @@ -2860,23 +2863,28 @@ class DoNotImportAsyncio(BaseChecker):

def visit_importfrom(self, node):
"""Check that we aren't importing from asyncio directly."""
if node.modname == "asyncio":
self.add_message(
msgid=f"do-not-import-asyncio",
node=node,
confidence=None,
)

def visit_import(self, node):
"""Check that we aren't importing asyncio."""
for name, _ in node.names:
if name == "asyncio":
try:
if node.modname == "asyncio":
self.add_message(
msgid=f"do-not-import-asyncio",
node=node,
confidence=None,
)
except:
pass

def visit_import(self, node):
"""Check that we aren't importing asyncio."""
try:
for name, _ in node.names:
if name == "asyncio":
self.add_message(
msgid=f"do-not-import-asyncio",
node=node,
confidence=None,
)
except:
pass


class InvalidUseOfOverload(BaseChecker):
Expand All @@ -2895,39 +2903,41 @@ class InvalidUseOfOverload(BaseChecker):

def visit_classdef(self, node):
"""Check that use of the @overload decorator matches the async/sync nature of the underlying function"""
try:
# Obtain a list of all functions and function names
functions = []
node.body
for item in node.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)

# Obtain a list of all functions and function names
functions = []
node.body
for item in node.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,
)
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):
Expand Down Expand Up @@ -2956,57 +2966,63 @@ def visit_try(self, node):
"""Check that exceptions aren't logged in exception blocks.
Go through exception block and branches and ensure error hasn't been logged.
"""
# Return a list of exception blocks
except_block = node.handlers
# Iterate through each exception block
for nod in except_block:
# Get exception blocks with an exception name
if nod.name is not None:
exception_name = nod.name.name
self.check_for_logging(nod.body, exception_name)
try:
# Return a list of exception blocks
except_block = node.handlers
# Iterate through each exception block
for nod in except_block:
# Get exception blocks with an exception name
if nod.name is not None:
exception_name = nod.name.name
self.check_for_logging(nod.body, exception_name)
except:
pass

def check_for_logging(self, node, exception_name):
""" Helper function - checks nodes to see if logging has occurred at all
levels.
"""
levels_matches = [".warning", ".error", ".info", ".debug"]
for j in node:
if isinstance(j, astroid.Expr):
expression = j.as_string().lower()
if any(x in expression for x in levels_matches) and "logger" in expression:
# Check for variables after strings
end_finder = expression.rfind("'")
delimiters = ["(", "{", "}", ")", "\"", ",", "'"]
if end_finder != -1:
expression_a = expression[end_finder + 1:]
# If there are variables after a string
if len(expression_a) > 1:
expression = expression_a
for delimiter in delimiters:
expression = " ".join(expression.split(delimiter))
expression1 = expression.split()
# Check for presence of exception name
for i in range(len(expression1)):
if exception_name == expression1[i]:
if i+1 < len(expression1):
# TODO: Investigate whether there are any other cases we don't want to raise a Pylint
# error
if ".__name__" not in expression1[i+1]:
try:
levels_matches = [".warning", ".error", ".info", ".debug"]
for j in node:
if isinstance(j, astroid.Expr):
expression = j.as_string().lower()
if any(x in expression for x in levels_matches) and "logger" in expression:
# Check for variables after strings
end_finder = expression.rfind("'")
delimiters = ["(", "{", "}", ")", "\"", ",", "'"]
if end_finder != -1:
expression_a = expression[end_finder + 1:]
# If there are variables after a string
if len(expression_a) > 1:
expression = expression_a
for delimiter in delimiters:
expression = " ".join(expression.split(delimiter))
expression1 = expression.split()
# Check for presence of exception name
for i in range(len(expression1)):
if exception_name == expression1[i]:
if i+1 < len(expression1):
# TODO: Investigate whether there are any other cases we don't want to raise a Pylint
# error
if ".__name__" not in expression1[i+1]:
self.add_message(
msgid=f"do-not-log-exceptions",
node=j,
confidence=None,
)
else:
self.add_message(
msgid=f"do-not-log-exceptions",
node=j,
confidence=None,
)
else:
self.add_message(
msgid=f"do-not-log-exceptions",
node=j,
confidence=None,
)
if isinstance(j, astroid.If):
self.check_for_logging(j.body, exception_name)
# Check any 'elif' or 'else' branches
self.check_for_logging(j.orelse, exception_name)
if isinstance(j, astroid.If):
self.check_for_logging(j.body, exception_name)
# Check any 'elif' or 'else' branches
self.check_for_logging(j.orelse, exception_name)
except:
pass


class DoNotHardcodeConnectionVerify(BaseChecker):
Expand All @@ -3025,15 +3041,18 @@ class DoNotHardcodeConnectionVerify(BaseChecker):

def visit_call(self, node):
"""Visit function calls to ensure it isn't used as a keyword parameter"""
if len(node.keywords) > 0:
for keyword in node.keywords:
if keyword.arg == "connection_verify":
if type(keyword.value.value) == bool:
self.add_message(
msgid=f"do-not-hardcode-connection-verify",
node=keyword,
confidence=None,
)
try:
if len(node.keywords) > 0:
for keyword in node.keywords:
if keyword.arg == "connection_verify":
if type(keyword.value.value) == bool:
self.add_message(
msgid=f"do-not-hardcode-connection-verify",
node=keyword,
confidence=None,
)
except:
pass

def visit_assign(self, node):
"""Visiting variable Assignments"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

setup(
name="azure-pylint-guidelines-checker",
version="0.5.0",
version="0.5.1",
url="http://github.com/Azure/azure-sdk-for-python",
license="MIT License",
description="A pylint plugin which enforces azure sdk guidelines.",
Expand Down
Loading