Skip to content

Run next pylint on Tables #30953

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

Merged
merged 16 commits into from
Jul 13, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,11 @@ class AzureSigningError(ClientAuthenticationError):


class _HttpChallenge(object): # pylint:disable=too-few-public-methods
"""Represents a parsed HTTP WWW-Authentication Bearer challenge from a server."""
"""Represents a parsed HTTP WWW-Authentication Bearer challenge from a server.

:param challenge: The WWW-Authenticate header of the challenge response.
:type challenge: str
"""

def __init__(self, challenge):
if not challenge:
Expand Down Expand Up @@ -78,7 +82,6 @@ def __init__(self, challenge):
self.resource = self._parameters.get("resource") or self._parameters.get("resource_id") or ""


# pylint: disable=no-self-use
class SharedKeyCredentialPolicy(SansIOHTTPPolicy):
def __init__(self, credential, is_emulated=False):
self._credential = credential
Expand Down Expand Up @@ -139,7 +142,7 @@ def _add_authorization_header(self, request, string_to_sign):
except Exception as ex:
# Wrap any error that occurred as signing error
# Doing so will clarify/locate the source of problem
raise _wrap_exception(ex, AzureSigningError)
raise _wrap_exception(ex, AzureSigningError) from ex

def on_request(self, request: PipelineRequest) -> None:
self.sign_request(request)
Expand All @@ -164,6 +167,7 @@ def _get_canonicalized_resource_query(self, request):


class BearerTokenChallengePolicy(BearerTokenCredentialPolicy):
# pylint:disable=docstring-should-be-keyword
"""Adds a bearer token Authorization header to requests, for the tenant provided in authentication challenges.

See https://docs.microsoft.com/azure/active-directory/develop/claims-challenge for documentation on AAD
Expand Down Expand Up @@ -198,6 +202,7 @@ def on_challenge(self, request: PipelineRequest, response: PipelineResponse) ->
:param ~azure.core.pipeline.PipelineRequest request: the request which elicited an authentication challenge
:param ~azure.core.pipeline.PipelineResponse response: the resource provider's response
:returns: a bool indicating whether the policy should send the request
:rtype: bool
"""
if not self._discover_tenant and not self._discover_scopes:
# We can't discover the tenant or use a different scope; the request will fail because it hasn't changed
Expand Down Expand Up @@ -268,5 +273,5 @@ def _configure_credential(
if isinstance(credential, AzureNamedKeyCredential):
return SharedKeyCredentialPolicy(credential)
if credential is not None:
raise TypeError("Unsupported credential: {}".format(credential))
raise TypeError(f"Unsupported credential: {credential}")
return None
69 changes: 35 additions & 34 deletions sdk/tables/azure-data-tables/azure/data/tables/_base_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,7 @@ def get_api_version(kwargs: Dict[str, Any], default: str) -> str:
if api_version and api_version not in _SUPPORTED_API_VERSIONS:
versions = "\n".join(_SUPPORTED_API_VERSIONS)
raise ValueError(
"Unsupported API version '{}'. Please select from:\n{}".format(
api_version, versions
)
f"Unsupported API version '{api_version}'. Please select from:\n{versions}"
)
return api_version or default

Expand All @@ -81,11 +79,11 @@ def __init__(
try:
if not account_url.lower().startswith("http"):
account_url = "https://" + account_url
except AttributeError:
raise ValueError("Account URL must be a string.")
except AttributeError as exc:
raise ValueError("Account URL must be a string.") from exc
parsed_url = urlparse(account_url.rstrip("/"))
if not parsed_url.netloc:
raise ValueError("Invalid URL: {}".format(account_url))
raise ValueError(f"Invalid URL: {account_url}")

_, sas_token = parse_query(parsed_url.query)
if not sas_token and not credential:
Expand Down Expand Up @@ -118,10 +116,8 @@ def __init__(
raise ValueError("Token credential is only supported with HTTPS.")
if hasattr(self.credential, "named_key"):
self.account_name = self.credential.named_key.name # type: ignore
secondary_hostname = "{}-secondary.table.{}".format(
self.credential.named_key.name, # type: ignore
os.getenv("TABLES_STORAGE_ENDPOINT_SUFFIX", DEFAULT_STORAGE_ENDPOINT_SUFFIX)
)
endpoint_suffix = os.getenv("TABLES_STORAGE_ENDPOINT_SUFFIX", DEFAULT_STORAGE_ENDPOINT_SUFFIX)
secondary_hostname = f"{self.account_name}-secondary.table.{endpoint_suffix}"

if not self._hosts:
if len(account) > 1:
Expand All @@ -148,6 +144,8 @@ def url(self):

This could be either the primary endpoint,
or the secondary endpoint depending on the current :func:`location_mode`.

:type: str
"""
return self._format_url(self._hosts[self._location_mode])

Expand Down Expand Up @@ -207,14 +205,14 @@ class TablesBaseClient(AccountHostsMixin):
:param str endpoint: A URL to an Azure Tables account.
:keyword credential:
The credentials with which to authenticate. This is optional if the
account URL already has a SAS token. The value can be one of AzureNamedKeyCredential (azure-core),
AzureSasCredential (azure-core), or TokenCredentials from azure-identity.
account URL already has a SAS token. The value can be one of AzureNamedKeyCredential,
AzureSasCredential, or TokenCredentials from azure-core.
:paramtype credential:
:class:`~azure.core.credentials.AzureNamedKeyCredential` or
:class:`~azure.core.credentials.AzureSasCredential` or
:class:`~azure.core.credentials.TokenCredential`
:keyword api_version: Specifies the version of the operation to use for this request. Default value
is "2019-02-02". Note that overriding this default value may result in unsupported behavior.
is "2019-02-02".
:paramtype api_version: str
"""

Expand Down Expand Up @@ -259,16 +257,25 @@ def _configure_policies(self, **kwargs):
]

def _batch_send(self, table_name: str, *reqs: HttpRequest, **kwargs) -> List[Mapping[str, Any]]:
"""Given a series of request, do a Storage batch call."""
# pylint:disable=docstring-should-be-keyword
"""Given a series of request, do a Storage batch call.

:param table_name: The table name.
:type table_name: str
:param reqs: The HTTP request.
:type reqs: ~azure.core.pipeline.transport.HttpRequest
:return: A list of batch part metadata in response.
:rtype: list[Mapping[str, Any]]
"""
# Pop it here, so requests doesn't feel bad about additional kwarg
policies = [StorageHeadersPolicy()]

changeset = HttpRequest("POST", None) # type: ignore
changeset.set_multipart_mixed(
*reqs, policies=policies, boundary="changeset_{}".format(uuid4()) # type: ignore
*reqs, policies=policies, boundary=f"changeset_{uuid4()}" # type: ignore
)
request = self._client._client.post( # pylint: disable=protected-access
url="{}://{}/$batch".format(self.scheme, self._primary_hostname),
url=f"{self.scheme}://{self._primary_hostname}/$batch",
headers={
"x-ms-version": self.api_version,
"DataServiceVersion": "3.0",
Expand All @@ -281,7 +288,7 @@ def _batch_send(self, table_name: str, *reqs: HttpRequest, **kwargs) -> List[Map
changeset,
policies=policies,
enforce_https=False,
boundary="batch_{}".format(uuid4()),
boundary=f"batch_{uuid4()}",
)
pipeline_response = self._client._client._pipeline.run(request, **kwargs) # pylint: disable=protected-access
response = pipeline_response.http_response
Expand Down Expand Up @@ -322,6 +329,9 @@ class TransportWrapper(HttpTransport):
"""Wrapper class that ensures that an inner client created
by a `get_client` method does not close the outer transport for the parent
when used in a context manager.

:param transport: The Http Transport instance
:type transport: ~azure.core.pipeline.transport.HttpTransport
"""
def __init__(self, transport):
self._transport = transport
Expand Down Expand Up @@ -352,25 +362,19 @@ def parse_connection_str(conn_str, credential, keyword_args):
if not credential:
try:
credential = AzureNamedKeyCredential(name=conn_settings["accountname"], key=conn_settings["accountkey"])
except KeyError:
except KeyError as exc:
credential = conn_settings.get("sharedaccesssignature", None)
if not credential:
raise ValueError("Connection string missing required connection details.")
raise ValueError("Connection string missing required connection details.") from exc
credential = AzureSasCredential(credential)
primary = conn_settings.get("tableendpoint")
secondary = conn_settings.get("tablesecondaryendpoint")
if not primary:
if secondary:
raise ValueError("Connection string specifies only secondary endpoint.")
try:
primary = "{}://{}.table.{}".format(
conn_settings["defaultendpointsprotocol"],
conn_settings["accountname"],
conn_settings["endpointsuffix"],
)
secondary = "{}-secondary.table.{}".format(
conn_settings["accountname"], conn_settings["endpointsuffix"]
)
primary = f"{conn_settings['defaultendpointsprotocol']}://{conn_settings['accountname']}.table.{conn_settings['endpointsuffix']}" # pylint: disable=line-too-long
secondary = f"{conn_settings['accountname']}-secondary.table.{conn_settings['endpointsuffix']}"
except KeyError:
pass

Expand All @@ -380,12 +384,9 @@ def parse_connection_str(conn_str, credential, keyword_args):
else:
endpoint_suffix = os.getenv("TABLES_STORAGE_ENDPOINT_SUFFIX", DEFAULT_STORAGE_ENDPOINT_SUFFIX)
try:
primary = "https://{}.table.{}".format(
conn_settings["accountname"],
conn_settings.get("endpointsuffix", endpoint_suffix),
)
except KeyError:
raise ValueError("Connection string missing required connection details.")
primary = f"https://{conn_settings['accountname']}.table.{conn_settings.get('endpointsuffix', endpoint_suffix)}" # pylint: disable=line-too-long
except KeyError as exc:
raise ValueError("Connection string missing required connection details.") from exc

if "secondary_hostname" not in keyword_args:
keyword_args["secondary_hostname"] = secondary
Expand Down Expand Up @@ -416,7 +417,7 @@ def parse_query(query_str):
sas_values = QueryStringConstants.to_list()
parsed_query = {k: v[0] for k, v in parse_qs(query_str).items()}
sas_params = [
"{}={}".format(k, quote(v, safe=""))
f"{k}={quote(v, safe='')}"
for k, v in parsed_query.items()
if k in sas_values
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,8 @@
# --------------------------------------------------------------------------
import base64
import hashlib
import datetime
import hmac


class UTC(datetime.tzinfo):
"""Time Zone info for handling UTC"""

def utcoffset(self, dt):
"""UTF offset for UTC is 0."""
return datetime.timedelta(0)

def tzname(self, dt):
"""Timestamp representation."""
return "Z"

def dst(self, dt):
"""No daylight saving for UTC."""
return datetime.timedelta(hours=1)


try:
from datetime import timezone
TZ_UTC = timezone.utc # type: ignore
except ImportError:
TZ_UTC = UTC() # type: ignore
from datetime import timezone


def _to_str(value):
Expand All @@ -38,7 +15,7 @@ def _to_str(value):

def _to_utc_datetime(value):
try:
value = value.astimezone(TZ_UTC)
value = value.astimezone(timezone.utc)
except ValueError:
# Before Python 3.8, this raised for a naive datetime.
pass
Expand Down
29 changes: 20 additions & 9 deletions sdk/tables/azure-data-tables/azure/data/tables/_deserialize.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@

from uuid import UUID
import logging
import datetime
from datetime import datetime, timezone

from ._entity import EntityProperty, EdmType, TableEntity
from ._common_conversion import _decode_base64_to_bytes, TZ_UTC
from ._common_conversion import _decode_base64_to_bytes


_LOGGER = logging.getLogger(__name__)
Expand All @@ -21,7 +21,7 @@
from urllib2 import quote # type: ignore


class TablesEntityDatetime(datetime.datetime):
class TablesEntityDatetime(datetime):

@property
def tables_service_value(self):
Expand Down Expand Up @@ -61,13 +61,13 @@ def _from_entity_datetime(value):
cleaned_value = clean_up_dotnet_timestamps(value)
try:
dt_obj = TablesEntityDatetime.strptime(cleaned_value, "%Y-%m-%dT%H:%M:%S.%fZ").replace(
tzinfo=TZ_UTC
tzinfo=timezone.utc
)
except ValueError:
dt_obj = TablesEntityDatetime.strptime(cleaned_value, "%Y-%m-%dT%H:%M:%SZ").replace(
tzinfo=TZ_UTC
tzinfo=timezone.utc
)
dt_obj._service_value = value # pylint:disable=protected-access
dt_obj._service_value = value # pylint:disable=protected-access,assigning-non-slot
return dt_obj


Expand Down Expand Up @@ -141,6 +141,11 @@ def _convert_to_entity(entry_element):
"PartitionKey":"my_partition_key",
"RowKey":"my_row_key"
}

:param entry_element: The entity in response.
:type entry_element: Mapping[str, Any]
:return: An entity dict with additional metadata.
:rtype: dict[str, Any]
"""
entity = TableEntity()

Expand Down Expand Up @@ -213,7 +218,13 @@ def _convert_to_entity(entry_element):


def _extract_etag(response):
""" Extracts the etag from the response headers. """
""" Extracts the etag from the response headers.

:param response: The PipelineResponse object.
:type response: ~azure.core.pipeline.PipelineResponse
:return: The etag from the response headers
:rtype: str or None
"""
if response and response.headers:
return response.headers.get("etag")

Expand All @@ -231,8 +242,8 @@ def _extract_continuation_token(continuation_token):
return None, None
try:
return continuation_token.get("PartitionKey"), continuation_token.get("RowKey")
except AttributeError:
raise ValueError("Invalid continuation token format.")
except AttributeError as exc:
raise ValueError("Invalid continuation token format.") from exc


def _normalize_headers(headers):
Expand Down
18 changes: 9 additions & 9 deletions sdk/tables/azure-data-tables/azure/data/tables/_error.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,11 @@ def _decode_error(response, error_message=None, error_type=None, **kwargs): # p
error_type = HttpResponseError

try:
error_message += "\nErrorCode:{}".format(error_code.value)
error_message += f"\nErrorCode:{error_code.value}"
except AttributeError:
error_message += "\nErrorCode:{}".format(error_code)
error_message += f"\nErrorCode:{error_code}"
for name, info in additional_data.items():
error_message += "\n{}:{}".format(name, info)
error_message += f"\n{name}:{info}"

error = error_type(message=error_message, response=response, **kwargs)
error.error_code = error_code
Expand All @@ -184,16 +184,16 @@ def _reraise_error(decoded_error):
_, _, exc_traceback = sys.exc_info()
try:
raise decoded_error.with_traceback(exc_traceback)
except AttributeError:
except AttributeError as exc:
decoded_error.__traceback__ = exc_traceback
raise decoded_error
raise decoded_error from exc


def _process_table_error(storage_error, table_name=None):
try:
decoded_error = _decode_error(storage_error.response, storage_error.message)
except AttributeError:
raise storage_error
except AttributeError as exc:
raise storage_error from exc
if table_name:
_validate_tablename_error(decoded_error, table_name)
_reraise_error(decoded_error)
Expand Down Expand Up @@ -227,8 +227,8 @@ def _reprocess_error(decoded_error, identifiers=None):
"Too many access policies provided. The server does not support setting more than 5 access policies"\
"on a single resource."
)
except AttributeError:
raise decoded_error
except AttributeError as exc:
raise decoded_error from exc


class TableTransactionError(HttpResponseError):
Expand Down
Loading