Skip to content
Open
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

### Changed

- chore: zero-argument `super()` everywhere and PEP 604 unions in `isinstance` checks, now that Python 3.10 is the minimum (#302) - Sena Köse

### Fixed

- model: escape single quotes in `Edm.String` literals, so filters on values containing an apostrophe produce a valid OData query - Francois Pilet
Expand Down
2 changes: 1 addition & 1 deletion pyodata/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def __new__(cls, message, response):
return super(HttpError, cls).__new__(cls, message, response)

def __init__(self, message, response):
super(HttpError, self).__init__(message)
super().__init__(message)

self.response = response

Expand Down
50 changes: 25 additions & 25 deletions pyodata/v2/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ def retain_null(self):

class Identifier:
def __init__(self, name):
super(Identifier, self).__init__()
super().__init__()

self._name = name

Expand Down Expand Up @@ -347,7 +347,7 @@ class EdmPrefixedTypTraits(TypTraits):
"""Is good for all types where values have form: prefix'value'"""

def __init__(self, prefix):
super(EdmPrefixedTypTraits, self).__init__()
super().__init__()
self._prefix = prefix

def to_literal(self, value):
Expand Down Expand Up @@ -423,7 +423,7 @@ class EdmDateTimeTypTraits(EdmPrefixedTypTraits):
"""

def __init__(self):
super(EdmDateTimeTypTraits, self).__init__('datetime')
super().__init__('datetime')

def to_literal(self, value):
"""Convert python datetime representation to literal format
Expand All @@ -440,7 +440,7 @@ def to_literal(self, value):
raise PyODataModelError('Edm.DateTime accepts only UTC')

# Sets timezone to none to avoid including timezone information in the literal form.
return super(EdmDateTimeTypTraits, self).to_literal(value.replace(tzinfo=None).isoformat())
return super().to_literal(value.replace(tzinfo=None).isoformat())

def to_json(self, value):
if isinstance(value, str):
Expand Down Expand Up @@ -484,7 +484,7 @@ def from_literal(self, value):
if value is None:
return None

value = super(EdmDateTimeTypTraits, self).from_literal(value)
value = super().from_literal(value)

return parse_datetime_literal(value).replace(tzinfo=datetime.timezone.utc)

Expand All @@ -509,7 +509,7 @@ class EdmDateTimeOffsetTypTraits(EdmPrefixedTypTraits):
"""

def __init__(self):
super(EdmDateTimeOffsetTypTraits, self).__init__('datetimeoffset')
super().__init__('datetimeoffset')

def to_literal(self, value):
"""Convert python datetime representation to literal format"""
Expand All @@ -518,7 +518,7 @@ def to_literal(self, value):
raise PyODataModelError(
f'Cannot convert value of type {type(value)} to literal. Datetime format including offset is required.')

return super(EdmDateTimeOffsetTypTraits, self).to_literal(value.isoformat())
return super().to_literal(value.isoformat())

def to_json(self, value):
# datetime.timestamp() does not work due to its limited precision
Expand Down Expand Up @@ -552,7 +552,7 @@ def from_literal(self, value):
if value is None:
return None

value = super(EdmDateTimeOffsetTypTraits, self).from_literal(value)
value = super().from_literal(value)

try:
normalized = value.upper().replace('Z', '+00:00')
Expand Down Expand Up @@ -639,7 +639,7 @@ def __init__(self, precision, suffix, conversion):
self.conversion = conversion

def __repr__(self):
parent = super(EdmFPNumTypTraits, self).__repr__()
parent = super().__repr__()

return f'{parent}({self.precision},{self.suffix})'

Expand Down Expand Up @@ -677,7 +677,7 @@ class EdmStructTypTraits(TypTraits):
"""Edm structural types (EntityType, ComplexType) traits"""

def __init__(self, edm_type=None):
super(EdmStructTypTraits, self).__init__()
super().__init__()
self._edm_type = edm_type

# pylint: disable=no-self-use
Expand Down Expand Up @@ -716,7 +716,7 @@ class Typ(Identifier):
Kinds = Enum('Kinds', 'Primitive Complex')

def __init__(self, name, null_value, traits=TypTraits(), kind=None):
super(Typ, self).__init__(name)
super().__init__(name)

self._null_value = null_value
self._kind = kind if kind is not None else Typ.Kinds.Primitive # no way how to us enum value for parameter default value
Expand All @@ -743,7 +743,7 @@ class Collection(Typ):
"""Represents collection items"""

def __init__(self, name, item_type):
super(Collection, self).__init__(name, [], kind=item_type.kind)
super().__init__(name, [], kind=item_type.kind)
self._item_type = item_type

def __repr__(self):
Expand Down Expand Up @@ -780,7 +780,7 @@ class VariableDeclaration(Identifier):
MAXIMUM_LENGTH = -1

def __init__(self, name, type_info, nullable, max_length, precision, scale, fixed_length=None):
super(VariableDeclaration, self).__init__(name)
super().__init__(name)

self._type_info = type_info
self._typ = None
Expand Down Expand Up @@ -962,7 +962,7 @@ def __getitem__(self, key):
raise KeyError(f'There is no Schema Namespace {key}')

def __init__(self, config: Config):
super(Schema, self).__init__()
super().__init__()

self._decls = Schema.Declarations()
self._config = config
Expand Down Expand Up @@ -1469,7 +1469,7 @@ def from_etree(schema_nodes, config: Config):

class StructType(Typ):
def __init__(self, name, label, is_value_list):
super(StructType, self).__init__(name, None, EdmStructTypTraits(self), Typ.Kinds.Complex)
super().__init__(name, None, EdmStructTypTraits(self), Typ.Kinds.Complex)

self._label = label
self._is_value_list = is_value_list
Expand Down Expand Up @@ -1565,7 +1565,7 @@ def parent(self):

class EnumType(Identifier):
def __init__(self, name, is_flags, underlying_type, namespace):
super(EnumType, self).__init__(name)
super().__init__(name)
self._member = list()
self._underlying_type = underlying_type
self._traits = TypTraits()
Expand Down Expand Up @@ -1656,7 +1656,7 @@ def namespace(self):

class EntityType(StructType):
def __init__(self, name, label, is_value_list):
super(EntityType, self).__init__(name, label, is_value_list)
super().__init__(name, label, is_value_list)

self._key = list()
self._nav_properties = dict()
Expand Down Expand Up @@ -1695,7 +1695,7 @@ def from_etree(cls, type_node, config: Config):
class EntitySet(Identifier):
def __init__(self, name, entity_type_info, addressable, creatable, updatable, deletable, searchable, countable,
pageable, topable, req_filter, label):
super(EntitySet, self).__init__(name)
super().__init__(name)

self._entity_type_info = entity_type_info
self._entity_type = None
Expand Down Expand Up @@ -1803,7 +1803,7 @@ class StructTypeProperty(VariableDeclaration):
def __init__(self, name, type_info, nullable, max_length, precision, scale, uncode, label, creatable, updatable,
sortable, filterable, filter_restr, req_in_filter, text, visible, display_format, value_list,
fixed_length=None):
super(StructTypeProperty, self).__init__(name, type_info, nullable, max_length, precision, scale, fixed_length)
super().__init__(name, type_info, nullable, max_length, precision, scale, fixed_length)

self._value_helper = None
self._struct_type = None
Expand Down Expand Up @@ -1964,7 +1964,7 @@ class NavigationTypeProperty(VariableDeclaration):
"""

def __init__(self, name, from_role_name, to_role_name, association_info):
super(NavigationTypeProperty, self).__init__(name, None, False, None, None, None, None)
super().__init__(name, None, False, None, None, None, None)

self.from_role_name = from_role_name
self.to_role_name = to_role_name
Expand Down Expand Up @@ -2304,7 +2304,7 @@ class Annotation:
Kinds = Enum('Kinds', 'ValueHelper')

def __init__(self, kind, target, qualifier=None):
super(Annotation, self).__init__()
super().__init__()

self._kind = kind
self._element_namespace, self._element = target.split('.')
Expand Down Expand Up @@ -2360,7 +2360,7 @@ def __init__(self, target, collection_path, label, search_supported):

# pylint: disable=unused-argument

super(ValueHelper, self).__init__(Annotation.Kinds.ValueHelper, target)
super().__init__(Annotation.Kinds.ValueHelper, target)

self._entity_type_name, self._proprty_name = self.element.split('/')
self._proprty = None
Expand Down Expand Up @@ -2486,7 +2486,7 @@ class ValueHelperParameter:
Direction = Enum('Direction', 'In InOut Out DisplayOnly FilterOnly Constant Constants')

def __init__(self, direction, local_property_name, list_property_name):
super(ValueHelperParameter, self).__init__()
super().__init__()

self._direction = direction
self._value_helper = None
Expand Down Expand Up @@ -2566,7 +2566,7 @@ def from_etree(value_help_parameter_node):

class FunctionImport(Identifier):
def __init__(self, name, return_type_info, entity_set, parameters, http_method='GET'):
super(FunctionImport, self).__init__(name)
super().__init__(name)

self._entity_set_name = entity_set
self._return_type_info = return_type_info
Expand Down Expand Up @@ -2637,7 +2637,7 @@ class FunctionImportParameter(VariableDeclaration):
Modes = Enum('Modes', 'In Out InOut')

def __init__(self, name, type_info, nullable, max_length, precision, scale, mode):
super(FunctionImportParameter, self).__init__(name, type_info, nullable, max_length, precision, scale, None)
super().__init__(name, type_info, nullable, max_length, precision, scale, None)

self._mode = mode

Expand Down
34 changes: 17 additions & 17 deletions pyodata/v2/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -383,8 +383,8 @@ class EntityGetRequest(ODataHttpRequest):
"""Used for GET operations of a single entity"""

def __init__(self, handler, entity_key, entity_set_proxy, encode_path=True):
super(EntityGetRequest, self).__init__(entity_set_proxy.service.url, entity_set_proxy.service.connection,
handler, response_hook=entity_set_proxy.service.response_hook)
super().__init__(entity_set_proxy.service.url, entity_set_proxy.service.connection,
handler, response_hook=entity_set_proxy.service.response_hook)
self._logger = logging.getLogger(LOGGER_NAME)
self._entity_key = entity_key
self._entity_set_proxy = entity_set_proxy
Expand Down Expand Up @@ -423,7 +423,7 @@ def get_default_headers(self):
return {'Accept': 'application/json'}

def get_query_params(self):
qparams = super(EntityGetRequest, self).get_query_params()
qparams = super().get_query_params()

if self._select is not None:
qparams['$select'] = self._select
Expand Down Expand Up @@ -462,12 +462,12 @@ class NavEntityGetRequest(EntityGetRequest):
"""Used for GET operations of a single entity accessed via a Navigation property"""

def __init__(self, handler, master_key, entity_set_proxy, nav_property):
super(NavEntityGetRequest, self).__init__(handler, master_key, entity_set_proxy)
super().__init__(handler, master_key, entity_set_proxy)

self._nav_property = nav_property

def get_path(self):
return f"{super(NavEntityGetRequest, self).get_path()}/{self._nav_property}"
return f"{super().get_path()}/{self._nav_property}"


class EntityCreateRequest(ODataHttpRequest):
Expand All @@ -477,7 +477,7 @@ class EntityCreateRequest(ODataHttpRequest):
and get the newly created entity."""

def __init__(self, url, connection, handler, entity_set, last_segment=None, response_hook=None):
super(EntityCreateRequest, self).__init__(url, connection, handler, response_hook=response_hook)
super().__init__(url, connection, handler, response_hook=response_hook)
self._logger = logging.getLogger(LOGGER_NAME)
self._entity_set = entity_set
self._entity_type = entity_set.entity_type
Expand Down Expand Up @@ -564,7 +564,7 @@ class EntityDeleteRequest(ODataHttpRequest):
"""Used for deleting entity (DELETE operations on a single entity)"""

def __init__(self, url, connection, handler, entity_set, entity_key, encode_path=True, response_hook=None):
super(EntityDeleteRequest, self).__init__(url, connection, handler, response_hook=response_hook)
super().__init__(url, connection, handler, response_hook=response_hook)
self._logger = logging.getLogger(LOGGER_NAME)
self._entity_set = entity_set
self._entity_key = entity_key
Expand Down Expand Up @@ -598,7 +598,7 @@ class EntityModifyRequest(ODataHttpRequest):
# pylint: disable=too-many-arguments
def __init__(self, url, connection, handler, entity_set, entity_key, method="PATCH", encode_path=True,
response_hook=None):
super(EntityModifyRequest, self).__init__(url, connection, handler, response_hook=response_hook)
super().__init__(url, connection, handler, response_hook=response_hook)
self._logger = logging.getLogger(LOGGER_NAME)
self._entity_set = entity_set
self._entity_type = entity_set.entity_type
Expand Down Expand Up @@ -663,7 +663,7 @@ class QueryRequest(ODataHttpRequest):
# pylint: disable=too-many-instance-attributes

def __init__(self, url, connection, handler, last_segment, response_hook=None):
super(QueryRequest, self).__init__(url, connection, handler, response_hook=response_hook)
super().__init__(url, connection, handler, response_hook=response_hook)

self._logger = logging.getLogger(LOGGER_NAME)
self._count = None
Expand Down Expand Up @@ -750,7 +750,7 @@ def get_query_params(self):
if self._next_url:
return {}

qparams = super(QueryRequest, self).get_query_params()
qparams = super().get_query_params()

if self._top is not None:
qparams['$top'] = self._top
Expand Down Expand Up @@ -780,7 +780,7 @@ class FunctionRequest(QueryRequest):
"""Function import request (Service call)"""

def __init__(self, url, connection, handler, function_import, response_hook=None):
super(FunctionRequest, self).__init__(
super().__init__(
url, connection, handler, function_import.name,
response_hook=response_hook)

Expand Down Expand Up @@ -1074,7 +1074,7 @@ class NavEntityProxy(EntityProxy):

def __init__(self, parent_entity, prop_name, entity_type, entity):
# pylint: disable=protected-access
super(NavEntityProxy, self).__init__(parent_entity._service, parent_entity._entity_set, entity_type, entity)
super().__init__(parent_entity._service, parent_entity._entity_set, entity_type, entity)

self._parent_entity = parent_entity
self._prop_name = prop_name
Expand Down Expand Up @@ -1317,7 +1317,7 @@ def _build_expression(self, field_name, operator, value):
return f'substringof({value}, {field_name}) eq true'

if operator == 'range':
if not isinstance(value, (tuple, list)):
if not isinstance(value, tuple | list):
raise TypeError(f'Range must be tuple or list not {type(value)}')

if len(value) != 2:
Expand Down Expand Up @@ -1347,7 +1347,7 @@ class GetEntitySetRequest(QueryRequest):
"""GET on EntitySet"""

def __init__(self, url, connection, handler, last_segment, entity_type, encode_path=True, response_hook=None):
super(GetEntitySetRequest, self).__init__(url, connection, handler, last_segment, response_hook=response_hook)
super().__init__(url, connection, handler, last_segment, response_hook=response_hook)

self._entity_type = entity_type
self._encode_path = encode_path
Expand Down Expand Up @@ -1392,7 +1392,7 @@ class ListWithTotalCount(list):
"""

def __init__(self, total_count, next_url):
super(ListWithTotalCount, self).__init__()
super().__init__()
self._total_count = total_count
self._next_url = next_url

Expand Down Expand Up @@ -1723,7 +1723,7 @@ def function_import_handler(fimport, response):
response_data = response.json()['d']

# 1. if return type is an entity type or collection, resolve the entity set once
if isinstance(fimport.return_type, (model.EntityType, model.Collection)):
if isinstance(fimport.return_type, model.EntityType | model.Collection):
entity_set = self._service.schema.entity_set(fimport.entity_set_name)

if isinstance(fimport.return_type, model.EntityType):
Expand Down Expand Up @@ -1915,7 +1915,7 @@ class MultipartRequest(ODataHttpRequest):
"""HTTP Batch request"""

def __init__(self, url, connection, handler, request_id=None):
super(MultipartRequest, self).__init__(url, connection, partial(MultipartRequest.http_response_handler, self))
super().__init__(url, connection, partial(MultipartRequest.http_response_handler, self))

self.requests = []
self._handler_decoded = handler
Expand Down
2 changes: 1 addition & 1 deletion pyodata/vendor/SAP.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,6 @@ def __init__(self, message, response):
'The HTTP error is not a SAP BusinessGateway JSON error')
logging.debug('JSON parsing error: %s', str(ex))

super(BusinessGatewayError, self).__init__(message, response)
super().__init__(message, response)

self.errordetails = errordetails