summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAarni Koskela <akx@iki.fi>2022-10-27 15:13:08 +0300
committerIvan Kanakarakis <ivan.kanak@gmail.com>2022-11-15 13:06:41 +0200
commit88feeba03c2f891a31a86cbb24b210070aab1fdc (patch)
tree4bf48f6b2ca8e86aac23e825fbc6e84b134c400c /src
parent4fa20a92a9d7fccc2ca34f1f6ad777cc0fd36ef7 (diff)
downloadpysaml2-88feeba03c2f891a31a86cbb24b210070aab1fdc.tar.gz
Run pyupgrade --py36-plus + black + isort
Diffstat (limited to 'src')
-rw-r--r--src/saml2/__init__.py26
-rw-r--r--src/saml2/assertion.py17
-rw-r--r--src/saml2/attribute_converter.py13
-rw-r--r--src/saml2/attribute_resolver.py3
-rw-r--r--src/saml2/authn.py18
-rw-r--r--src/saml2/authn_context/__init__.py2
-rw-r--r--src/saml2/cache.py6
-rw-r--r--src/saml2/cert.py17
-rw-r--r--src/saml2/client.py13
-rw-r--r--src/saml2/client_base.py19
-rw-r--r--src/saml2/config.py6
-rw-r--r--src/saml2/country_codes.py1
-rw-r--r--src/saml2/cryptography/symmetric.py12
-rw-r--r--src/saml2/discovery.py8
-rw-r--r--src/saml2/ecp.py5
-rw-r--r--src/saml2/ecp_client.py12
-rw-r--r--src/saml2/entity.py12
-rw-r--r--src/saml2/eptid.py17
-rw-r--r--src/saml2/filter.py4
-rw-r--r--src/saml2/httpbase.py14
-rw-r--r--src/saml2/httputil.py18
-rw-r--r--src/saml2/ident.py20
-rw-r--r--src/saml2/mcache.py4
-rw-r--r--src/saml2/mdbcache.py2
-rw-r--r--src/saml2/mdie.py14
-rw-r--r--src/saml2/mdstore.py75
-rw-r--r--src/saml2/metadata.py16
-rw-r--r--src/saml2/mongo_store.py14
-rw-r--r--src/saml2/pack.py34
-rw-r--r--src/saml2/population.py4
-rw-r--r--src/saml2/request.py6
-rw-r--r--src/saml2/response.py31
-rw-r--r--src/saml2/s2repoze/__init__.py1
-rw-r--r--src/saml2/s2repoze/plugins/__init__.py1
-rw-r--r--src/saml2/s2repoze/plugins/entitlement.py6
-rw-r--r--src/saml2/s2repoze/plugins/formswithhidden.py5
-rw-r--r--src/saml2/s2repoze/plugins/ini.py2
-rw-r--r--src/saml2/s2repoze/plugins/sp.py24
-rw-r--r--src/saml2/s_utils.py12
-rw-r--r--src/saml2/saml.py4
-rw-r--r--src/saml2/sdb.py2
-rw-r--r--src/saml2/server.py11
-rw-r--r--src/saml2/sigver.py65
-rw-r--r--src/saml2/soap.py21
-rw-r--r--src/saml2/time_util.py12
-rw-r--r--src/saml2/tools/parse_xsd2.py126
-rw-r--r--src/saml2/tools/sync_attrmaps.py16
-rw-r--r--src/saml2/userinfo/__init__.py2
-rw-r--r--src/saml2/validate.py21
-rw-r--r--src/saml2/virtual_org.py2
-rw-r--r--src/saml2/xmldsig/__init__.py4
-rw-r--r--src/saml2test/check.py8
-rw-r--r--src/saml2test/interaction.py10
-rw-r--r--src/saml2test/opfunc.py6
-rw-r--r--src/saml2test/tool.py4
55 files changed, 395 insertions, 433 deletions
diff --git a/src/saml2/__init__.py b/src/saml2/__init__.py
index 34272fe8..0e38e551 100644
--- a/src/saml2/__init__.py
+++ b/src/saml2/__init__.py
@@ -1,5 +1,4 @@
#!/usr/bin/env python
-# -*- coding: utf-8 -*-
"""Contains base classes representing SAML elements.
@@ -26,7 +25,7 @@ from saml2.version import version as __version__
try:
- from xml.etree import cElementTree as ElementTree
+ from xml.etree import ElementTree as ElementTree
if ElementTree.VERSION < "1.3.0":
# cElementTree has no support for register_namespace
@@ -79,7 +78,7 @@ BINDING_URI = "urn:oasis:names:tc:SAML:2.0:bindings:URI"
def class_name(instance):
- return "%s:%s" % (instance.c_namespace, instance.c_tag)
+ return f"{instance.c_namespace}:{instance.c_tag}"
def create_class_from_xml_string(target_class, xml_string):
@@ -96,7 +95,7 @@ def create_class_from_xml_string(target_class, xml_string):
the contents of the XML - or None if the root XML tag and namespace did
not match those of the target class.
"""
- if not isinstance(xml_string, six.binary_type):
+ if not isinstance(xml_string, bytes):
xml_string = xml_string.encode("utf-8")
tree = defusedxml.ElementTree.fromstring(xml_string)
return create_class_from_element_tree(target_class, tree)
@@ -126,7 +125,7 @@ def create_class_from_element_tree(target_class, tree, namespace=None, tag=None)
namespace = target_class.c_namespace
if tag is None:
tag = target_class.c_tag
- if tree.tag == "{%s}%s" % (namespace, tag):
+ if tree.tag == f"{{{namespace}}}{tag}":
target = target_class()
target.harvest_element_tree(tree)
return target
@@ -144,7 +143,7 @@ class SAMLError(Exception):
pass
-class ExtensionElement(object):
+class ExtensionElement:
"""XML which is not part of the SAML specification,
these are called extension elements. If a classes parser
encounters an unexpected XML construct, it is translated into an
@@ -184,7 +183,7 @@ class ExtensionElement(object):
element_tree = ElementTree.Element("")
if self.namespace is not None:
- element_tree.tag = "{%s}%s" % (self.namespace, self.tag)
+ element_tree.tag = f"{{{self.namespace}}}{self.tag}"
else:
element_tree.tag = self.tag
@@ -300,7 +299,7 @@ def _extension_element_from_element_tree(element_tree):
return extension
-class ExtensionContainer(object):
+class ExtensionContainer:
c_tag = ""
c_namespace = ""
@@ -464,8 +463,7 @@ class SamlBase(ExtensionContainer):
def _get_all_c_children_with_order(self):
if len(self.c_child_order) > 0:
- for child in self.c_child_order:
- yield child
+ yield from self.c_child_order
else:
for _, values in iter(self.__class__.c_children.items()):
yield values[0]
@@ -542,7 +540,7 @@ class SamlBase(ExtensionContainer):
should not be called on in this class.
"""
- new_tree = ElementTree.Element("{%s}%s" % (self.__class__.c_namespace, self.__class__.c_tag))
+ new_tree = ElementTree.Element(f"{{{self.__class__.c_namespace}}}{self.__class__.c_tag}")
self._add_members_to_element_tree(new_tree)
return new_tree
@@ -689,7 +687,7 @@ class SamlBase(ExtensionContainer):
def __str__(self):
# Yes this is confusing. http://bugs.python.org/issue10942
x = self.to_string()
- if not isinstance(x, six.string_types):
+ if not isinstance(x, str):
x = x.decode("utf-8")
return x
@@ -742,7 +740,7 @@ class SamlBase(ExtensionContainer):
self.text = "true" if val else "false"
elif isinstance(val, int):
self.text = str(val)
- elif isinstance(val, six.string_types):
+ elif isinstance(val, str):
self.text = val
elif val is None:
pass
@@ -817,7 +815,7 @@ class SamlBase(ExtensionContainer):
continue
svals = self.__dict__[key]
ovals = other.__dict__[key]
- if isinstance(svals, six.string_types):
+ if isinstance(svals, str):
if svals != ovals:
return False
elif isinstance(svals, list):
diff --git a/src/saml2/assertion.py b/src/saml2/assertion.py
index 237bca7b..40ae7112 100644
--- a/src/saml2/assertion.py
+++ b/src/saml2/assertion.py
@@ -1,5 +1,4 @@
#!/usr/bin/env python
-# -*- coding: utf-8 -*-
import copy
import importlib
import logging
@@ -40,7 +39,7 @@ def _filter_values(vals, vlist=None, must=False):
if vals is None: # cannot iterate over None, return early
return vals
- if isinstance(vlist, six.string_types):
+ if isinstance(vlist, str):
vlist = [vlist]
res = []
@@ -148,7 +147,7 @@ def filter_on_demands(ava, required=None, optional=None):
if required is None:
required = {}
- lava = dict([(k.lower(), k) for k in ava.keys()])
+ lava = {k.lower(): k for k in ava.keys()}
for attr, vals in required.items():
attr = attr.lower()
@@ -156,9 +155,9 @@ def filter_on_demands(ava, required=None, optional=None):
if vals:
for val in vals:
if val not in ava[lava[attr]]:
- raise MissingValue("Required attribute value missing: %s,%s" % (attr, val))
+ raise MissingValue(f"Required attribute value missing: {attr},{val}")
else:
- raise MissingValue("Required attribute missing: %s" % (attr,))
+ raise MissingValue(f"Required attribute missing: {attr}")
if optional is None:
optional = {}
@@ -184,7 +183,7 @@ def filter_on_wire_representation(ava, acs, required=None, optional=None):
:param optional: A list of saml.Attributes
:return: Dictionary of expected/wanted attributes and values
"""
- acsdic = dict([(ac.name_format, ac) for ac in acs])
+ acsdic = {ac.name_format: ac for ac in acs}
if required is None:
required = []
@@ -239,7 +238,7 @@ def filter_attribute_value_assertions(ava, attribute_restrictions=None):
else:
if _rests is None:
continue
- if isinstance(vals, six.string_types):
+ if isinstance(vals, str):
vals = [vals]
rvals = []
for restr in _rests:
@@ -308,7 +307,7 @@ def compile(restrictions):
return restrictions
-class Policy(object):
+class Policy:
"""Handles restrictions on assertions."""
def __init__(self, restrictions=None, mds=None):
@@ -582,7 +581,7 @@ class Policy(object):
)
-class EntityCategories(object):
+class EntityCategories:
pass
diff --git a/src/saml2/attribute_converter.py b/src/saml2/attribute_converter.py
index 900384f9..505d1564 100644
--- a/src/saml2/attribute_converter.py
+++ b/src/saml2/attribute_converter.py
@@ -1,5 +1,4 @@
#!/usr/bin/env python
-# -*- coding: utf-8 -*-
#
from importlib import import_module
@@ -131,7 +130,7 @@ def list_to_local(acs, attrlist, allow_unknown_attributes=False):
acs = [AttributeConverter()]
acsd = {"": acs}
else:
- acsd = dict([(a.name_format, a) for a in acs])
+ acsd = {a.name_format: a for a in acs}
ava = {}
for attr in attrlist:
@@ -227,7 +226,7 @@ def d_to_local_name(acs, attr):
raise ConverterError("Could not find local name for %s" % attr)
-class AttributeConverter(object):
+class AttributeConverter:
"""Converts from an attribute statement to a key,value dictionary and
vice-versa"""
@@ -242,9 +241,9 @@ class AttributeConverter(object):
"""
if self._fro is None and self._to is not None:
- self._fro = dict([(value.lower(), key) for key, value in self._to.items()])
+ self._fro = {value.lower(): key for key, value in self._to.items()}
if self._to is None and self._fro is not None:
- self._to = dict([(value.lower(), key) for key, value in self._fro.items()])
+ self._to = {value.lower(): key for key, value in self._fro.items()}
def from_dict(self, mapdict):
"""Import the attribute map from a dictionary
@@ -254,11 +253,11 @@ class AttributeConverter(object):
self.name_format = mapdict["identifier"]
try:
- self._fro = dict([(k.lower(), v) for k, v in mapdict["fro"].items()])
+ self._fro = {k.lower(): v for k, v in mapdict["fro"].items()}
except KeyError:
pass
try:
- self._to = dict([(k.lower(), v) for k, v in mapdict["to"].items()])
+ self._to = {k.lower(): v for k, v in mapdict["to"].items()}
except KeyError:
pass
diff --git a/src/saml2/attribute_resolver.py b/src/saml2/attribute_resolver.py
index c89dd095..e555c58c 100644
--- a/src/saml2/attribute_resolver.py
+++ b/src/saml2/attribute_resolver.py
@@ -1,5 +1,4 @@
#!/usr/bin/env python
-# -*- coding: utf-8 -*-
#
"""
@@ -17,7 +16,7 @@ logger = logging.getLogger(__name__)
DEFAULT_BINDING = BINDING_SOAP
-class AttributeResolver(object):
+class AttributeResolver:
def __init__(self, saml2client, metadata=None, config=None):
self.metadata = metadata
self.saml2client = saml2client
diff --git a/src/saml2/authn.py b/src/saml2/authn.py
index 156c3795..1ed41152 100644
--- a/src/saml2/authn.py
+++ b/src/saml2/authn.py
@@ -1,10 +1,10 @@
import logging
import time
+from urllib.parse import parse_qs
+from urllib.parse import urlencode
+from urllib.parse import urlsplit
import six
-from six.moves.urllib.parse import parse_qs
-from six.moves.urllib.parse import urlencode
-from six.moves.urllib.parse import urlsplit
from saml2 import SAMLError
import saml2.cryptography.symmetric
@@ -28,7 +28,7 @@ class EncodeError(SAMLError):
pass
-class UserAuthnMethod(object):
+class UserAuthnMethod:
def __init__(self, srv):
self.srv = srv
@@ -80,7 +80,7 @@ def create_return_url(base, query, **kwargs):
for key, values in parse_qs(query).items():
if key in kwargs:
- if isinstance(kwargs[key], six.string_types):
+ if isinstance(kwargs[key], str):
kwargs[key] = [kwargs[key]]
kwargs[key].extend(values)
else:
@@ -89,7 +89,7 @@ def create_return_url(base, query, **kwargs):
if part.query:
for key, values in parse_qs(part.query).items():
if key in kwargs:
- if isinstance(kwargs[key], six.string_types):
+ if isinstance(kwargs[key], str):
kwargs[key] = [kwargs[key]]
kwargs[key].extend(values)
else:
@@ -101,7 +101,7 @@ def create_return_url(base, query, **kwargs):
logger.debug("kwargs: %s" % kwargs)
- return "%s?%s" % (_pre, url_encode_params(kwargs))
+ return f"{_pre}?{url_encode_params(kwargs)}"
class UsernamePasswordMako(UserAuthnMethod):
@@ -166,7 +166,7 @@ class UsernamePasswordMako(UserAuthnMethod):
"""
# logger.debug("verify(%s)" % request)
- if isinstance(request, six.string_types):
+ if isinstance(request, str):
_dict = parse_qs(request)
elif isinstance(request, dict):
_dict = request
@@ -225,7 +225,7 @@ class SocialService(UserAuthnMethod):
return self.social.callback(server_env, cookie, sid, query, **kwargs)
-class AuthnMethodChooser(object):
+class AuthnMethodChooser:
def __init__(self, methods=None):
self.methods = methods
diff --git a/src/saml2/authn_context/__init__.py b/src/saml2/authn_context/__init__.py
index 8209f7df..76649529 100644
--- a/src/saml2/authn_context/__init__.py
+++ b/src/saml2/authn_context/__init__.py
@@ -26,7 +26,7 @@ AL4 = "http://idmanagement.gov/icam/2009/12/saml_2.0_profile/assurancelevel4"
CMP_TYPE = ["exact", "minimum", "maximum", "better"]
-class AuthnBroker(object):
+class AuthnBroker:
def __init__(self):
self.db = {"info": {}, "key": {}}
self.next = 0
diff --git a/src/saml2/cache.py b/src/saml2/cache.py
index dab91546..172afe98 100644
--- a/src/saml2/cache.py
+++ b/src/saml2/cache.py
@@ -30,7 +30,7 @@ class CacheError(SAMLError):
pass
-class Cache(object):
+class Cache:
def __init__(self, filename=None):
if filename:
self._db = shelve.open(filename, writeback=True, protocol=2)
@@ -108,7 +108,7 @@ class Cache(object):
if check_not_on_or_after and time_util.after(timestamp):
raise TooOld("past %s" % str(timestamp))
- if "name_id" in info and isinstance(info["name_id"], six.string_types):
+ if "name_id" in info and isinstance(info["name_id"], str):
info["name_id"] = decode(info["name_id"])
return info or None
@@ -123,7 +123,7 @@ class Cache(object):
:param not_on_or_after: A time after which the assertion is not valid.
"""
info = dict(info)
- if "name_id" in info and not isinstance(info["name_id"], six.string_types):
+ if "name_id" in info and not isinstance(info["name_id"], str):
# make friendly to (JSON) serialization
info["name_id"] = code(name_id)
diff --git a/src/saml2/cert.py b/src/saml2/cert.py
index 2354a714..08f0bd25 100644
--- a/src/saml2/cert.py
+++ b/src/saml2/cert.py
@@ -25,7 +25,7 @@ class PayloadError(Exception):
pass
-class OpenSSLWrapper(object):
+class OpenSSLWrapper:
def __init__(self):
pass
@@ -165,15 +165,15 @@ class OpenSSLWrapper(object):
tmp_key = None
if cipher_passphrase is not None:
passphrase = cipher_passphrase["passphrase"]
- if isinstance(cipher_passphrase["passphrase"], six.string_types):
+ if isinstance(cipher_passphrase["passphrase"], str):
passphrase = passphrase.encode("utf-8")
tmp_key = crypto.dump_privatekey(crypto.FILETYPE_PEM, k, cipher_passphrase["cipher"], passphrase)
else:
tmp_key = crypto.dump_privatekey(crypto.FILETYPE_PEM, k)
if write_to_file:
- with open(c_f, "wt") as fc:
+ with open(c_f, "w") as fc:
fc.write(tmp_cert.decode("utf-8"))
- with open(k_f, "wt") as fk:
+ with open(k_f, "w") as fk:
fk.write(tmp_key.decode("utf-8"))
return c_f, k_f
return tmp_cert, tmp_key
@@ -181,7 +181,7 @@ class OpenSSLWrapper(object):
raise CertificateError("Certificate cannot be generated.", ex)
def write_str_to_file(self, file, str_data):
- with open(file, "wt") as f:
+ with open(file, "w") as f:
f.write(str_data)
def read_str_from_file(self, file, type="pem"):
@@ -256,7 +256,7 @@ class OpenSSLWrapper(object):
cert.sign(ca_key, hash_alg)
cert_dump = crypto.dump_certificate(crypto.FILETYPE_PEM, cert)
- if isinstance(cert_dump, six.string_types):
+ if isinstance(cert_dump, str):
return cert_dump
return cert_dump.decode("utf-8")
@@ -323,9 +323,8 @@ class OpenSSLWrapper(object):
return False, ("CN may not be equal for CA certificate and the " "signed certificate.")
cert_algorithm = cert.get_signature_algorithm()
- if six.PY3:
- cert_algorithm = cert_algorithm.decode("ascii")
- cert_str = cert_str.encode("ascii")
+ cert_algorithm = cert_algorithm.decode("ascii")
+ cert_str = cert_str.encode("ascii")
cert_crypto = saml2.cryptography.pki.load_pem_x509_certificate(cert_str)
diff --git a/src/saml2/client.py b/src/saml2/client.py
index bf07cf6a..018ae6ef 100644
--- a/src/saml2/client.py
+++ b/src/saml2/client.py
@@ -1,5 +1,4 @@
# !/usr/bin/env python
-# -*- coding: utf-8 -*-
#
import six
@@ -88,9 +87,7 @@ class Saml2Client(Base):
)
if negotiated_binding != binding:
- raise ValueError(
- "Negotiated binding '{}' does not match binding to use '{}'".format(negotiated_binding, binding)
- )
+ raise ValueError(f"Negotiated binding '{negotiated_binding}' does not match binding to use '{binding}'")
return reqid, info
@@ -212,7 +209,7 @@ class Saml2Client(Base):
conversation.
"""
- if isinstance(name_id, six.string_types):
+ if isinstance(name_id, str):
name_id = decode(name_id)
logger.debug("logout request for: %s", name_id)
@@ -379,7 +376,7 @@ class Saml2Client(Base):
if not_done:
# upstream should try later
- raise LogoutError("%s" % (entity_ids,))
+ raise LogoutError(f"{entity_ids}")
return responses
@@ -505,9 +502,9 @@ class Saml2Client(Base):
srvs = self.metadata.assertion_id_request_service(entity_id, BINDING_SOAP)
if not srvs:
- raise NoServiceDefined("%s: %s" % (entity_id, "assertion_id_request_service"))
+ raise NoServiceDefined("{}: {}".format(entity_id, "assertion_id_request_service"))
- if isinstance(assertion_ids, six.string_types):
+ if isinstance(assertion_ids, str):
assertion_ids = [assertion_ids]
_id_refs = [AssertionIDRef(_id) for _id in assertion_ids]
diff --git a/src/saml2/client_base.py b/src/saml2/client_base.py
index 69f1b3af..146ae45c 100644
--- a/src/saml2/client_base.py
+++ b/src/saml2/client_base.py
@@ -1,5 +1,4 @@
#!/usr/bin/env python
-# -*- coding: utf-8 -*-
#
"""Contains classes and functions that a SAML2.0 Service Provider (SP) may use
@@ -9,12 +8,12 @@ import logging
import threading
import time
from typing import Mapping
+from urllib.parse import parse_qs
+from urllib.parse import urlencode
+from urllib.parse import urlparse
from warnings import warn as _warn
import six
-from six.moves.urllib.parse import parse_qs
-from six.moves.urllib.parse import urlencode
-from six.moves.urllib.parse import urlparse
import saml2
from saml2 import BINDING_HTTP_POST
@@ -383,7 +382,7 @@ class Base(Entity):
if isinstance(_item, _msg.child_class(param)):
args[param] = _item
else:
- raise ValueError("Wrong type for param {name}".format(name=param))
+ raise ValueError(f"Wrong type for param {param}")
# NameIDPolicy
nameid_policy_format_config = self.config.getattr("name_id_policy_format", "sp")
@@ -513,7 +512,7 @@ class Base(Entity):
pass
else:
raise AttributeError("Missing required parameter")
- elif isinstance(name_id, six.string_types):
+ elif isinstance(name_id, str):
name_id = saml.NameID(text=name_id)
for key in ["sp_name_qualifier", "name_qualifier", "format"]:
try:
@@ -627,7 +626,7 @@ class Base(Entity):
"""
if action:
- if isinstance(action, six.string_types):
+ if isinstance(action, str):
_action = [saml.Action(text=action)]
else:
_action = [saml.Action(text=a) for a in action]
@@ -657,7 +656,7 @@ class Base(Entity):
:return: One ID ref
"""
- if isinstance(assertion_id_refs, six.string_types):
+ if isinstance(assertion_id_refs, str):
return 0, assertion_id_refs
else:
return 0, assertion_id_refs[0]
@@ -1003,9 +1002,9 @@ class Base(Entity):
params = urlencode({k: v for k, v in args.items() if v})
# url can already contain some parameters
if "?" in url:
- return "%s&%s" % (url, params)
+ return f"{url}&{params}"
else:
- return "%s?%s" % (url, params)
+ return f"{url}?{params}"
@staticmethod
def parse_discovery_service_response(url="", query="", returnIDParam="entityID"):
diff --git a/src/saml2/config.py b/src/saml2/config.py
index a92642d9..dcf8fd75 100644
--- a/src/saml2/config.py
+++ b/src/saml2/config.py
@@ -163,7 +163,7 @@ class ConfigurationError(SAMLError):
pass
-class Config(object):
+class Config:
def_context = ""
def __init__(self, homedir="."):
@@ -234,7 +234,7 @@ class Config(object):
if context == "":
setattr(self, attr, val)
else:
- setattr(self, "_%s_%s" % (context, attr), val)
+ setattr(self, f"_{context}_{attr}", val)
def getattr(self, attr, context=None):
if context is None:
@@ -243,7 +243,7 @@ class Config(object):
if context == "":
return getattr(self, attr, None)
else:
- return getattr(self, "_%s_%s" % (context, attr), None)
+ return getattr(self, f"_{context}_{attr}", None)
def load_special(self, cnf, typ):
for arg in SPEC[typ]:
diff --git a/src/saml2/country_codes.py b/src/saml2/country_codes.py
index bf4b60a4..55271d7b 100644
--- a/src/saml2/country_codes.py
+++ b/src/saml2/country_codes.py
@@ -1,5 +1,4 @@
#!/usr/bin/env python
-# This Python file uses the following encoding: utf-8
# ISO 3166-1 country names and codes from http://opencountrycodes.appspot.com/python
COUNTRIES = (
diff --git a/src/saml2/cryptography/symmetric.py b/src/saml2/cryptography/symmetric.py
index 636bc340..ea4565b8 100644
--- a/src/saml2/cryptography/symmetric.py
+++ b/src/saml2/cryptography/symmetric.py
@@ -18,7 +18,7 @@ from .errors import SymmetricCryptographyError
logger = logging.getLogger(__name__)
-class Fernet(object):
+class Fernet:
"""The default symmetric cryptography method."""
@staticmethod
@@ -97,7 +97,7 @@ class Fernet(object):
_warn(_deprecation_msg, DeprecationWarning)
-class AESCipher(object):
+class AESCipher:
"""[deprecated] Symmetric cryptography method using AES.
The default parameter set is AES 128bit in CBC mode.
@@ -142,18 +142,18 @@ class AESCipher(object):
iv = _os.urandom(self.AES_BLOCK_SIZE)
if len(iv) != self.AES_BLOCK_SIZE:
- raise Exception("Wrong iv size: {}".format(len(iv)))
+ raise Exception(f"Wrong iv size: {len(iv)}")
if bits not in _ciphers.algorithms.AES.key_sizes:
- raise Exception("Unsupported key length: {}".format(bits))
+ raise Exception(f"Unsupported key length: {bits}")
if len(self.key) != bits / 8:
- raise Exception("Wrong Key length: {}".format(len(self.key)))
+ raise Exception(f"Wrong Key length: {len(self.key)}")
try:
mode = self.POSTFIX_MODE[cmode]
except KeyError:
- raise Exception("Unsupported chaining mode: {}".format(cmode))
+ raise Exception(f"Unsupported chaining mode: {cmode}")
cipher = _ciphers.Cipher(_ciphers.algorithms.AES(self.key), mode(iv))
diff --git a/src/saml2/discovery.py b/src/saml2/discovery.py
index f7de497b..d4be1ef3 100644
--- a/src/saml2/discovery.py
+++ b/src/saml2/discovery.py
@@ -1,4 +1,4 @@
-from six.moves.urllib import parse
+from urllib import parse
from saml2.entity import Entity
from saml2.response import VerificationError
@@ -28,7 +28,7 @@ class DiscoveryServer(Entity):
for key in ["isPassive", "return", "returnIDParam", "policy", "entityID"]:
try:
if len(dsr[key]) != 1:
- raise Exception("Invalid DS request keys: {k}".format(k=key))
+ raise Exception(f"Invalid DS request keys: {key}")
dsr[key] = dsr[key][0]
except KeyError:
pass
@@ -77,9 +77,9 @@ class DiscoveryServer(Entity):
part = parse.urlparse(return_url)
if part.query:
# Iff there is a query part add the new info at the end
- return_url = "%s&%s" % (return_url, qp)
+ return_url = f"{return_url}&{qp}"
else:
- return_url = "%s?%s" % (return_url, qp)
+ return_url = f"{return_url}?{qp}"
return return_url
diff --git a/src/saml2/ecp.py b/src/saml2/ecp.py
index 676544c4..4615fc49 100644
--- a/src/saml2/ecp.py
+++ b/src/saml2/ecp.py
@@ -1,5 +1,4 @@
#!/usr/bin/env python
-# -*- coding: utf-8 -*-
#
"""
@@ -31,7 +30,7 @@ logger = logging.getLogger(__name__)
def ecp_capable(headers):
if MIME_PAOS in headers["Accept"]:
if "PAOS" in headers:
- if 'ver="%s";"%s"' % (paos.NAMESPACE, SERVICE) in headers["PAOS"]:
+ if f'ver="{paos.NAMESPACE}";"{SERVICE}"' in headers["PAOS"]:
return True
return False
@@ -70,7 +69,7 @@ def ecp_auth_request(cls, entityid=None, relay_state="", sign=None, sign_alg=Non
# <samlp:AuthnRequest>
# ----------------------------------------
- logger.info("entityid: %s, binding: %s" % (entityid, BINDING_SOAP))
+ logger.info(f"entityid: {entityid}, binding: {BINDING_SOAP}")
location = cls._sso_location(entityid, binding=BINDING_SOAP)
req_id, authn_req = cls.create_authn_request(
diff --git a/src/saml2/ecp_client.py b/src/saml2/ecp_client.py
index 8286ccea..ce1fca2c 100644
--- a/src/saml2/ecp_client.py
+++ b/src/saml2/ecp_client.py
@@ -1,5 +1,4 @@
#!/usr/bin/env python
-# -*- coding: utf-8 -*-
#
"""
@@ -7,10 +6,9 @@ Contains a class that can do SAML ECP Authentication for other python
programs.
"""
+from http import cookiejar as cookielib
import logging
-from six.moves import http_cookiejar as cookielib
-
from saml2 import BINDING_SOAP
from saml2 import SAMLError
from saml2 import saml
@@ -28,7 +26,7 @@ from saml2.s_utils import BadRequest
SERVICE = "urn:oasis:names:tc:SAML:2.0:profiles:SSO:ecp"
-PAOS_HEADER_INFO = 'ver="%s";"%s"' % (paos.NAMESPACE, SERVICE)
+PAOS_HEADER_INFO = f'ver="{paos.NAMESPACE}";"{SERVICE}"'
logger = logging.getLogger(__name__)
@@ -139,9 +137,7 @@ class Client(Entity):
logger.debug("[P2] Got IdP response: %s", response)
if response.status_code != 200:
- raise SAMLError(
- "Request to IdP failed ({status}): {text}".format(status=response.status_code, text=response.text)
- )
+ raise SAMLError(f"Request to IdP failed ({response.status_code}): {response.text}")
# SAMLP response in a SOAP envelope body, ecp response in headers
respdict = self.parse_soap_message(response.text)
@@ -322,7 +318,7 @@ class Client(Entity):
raise
if response.status_code >= 400:
- raise SAMLError("Error performing operation: %s" % (response.text,))
+ raise SAMLError(f"Error performing operation: {response.text}")
return response
diff --git a/src/saml2/entity.py b/src/saml2/entity.py
index aac23afc..b56388d9 100644
--- a/src/saml2/entity.py
+++ b/src/saml2/entity.py
@@ -117,11 +117,11 @@ def create_artifact(entity_id, message_handle, endpoint_index=0):
:param endpoint_index:
:return:
"""
- if not isinstance(entity_id, six.binary_type):
+ if not isinstance(entity_id, bytes):
entity_id = entity_id.encode("utf-8")
sourceid = sha1(entity_id)
- if not isinstance(message_handle, six.binary_type):
+ if not isinstance(message_handle, bytes):
message_handle = message_handle.encode("utf-8")
ter = b"".join((ARTIFACT_TYPECODE, ("%.2x" % endpoint_index).encode("ascii"), sourceid.digest(), message_handle))
return base64.b64encode(ter).decode("ascii")
@@ -182,7 +182,7 @@ class Entity(HTTPBase):
self.sec = security_context(self.config)
if virtual_organization:
- if isinstance(virtual_organization, six.string_types):
+ if isinstance(virtual_organization, str):
self.vorg = self.config.vorg[virtual_organization]
elif isinstance(virtual_organization, VirtualOrg):
self.vorg = virtual_organization
@@ -268,7 +268,7 @@ class Entity(HTTPBase):
sign = sign if sign is not None else self.should_sign
sign_alg = sigalg or self.signing_algorithm
if sign_alg not in [long_name for short_name, long_name in SIG_ALLOWED_ALG]:
- raise Exception("Signature algo not in allowed list: {algo}".format(algo=sign_alg))
+ raise Exception(f"Signature algo not in allowed list: {sign_alg}")
# unless if BINDING_HTTP_ARTIFACT
if response:
@@ -499,9 +499,9 @@ class Entity(HTTPBase):
sign_alg = sign_alg or self.signing_algorithm
digest_alg = digest_alg or self.digest_algorithm
if sign_alg not in [long_name for short_name, long_name in SIG_ALLOWED_ALG]:
- raise Exception("Signature algo not in allowed list: {algo}".format(algo=sign_alg))
+ raise Exception(f"Signature algo not in allowed list: {sign_alg}")
if digest_alg not in [long_name for short_name, long_name in DIGEST_ALLOWED_ALG]:
- raise Exception("Digest algo not in allowed list: {algo}".format(algo=digest_alg))
+ raise Exception(f"Digest algo not in allowed list: {digest_alg}")
if msg.signature is None:
msg.signature = pre_signature_part(msg.id, self.sec.my_cert, 1, sign_alg=sign_alg, digest_alg=digest_alg)
diff --git a/src/saml2/eptid.py b/src/saml2/eptid.py
index de32015e..65108d4c 100644
--- a/src/saml2/eptid.py
+++ b/src/saml2/eptid.py
@@ -14,7 +14,7 @@ import six
logger = logging.getLogger(__name__)
-class Eptid(object):
+class Eptid:
def __init__(self, secret):
self._db = {}
self.secret = secret
@@ -23,27 +23,27 @@ class Eptid(object):
md5 = hashlib.md5()
for arg in args:
md5.update(arg.encode("utf-8"))
- if isinstance(sp, six.binary_type):
+ if isinstance(sp, bytes):
md5.update(sp)
else:
md5.update(sp.encode("utf-8"))
- if isinstance(self.secret, six.binary_type):
+ if isinstance(self.secret, bytes):
md5.update(self.secret)
else:
md5.update(self.secret.encode("utf-8"))
md5.digest()
hashval = md5.hexdigest()
- if isinstance(hashval, six.binary_type):
+ if isinstance(hashval, bytes):
hashval = hashval.decode("ascii")
return "!".join([idp, sp, hashval])
def __getitem__(self, key):
- if six.PY3 and isinstance(key, six.binary_type):
+ if six.PY3 and isinstance(key, bytes):
key = key.decode("utf-8")
return self._db[key]
def __setitem__(self, key, value):
- if six.PY3 and isinstance(key, six.binary_type):
+ if six.PY3 and isinstance(key, bytes):
key = key.decode("utf-8")
self._db[key] = value
@@ -64,9 +64,8 @@ class Eptid(object):
class EptidShelve(Eptid):
def __init__(self, secret, filename):
Eptid.__init__(self, secret)
- if six.PY3:
- if filename.endswith(".db"):
- filename = filename.rsplit(".db", 1)[0]
+ if filename.endswith(".db"):
+ filename = filename.rsplit(".db", 1)[0]
self._db = shelve.open(filename, writeback=True, protocol=2)
def close(self):
diff --git a/src/saml2/filter.py b/src/saml2/filter.py
index 6aad1000..849cfe5d 100644
--- a/src/saml2/filter.py
+++ b/src/saml2/filter.py
@@ -1,7 +1,7 @@
__author__ = "roland"
-class Filter(object):
+class Filter:
def __init__(self):
pass
@@ -16,7 +16,7 @@ class AllowDescriptor(Filter):
:param allow: List of allowed descriptors
:return:
"""
- super(AllowDescriptor, self).__init__()
+ super().__init__()
self.allow = allow
def __call__(self, entity_descriptor):
diff --git a/src/saml2/httpbase.py b/src/saml2/httpbase.py
index 4c0a5ad4..f183cf8e 100644
--- a/src/saml2/httpbase.py
+++ b/src/saml2/httpbase.py
@@ -1,14 +1,14 @@
import calendar
import copy
+from http.cookies import SimpleCookie
import logging
import re
import time
+from urllib.parse import urlencode
+from urllib.parse import urlparse
import requests
from six.moves import http_cookiejar
-from six.moves.http_cookies import SimpleCookie
-from six.moves.urllib.parse import urlencode
-from six.moves.urllib.parse import urlparse
from saml2 import SAMLError
from saml2 import class_name
@@ -80,7 +80,7 @@ def _since_epoch(cdate):
break
if t == -1:
- err = 'ValueError: Date "{0}" does not match any of: {1}'.format(cdate, TIME_FORMAT)
+ err = f'ValueError: Date "{cdate}" does not match any of: {TIME_FORMAT}'
raise Exception(err)
return calendar.timegm(t)
@@ -94,7 +94,7 @@ def dict2set_list(dic):
return [(k, v) for k, v in dic.items()]
-class HTTPBase(object):
+class HTTPBase:
def __init__(self, verify=True, ca_bundle=None, key_file=None, cert_file=None, http_client_timeout=None):
self.request_args = {"allow_redirects": False}
# self.cookies = {}
@@ -250,7 +250,7 @@ class HTTPBase(object):
query = urlencode({"SAMLart": message, "RelayState": relay_state})
else:
query = urlencode({"SAMLart": message})
- info = {"data": "", "url": "%s?%s" % (destination, query)}
+ info = {"data": "", "url": f"{destination}?{query}"}
return info
@staticmethod
@@ -274,7 +274,7 @@ class HTTPBase(object):
query = urlencode({"ID": message, "RelayState": relay_state})
else:
query = urlencode({"ID": message})
- info = {"data": "", "url": "%s?%s" % (destination, query)}
+ info = {"data": "", "url": f"{destination}?{query}"}
else:
raise NotImplementedError
diff --git a/src/saml2/httputil.py b/src/saml2/httputil.py
index 2e5e7c27..e0d9bd24 100644
--- a/src/saml2/httputil.py
+++ b/src/saml2/httputil.py
@@ -1,13 +1,13 @@
import cgi
import hashlib
import hmac
+from http.cookies import SimpleCookie
import logging
import time
+from urllib.parse import parse_qs
+from urllib.parse import quote
import six
-from six.moves.http_cookies import SimpleCookie
-from six.moves.urllib.parse import parse_qs
-from six.moves.urllib.parse import quote
from saml2 import BINDING_HTTP_ARTIFACT
from saml2 import BINDING_HTTP_POST
@@ -23,7 +23,7 @@ __author__ = "rohe0002"
logger = logging.getLogger(__name__)
-class Response(object):
+class Response:
_template = None
_status = "200 OK"
_content_type = "text/html"
@@ -63,9 +63,9 @@ class Response(object):
mte = self.mako_lookup.get_template(self.mako_template)
message = mte.render(**argv)
- if isinstance(message, six.string_types):
+ if isinstance(message, str):
return [message.encode("utf-8")]
- elif isinstance(message, six.binary_type):
+ elif isinstance(message, bytes):
return [message]
else:
return message
@@ -159,7 +159,7 @@ class BadGateway(Response):
_status = "502 Bad Gateway"
-class HttpParameters(object):
+class HttpParameters:
"""GET or POST signature parameters for Redirect or POST-SimpleSign bindings
because they are not contained in XML unlike the POST binding
"""
@@ -253,13 +253,13 @@ def get_response(environ, start_response):
def unpack_redirect(environ):
if "QUERY_STRING" in environ:
_qs = environ["QUERY_STRING"]
- return dict([(k, v[0]) for k, v in parse_qs(_qs).items()])
+ return {k: v[0] for k, v in parse_qs(_qs).items()}
else:
return None
def unpack_post(environ):
- return dict([(k, v[0]) for k, v in parse_qs(get_post(environ))])
+ return {k: v[0] for k, v in parse_qs(get_post(environ))}
def unpack_soap(environ):
diff --git a/src/saml2/ident.py b/src/saml2/ident.py
index d52051d1..d94dd756 100644
--- a/src/saml2/ident.py
+++ b/src/saml2/ident.py
@@ -2,10 +2,10 @@ import copy
from hashlib import sha256
import logging
import shelve
+from urllib.parse import quote
+from urllib.parse import unquote
import six
-from six.moves.urllib.parse import quote
-from six.moves.urllib.parse import unquote
from saml2 import SAMLError
from saml2.s_utils import PolicyError
@@ -52,7 +52,7 @@ def code_binary(item):
Return a binary 'code' suitable for hashing.
"""
code_str = code(item)
- if isinstance(code_str, six.string_types):
+ if isinstance(code_str, str):
return code_str.encode("utf-8")
return code_str
@@ -73,13 +73,13 @@ def decode(txt):
return _nid
-class IdentDB(object):
+class IdentDB:
"""A class that handles identifiers of entities
Keeps a list of all nameIDs returned per SP
"""
def __init__(self, db, domain="", name_qualifier=""):
- if isinstance(db, six.string_types):
+ if isinstance(db, str):
self.db = shelve.open(db, protocol=2)
else:
self.db = db
@@ -88,15 +88,15 @@ class IdentDB(object):
def _create_id(self, nformat, name_qualifier="", sp_name_qualifier=""):
_id = sha256(rndbytes(32))
- if not isinstance(nformat, six.binary_type):
+ if not isinstance(nformat, bytes):
nformat = nformat.encode("utf-8")
_id.update(nformat)
if name_qualifier:
- if not isinstance(name_qualifier, six.binary_type):
+ if not isinstance(name_qualifier, bytes):
name_qualifier = name_qualifier.encode("utf-8")
_id.update(name_qualifier)
if sp_name_qualifier:
- if not isinstance(sp_name_qualifier, six.binary_type):
+ if not isinstance(sp_name_qualifier, bytes):
sp_name_qualifier = sp_name_qualifier.encode("utf-8")
_id.update(sp_name_qualifier)
return _id.hexdigest()
@@ -160,7 +160,7 @@ class IdentDB(object):
if nformat == NAMEID_FORMAT_PERSISTENT:
nameid = self.match_local_id(userid, sp_name_qualifier, name_qualifier)
if nameid:
- logger.debug("Found existing persistent NameId %s for user %s" % (nameid, userid))
+ logger.debug(f"Found existing persistent NameId {nameid} for user {userid}")
return nameid
_id = self.create_id(nformat, name_qualifier, sp_name_qualifier)
@@ -169,7 +169,7 @@ class IdentDB(object):
if not self.domain:
raise SAMLError("Can't issue email nameids, unknown domain")
- _id = "%s@%s" % (_id, self.domain)
+ _id = f"{_id}@{self.domain}"
nameid = NameID(
format=nformat,
diff --git a/src/saml2/mcache.py b/src/saml2/mcache.py
index f89e616c..9540d0f0 100644
--- a/src/saml2/mcache.py
+++ b/src/saml2/mcache.py
@@ -16,10 +16,10 @@ logger = logging.getLogger(__name__)
def _key(prefix, name):
- return "%s_%s" % (prefix, name)
+ return f"{prefix}_{name}"
-class Cache(object):
+class Cache:
def __init__(self, servers, debug=0):
self._cache = memcache.Client(servers, debug)
diff --git a/src/saml2/mdbcache.py b/src/saml2/mdbcache.py
index 01b50e13..20215bb6 100644
--- a/src/saml2/mdbcache.py
+++ b/src/saml2/mdbcache.py
@@ -17,7 +17,7 @@ from saml2.time_util import TIME_FORMAT
logger = logging.getLogger(__name__)
-class Cache(object):
+class Cache:
def __init__(self, server=None, debug=0, db=None):
if server:
connection = MongoClient(server)
diff --git a/src/saml2/mdie.py b/src/saml2/mdie.py
index 9a741495..c5d30557 100644
--- a/src/saml2/mdie.py
+++ b/src/saml2/mdie.py
@@ -26,7 +26,7 @@ def _eval(val, onts, mdb_safe):
:param onts: Schemas to be used in the conversion
:return: The basic dictionary
"""
- if isinstance(val, six.string_types):
+ if isinstance(val, str):
val = val.strip()
if not val:
return None
@@ -57,7 +57,7 @@ def to_dict(_dict, onts, mdb_safe=False):
"""
res = {}
if isinstance(_dict, SamlBase):
- res["__class__"] = "%s&%s" % (_dict.c_namespace, _dict.c_tag)
+ res["__class__"] = f"{_dict.c_namespace}&{_dict.c_tag}"
for key in _dict.keyswv():
if key in IMP_SKIP:
continue
@@ -67,7 +67,7 @@ def to_dict(_dict, onts, mdb_safe=False):
_val = [_eval(_v, onts, mdb_safe) for _v in _eel]
elif key == "extension_attributes":
if mdb_safe:
- _val = dict([(k.replace(".", "__"), v) for k, v in val.items()])
+ _val = {k.replace(".", "__"): v for k, v in val.items()}
# _val = {k.replace(".", "__"): v for k, v in val.items()}
else:
_val = val
@@ -86,7 +86,7 @@ def to_dict(_dict, onts, mdb_safe=False):
for _val in [_eval(val, onts, mdb_safe)]
if _val
}
- res["__class__"] = "%s&%s" % (_dict.namespace, _dict.tag)
+ res["__class__"] = f"{_dict.namespace}&{_dict.tag}"
else:
for key, val in _dict.items():
_val = _eval(val, onts, mdb_safe)
@@ -110,11 +110,11 @@ def _kwa(val, onts, mdb_safe=False):
:return: A converted dictionary
"""
if not mdb_safe:
- return dict([(k, from_dict(v, onts)) for k, v in val.items() if k not in EXP_SKIP])
+ return {k: from_dict(v, onts) for k, v in val.items() if k not in EXP_SKIP}
else:
_skip = ["_id"]
_skip.extend(EXP_SKIP)
- return dict([(k.replace("__", "."), from_dict(v, onts)) for k, v in val.items() if k not in _skip])
+ return {k.replace("__", "."): from_dict(v, onts) for k, v in val.items() if k not in _skip}
def from_dict(val, onts, mdb_safe=False):
@@ -151,7 +151,7 @@ def from_dict(val, onts, mdb_safe=False):
key = key.replace("__", ".")
res[key] = from_dict(v, onts)
return res
- elif isinstance(val, six.string_types):
+ elif isinstance(val, str):
return val
elif isinstance(val, list):
return [from_dict(v, onts) for v in val]
diff --git a/src/saml2/mdstore.py b/src/saml2/mdstore.py
index 3030f6a7..8dc9e636 100644
--- a/src/saml2/mdstore.py
+++ b/src/saml2/mdstore.py
@@ -1,5 +1,3 @@
-from __future__ import print_function
-
import hashlib
from hashlib import sha1
import importlib
@@ -69,21 +67,21 @@ from saml2.validate import valid_instance
logger = logging.getLogger(__name__)
classnames = {
- "mdattr_entityattributes": "{ns}&{tag}".format(ns=NS_MDATTR, tag=EntityAttributes.c_tag),
- "algsupport_signing_method": "{ns}&{tag}".format(ns=NS_ALGSUPPORT, tag=SigningMethod.c_tag),
- "algsupport_digest_method": "{ns}&{tag}".format(ns=NS_ALGSUPPORT, tag=DigestMethod.c_tag),
- "mdui_uiinfo": "{ns}&{tag}".format(ns=NS_MDUI, tag=UIInfo.c_tag),
- "mdui_uiinfo_display_name": "{ns}&{tag}".format(ns=NS_MDUI, tag=DisplayName.c_tag),
- "mdui_uiinfo_description": "{ns}&{tag}".format(ns=NS_MDUI, tag=Description.c_tag),
- "mdui_uiinfo_information_url": "{ns}&{tag}".format(ns=NS_MDUI, tag=InformationURL.c_tag),
- "mdui_uiinfo_privacy_statement_url": "{ns}&{tag}".format(ns=NS_MDUI, tag=PrivacyStatementURL.c_tag),
- "mdui_uiinfo_logo": "{ns}&{tag}".format(ns=NS_MDUI, tag=Logo.c_tag),
- "service_artifact_resolution": "{ns}&{tag}".format(ns=NS_MD, tag=ArtifactResolutionService.c_tag),
- "service_single_sign_on": "{ns}&{tag}".format(ns=NS_MD, tag=SingleSignOnService.c_tag),
- "service_nameid_mapping": "{ns}&{tag}".format(ns=NS_MD, tag=NameIDMappingService.c_tag),
- "mdrpi_registration_info": "{ns}&{tag}".format(ns=NS_MDRPI, tag=RegistrationInfo.c_tag),
- "mdrpi_registration_policy": "{ns}&{tag}".format(ns=NS_MDRPI, tag=RegistrationPolicy.c_tag),
- "shibmd_scope": "{ns}&{tag}".format(ns=NS_SHIBMD, tag=Scope.c_tag),
+ "mdattr_entityattributes": f"{NS_MDATTR}&{EntityAttributes.c_tag}",
+ "algsupport_signing_method": f"{NS_ALGSUPPORT}&{SigningMethod.c_tag}",
+ "algsupport_digest_method": f"{NS_ALGSUPPORT}&{DigestMethod.c_tag}",
+ "mdui_uiinfo": f"{NS_MDUI}&{UIInfo.c_tag}",
+ "mdui_uiinfo_display_name": f"{NS_MDUI}&{DisplayName.c_tag}",
+ "mdui_uiinfo_description": f"{NS_MDUI}&{Description.c_tag}",
+ "mdui_uiinfo_information_url": f"{NS_MDUI}&{InformationURL.c_tag}",
+ "mdui_uiinfo_privacy_statement_url": f"{NS_MDUI}&{PrivacyStatementURL.c_tag}",
+ "mdui_uiinfo_logo": f"{NS_MDUI}&{Logo.c_tag}",
+ "service_artifact_resolution": f"{NS_MD}&{ArtifactResolutionService.c_tag}",
+ "service_single_sign_on": f"{NS_MD}&{SingleSignOnService.c_tag}",
+ "service_nameid_mapping": f"{NS_MD}&{NameIDMappingService.c_tag}",
+ "mdrpi_registration_info": f"{NS_MDRPI}&{RegistrationInfo.c_tag}",
+ "mdrpi_registration_policy": f"{NS_MDRPI}&{RegistrationPolicy.c_tag}",
+ "shibmd_scope": f"{NS_SHIBMD}&{Scope.c_tag}",
}
ENTITY_CATEGORY = "http://macedir.org/entity-category"
@@ -242,7 +240,7 @@ def repack_cert(cert):
return "\n".join([s.strip() for s in part])
-class MetaData(object):
+class MetaData:
def __init__(self, attrc, metadata="", node_name=None, check_validity=True, security=None, **kwargs):
self.attrc = attrc
self.metadata = metadata
@@ -380,7 +378,7 @@ class MetaData(object):
for entid, item in self.items():
hit = False
try:
- descr = item["{}sso_descriptor".format(typ)]
+ descr = item[f"{typ}sso_descriptor"]
except KeyError:
continue
else:
@@ -507,7 +505,7 @@ class MetaData(object):
class InMemoryMetaData(MetaData):
def __init__(self, attrc, metadata="", node_name=None, check_validity=True, security=None, **kwargs):
- super(InMemoryMetaData, self).__init__(attrc, metadata=metadata)
+ super().__init__(attrc, metadata=metadata)
self.entity = {}
self.security = security
self.node_name = node_name
@@ -696,7 +694,7 @@ class InMemoryMetaData(MetaData):
try:
for srv in ent[desc]:
if "artifact_resolution_service" in srv:
- if isinstance(eid, six.string_types):
+ if isinstance(eid, str):
eid = eid.encode("utf-8")
s = sha1(eid)
res[s.digest()] = ent
@@ -769,7 +767,7 @@ class MetaDataFile(InMemoryMetaData):
"""
def __init__(self, attrc, filename=None, cert=None, **kwargs):
- super(MetaDataFile, self).__init__(attrc, **kwargs)
+ super().__init__(attrc, **kwargs)
if not filename:
raise SAMLError("No file specified.")
self.filename = filename
@@ -791,7 +789,7 @@ class MetaDataLoader(MetaDataFile):
"""
def __init__(self, attrc, loader_callable, cert=None, security=None, **kwargs):
- super(MetaDataLoader, self).__init__(attrc, **kwargs)
+ super().__init__(attrc, **kwargs)
self.metadata_provider_callable = self.get_metadata_loader(loader_callable)
self.cert = cert
self.security = security
@@ -806,15 +804,15 @@ class MetaDataLoader(MetaDataFile):
try:
mod = importlib.import_module(module)
except Exception as e:
- raise RuntimeError('Cannot find metadata provider function %s: "%s"' % (func, e))
+ raise RuntimeError(f'Cannot find metadata provider function {func}: "{e}"')
try:
metadata_loader = getattr(mod, attr)
except AttributeError:
- raise RuntimeError('Module "%s" does not define a "%s" metadata loader' % (module, attr))
+ raise RuntimeError(f'Module "{module}" does not define a "{attr}" metadata loader')
if not callable(metadata_loader):
- raise RuntimeError("Metadata loader %s.%s must be callable" % (module, attr))
+ raise RuntimeError(f"Metadata loader {module}.{attr} must be callable")
return metadata_loader
@@ -836,7 +834,7 @@ class MetaDataExtern(InMemoryMetaData):
:params cert: CertificMDloaderate used to sign the metadata
:params http:
"""
- super(MetaDataExtern, self).__init__(attrc, **kwargs)
+ super().__init__(attrc, **kwargs)
if not url:
raise SAMLError("URL not specified.")
else:
@@ -869,7 +867,7 @@ class MetaDataMD(InMemoryMetaData):
"""
def __init__(self, attrc, filename, **kwargs):
- super(MetaDataMD, self).__init__(attrc, **kwargs)
+ super().__init__(attrc, **kwargs)
self.filename = filename
def load(self, *args, **kwargs):
@@ -889,7 +887,7 @@ class MetaDataMDX(InMemoryMetaData):
@staticmethod
def sha1_entity_transform(entity_id):
entity_id_sha1 = hashlib.sha1(entity_id.encode("utf-8")).hexdigest()
- transform = "{{sha1}}{digest}".format(digest=entity_id_sha1)
+ transform = f"{{sha1}}{entity_id_sha1}"
return transform
def __init__(
@@ -915,7 +913,7 @@ class MetaDataMDX(InMemoryMetaData):
https://www.w3.org/TR/xmlschema-2/#duration
:params http_client_timeout: timeout of http requests
"""
- super(MetaDataMDX, self).__init__(None, **kwargs)
+ super().__init__(None, **kwargs)
if not url:
raise SAMLError("URL for MDQ server not specified.")
@@ -938,26 +936,26 @@ class MetaDataMDX(InMemoryMetaData):
# <EntitiesDescriptor> element but we will not currently support
# that use case since it is unlikely to be leveraged for most
# flows.
- self.node_name = "{ns}:{tag}".format(ns=EntityDescriptor.c_namespace, tag=EntityDescriptor.c_tag)
+ self.node_name = f"{EntityDescriptor.c_namespace}:{EntityDescriptor.c_tag}"
def load(self, *args, **kwargs):
# Do nothing
pass
def _fetch_metadata(self, item):
- mdx_url = "{url}/entities/{id}".format(url=self.url, id=self.entity_transform(item))
+ mdx_url = f"{self.url}/entities/{self.entity_transform(item)}"
response = requests.get(
mdx_url, headers={"Accept": SAML_METADATA_CONTENT_TYPE}, timeout=self.http_client_timeout
)
if response.status_code != 200:
- error_msg = "Fething {item}: Got response status {status}".format(item=item, status=response.status_code)
+ error_msg = f"Fething {item}: Got response status {response.status_code}"
logger.warning(error_msg)
raise KeyError(error_msg)
_txt = response.content
if not self.parse_and_check_signature(_txt):
- error_msg = "Fething {item}: invalid signature".format(item=item)
+ error_msg = f"Fething {item}: invalid signature"
logger.error(error_msg)
raise KeyError(error_msg)
@@ -972,7 +970,7 @@ class MetaDataMDX(InMemoryMetaData):
if item not in self.entity:
entity = self._fetch_metadata(item)
elif not self._is_metadata_fresh(item):
- msg = "Metadata for {} have expired; refreshing metadata".format(item)
+ msg = f"Metadata for {item} have expired; refreshing metadata"
logger.info(msg)
_ = self.entity.pop(item)
entity = self._fetch_metadata(item)
@@ -1282,7 +1280,10 @@ class MetadataStore(MetaData):
if binding is None:
binding = BINDING_DISCO
return self.ext_service(
- entity_id, "spsso_descriptor", "%s&%s" % (DiscoveryResponse.c_namespace, DiscoveryResponse.c_tag), binding
+ entity_id,
+ "spsso_descriptor",
+ f"{DiscoveryResponse.c_namespace}&{DiscoveryResponse.c_tag}",
+ binding,
)
def attribute_requirement(self, entity_id, index=None):
@@ -1646,7 +1647,7 @@ class MetadataStore(MetaData):
def __str__(self):
_str = ["{"]
for key, val in self.metadata.items():
- _str.append("%s: %s" % (key, val))
+ _str.append(f"{key}: {val}")
_str.append("}")
return "\n".join(_str)
diff --git a/src/saml2/metadata.py b/src/saml2/metadata.py
index f8aa2c9c..707e1d54 100644
--- a/src/saml2/metadata.py
+++ b/src/saml2/metadata.py
@@ -153,7 +153,7 @@ def do_organization_info(ava):
for dkey, (ckey, klass) in ORG_ATTR_TRANSL.items():
if ckey not in ava:
continue
- if isinstance(ava[ckey], six.string_types):
+ if isinstance(ava[ckey], str):
setattr(org, dkey, [_localized_name(ava[ckey], klass)])
elif isinstance(ava[ckey], list):
setattr(org, dkey, [_localized_name(n, klass) for n in ava[ckey]])
@@ -210,7 +210,7 @@ def do_requested_attribute(attributes, acs, is_required="false", name_format=NAM
for attr in attributes:
attr = from_local_name(acs, attr, name_format)
args = {}
- if isinstance(attr, six.string_types):
+ if isinstance(attr, str):
args["name"] = attr
else:
for key in attr.keyswv():
@@ -231,7 +231,7 @@ def do_uiinfo(_uiinfo):
aclass = uii.child_class(attr)
inst = getattr(uii, attr)
- if isinstance(val, six.string_types):
+ if isinstance(val, str):
ainst = aclass(text=val)
inst.append(ainst)
elif isinstance(val, dict):
@@ -241,7 +241,7 @@ def do_uiinfo(_uiinfo):
inst.append(ainst)
else:
for value in val:
- if isinstance(value, six.string_types):
+ if isinstance(value, str):
ainst = aclass(text=value)
inst.append(ainst)
elif isinstance(value, dict):
@@ -281,7 +281,7 @@ def do_uiinfo(_uiinfo):
if isinstance(val, list):
for value in val:
keyw = mdui.Keywords()
- if isinstance(value, six.string_types):
+ if isinstance(value, str):
keyw.text = value
elif isinstance(value, dict):
keyw.text = " ".join(value["text"])
@@ -369,7 +369,7 @@ def _do_nameid_format(cls, conf, typ):
if not name_id_format:
return
- if isinstance(name_id_format, six.string_types):
+ if isinstance(name_id_format, str):
name_id_format = [name_id_format]
formats = [md.NameIDFormat(text=format) for format in name_id_format]
@@ -384,7 +384,7 @@ def do_endpoints(conf, endpoints):
servs = []
i = 1
for args in conf[endpoint]:
- if isinstance(args, six.string_types): # Assume it's the location
+ if isinstance(args, str): # Assume it's the location
args = {"location": args, "binding": DEFAULT_BINDING[endpoint]}
elif isinstance(args, tuple) or isinstance(args, list):
if len(args) == 2: # (location, binding)
@@ -520,7 +520,7 @@ def do_spsso_descriptor(conf, cert=None, enc_cert=None):
if val is None:
setattr(spsso, key, DEFAULT[key]) # default ?!
else:
- strval = "{0:>s}".format(str(val))
+ strval = f"{str(val):>s}"
setattr(spsso, key, strval.lower())
except KeyError:
setattr(spsso, key, DEFAULTS[key])
diff --git a/src/saml2/mongo_store.py b/src/saml2/mongo_store.py
index cfadd1c3..230a0d09 100644
--- a/src/saml2/mongo_store.py
+++ b/src/saml2/mongo_store.py
@@ -38,7 +38,7 @@ def context_match(cfilter, cntx):
return True
-class SessionStorageMDB(object):
+class SessionStorageMDB:
"""Session information is stored in a MongoDB database"""
def __init__(self, database="", collection="assertion", **kwargs):
@@ -193,7 +193,7 @@ class IdentMDB(IdentDB):
return self.construct_nameid(_id, name_id_policy=name_id_policy)
-class MDB(object):
+class MDB:
primary_key = "mdb"
def __init__(self, database, collection, **kwargs):
@@ -322,14 +322,14 @@ def protect(dic):
res = {}
for key, val in dic.items():
key = key.replace(".", "__")
- if isinstance(val, six.string_types):
+ if isinstance(val, str):
pass
elif isinstance(val, dict):
val = protect(val)
elif isinstance(val, list):
li = []
for va in val:
- if isinstance(va, six.string_types):
+ if isinstance(va, str):
pass
elif isinstance(va, dict):
va = protect(va)
@@ -347,14 +347,14 @@ def unprotect(dic):
pass
else:
key = key.replace("__", ".")
- if isinstance(val, six.string_types):
+ if isinstance(val, str):
pass
elif isinstance(val, dict):
val = unprotect(val)
elif isinstance(val, list):
li = []
for va in val:
- if isinstance(va, six.string_types):
+ if isinstance(va, str):
pass
elif isinstance(val, dict):
va = unprotect(va)
@@ -377,7 +377,7 @@ def export_mdstore_to_mongo_db(mds, database, collection, sub_collection=""):
class MetadataMDB(InMemoryMetaData):
def __init__(self, attrc, database="", collection=""):
- super(MetadataMDB, self).__init__(attrc)
+ super().__init__(attrc)
self.mdb = MDB(database, collection)
self.mdb.primary_key = "entity_id"
diff --git a/src/saml2/pack.py b/src/saml2/pack.py
index c065d2d3..f8328b5c 100644
--- a/src/saml2/pack.py
+++ b/src/saml2/pack.py
@@ -16,10 +16,10 @@ except Exception:
import cgi as html
import logging
+from urllib.parse import urlencode
+from urllib.parse import urlparse
import six
-from six.moves.urllib.parse import urlencode
-from six.moves.urllib.parse import urlparse
import saml2
from saml2.s_utils import deflate_and_base64_encode
@@ -29,7 +29,7 @@ from saml2.xmldsig import SIG_ALLOWED_ALG
try:
- from xml.etree import cElementTree as ElementTree
+ from xml.etree import ElementTree as ElementTree
if ElementTree.VERSION < "1.3.0":
# cElementTree has no support for register_namespace
@@ -89,9 +89,9 @@ def http_form_post_message(message, location, relay_state="", typ="SAMLRequest",
:param relay_state: for preserving and conveying state information
:return: A tuple containing header information and a HTML message.
"""
- if not isinstance(message, six.string_types):
+ if not isinstance(message, str):
message = str(message)
- if not isinstance(message, six.binary_type):
+ if not isinstance(message, bytes):
message = message.encode("utf-8")
if typ == "SAMLRequest" or typ == "SAMLResponse":
@@ -122,9 +122,9 @@ def http_post_message(message, relay_state="", typ="SAMLRequest", **kwargs):
:param relay_state: for preserving and conveying state information
:return: A tuple containing header information and a HTML message.
"""
- if not isinstance(message, six.string_types):
+ if not isinstance(message, str):
message = str(message)
- if not isinstance(message, six.binary_type):
+ if not isinstance(message, bytes):
message = message.encode("utf-8")
if typ == "SAMLRequest" or typ == "SAMLResponse":
@@ -166,8 +166,8 @@ def http_redirect_message(
:return: A tuple containing header information and a HTML message.
"""
- if not isinstance(message, six.string_types):
- message = "%s" % (message,)
+ if not isinstance(message, str):
+ message = f"{message}"
_order = None
if typ in ["SAMLRequest", "SAMLResponse"]:
@@ -187,10 +187,10 @@ def http_redirect_message(
if sign:
# sigalgs, should be one defined in xmldsig
if sigalg not in [long_name for short_name, long_name in SIG_ALLOWED_ALG]:
- raise Exception("Signature algo not in allowed list: {algo}".format(algo=sigalg))
+ raise Exception(f"Signature algo not in allowed list: {sigalg}")
signer = backend.get_signer(sigalg) if sign and sigalg else None
if not signer:
- raise Exception("Could not init signer fro algo {algo}".format(algo=sigalg))
+ raise Exception(f"Could not init signer fro algo {sigalg}")
args["SigAlg"] = sigalg
string = "&".join(urlencode({k: args[k]}) for k in _order if k in args)
@@ -232,7 +232,7 @@ def make_soap_enveloped_saml_thingy(thingy, header_parts=None):
body.tag = "{%s}Body" % NAMESPACE
envelope.append(body)
- if isinstance(thingy, six.string_types):
+ if isinstance(thingy, str):
# remove the first XML version/encoding line
if thingy[0:5].lower() == "<?xml":
logger.debug("thingy0: %s", thingy)
@@ -244,7 +244,7 @@ def make_soap_enveloped_saml_thingy(thingy, header_parts=None):
_child.tag = "{%s}FuddleMuddle" % DUMMY_NAMESPACE
body.append(_child)
_str = ElementTree.tostring(envelope, encoding="UTF-8")
- if isinstance(_str, six.binary_type):
+ if isinstance(_str, bytes):
_str = _str.decode("utf-8")
logger.debug("SOAP precursor: %s", _str)
# find an remove the namespace definition
@@ -252,7 +252,7 @@ def make_soap_enveloped_saml_thingy(thingy, header_parts=None):
j = _str.rfind("xmlns:", 0, i)
cut1 = _str[j : i + len(DUMMY_NAMESPACE) + 1]
_str = _str.replace(cut1, "")
- first = _str.find("<%s:FuddleMuddle" % (cut1[6:9],))
+ first = _str.find(f"<{cut1[6:9]}:FuddleMuddle")
last = _str.find(">", first + 14)
cut2 = _str[first : last + 1]
return _str.replace(cut2, thingy)
@@ -287,9 +287,7 @@ def parse_soap_enveloped_saml(text, body_class, header_class=None):
envelope_tag = "{%s}Envelope" % NAMESPACE
if envelope.tag != envelope_tag:
- raise ValueError(
- "Invalid envelope tag '{invalid}' should be '{valid}'".format(invalid=envelope.tag, valid=envelope_tag)
- )
+ raise ValueError(f"Invalid envelope tag '{envelope.tag}' should be '{envelope_tag}'")
# print(len(envelope))
body = None
@@ -310,7 +308,7 @@ def parse_soap_enveloped_saml(text, body_class, header_class=None):
# print(">>",sub.tag)
for klass in header_class:
# print("?{%s}%s" % (klass.c_namespace,klass.c_tag))
- if sub.tag == "{%s}%s" % (klass.c_namespace, klass.c_tag):
+ if sub.tag == f"{{{klass.c_namespace}}}{klass.c_tag}":
header[sub.tag] = saml2.create_class_from_element_tree(klass, sub)
break
diff --git a/src/saml2/population.py b/src/saml2/population.py
index 72baa830..8c066d63 100644
--- a/src/saml2/population.py
+++ b/src/saml2/population.py
@@ -8,10 +8,10 @@ from saml2.cache import Cache
logger = logging.getLogger(__name__)
-class Population(object):
+class Population:
def __init__(self, cache=None):
if cache:
- if isinstance(cache, six.string_types):
+ if isinstance(cache, str):
self.cache = Cache(cache)
else:
self.cache = cache
diff --git a/src/saml2/request.py b/src/saml2/request.py
index 1d62d0ed..6b8474e6 100644
--- a/src/saml2/request.py
+++ b/src/saml2/request.py
@@ -18,7 +18,7 @@ def _dummy(data, **_arg):
return ""
-class Request(object):
+class Request:
def __init__(self, sec_context, receiver_addrs, attribute_converters=None, timeslack=0):
self.sec = sec_context
self.receiver_addrs = receiver_addrs
@@ -126,9 +126,7 @@ class Request(object):
def _verify(self):
valid_version = "2.0"
if self.message.version != valid_version:
- raise VersionMismatch(
- "Invalid version {invalid} should be {valid}".format(invalid=self.message.version, valid=valid_version)
- )
+ raise VersionMismatch(f"Invalid version {self.message.version} should be {valid_version}")
if self.message.destination and self.receiver_addrs and self.message.destination not in self.receiver_addrs:
logger.error("%s not in %s", self.message.destination, self.receiver_addrs)
diff --git a/src/saml2/response.py b/src/saml2/response.py
index 403bb72b..d6500336 100644
--- a/src/saml2/response.py
+++ b/src/saml2/response.py
@@ -1,5 +1,4 @@
#!/usr/bin/env python
-# -*- coding: utf-8 -*-
#
import calendar
import logging
@@ -220,7 +219,7 @@ def for_me(conditions, myself):
if audience.text and audience.text.strip() == myself:
return True
else:
- logger.debug("AudienceRestriction - One condition not satisfied: %s != %s" % (audience.text, myself))
+ logger.debug(f"AudienceRestriction - One condition not satisfied: {audience.text} != {myself}")
logger.debug("AudienceRestrictions not satisfied!")
return False
@@ -277,7 +276,7 @@ def attribute_response(conf, return_addrs, timeslack=0, asynchop=False, test=Fal
)
-class StatusResponse(object):
+class StatusResponse:
msgtype = "status_response"
def __init__(self, sec_context, return_addrs=None, timeslack=0, request_id=0, asynchop=True, conv_info=None):
@@ -344,7 +343,7 @@ class StatusResponse(object):
def _loads(self, xmldata, decode=True, origxml=None):
# own copy
- if isinstance(xmldata, six.binary_type):
+ if isinstance(xmldata, bytes):
self.xmlstr = xmldata[:].decode("utf-8")
else:
self.xmlstr = xmldata[:]
@@ -365,7 +364,7 @@ class StatusResponse(object):
origdoc=origxml,
must=self.require_signature,
require_response_signature=self.require_response_signature,
- **args
+ **args,
)
except TypeError:
@@ -389,7 +388,7 @@ class StatusResponse(object):
err_msg = status.status_message.text if status.status_message else err_code or "Unknown error"
err_cls = STATUSCODE2EXCEPTION.get(err_code, StatusError)
- msg = "Unsuccessful operation: {status}\n{msg} from {code}".format(status=status, msg=err_msg, code=err_code)
+ msg = f"Unsuccessful operation: {status}\n{err_msg} from {err_code}"
logger.debug(msg)
raise err_cls(msg)
@@ -493,7 +492,7 @@ class AuthnResponse(StatusResponse):
want_assertions_or_response_signed=False,
want_response_signed=False,
conv_info=None,
- **kwargs
+ **kwargs,
):
StatusResponse.__init__(self, sec_context, return_addrs, timeslack, asynchop=asynchop, conv_info=conv_info)
@@ -561,7 +560,7 @@ class AuthnResponse(StatusResponse):
if optional:
return True
else:
- msg = "Invalid number of AuthnStatement found in Response: {n}".format(n=n_authn_statements)
+ msg = f"Invalid number of AuthnStatement found in Response: {n_authn_statements}"
raise ValueError(msg)
authn_statement = self.assertion.authn_statement[0]
@@ -675,7 +674,7 @@ class AuthnResponse(StatusResponse):
if _assertion.attribute_statement:
logger.debug("Assertion contains %s attribute statement(s)", (len(self.assertion.attribute_statement)))
for _attr_statem in _assertion.attribute_statement:
- logger.debug("Attribute Statement: %s" % (_attr_statem,))
+ logger.debug(f"Attribute Statement: {_attr_statem}")
ava.update(self.read_attribute_statement(_attr_statem))
if not ava:
logger.debug("Assertion contains no attribute statements")
@@ -732,7 +731,7 @@ class AuthnResponse(StatusResponse):
raise ValueError("Missing assertion")
if not self.assertion.subject:
- raise ValueError("Invalid assertion subject: {subject}".format(subject=self.assertion.subject))
+ raise ValueError(f"Invalid assertion subject: {self.assertion.subject}")
subject = self.assertion.subject
subjconf = []
@@ -751,7 +750,7 @@ class AuthnResponse(StatusResponse):
elif subject_confirmation.method == SCM_SENDER_VOUCHES:
pass
else:
- raise ValueError("Unknown subject confirmation method: %s" % (subject_confirmation.method,))
+ raise ValueError(f"Unknown subject confirmation method: {subject_confirmation.method}")
_recip = _data.recipient
if not _recip or not self.verify_recipient(_recip):
@@ -914,9 +913,7 @@ class AuthnResponse(StatusResponse):
n_assertions = len(self.response.assertion)
n_assertions_enc = len(self.response.encrypted_assertion)
if n_assertions != 1 and n_assertions_enc != 1 and self.assertion is None:
- raise InvalidAssertion(
- "Invalid number of assertions in Response: {n}".format(n=n_assertions + n_assertions_enc)
- )
+ raise InvalidAssertion(f"Invalid number of assertions in Response: {n_assertions + n_assertions_enc}")
if self.response.assertion:
logger.debug("***Unencrypted assertion***")
@@ -941,7 +938,7 @@ class AuthnResponse(StatusResponse):
resp = samlp.response_from_string(decr_text)
# check and prepare for comparison between str and unicode
if type(decr_text_old) != type(decr_text):
- if isinstance(decr_text_old, six.binary_type):
+ if isinstance(decr_text_old, bytes):
decr_text_old = decr_text_old.decode("utf-8")
else:
decr_text_old = decr_text_old.encode("utf-8")
@@ -962,7 +959,7 @@ class AuthnResponse(StatusResponse):
_enc_assertions = self.decrypt_assertions(resp.encrypted_assertion, decr_text, verified=True)
# check and prepare for comparison between str and unicode
if type(decr_text_old) != type(decr_text):
- if isinstance(decr_text_old, six.binary_type):
+ if isinstance(decr_text_old, bytes):
decr_text_old = decr_text_old.decode("utf-8")
else:
decr_text_old = decr_text_old.encode("utf-8")
@@ -1350,7 +1347,7 @@ def response_factory(
# A class of it's own
-class AssertionIDResponse(object):
+class AssertionIDResponse:
msgtype = "assertion_id_response"
def __init__(self, sec_context, attribute_converters, timeslack=0, **kwargs):
diff --git a/src/saml2/s2repoze/__init__.py b/src/saml2/s2repoze/__init__.py
index 766c3cb1..1b3570ab 100644
--- a/src/saml2/s2repoze/__init__.py
+++ b/src/saml2/s2repoze/__init__.py
@@ -1,2 +1 @@
-# -*- coding: utf-8 -*-
# Created by Roland Hedberg
diff --git a/src/saml2/s2repoze/plugins/__init__.py b/src/saml2/s2repoze/plugins/__init__.py
index 40a96afc..e69de29b 100644
--- a/src/saml2/s2repoze/plugins/__init__.py
+++ b/src/saml2/s2repoze/plugins/__init__.py
@@ -1 +0,0 @@
-# -*- coding: utf-8 -*-
diff --git a/src/saml2/s2repoze/plugins/entitlement.py b/src/saml2/s2repoze/plugins/entitlement.py
index bd5fae51..81bc0cc5 100644
--- a/src/saml2/s2repoze/plugins/entitlement.py
+++ b/src/saml2/s2repoze/plugins/entitlement.py
@@ -6,7 +6,7 @@ from repoze.who.interfaces import IMetadataProvider
from zope.interface import implements
-class EntitlementMetadataProvider(object):
+class EntitlementMetadataProvider:
implements(IMetadataProvider)
@@ -63,13 +63,13 @@ class EntitlementMetadataProvider(object):
vorg = environ["myapp.vo"]
try:
ents = user["entitlement"][vorg]
- identity["user"] = {"entitlement": ["%s:%s" % (vorg, e) for e in ents]}
+ identity["user"] = {"entitlement": [f"{vorg}:{e}" for e in ents]}
except KeyError:
pass
except KeyError:
res = []
for vorg, ents in user["entitlement"].items():
- res.extend(["%s:%s" % (vorg, e) for e in ents])
+ res.extend([f"{vorg}:{e}" for e in ents])
identity["user"] = res
diff --git a/src/saml2/s2repoze/plugins/formswithhidden.py b/src/saml2/s2repoze/plugins/formswithhidden.py
index 02e2ad95..1483af92 100644
--- a/src/saml2/s2repoze/plugins/formswithhidden.py
+++ b/src/saml2/s2repoze/plugins/formswithhidden.py
@@ -1,3 +1,5 @@
+from urllib.parse import urlencode
+
from paste.httpexceptions import HTTPFound
from paste.httpheaders import CONTENT_LENGTH
from paste.httpheaders import CONTENT_TYPE
@@ -8,7 +10,6 @@ from paste.request import parse_formvars
from repoze.who.interfaces import IChallenger
from repoze.who.interfaces import IIdentifier
from repoze.who.plugins.form import FormPlugin
-from six.moves.urllib.parse import urlencode
from zope.interface import implements
@@ -114,7 +115,7 @@ def make_plugin(login_form_qs="__do_login", rememberer_name=None, form=None):
if rememberer_name is None:
raise ValueError("must include rememberer key (name of another IIdentifier plugin)")
if form is not None:
- with open(form, "r") as f:
+ with open(form) as f:
form = f.read()
plugin = FormHiddenPlugin(login_form_qs, rememberer_name, form)
return plugin
diff --git a/src/saml2/s2repoze/plugins/ini.py b/src/saml2/s2repoze/plugins/ini.py
index 74dcc111..ef36c6f4 100644
--- a/src/saml2/s2repoze/plugins/ini.py
+++ b/src/saml2/s2repoze/plugins/ini.py
@@ -5,7 +5,7 @@ from repoze.who.interfaces import IMetadataProvider
from zope.interface import implements
-class INIMetadataProvider(object):
+class INIMetadataProvider:
implements(IMetadataProvider)
diff --git a/src/saml2/s2repoze/plugins/sp.py b/src/saml2/s2repoze/plugins/sp.py
index ea3cd388..e3d25bfe 100644
--- a/src/saml2/s2repoze/plugins/sp.py
+++ b/src/saml2/s2repoze/plugins/sp.py
@@ -5,11 +5,13 @@ and SAML2 attribute aggregations as metadata collector in your
WSGI application.
"""
+from io import StringIO
import logging
import platform
import shelve
import sys
import traceback
+from urllib import parse
from paste.httpexceptions import HTTPInternalServerError
from paste.httpexceptions import HTTPNotImplemented
@@ -22,8 +24,6 @@ from repoze.who.interfaces import IChallenger
from repoze.who.interfaces import IIdentifier
from repoze.who.interfaces import IMetadataProvider
import six
-from six import StringIO
-from six.moves.urllib import parse
from zope.interface import implementer
from saml2 import BINDING_HTTP_POST
@@ -50,7 +50,7 @@ from saml2.samlp import Extensions
logger = logging.getLogger(__name__)
-PAOS_HEADER_INFO = 'ver="%s";"%s"' % (paos.NAMESPACE, ECP_SERVICE)
+PAOS_HEADER_INFO = f'ver="{paos.NAMESPACE}";"{ECP_SERVICE}"'
def construct_came_from(environ):
@@ -66,11 +66,11 @@ def construct_came_from(environ):
def exception_trace(tag, exc, log):
message = traceback.format_exception(*sys.exc_info())
- log.error("[%s] ExcList: %s" % (tag, "".join(message)))
- log.error("[%s] Exception: %s" % (tag, exc))
+ log.error("[{}] ExcList: {}".format(tag, "".join(message)))
+ log.error(f"[{tag}] Exception: {exc}")
-class ECP_response(object):
+class ECP_response:
code = 200
title = "OK"
@@ -79,12 +79,12 @@ class ECP_response(object):
# noinspection PyUnusedLocal
def __call__(self, environ, start_response):
- start_response("%s %s" % (self.code, self.title), [("Content-Type", "text/xml")])
+ start_response(f"{self.code} {self.title}", [("Content-Type", "text/xml")])
return [self.content]
@implementer(IChallenger, IIdentifier, IAuthenticator, IMetadataProvider)
-class SAML2Plugin(object):
+class SAML2Plugin:
def __init__(
self,
rememberer_name,
@@ -163,7 +163,7 @@ class SAML2Plugin(object):
sid_ = sid()
self.outstanding_queries[sid_] = came_from
logger.info("Redirect to WAYF function: %s", self.wayf)
- return -1, HTTPSeeOther(headers=[("Location", "%s?%s" % (self.wayf, sid_))])
+ return -1, HTTPSeeOther(headers=[("Location", f"{self.wayf}?{sid_}")])
# noinspection PyUnusedLocal
def _pick_idp(self, environ, came_from):
@@ -409,12 +409,12 @@ class SAML2Plugin(object):
)
except Exception as excp:
- logger.exception("Exception: %s" % (excp,))
+ logger.exception(f"Exception: {excp}")
raise
session_info = authresp.session_info()
except TypeError as excp:
- logger.exception("Exception: %s" % (excp,))
+ logger.exception(f"Exception: {excp}")
return None
if session_info["came_from"]:
@@ -553,7 +553,7 @@ class SAML2Plugin(object):
def add_metadata(self, environ, identity):
"""Add information to the knowledge I have about the user"""
name_id = identity["repoze.who.userid"]
- if isinstance(name_id, six.string_types):
+ if isinstance(name_id, str):
try:
# Make sure that userids authenticated by another plugin
# don't cause problems here.
diff --git a/src/saml2/s_utils.py b/src/saml2/s_utils.py
index 6e2fd9c2..1df61572 100644
--- a/src/saml2/s_utils.py
+++ b/src/saml2/s_utils.py
@@ -160,7 +160,7 @@ def deflate_and_base64_encode(string_val):
:param string_val: The string to deflate and encode
:return: The deflated and encoded string
"""
- if not isinstance(string_val, six.binary_type):
+ if not isinstance(string_val, bytes):
string_val = string_val.encode("utf-8")
return base64.b64encode(zlib.compress(string_val)[2:-4])
@@ -183,7 +183,7 @@ def rndbytes(size=16, alphabet=""):
Returns rndstr always as a binary type
"""
x = rndstr(size, alphabet)
- if isinstance(x, six.string_types):
+ if isinstance(x, str):
return x.encode("utf-8")
return x
@@ -307,7 +307,7 @@ def _attrval(val, typ=""):
def do_ava(val, typ=""):
- if isinstance(val, six.string_types):
+ if isinstance(val, str):
ava = saml.AttributeValue()
ava.set_text(val)
attrval = [ava]
@@ -335,7 +335,7 @@ def do_attribute(val, typ, key):
if attrval:
attr.attribute_value = attrval
- if isinstance(key, six.string_types):
+ if isinstance(key, str):
attr.name = key
elif isinstance(key, tuple): # 3-tuple or 2-tuple
try:
@@ -391,11 +391,11 @@ def factory(klass, **kwargs):
def signature(secret, parts):
"""Generates a signature. All strings are assumed to be utf-8"""
- if not isinstance(secret, six.binary_type):
+ if not isinstance(secret, bytes):
secret = secret.encode("utf-8")
newparts = []
for part in parts:
- if not isinstance(part, six.binary_type):
+ if not isinstance(part, bytes):
part = part.encode("utf-8")
newparts.append(part)
parts = newparts
diff --git a/src/saml2/saml.py b/src/saml2/saml.py
index d8ac648b..d3cca114 100644
--- a/src/saml2/saml.py
+++ b/src/saml2/saml.py
@@ -231,7 +231,7 @@ class AttributeValueBase(SamlBase):
raise ValueError(msg)
# only work with six.string_types
- if isinstance(value, six.binary_type):
+ if isinstance(value, bytes):
value = value.decode("utf-8")
type_to_xsd = {
@@ -344,7 +344,7 @@ class AttributeValueBase(SamlBase):
_wrong_type_value(xsd=xsd_type, value=value)
text = to_text(value)
- self.set_type("{ns}:{type}".format(ns=xsd_ns, type=xsd_type) if xsd_ns else xsd_type if xsd_type else "")
+ self.set_type(f"{xsd_ns}:{xsd_type}" if xsd_ns else xsd_type if xsd_type else "")
SamlBase.__setattr__(self, "text", text)
return self
diff --git a/src/saml2/sdb.py b/src/saml2/sdb.py
index 4349b310..df9613a4 100644
--- a/src/saml2/sdb.py
+++ b/src/saml2/sdb.py
@@ -15,7 +15,7 @@ def context_match(cfilter, cntx):
# The key to the stored authn statement is placed encrypted in the cookie
-class SessionStorage(object):
+class SessionStorage:
"""In memory storage of session information"""
def __init__(self):
diff --git a/src/saml2/server.py b/src/saml2/server.py
index 2b1cbf66..153ea91b 100644
--- a/src/saml2/server.py
+++ b/src/saml2/server.py
@@ -1,5 +1,4 @@
#!/usr/bin/env python
-# -*- coding: utf-8 -*-
#
"""Contains classes and functions that a SAML2.0 Identity provider (IdP)
@@ -110,7 +109,7 @@ class Server(Entity):
_spec = self.config.getattr("session_storage", "idp")
if not _spec:
return SessionStorage()
- elif isinstance(_spec, six.string_types):
+ elif isinstance(_spec, str):
if _spec.lower() == "memory":
return SessionStorage()
else: # Should be tuple
@@ -137,7 +136,7 @@ class Server(Entity):
typ = ""
if not dbspec:
idb = {}
- elif isinstance(dbspec, six.string_types):
+ elif isinstance(dbspec, str):
idb = _shelve_compat(dbspec, writeback=True, protocol=2)
else: # database spec is a a 2-tuple (type, address)
# print(>> sys.stderr, "DBSPEC: %s" % (dbspec,))
@@ -164,7 +163,7 @@ class Server(Entity):
elif idb is not None:
self.ident = IdentDB(idb)
elif dbspec:
- raise Exception("Couldn't open identity database: %s" % (dbspec,))
+ raise Exception(f"Couldn't open identity database: {dbspec}")
try:
_domain = self.config.getattr("domain", "idp")
@@ -404,7 +403,7 @@ class Server(Entity):
if authn: # expected to be a dictionary
# Would like to use dict comprehension but ...
- authn_args = dict([(AUTHN_DICT_MAP[k], v) for k, v in authn.items() if k in AUTHN_DICT_MAP])
+ authn_args = {AUTHN_DICT_MAP[k]: v for k, v in authn.items() if k in AUTHN_DICT_MAP}
authn_args.update(kwargs)
assertion = ast.construct(
@@ -848,7 +847,7 @@ class Server(Entity):
pefim=pefim,
**kwargs,
)
- except IOError as exc:
+ except OSError as exc:
response = self.create_error_response(
in_response_to,
destination=destination,
diff --git a/src/saml2/sigver.py b/src/saml2/sigver.py
index b8004ce4..06836cf6 100644
--- a/src/saml2/sigver.py
+++ b/src/saml2/sigver.py
@@ -27,9 +27,10 @@ if sys.version_info[:2] >= (3, 9):
else:
from importlib_resources import files as _resource_files
+from urllib import parse
+
from OpenSSL import crypto
import pytz
-from six.moves.urllib import parse
from saml2 import ExtensionElement
from saml2 import SamlBase
@@ -204,7 +205,7 @@ def get_xmlsec_binary(paths=None):
except OSError:
pass
- raise SigverError("Cannot find {binary}".format(binary=bin_name))
+ raise SigverError(f"Cannot find {bin_name}")
def _get_xmlsec_cryptobackend(path=None, search_paths=None, delete_tmpfiles=True):
@@ -326,7 +327,7 @@ def signed_instance_factory(instance, seccont, elements_to_sign=None):
return instance
signed_xml = instance
- if not isinstance(instance, six.string_types):
+ if not isinstance(instance, str):
signed_xml = instance.to_string()
for (node_name, nodeid) in elements_to_sign:
@@ -353,7 +354,7 @@ def make_temp(content, suffix="", decode=True, delete_tmpfiles=True):
close the file) and filename (which is for instance needed by the
xmlsec function).
"""
- content_encoded = content.encode("utf-8") if not isinstance(content, six.binary_type) else content
+ content_encoded = content.encode("utf-8") if not isinstance(content, bytes) else content
content_raw = base64.b64decode(content_encoded) if decode else content_encoded
ntf = NamedTemporaryFile(suffix=suffix, delete=delete_tmpfiles)
ntf.write(content_raw)
@@ -492,7 +493,7 @@ def sha1_digest(msg):
return hashlib.sha1(msg).digest()
-class Signer(object):
+class Signer:
"""Abstract base class for signing algorithms."""
def __init__(self, key):
@@ -540,7 +541,7 @@ RESP_ORDER = [
]
-class RSACrypto(object):
+class RSACrypto:
def __init__(self, key):
self.key = key
@@ -594,7 +595,7 @@ def verify_redirect_signature(saml_msg, crypto, cert=None, sigkey=None):
return bool(signer.verify(string, _sign, _key))
-class CryptoBackend(object):
+class CryptoBackend:
def version(self):
raise NotImplementedError()
@@ -614,9 +615,7 @@ class CryptoBackend(object):
raise NotImplementedError()
-ASSERT_XPATH = "".join(
- ["/*[local-name()='{name}']".format(name=n) for n in ["Response", "EncryptedAssertion", "Assertion"]]
-)
+ASSERT_XPATH = "".join([f"/*[local-name()='{n}']" for n in ["Response", "EncryptedAssertion", "Assertion"]])
class CryptoBackendXmlSec1(CryptoBackend):
@@ -629,7 +628,7 @@ class CryptoBackendXmlSec1(CryptoBackend):
def __init__(self, xmlsec_binary, delete_tmpfiles=True, **kwargs):
CryptoBackend.__init__(self, **kwargs)
- if not isinstance(xmlsec_binary, six.string_types):
+ if not isinstance(xmlsec_binary, str):
raise ValueError("xmlsec_binary should be of type string")
self.xmlsec = xmlsec_binary
self.delete_tmpfiles = delete_tmpfiles
@@ -678,7 +677,7 @@ class CryptoBackendXmlSec1(CryptoBackend):
try:
(_stdout, _stderr, output) = self._run_xmlsec(com_list, [template])
except XmlsecError as e:
- six.raise_from(EncryptError(com_list), e)
+ raise EncryptError(com_list) from e
return output
@@ -721,7 +720,7 @@ class CryptoBackendXmlSec1(CryptoBackend):
try:
(_stdout, _stderr, output) = self._run_xmlsec(com_list, [tmp2.name])
except XmlsecError as e:
- six.raise_from(EncryptError(com_list), e)
+ raise EncryptError(com_list) from e
return output.decode("utf-8")
@@ -748,7 +747,7 @@ class CryptoBackendXmlSec1(CryptoBackend):
try:
(_stdout, _stderr, output) = self._run_xmlsec(com_list, [tmp.name])
except XmlsecError as e:
- six.raise_from(DecryptError(com_list), e)
+ raise DecryptError(com_list) from e
return output.decode("utf-8")
@@ -802,7 +801,7 @@ class CryptoBackendXmlSec1(CryptoBackend):
:param node_id: The identifier of the node
:return: Boolean True if the signature was correct otherwise False.
"""
- if not isinstance(signedtext, six.binary_type):
+ if not isinstance(signedtext, bytes):
signedtext = signedtext.encode("utf-8")
tmp = make_temp(signedtext, suffix=".xml", decode=False, delete_tmpfiles=self.delete_tmpfiles)
@@ -814,7 +813,7 @@ class CryptoBackendXmlSec1(CryptoBackend):
"empty,same-doc",
"--enabled-key-data",
"raw-x509-cert",
- "--pubkey-cert-{type}".format(type=cert_type),
+ f"--pubkey-cert-{cert_type}",
cert_file,
"--id-attr:ID",
node_name,
@@ -826,7 +825,7 @@ class CryptoBackendXmlSec1(CryptoBackend):
try:
(_stdout, stderr, _output) = self._run_xmlsec(com_list, [tmp.name])
except XmlsecError as e:
- six.raise_from(SignatureError(com_list), e)
+ raise SignatureError(com_list) from e
return parse_xmlsec_output(stderr)
@@ -900,7 +899,7 @@ class CryptoBackendXMLSecurity(CryptoBackend):
xml = xmlsec.parse_xml(statement)
signed = xmlsec.sign(xml, key_file)
signed_str = lxml.etree.tostring(signed, xml_declaration=False, encoding="UTF-8")
- if not isinstance(signed_str, six.string_types):
+ if not isinstance(signed_str, str):
signed_str = signed_str.decode("utf-8")
return signed_str
@@ -970,7 +969,7 @@ def security_context(conf):
try:
rsa_key = import_rsa_key_from_file(_file_name)
except Exception as err:
- logger.error("Cannot import key from {file}: {err_msg}".format(file=_file_name, err_msg=err))
+ logger.error(f"Cannot import key from {_file_name}: {err}")
raise
else:
sec_backend = RSACrypto(rsa_key)
@@ -1029,7 +1028,7 @@ def encrypt_cert_from_item(item):
return _encrypt_cert
-class CertHandlerExtra(object):
+class CertHandlerExtra:
def __init__(self):
pass
@@ -1048,7 +1047,7 @@ class CertHandlerExtra(object):
# Excepts to return True/False
-class CertHandler(object):
+class CertHandler:
def __init__(
self,
security_context,
@@ -1164,7 +1163,7 @@ class CertHandler(object):
# How to get a rsa pub key fingerprint from a certificate
# openssl x509 -inform pem -noout -in server.crt -pubkey > publickey.pem
# openssl rsa -inform pem -noout -in publickey.pem -pubin -modulus
-class SecurityContext(object):
+class SecurityContext:
my_cert = None
def __init__(
@@ -1292,7 +1291,7 @@ class SecurityContext(object):
keys = [keys]
keys_filtered = (key for key in keys if key)
- keys_encoded = (key.encode("ascii") if not isinstance(key, six.binary_type) else key for key in keys_filtered)
+ keys_encoded = (key.encode("ascii") if not isinstance(key, bytes) else key for key in keys_filtered)
key_files = list(make_temp(key, decode=False, delete_tmpfiles=self.delete_tmpfiles) for key in keys_encoded)
key_file_names = list(tmp.name for tmp in key_files)
@@ -1369,7 +1368,7 @@ class SecurityContext(object):
certs = []
for cert_name, cert in _certs:
- if isinstance(cert, six.string_types):
+ if isinstance(cert, str):
content = pem_format(cert)
tmp = make_temp(content, suffix=".pem", decode=False, delete_tmpfiles=self.delete_tmpfiles)
certs.append(tmp)
@@ -1422,9 +1421,9 @@ class SecurityContext(object):
and references[0].uri.startswith("#")
and len(references[0].uri) > 1
)
- the_anchor_points_to_the_enclosing_element_ID_attribute = the_URI_attribute_contains_an_anchor and references[
- 0
- ].uri == "#{id}".format(id=item.id)
+ the_anchor_points_to_the_enclosing_element_ID_attribute = (
+ the_URI_attribute_contains_an_anchor and references[0].uri == f"#{item.id}"
+ )
# SAML implementations SHOULD use Exclusive Canonicalization,
# with or without comments
@@ -1541,13 +1540,13 @@ class SecurityContext(object):
:return:
"""
- attr = "{type}_from_string".format(type=msgtype)
+ attr = f"{msgtype}_from_string"
_func = getattr(saml, attr, None)
_func = getattr(samlp, attr, _func)
msg = _func(decoded_xml)
if not msg:
- raise TypeError("Not a {type}".format(type=msgtype))
+ raise TypeError(f"Not a {msgtype}")
if not msg.signature:
if must:
@@ -1778,7 +1777,7 @@ def pre_signature_part(
digest_method = ds.DigestMethod(algorithm=digest_alg)
reference = ds.Reference(
- uri="#{id}".format(id=ident), digest_value=ds.DigestValue(), transforms=transforms, digest_method=digest_method
+ uri=f"#{ident}", digest_value=ds.DigestValue(), transforms=transforms, digest_method=digest_method
)
signed_info = ds.SignedInfo(
@@ -1788,7 +1787,7 @@ def pre_signature_part(
signature = ds.Signature(signed_info=signed_info, signature_value=ds.SignatureValue())
if identifier:
- signature.id = "Signature{n}".format(n=identifier)
+ signature.id = f"Signature{identifier}"
# XXX remove - do not embed the cert
if public_key:
@@ -1836,8 +1835,8 @@ def pre_encryption_part(
encrypted_data_id=None,
encrypt_cert=None,
):
- ek_id = encrypted_key_id or "EK_{id}".format(id=gen_random_key())
- ed_id = encrypted_data_id or "ED_{id}".format(id=gen_random_key())
+ ek_id = encrypted_key_id or f"EK_{gen_random_key()}"
+ ed_id = encrypted_data_id or f"ED_{gen_random_key()}"
msg_encryption_method = EncryptionMethod(algorithm=msg_enc)
key_encryption_method = EncryptionMethod(algorithm=key_enc)
diff --git a/src/saml2/soap.py b/src/saml2/soap.py
index dc2e75e5..866bff14 100644
--- a/src/saml2/soap.py
+++ b/src/saml2/soap.py
@@ -1,5 +1,4 @@
#!/usr/bin/env python
-# -*- coding: utf-8 -*-
#
"""
@@ -14,7 +13,7 @@ from saml2.schema import soapenv
try:
- from xml.etree import cElementTree as ElementTree
+ from xml.etree import ElementTree as ElementTree
except ImportError:
try:
import cElementTree as ElementTree
@@ -138,9 +137,7 @@ def parse_soap_enveloped_saml_thingy(text, expected_tags):
envelope_tag = "{%s}Envelope" % soapenv.NAMESPACE
if envelope.tag != envelope_tag:
- raise ValueError(
- "Invalid envelope tag '{invalid}' should be '{valid}'".format(invalid=envelope.tag, valid=envelope_tag)
- )
+ raise ValueError(f"Invalid envelope tag '{envelope.tag}' should be '{envelope_tag}'")
if len(envelope) < 1:
raise Exception("No items in envelope.")
@@ -150,7 +147,7 @@ def parse_soap_enveloped_saml_thingy(text, expected_tags):
if part.tag == "{%s}Body" % soapenv.NAMESPACE:
n_children = len(part)
if n_children != 1:
- raise Exception("Expected a single child element, found {n}".format(n=n_children))
+ raise Exception(f"Expected a single child element, found {n_children}")
body = part
break
@@ -161,7 +158,7 @@ def parse_soap_enveloped_saml_thingy(text, expected_tags):
if saml_part.tag in expected_tags:
return ElementTree.tostring(saml_part, encoding="UTF-8")
else:
- raise WrongMessageType("Was '%s' expected one of %s" % (saml_part.tag, expected_tags))
+ raise WrongMessageType(f"Was '{saml_part.tag}' expected one of {expected_tags}")
NS_AND_TAG = re.compile(r"\{([^}]+)\}(.*)")
@@ -177,7 +174,7 @@ def instanciate_class(item, modules):
return create_class_from_element_tree(target, item)
except KeyError:
continue
- raise Exception("Unknown class: ns='%s', tag='%s'" % (ns, tag))
+ raise Exception(f"Unknown class: ns='{ns}', tag='{tag}'")
def class_instances_from_soap_enveloped_saml_thingies(text, modules):
@@ -195,9 +192,7 @@ def class_instances_from_soap_enveloped_saml_thingies(text, modules):
envelope_tag = "{%s}Envelope" % soapenv.NAMESPACE
if envelope.tag != envelope_tag:
- raise ValueError(
- "Invalid envelope tag '{invalid}' should be '{valid}'".format(invalid=envelope.tag, valid=envelope_tag)
- )
+ raise ValueError(f"Invalid envelope tag '{envelope.tag}' should be '{envelope_tag}'")
if len(envelope) < 1:
raise Exception("No items in envelope.")
@@ -229,9 +224,7 @@ def open_soap_envelope(text):
envelope_tag = "{%s}Envelope" % soapenv.NAMESPACE
if envelope.tag != envelope_tag:
- raise ValueError(
- "Invalid envelope tag '{invalid}' should be '{valid}'".format(invalid=envelope.tag, valid=envelope_tag)
- )
+ raise ValueError(f"Invalid envelope tag '{envelope.tag}' should be '{envelope_tag}'")
if len(envelope) < 1:
raise Exception("No items in envelope.")
diff --git a/src/saml2/time_util.py b/src/saml2/time_util.py
index c85fdf73..2ef2adb6 100644
--- a/src/saml2/time_util.py
+++ b/src/saml2/time_util.py
@@ -1,11 +1,9 @@
#!/usr/bin/env python
-# -*- coding: utf-8 -*-
#
"""
Implements some usefull functions when dealing with validity of
different types of information.
"""
-from __future__ import print_function
import calendar
from datetime import datetime
@@ -71,7 +69,7 @@ def parse_duration(duration):
raise ValueError("Parse Duration is not valid.")
index += 1
- dic = dict([(typ, 0) for (code, typ) in D_FORMAT if typ])
+ dic = {typ: 0 for (code, typ) in D_FORMAT if typ}
dlen = len(duration)
for code, typ in D_FORMAT:
@@ -239,7 +237,7 @@ def str_to_time(timestr, format=TIME_FORMAT):
try:
elem = TIME_FORMAT_WITH_FRAGMENT.match(timestr)
except Exception as exc:
- print("Exception: %s on %s" % (exc, timestr), file=sys.stderr)
+ print(f"Exception: {exc} on {timestr}", file=sys.stderr)
raise
then = time.strptime(elem.groups()[0] + "Z", TIME_FORMAT)
@@ -272,7 +270,7 @@ def before(point):
if not point:
return True
- if isinstance(point, six.string_types):
+ if isinstance(point, str):
point = str_to_time(point)
elif isinstance(point, int):
point = time.gmtime(point)
@@ -304,12 +302,12 @@ def utc_time_sans_frac():
def later_than(after, before):
"""True if then is later or equal to that"""
- if isinstance(after, six.string_types):
+ if isinstance(after, str):
after = str_to_time(after)
elif isinstance(after, int):
after = time.gmtime(after)
- if isinstance(before, six.string_types):
+ if isinstance(before, str):
before = str_to_time(before)
elif isinstance(before, int):
before = time.gmtime(before)
diff --git a/src/saml2/tools/parse_xsd2.py b/src/saml2/tools/parse_xsd2.py
index db775548..ce9f433f 100644
--- a/src/saml2/tools/parse_xsd2.py
+++ b/src/saml2/tools/parse_xsd2.py
@@ -13,7 +13,7 @@ import six
__version__ = 0.5
-from xml.etree import cElementTree as ElementTree
+from xml.etree import ElementTree as ElementTree
INDENT = 4 * " "
@@ -65,9 +65,9 @@ def def_init(imports, attributes):
_name = elem[0]
if elem[2]:
- line.append("%s%s='%s'," % (indent3, _name, elem[2]))
+ line.append(f"{indent3}{_name}='{elem[2]}',")
else:
- line.append("%s%s=%s," % (indent3, _name, elem[2]))
+ line.append(f"{indent3}{_name}={elem[2]},")
for _, elems in imports.items():
for elem in elems:
@@ -75,7 +75,7 @@ def def_init(imports, attributes):
_name = elem + "_"
else:
_name = elem
- line.append("%s%s=None," % (indent3, _name))
+ line.append(f"{indent3}{_name}=None,")
line.append("%stext=None," % indent3)
line.append("%sextension_elements=None," % indent3)
@@ -94,12 +94,12 @@ def base_init(imports):
_name = attr + "_"
else:
_name = attr
- line.append("%s%s=%s," % (indent4, _name, _name))
+ line.append(f"{indent4}{_name}={_name},")
line.append("%s)" % indent4)
else:
# TODO have to keep apart which properties come from which superior
for sup, elems in imports.items():
- line.append("%s%s.__init__(self, " % (INDENT + INDENT, sup))
+ line.append(f"{INDENT + INDENT}{sup}.__init__(self, ")
lattr = elems[:]
lattr.extend(BASE_ELEMENT)
for attr in lattr:
@@ -107,7 +107,7 @@ def base_init(imports):
_name = attr + "_"
else:
_name = attr
- line.append("%s%s=%s," % (indent4, _name, _name))
+ line.append(f"{indent4}{_name}={_name},")
line.append("%s)" % indent4)
return line
@@ -126,7 +126,7 @@ def initialize(attributes):
else:
_vname = val
- line.append("%sself.%s=%s" % (indent, _name, _vname))
+ line.append(f"{indent}self.{_name}={_vname}")
return line
@@ -211,7 +211,7 @@ def klass_namn(obj):
return obj.name
-class PyObj(object):
+class PyObj:
def __init__(self, name=None, pyname=None, root=None):
self.name = name
self.done = False
@@ -235,15 +235,15 @@ class PyObj(object):
def child_spec(self, target_namespace, prop, mod, typ, lista):
if mod:
namesp = external_namespace(self.root.modul[mod])
- pkey = "{%s}%s" % (namesp, prop.name)
- typ = "%s.%s" % (mod, typ)
+ pkey = f"{{{namesp}}}{prop.name}"
+ typ = f"{mod}.{typ}"
else:
- pkey = "{%s}%s" % (target_namespace, prop.name)
+ pkey = f"{{{target_namespace}}}{prop.name}"
if lista:
- return "c_children['%s'] = ('%s', [%s])" % (pkey, prop.pyname, typ)
+ return f"c_children['{pkey}'] = ('{prop.pyname}', [{typ}])"
else:
- return "c_children['%s'] = ('%s', %s)" % (pkey, prop.pyname, typ)
+ return f"c_children['{pkey}'] = ('{prop.pyname}', {typ})"
def knamn(self, sup, cdict):
cname = cdict[sup].class_name
@@ -251,7 +251,7 @@ class PyObj(object):
(namesp, tag) = cdict[sup].name.split(".")
if namesp:
ctag = self.root.modul[namesp].factory(tag).__class__.__name__
- cname = "%s.%s" % (namesp, ctag)
+ cname = f"{namesp}.{ctag}"
else:
cname = tag + "_"
return cname
@@ -267,7 +267,7 @@ class PyObj(object):
for prop in own:
if isinstance(prop, PyAttribute):
- line.append("%sc_attributes['%s'] = %s" % (INDENT, prop.name, prop.spec()))
+ line.append(f"{INDENT}c_attributes['{prop.name}'] = {prop.spec()}")
if prop.fixed:
args.append((prop.pyname, prop.fixed, None))
else:
@@ -290,20 +290,20 @@ class PyObj(object):
if prop.name in ignore:
pass
else:
- line.append("%s%s" % (INDENT, self.child_spec(target_namespace, prop, mod, cname, lista)))
+ line.append(f"{INDENT}{self.child_spec(target_namespace, prop, mod, cname, lista)}")
pmin = int(getattr(prop, "min", 1))
if pmax == 1 and pmin == 1:
pass
elif prop.max == "unbounded":
- line.append("%sc_cardinality['%s'] = {\"min\":%s}" % (INDENT, prop.pyname, pmin))
+ line.append(f"{INDENT}c_cardinality['{prop.pyname}'] = {{\"min\":{pmin}}}")
else:
line.append('%sc_cardinality[\'%s\'] = {"min":%s, "max":%d}' % (INDENT, prop.pyname, pmin, pmax))
child.append(prop.pyname)
if lista:
- args.append((prop.pyname, "%s or []" % (prop.pyname,), None))
+ args.append((prop.pyname, f"{prop.pyname} or []", None))
else:
args.append((prop.pyname, prop.pyname, None))
@@ -341,38 +341,38 @@ class PyObj(object):
c_name = klass_namn(self)
if not superior:
- line.append("class %s(SamlBase):" % (c_name,))
+ line.append(f"class {c_name}(SamlBase):")
else:
- line.append("class %s(%s):" % (c_name, ",".join(sups)))
+ line.append("class {}({}):".format(c_name, ",".join(sups)))
if hasattr(self, "scoped"):
pass
else:
- line.append('%s"""The %s:%s element """' % (INDENT, target_namespace, self.name))
+ line.append(f'{INDENT}"""The {target_namespace}:{self.name} element """')
line.append("")
- line.append("%sc_tag = '%s'" % (INDENT, self.name))
- line.append("%sc_namespace = NAMESPACE" % (INDENT,))
+ line.append(f"{INDENT}c_tag = '{self.name}'")
+ line.append(f"{INDENT}c_namespace = NAMESPACE")
try:
if self.value_type:
- if isinstance(self.value_type, six.string_types):
- line.append("%sc_value_type = '%s'" % (INDENT, self.value_type))
+ if isinstance(self.value_type, str):
+ line.append(f"{INDENT}c_value_type = '{self.value_type}'")
else:
- line.append("%sc_value_type = %s" % (INDENT, self.value_type))
+ line.append(f"{INDENT}c_value_type = {self.value_type}")
except AttributeError:
pass
if not superior:
for var, cps in CLASS_PROP:
- line.append("%s%s = SamlBase.%s%s" % (INDENT, var, var, cps))
+ line.append(f"{INDENT}{var} = SamlBase.{var}{cps}")
else:
for sup in sups:
for var, cps in CLASS_PROP:
- line.append("%s%s = %s.%s%s" % (INDENT, var, sup, var, cps))
+ line.append(f"{INDENT}{var} = {sup}.{var}{cps}")
(args, child, inh) = self._do_properties(line, cdict, ignore, target_namespace)
if child:
- line.append("%sc_child_order.extend([%s])" % (INDENT, "'" + "', '".join(child) + "'"))
+ line.append("{}c_child_order.extend([{}])".format(INDENT, "'" + "', '".join(child) + "'"))
if args:
if inh:
@@ -386,7 +386,7 @@ class PyObj(object):
line.append("")
if not self.abstract or not self.class_name.endswith("_"):
line.append("def %s_from_string(xml_string):" % pyify(self.class_name))
- line.append("%sreturn saml2.create_class_from_xml_string(%s, xml_string)" % (INDENT, self.class_name))
+ line.append(f"{INDENT}return saml2.create_class_from_xml_string({self.class_name}, xml_string)")
line.append("")
self.done = True
@@ -436,7 +436,7 @@ class PyElement(PyObj):
def __init__(self, name=None, pyname=None, root=None, parent=""):
PyObj.__init__(self, name, pyname, root)
if parent:
- self.class_name = "%s_%s" % (leading_uppercase(parent), self.name)
+ self.class_name = f"{leading_uppercase(parent)}_{self.name}"
else:
self.class_name = leading_uppercase(self.name)
self.ref = None
@@ -499,7 +499,7 @@ class PyElement(PyObj):
def _external_class(self, mod, typ, cdict, child, target_namespace, ignore):
# Will raise exception if class can't be found
cname = self.root.modul[mod].factory(typ).__class__.__name__
- imp_name = "%s.%s" % (mod, cname)
+ imp_name = f"{mod}.{cname}"
if imp_name not in cdict:
# create import object so I can get the properties from it
@@ -554,7 +554,7 @@ class PyElement(PyObj):
if verify_import(self.root.modul[mod], typ):
return req, text
else:
- raise Exception("Import attempted on %s from %s module failed - wasn't there" % (typ, mod))
+ raise Exception(f"Import attempted on {typ} from {mod} module failed - wasn't there")
elif not child:
self.superior = [typ]
text = self.class_definition(target_namespace, cdict, ignore=ignore)
@@ -580,7 +580,7 @@ def _do(obj, target_namespace, cdict, prep):
else:
obj.done = True
if req:
- if isinstance(req, six.string_types):
+ if isinstance(req, str):
prep.append(req)
else:
prep.extend(req)
@@ -716,12 +716,12 @@ class PyAttribute(PyObj):
def spec(self):
if isinstance(self.type, PyObj):
- return "('%s', %s, %s)" % (self.pyname, self.type.class_name, self.required)
+ return f"('{self.pyname}', {self.type.class_name}, {self.required})"
else:
if self.type:
- return "('%s', '%s', %s)" % (self.pyname, self.type, self.required)
+ return f"('{self.pyname}', '{self.type}', {self.required})"
else:
- return "('%s', '%s', %s)" % (self.pyname, self.base, self.required)
+ return f"('{self.pyname}', '{self.base}', {self.required})"
class PyAny(PyObj):
@@ -730,14 +730,14 @@ class PyAny(PyObj):
self.done = True
-class PyAttributeGroup(object):
+class PyAttributeGroup:
def __init__(self, name, root):
self.name = name
self.root = root
self.properties = []
-class PyGroup(object):
+class PyGroup:
def __init__(self, name, root):
self.name = name
self.root = root
@@ -828,7 +828,7 @@ def _spec(elem):
def _do_from_string(name):
print
print("def %s_from_string(xml_string):" % pyify(name))
- print("%sreturn saml2.create_class_from_xml_string(%s, xml_string)" % (INDENT, name))
+ print(f"{INDENT}return saml2.create_class_from_xml_string({name}, xml_string)")
def _namespace_and_tag(obj, param, top):
@@ -847,7 +847,7 @@ def _namespace_and_tag(obj, param, top):
# -----------------------------------------------------------------------------
-class Simple(object):
+class Simple:
def __init__(self, elem):
self.default = None
self.fixed = None
@@ -905,10 +905,10 @@ class Attribute(Simple):
name = tag
else:
external = True
- name = "{%s}%s" % (self.xmlns_map[namespace], tag)
+ name = f"{{{self.xmlns_map[namespace]}}}{tag}"
else:
if namespace == "xml":
- name = "{%s}%s" % (XML_NAMESPACE, tag)
+ name = f"{{{XML_NAMESPACE}}}{tag}"
except AttributeError:
name = self.name
pyname = pyify(name)
@@ -965,7 +965,7 @@ class Attribute(Simple):
pass
if DEBUG:
- print("#--ATTR py_attr:%s" % (objekt,))
+ print(f"#--ATTR py_attr:{objekt}")
return objekt
@@ -1036,7 +1036,7 @@ def name_or_ref(elem, top):
return elem.name
-class Complex(object):
+class Complex:
def __init__(self, elem):
self.value_of = ""
self.parts = []
@@ -1146,7 +1146,7 @@ def min_max(cls, objekt, argv):
class Element(Complex):
def __str__(self):
- return "%s" % (self.__dict__,)
+ return f"{self.__dict__}"
def klass(self, top):
xns = None
@@ -1187,7 +1187,7 @@ class Element(Complex):
if ctyp:
return ctyp.elements(top)
elif xns:
- return ["%s.%s" % (xns, name)]
+ return [f"{xns}.{name}"]
else:
return []
@@ -1207,7 +1207,7 @@ class Element(Complex):
myname = ""
if DEBUG:
- print("#Element.repr '%s' (child=%s) [%s]" % (myname, child, self._generated))
+ print(f"#Element.repr '{myname}' (child={child}) [{self._generated}]")
self.py_class = objekt = PyElement(myname, root=top)
min_max(self, objekt, argv)
@@ -1265,7 +1265,7 @@ class Element(Complex):
raise
if parent:
- objekt.class_name = "%s_%s" % (leading_uppercase(parent), objekt.name)
+ objekt.class_name = f"{leading_uppercase(parent)}_{objekt.name}"
objekt.scoped = True
return objekt
@@ -1409,7 +1409,7 @@ class ComplexType(Complex):
new_sup = None
value_type = name
else:
- new_sup = "%s.%s" % (namespace, name)
+ new_sup = f"{namespace}.{name}"
# print("#Superior: %s" % new_sup)
if new_sup:
@@ -1647,7 +1647,7 @@ def output(elem, target_namespace, eldict, ignore=None):
for prep in preps:
if prep:
done = 1
- if isinstance(prep, six.string_types):
+ if isinstance(prep, str):
print(prep)
else:
for item in prep:
@@ -1745,7 +1745,7 @@ class Schema(Complex):
lista = False
spec = objekt.child_spec(self.target_namespace, prop, mod, cname, lista)
- lines = ["%s.%s" % (objekt.class_name, spec)]
+ lines = [f"{objekt.class_name}.{spec}"]
tup.append((prop, lines, spec))
return tup
@@ -1796,7 +1796,7 @@ class Schema(Complex):
for sup in sups:
if sup.name == ref:
for tup in tups:
- tup[1].append("%s.%s" % (objekt.class_name, tup[2]))
+ tup[1].append(f"{objekt.class_name}.{tup[2]}")
break
else:
pass
@@ -1842,7 +1842,7 @@ class Schema(Complex):
continue
if elem.abstract:
continue
- print("%s%s.c_tag: %s_from_string," % (INDENT, elem.class_name, pyify(elem.class_name)))
+ print(f"{INDENT}{elem.class_name}.c_tag: {pyify(elem.class_name)}_from_string,")
print("}")
print()
@@ -1855,14 +1855,14 @@ class Schema(Complex):
if elem.abstract:
continue
lcen = elem.name
- print("%s'%s': %s," % (INDENT, lcen, elem.class_name))
+ print(f"{INDENT}'{lcen}': {elem.class_name},")
listed.append(lcen)
for elem in self.elems:
if isinstance(elem, PyAttribute) or isinstance(elem, PyGroup):
continue
lcen = elem.name
if elem.abstract and lcen not in listed:
- print("%s'%s': %s," % (INDENT, lcen, elem.class_name))
+ print(f"{INDENT}'{lcen}': {elem.class_name},")
listed.append(lcen)
print("}")
print
@@ -1892,7 +1892,7 @@ class Schema(Complex):
print("from %s import *" % modul)
for _namespace, (mod, namn) in self.impo.items():
if namn:
- print("import %s as %s" % (mod, namn))
+ print(f"import {mod} as {namn}")
print()
print("NAMESPACE = '%s'" % self.target_namespace)
print
@@ -1928,9 +1928,9 @@ class Schema(Complex):
print("AG_%s = [" % attrgrp.name)
for prop in attrgrp.properties[0]:
if isinstance(prop.type, PyObj):
- print("%s('%s', %s_, %s)," % (INDENT, prop.name, prop.type.name, prop.required))
+ print(f"{INDENT}('{prop.name}', {prop.type.name}_, {prop.required}),")
else:
- print("%s('%s', '%s', %s)," % (INDENT, prop.name, prop.type, prop.required))
+ print(f"{INDENT}('{prop.name}', '{prop.type}', {prop.required}),")
print("]")
print()
@@ -1982,7 +1982,7 @@ ELEMENTFUNCTION = {}
for nsp in NAMESPACE_BASE:
for nskey, func in _MAP.items():
- ELEMENTFUNCTION["{%s}%s" % (nsp, nskey)] = func
+ ELEMENTFUNCTION[f"{{{nsp}}}{nskey}"] = func
def evaluate(typ, elem):
@@ -2084,12 +2084,12 @@ def find_and_replace(base, mods):
def read_schema(doc, add, defs, impo, modul, ignore, sdir):
for path in sdir:
- fil = "%s%s" % (path, doc)
+ fil = f"{path}{doc}"
try:
fp = open(fil)
fp.close()
break
- except IOError as e:
+ except OSError as e:
if e.errno == errno.EACCES:
continue
else:
diff --git a/src/saml2/tools/sync_attrmaps.py b/src/saml2/tools/sync_attrmaps.py
index 718508c0..f20e2d6c 100644
--- a/src/saml2/tools/sync_attrmaps.py
+++ b/src/saml2/tools/sync_attrmaps.py
@@ -37,7 +37,7 @@ def intcmp(s1, s2):
return 0
-class AMap(object):
+class AMap:
def __init__(self, head, tail, indent=4 * " "):
self.mod = load(head, tail)
self.variable = {}
@@ -59,10 +59,10 @@ class AMap(object):
try:
assert self.mod.MAP["to"][val] == key
except KeyError: # missing value
- print("# Added %s=%s" % (self.mod.MAP["to"][val], key))
+ print("# Added {}={}".format(self.mod.MAP["to"][val], key))
self.mod.MAP["to"][val] = key
except AssertionError:
- raise Exception("Mismatch key:%s '%s' != '%s'" % (key, val, self.mod.MAP["to"][val]))
+ raise Exception("Mismatch key:{} '{}' != '{}'".format(key, val, self.mod.MAP["to"][val]))
for val in self.mod.MAP["to"].values():
if val not in self.mod.MAP["fro"]:
@@ -77,7 +77,7 @@ class AMap(object):
li = [k[len(_v) :] for k in _fro.keys() if k.startswith(_v)]
li.sort(intcmp)
for item in li:
- txt.append("%s%s+'%s': '%s'," % (i2, var, item, _fro[_v + item]))
+ txt.append(f"{i2}{var}+'{item}': '{_fro[_v + item]}',")
txt.append("%s}," % self.indent)
return txt
@@ -87,13 +87,13 @@ class AMap(object):
_to = self.mod.MAP["to"]
_keys = _to.keys()
_keys.sort()
- invmap = dict([(v, k) for k, v in self.variable.items()])
+ invmap = {v: k for k, v in self.variable.items()}
for key in _keys:
val = _to[key]
for _urn, _name in invmap.items():
if val.startswith(_urn):
- txt.append("%s'%s': %s+'%s'," % (i2, key, _name, val[len(_urn) :]))
+ txt.append(f"{i2}'{key}': {_name}+'{val[len(_urn) :]}',")
txt.append("%s}" % self.indent)
return txt
@@ -102,12 +102,12 @@ class AMap(object):
self.sync()
text = []
for key in self.vars:
- text.append("%s = '%s'" % (key, self.variable[key]))
+ text.append(f"{key} = '{self.variable[key]}'")
text.extend(["", ""])
text.append("MAP = {")
- text.append("%s'identifier': '%s'," % (self.indent, self.mod.MAP["identifier"]))
+ text.append("{}'identifier': '{}',".format(self.indent, self.mod.MAP["identifier"]))
text.extend(self.do_fro())
text.extend(self.do_to())
diff --git a/src/saml2/userinfo/__init__.py b/src/saml2/userinfo/__init__.py
index 9e5bccd4..1415d300 100644
--- a/src/saml2/userinfo/__init__.py
+++ b/src/saml2/userinfo/__init__.py
@@ -3,7 +3,7 @@
import copy
-class UserInfo(object):
+class UserInfo:
"""Read only interface to a user info store"""
def __init__(self):
diff --git a/src/saml2/validate.py b/src/saml2/validate.py
index 77163598..33083886 100644
--- a/src/saml2/validate.py
+++ b/src/saml2/validate.py
@@ -6,8 +6,7 @@ from ipaddress import IPv6Address
import re
import struct
import time
-
-from six.moves.urllib.parse import urlparse
+from urllib.parse import urlparse
from saml2 import time_util
@@ -334,9 +333,9 @@ def _valid_instance(instance, val):
try:
val.verify()
except NotValid as exc:
- raise NotValid("Class '%s' instance: %s" % (instance.__class__.__name__, exc.args[0]))
+ raise NotValid(f"Class '{instance.__class__.__name__}' instance: {exc.args[0]}")
except OutsideCardinality as exc:
- raise NotValid("Class '%s' instance cardinality error: %s" % (instance.__class__.__name__, exc.args[0]))
+ raise NotValid(f"Class '{instance.__class__.__name__}' instance cardinality error: {exc.args[0]}")
ERROR_TEXT = "Wrong type of value '%s' on attribute '%s' expected it to be %s"
@@ -355,13 +354,13 @@ def valid_instance(instance):
try:
validate_value_type(instance.text.strip(), instclass.c_value_type)
except NotValid as exc:
- raise NotValid("Class '%s' instance: %s" % (class_name, exc.args[0]))
+ raise NotValid(f"Class '{class_name}' instance: {exc.args[0]}")
for (name, typ, required) in instclass.c_attributes.values():
value = getattr(instance, name, "")
if required and not value:
txt = "Required value on property '%s' missing" % name
- raise MustValueError("Class '%s' instance: %s" % (class_name, txt))
+ raise MustValueError(f"Class '{class_name}' instance: {txt}")
if value:
try:
@@ -376,7 +375,7 @@ def valid_instance(instance):
valid(typ, value)
except (NotValid, ValueError) as exc:
txt = ERROR_TEXT % (value, name, exc.args[0])
- raise NotValid("Class '%s' instance: %s" % (class_name, txt))
+ raise NotValid(f"Class '{class_name}' instance: {txt}")
for (name, _spec) in instclass.c_children.values():
value = getattr(instance, name, "")
@@ -406,13 +405,11 @@ def valid_instance(instance):
if _card:
if _cmin is not None and _cmin > vlen:
raise NotValid(
- "Class '%s' instance cardinality error: %s"
- % (class_name, "less then min (%s<%s)" % (vlen, _cmin))
+ "Class '%s' instance cardinality error: %s" % (class_name, f"less then min ({vlen}<{_cmin})")
)
if _cmax is not None and vlen > _cmax:
raise NotValid(
- "Class '%s' instance cardinality error: %s"
- % (class_name, "more then max (%s>%s)" % (vlen, _cmax))
+ "Class '%s' instance cardinality error: %s" % (class_name, f"more then max ({vlen}>{_cmax})")
)
if _list:
@@ -424,7 +421,7 @@ def valid_instance(instance):
else:
if _cmin:
raise NotValid(
- "Class '%s' instance cardinality error: %s" % (class_name, "too few values on %s" % name)
+ "Class '{}' instance cardinality error: {}".format(class_name, "too few values on %s" % name)
)
return True
diff --git a/src/saml2/virtual_org.py b/src/saml2/virtual_org.py
index 375044b4..d5d8dcba 100644
--- a/src/saml2/virtual_org.py
+++ b/src/saml2/virtual_org.py
@@ -7,7 +7,7 @@ from saml2.saml import NAMEID_FORMAT_PERSISTENT
logger = logging.getLogger(__name__)
-class VirtualOrg(object):
+class VirtualOrg:
def __init__(self, sp, vorg, cnf):
self.sp = sp # The parent SP client instance
self._name = vorg
diff --git a/src/saml2/xmldsig/__init__.py b/src/saml2/xmldsig/__init__.py
index 18c9eed4..85f89263 100644
--- a/src/saml2/xmldsig/__init__.py
+++ b/src/saml2/xmldsig/__init__.py
@@ -75,8 +75,8 @@ ALLOWED_TRANSFORMS = {
}
-class DefaultSignature(object):
- class _DefaultSignature(object):
+class DefaultSignature:
+ class _DefaultSignature:
def __init__(self, sign_alg=None, digest_alg=None):
if sign_alg is None:
self.sign_alg = sig_default
diff --git a/src/saml2test/check.py b/src/saml2test/check.py
index 7ef51279..726860ac 100644
--- a/src/saml2test/check.py
+++ b/src/saml2test/check.py
@@ -23,7 +23,7 @@ CONT_JSON = "application/json"
CONT_JWT = "application/jwt"
-class Check(object):
+class Check:
"""General test"""
cid = "check"
@@ -88,7 +88,7 @@ class ResponseInfo(Information):
self._status = self.status
_msg = conv.last_content
- if isinstance(_msg, six.string_types):
+ if isinstance(_msg, str):
self._message = _msg
else:
self._message = _msg.to_dict()
@@ -259,7 +259,7 @@ class Parse(CriticalError):
if conv.exception:
self._status = self.status
err = conv.exception
- self._message = "%s: %s" % (err.__class__.__name__, err)
+ self._message = f"{err.__class__.__name__}: {err}"
else:
_rmsg = conv.response_message
cname = _rmsg.type()
@@ -267,7 +267,7 @@ class Parse(CriticalError):
self._status = self.status
self._message = (
"Didn't get a response of the type I expected:",
- " '%s' instead of '%s', content:'%s'" % (cname, conv.response_type, _rmsg),
+ f" '{cname}' instead of '{conv.response_type}', content:'{_rmsg}'",
)
return {"response_type": conv.response_type, "url": conv.position}
diff --git a/src/saml2test/interaction.py b/src/saml2test/interaction.py
index 9c1dad6e..6fe6424a 100644
--- a/src/saml2test/interaction.py
+++ b/src/saml2test/interaction.py
@@ -92,7 +92,7 @@ class RResponse:
return self.text
-class Interaction(object):
+class Interaction:
def __init__(self, httpc, interactions=None):
self.httpc = httpc
self.interactions = interactions
@@ -123,7 +123,7 @@ class Interaction(object):
_match += 1
else:
_c = _bs.title.contents
- if isinstance(_c, list) and not isinstance(_c, six.string_types):
+ if isinstance(_c, list) and not isinstance(_c, str):
for _line in _c:
if val in _line:
_match += 1
@@ -183,7 +183,7 @@ class Interaction(object):
_default = _ava["value"]
try:
orig_val = form[prop]
- if isinstance(orig_val, six.string_types):
+ if isinstance(orig_val, str):
if orig_val == _default:
_form = form
elif _default in orig_val:
@@ -309,7 +309,7 @@ class Interaction(object):
_url = kwargs["location"]
part = urlparse(_url)
- url = "%s://%s%s" % (part[0], part[1], path)
+ url = f"{part[0]}://{part[1]}{path}"
else:
url = path
@@ -361,7 +361,7 @@ class Interaction(object):
# ========================================================================
-class Action(object):
+class Action:
def __init__(self, args):
self.args = args or {}
self.request = None
diff --git a/src/saml2test/opfunc.py b/src/saml2test/opfunc.py
index 09491739..c46f614d 100644
--- a/src/saml2test/opfunc.py
+++ b/src/saml2test/opfunc.py
@@ -164,7 +164,7 @@ def pick_form(response, content, url=None, **kwargs):
_default = _ava["value"]
try:
orig_val = form[prop]
- if isinstance(orig_val, six.string_types):
+ if isinstance(orig_val, str):
if orig_val == _default:
_form = form
elif _default in orig_val:
@@ -295,7 +295,7 @@ def chose(client, orig_response, content, path, **kwargs):
_url = kwargs["location"]
part = urlparse(_url)
- url = "%s://%s%s" % (part[0], part[1], path)
+ url = f"{part[0]}://{part[1]}{path}"
else:
url = path
@@ -339,7 +339,7 @@ def interaction(args):
# ========================================================================
-class Operation(object):
+class Operation:
def __init__(self, conv, args=None, features=None):
if args:
self.function = interaction(args)
diff --git a/src/saml2test/tool.py b/src/saml2test/tool.py
index f87f0e2a..7a2f8f0b 100644
--- a/src/saml2test/tool.py
+++ b/src/saml2test/tool.py
@@ -24,7 +24,7 @@ __author__ = "rolandh"
logger = logging.getLogger(__name__)
-class Conversation(object):
+class Conversation:
"""
:ivar response: The received HTTP messages
:ivar protocol_response: List of the received protocol messages
@@ -75,7 +75,7 @@ class Conversation(object):
raise CheckError
def do_check(self, test, **kwargs):
- if isinstance(test, six.string_types):
+ if isinstance(test, str):
chk = self.check_factory(test)(**kwargs)
else:
chk = test(**kwargs)