src/saml2/response.py

This commit is contained in:
Roland Hedberg
2011-03-14 13:00:46 +01:00
parent 1b98cfdaad
commit 89ef48df47
29 changed files with 326 additions and 224 deletions

View File

@@ -75,7 +75,7 @@ class MyChallengeDecider:
# require a challenge for login
for regex in self.path_login:
if regex.match(uri) != None:
if regex.match(uri) is not None:
return True
return False

View File

@@ -47,7 +47,7 @@ class EntitlementMetadataProvider(object):
elif "entitlement" not in self._store[user]:
self._store[user]["entitlement"] = {}
if entitlement == None:
if entitlement is None:
entitlement = []
self._store[user]["entitlement"][virtualorg] = entitlement
self._store.sync()

View File

@@ -36,10 +36,12 @@ from repoze.who.plugins.form import FormPluginBase
from saml2 import BINDING_HTTP_REDIRECT
from saml2.client import Saml2Client
#from saml2.attribute_resolver import AttributeResolver
from saml2.config import SPConfig
from saml2.s_utils import sid
from saml2.virtual_org import VirtualOrg
#from saml2.population import Population
#from saml2.attribute_resolver import AttributeResolver
def construct_came_from(environ):
""" The URL that the user used when the process where interupted
@@ -71,7 +73,7 @@ class SAML2Plugin(FormPluginBase):
implements(IChallenger, IIdentifier, IAuthenticator, IMetadataProvider)
def __init__(self, rememberer_name, config, saml_client,
virtual_organization, wayf, _cache, debug, sid_store=None):
wayf, _cache, debug, sid_store=None):
FormPluginBase.__init__(self)
self.rememberer_name = rememberer_name
@@ -82,18 +84,7 @@ class SAML2Plugin(FormPluginBase):
self.conf = config
self.srv = self.conf["service"]["sp"]
self.log = None
if virtual_organization:
self.vorg = virtual_organization
self.vorg_conf = None
# try:
# self.vorg_conf = self.conf[
# "virtual_organization"][virtual_organization]
# except KeyError:
# self.vorg = None
else:
self.vorg = None
try:
self.metadata = self.conf["metadata"]
except KeyError:
@@ -116,8 +107,8 @@ class SAML2Plugin(FormPluginBase):
if len( idps ) == 1:
idp_url = idps[0]["single_sign_on_service"][BINDING_HTTP_REDIRECT]
elif len( idps ) == 0:
return (1, HTTPInternalServerError(detail='Misconfiguration'))
elif not len(idps):
return 1, HTTPInternalServerError(detail='Misconfiguration')
else:
if self.wayf:
wayf_selected = environ.get('s2repose.wayf_selected','')
@@ -140,9 +131,9 @@ class SAML2Plugin(FormPluginBase):
detail="Do not know how to talk to '%s'!" & (
wayf_selected,)))
else:
return (1, HTTPNotImplemented(detail='No WAYF present!'))
return 1, HTTPNotImplemented(detail='No WAYF present!')
return (0, idp_url)
return 0, idp_url
#### IChallenger ####
def challenge(self, environ, _status, _app_headers, _forget_headers):
@@ -165,7 +156,8 @@ class SAML2Plugin(FormPluginBase):
try:
vorg = environ["myapp.vo"]
except KeyError:
vorg = self.vorg
vorg = self.saml_client.vorg
self.log and self.log.info("[sp.challenge] VO: %s" % vorg)
# If more than one idp and if none is selected, I have to do wayf
@@ -176,8 +168,9 @@ class SAML2Plugin(FormPluginBase):
idp_url = response
# Do the AuthnRequest
(sid_, result) = self.saml_client.authenticate(location=idp_url,
relay_state=came_from,
vorg=vorg)
relay_state=came_from,
log=self.log,
vorg=vorg)
# remember the request
self.outstanding_queries[sid_] = came_from
@@ -230,11 +223,12 @@ class SAML2Plugin(FormPluginBase):
return post
def _construct_identity(self, session_info):
identity = {}
identity["login"] = session_info["name_id"]
identity["password"] = ""
identity['repoze.who.userid'] = session_info["name_id"]
identity["user"] = session_info["ava"]
identity = {
"login": session_info["name_id"],
"password": "",
'repoze.who.userid': session_info["name_id"],
"user": session_info["ava"],
}
if self.debug and self.log:
self.log.info("Identity: %s" % identity)
@@ -329,12 +323,12 @@ class SAML2Plugin(FormPluginBase):
environ["s2repoze.sessioninfo"] = session_info
name_id = session_info["name_id"]
# contruct and return the identity
identity = {}
identity["login"] = name_id
identity["password"] = ""
identity['repoze.who.userid'] = name_id
identity["user"] = self.saml_client.users.get_identity(name_id)[0]
identity = {
"login": name_id,
"password": "",
'repoze.who.userid': name_id,
"user": self.saml_client.users.get_identity(name_id)[0],
}
self.log.info("[sp.identify] IDENTITY: %s" % (identity,))
return identity
else:
@@ -371,23 +365,29 @@ class SAML2Plugin(FormPluginBase):
if "pysaml2_vo_expanded" not in identity:
# is this a Virtual Organization situation
if self.vorg:
if self.vorg.do_vo_aggregation(subject_id):
# Get the extended identity
identity["user"] = self.saml_client.users.get_identity(
if self.saml_client.vorg:
try:
if self.saml_client.vorg.do_aggregation(subject_id,
log=self.log):
# Get the extended identity
identity["user"] = self.saml_client.users.get_identity(
subject_id)[0]
# Only do this once, mark that the identity has been
# expanded
identity["pysaml2_vo_expanded"] = 1
# Only do this once, mark that the identity has been
# expanded
identity["pysaml2_vo_expanded"] = 1
except KeyError:
self.log and self.log.error(
"Failed to do attribute aggregation, "
"missing common attribute")
if self.debug:
self.log and self.log.info("[add_metadata] returns: %s" % (dict(identity),))
self.log and self.log.info("[add_metadata] returns: %s" % (
dict(identity),))
# @return
# used 2 times : one to get the ticket, the other to validate it
def _service_url(self, environ, qstr=None):
if qstr != None:
if qstr is not None:
url = construct_url(environ, querystring = qstr)
else:
url = construct_url(environ)
@@ -422,11 +422,12 @@ def make_plugin(rememberer_name=None, # plugin for remember
config = SPConfig()
config.load_file(saml_conf)
scl = Saml2Client(config, identity_cache=identity_cache,
virtual_organization=virtual_organization)
scl = Saml2Client(config, identity_cache=identity_cache)
plugin = SAML2Plugin(rememberer_name, config, scl,
virtual_organization, wayf, cache, debug, sid_store)
plugin = SAML2Plugin(rememberer_name, config, scl, wayf, cache, debug,
sid_store)
return plugin
# came_from = re.sub(r'ticket=[^&]*&?', '', came_from)

View File

@@ -593,7 +593,7 @@ class SamlBase(ExtensionContainer):
setattr(self, "text", "%d" % val)
elif isinstance(val, basestring):
setattr(self, "text", val)
elif val == None:
elif val is None:
pass
else:
raise ValueError( "Type shouldn't be '%s'" % (val,))
@@ -660,7 +660,7 @@ class SamlBase(ExtensionContainer):
try:
restriction = self.c_cardinality[prop]
val = getattr(self, prop)
if val == None:
if val is None:
num = 0
elif isinstance(val, list):
num = len(val)

View File

@@ -70,7 +70,7 @@ def filter_on_attributes(ava, required=None, optional=None):
"""
res = {}
if required == None:
if required is None:
required = []
for attr in required:
@@ -84,7 +84,7 @@ def filter_on_attributes(ava, required=None, optional=None):
print >> sys.stderr, ava.keys()
raise MissingValue("Required attribute missing: '%s'" % (attr.friendly_name,))
if optional == None:
if optional is None:
optional = []
for attr in optional:
@@ -189,7 +189,7 @@ class Policy(object):
self._restrictions = restrictions.copy()
for _, spec in self._restrictions.items():
if spec == None:
if spec is None:
continue
try:
@@ -197,7 +197,7 @@ class Policy(object):
except KeyError:
continue
if restr == None:
if restr is None:
continue
for key, values in restr.items():

View File

@@ -44,7 +44,7 @@ def ac_factory(path):
def ava_fro(acs, statement):
""" translates attributes according to their name_formats """
if statement == []:
if not statement:
return {}
acsdic = dict([(ac.name_format, ac) for ac in acs])
@@ -123,9 +123,9 @@ class AttributeConverter(object):
self._to = eval(open(filename).read())
def adjust(self):
if self._fro == None and self._to != None:
if self._fro is None and self._to is not None:
self._fro = dict([(value, key) for key, value in self._to.items()])
if self._to == None and self.fro != None:
if self._to is None and self.fro is not None:
self._to = dict([(value, key) for key, value in self._fro.items()])
def fail_safe_fro(self, statement):
@@ -161,7 +161,7 @@ class AttributeConverter(object):
else:
val.append(value.text.strip())
return (attr, val)
return attr, val
def fro(self, statement):
""" Get the attributes and the attribute values

View File

@@ -21,17 +21,18 @@ to do attribute aggregation.
"""
import saml2
DEFAULT_BINDING = saml2.BINDING_HTTP_REDIRECT
DEFAULT_BINDING = saml2.BINDING_SOAP
class AttributeResolver(object):
def __init__(self, environ, metadata=None, config=None, saml2client=None):
def __init__(self, metadata=None, config=None, saml2client=None):
self.metadata = metadata
if saml2client:
self.saml2client = saml2client
self.metadata = saml2client.config.metadata
else:
self.saml2client = saml2.client.Saml2Client(environ, config)
self.saml2client = saml2.client.Saml2Client(config)
def extend(self, subject_id, issuer, vo_members, name_id_format=None,
sp_name_qualifier=None, log=None):
@@ -51,14 +52,19 @@ class AttributeResolver(object):
for member in vo_members:
for ass in self.metadata.attribute_services(member):
for attr_serv in ass.attribute_service:
log and log.info("Send attribute request to %s" % \
attr_serv.location)
if log:
log.info(
"Send attribute request to %s" % attr_serv.location)
if attr_serv.binding != saml2.BINDING_SOAP:
continue
# attribute query assumes SOAP binding
session_info = self.saml2client.attribute_query(
subject_id,
issuer,
attr_serv.location,
sp_name_qualifier=sp_name_qualifier,
format=name_id_format, log=log)
subject_id,
attr_serv.location,
issuer_id=issuer,
sp_name_qualifier=sp_name_qualifier,
nameid_format=name_id_format,
log=log)
if session_info:
result.append(session_info)
return result

View File

@@ -71,7 +71,7 @@ def http_post_message(message, location, relay_state="", typ="SAMLRequest"):
response.append("""</script>""")
response.append("</body>")
return ([("Content-type", "text/html")], response)
return [("Content-type", "text/html")], response
def http_redirect_message(message, location, relay_state="",
typ="SAMLRequest"):
@@ -100,7 +100,7 @@ def http_redirect_message(message, location, relay_state="",
headers = [('Location', login_url)]
body = [""]
return (headers, body)
return headers, body
def make_soap_enveloped_saml_thingy(thingy, header_parts=None):
""" Returns a soap envelope containing a SAML request
@@ -179,15 +179,15 @@ def parse_soap_enveloped_saml(text, body_class, header_class=None):
#
#
# http = HTTPClient(destination, key_file, cert_file, log)
# log and log.info("HTTP client initiated")
# if log: log.info("HTTP client initiated")
#
# try:
# response = http.get()
# except Exception, exc:
# log and log.info("HTTPClient exception: %s" % (exc,))
# if log: log.info("HTTPClient exception: %s" % (exc,))
# return None
#
# log and log.info("HTTP request sent and got response: %s" % response)
# if log: log.info("HTTP request sent and got response: %s" % response)
#
# return response
@@ -195,7 +195,8 @@ def send_using_http_post(request, destination, relay_state, key_file=None,
cert_file=None, log=None):
http = HTTPClient(destination, key_file, cert_file, log)
log and log.info("HTTP client initiated")
if log:
log.info("HTTP client initiated")
if not isinstance(request, basestring):
request = "%s" % (request,)
@@ -204,10 +205,12 @@ def send_using_http_post(request, destination, relay_state, key_file=None,
try:
response = http.post(message, headers)
except Exception, exc:
log and log.info("HTTPClient exception: %s" % (exc,))
if log:
log.info("HTTPClient exception: %s" % (exc,))
return None
log and log.info("HTTP request sent and got response: %s" % response)
if log:
log.info("HTTP request sent and got response: %s" % response)
return response
@@ -225,14 +228,17 @@ def send_using_soap(message, destination, key_file=None, cert_file=None,
SOAPClient
"""
soapclient = SOAPClient(destination, key_file, cert_file, log)
log and log.info("SOAP client initiated")
if log:
log.info("SOAP client initiated")
try:
response = soapclient.send(message)
except Exception, exc:
log and log.info("SoapClient exception: %s" % (exc,))
if log:
log.info("SoapClient exception: %s" % (exc,))
return None
log and log.info("SOAP request sent and got response: %s" % response)
if log:
log.info("SOAP request sent and got response: %s" % response)
return response

View File

@@ -38,7 +38,7 @@ class Cache(object):
try:
entities = self._db[subject_id].keys()
except KeyError:
return ({}, [])
return {}, []
res = {}
oldees = []
@@ -54,7 +54,7 @@ class Cache(object):
res[key] = list(tmp)
except KeyError:
res[key] = vals
return (res, oldees)
return res, oldees
def get(self, subject_id, entity_id):
""" Get session information about a subject gotten from a

View File

@@ -45,6 +45,7 @@ from saml2.response import authn_response
from saml2.response import response_factory
from saml2.response import LogoutResponse
from saml2.response import AuthnResponse
from saml2.response import attribute_response
from saml2 import BINDING_HTTP_REDIRECT, BINDING_SOAP, BINDING_HTTP_POST
@@ -70,12 +71,13 @@ class LogoutError(Exception):
class Saml2Client(object):
""" The basic pySAML2 service provider class """
def __init__(self, config=None, debug=0, vorg=None,
identity_cache=None, state_cache=None):
def __init__(self, config=None, debug=0,
identity_cache=None, state_cache=None,
virtual_organization=None):
"""
:param config: A saml2.config.Config instance
"""
self.vorg = None
self.users = Population(identity_cache)
# for server state storage
@@ -83,20 +85,21 @@ class Saml2Client(object):
self.state = {} # in memory storage
else:
self.state = state_cache
self.sec = None
if config:
self.config = config
if "metadata" in config:
self.metadata = config["metadata"]
if vorg:
self.vorg = VirtualOrg(self.metadata, vorg,
self.users.cache,
log=None, vorg_conf=None)
self.sec = security_context(config)
else:
self.config = {}
if virtual_organization:
self.vorg = VirtualOrg(self, virtual_organization)
else:
self.vorg = None
if not debug and self.config:
self.debug = self.config.debug()
else:
@@ -169,15 +172,18 @@ class Saml2Client(object):
reply_addr, outstanding, log,
debug=self.debug)
except Exception, exc:
log and log.error("%s" % exc)
if log:
log.error("%s" % exc)
return None
if self.debug:
log and log.info(">>", resp)
if log:
log.info(">>", resp)
resp = resp.verify()
if isinstance(resp, AuthnResponse):
self.users.add_information_about_person(resp.session_info())
log and log.error("--- ADDED person info ----")
if log:
log.error("--- ADDED person info ----")
elif isinstance(resp, LogoutResponse):
self.handle_logout_response(resp, log)
elif log:
@@ -231,16 +237,23 @@ class Saml2Client(object):
to_sign = []
request.name_id_policy = name_id_policy
request.issuer = factory(saml.Issuer, text=spentityid )
request.issuer = self.issuer(spentityid)
if log:
log.info("REQUEST: %s" % request)
return "%s" % signed_instance_factory(request, self.sec, to_sign)
def issuer(self):
def issuer(self, entityid=None):
""" Return an Issuer instance """
return saml.Issuer(text=self.config["entityid"],
if entityid:
if isinstance(entityid, saml.Issuer):
return entityid
else:
return saml.Issuer(text=entityid,
format=saml.NAMEID_FORMAT_ENTITY)
else:
return saml.Issuer(text=self.config["entityid"],
format=saml.NAMEID_FORMAT_ENTITY)
def _spentityid(self, spentityid=None):
@@ -306,7 +319,8 @@ class Saml2Client(object):
authen_req = self.authn_request(session_id, location,
service_url, spentityid, my_name, vorg,
scoping, log, sign)
log and log.info("AuthNReq: %s" % authen_req)
if log:
log.info("AuthNReq: %s" % authen_req)
if binding == saml2.BINDING_HTTP_POST:
# No valid ticket; Send a form to the client
@@ -319,11 +333,11 @@ class Saml2Client(object):
response = head[0]
else:
raise Exception("Unkown binding type: %s" % binding)
return (session_id, response)
return session_id, response
def create_attribute_query(self, session_id, subject_id, destination,
issuer=None, attribute=None, sp_name_qualifier=None,
issuer_id=None, attribute=None, sp_name_qualifier=None,
name_qualifier=None, nameid_format=None, sign=False):
""" Constructs an AttributeQuery
@@ -359,7 +373,7 @@ class Saml2Client(object):
version=VERSION,
issue_instant=instant(),
destination=destination,
issuer=issuer,
issuer=self.issuer(issuer_id),
subject=subject,
)
@@ -376,10 +390,10 @@ class Saml2Client(object):
return query
def attribute_query(self, subject_id, destination, issuer=None,
def attribute_query(self, subject_id, destination, issuer_id=None,
attribute=None, sp_name_qualifier=None, name_qualifier=None,
nameid_format=None, log=None):
""" Does a attribute request from an attribute authority
""" Does a attribute request to an attribute authority
:param subject_id: The identifier of the subject
:param destination: To whom the query should be sent
@@ -395,45 +409,50 @@ class Saml2Client(object):
"""
session_id = sid()
if not issuer:
issuer = self.issuer()
issuer = self.issuer(issuer_id)
request = self.create_attribute_query(session_id, subject_id,
destination, issuer, attribute, sp_name_qualifier,
name_qualifier, nameid_format=nameid_format)
log and log.info("Request, created: %s" % request)
if log:
log.info("Request, created: %s" % request)
soapclient = SOAPClient(destination, self.config["key_file"],
self.config["cert_file"])
log and log.info("SOAP client initiated")
if log:
log.info("SOAP client initiated")
try:
response = soapclient.send(request)
except Exception, exc:
log and log.info("SoapClient exception: %s" % (exc,))
if log:
log.info("SoapClient exception: %s" % (exc,))
return None
log and log.info("SOAP request sent and got response: %s" % response)
if log:
log.info("SOAP request sent and got response: %s" % response)
if response:
log and log.info("Verifying response")
if log:
log.info("Verifying response")
try:
aresp = authn_response(self.config, "", issuer,
outstanding_queries={session_id:""},
log=log)
aresp = attribute_response(self.config, "", issuer, log=log)
except Exception, exc:
log and log.error("%s", (exc,))
if log:
log.error("%s", (exc,))
return None
session_info = aresp.loads(response).verify().session_info()
session_info = aresp.loads(response, False).verify().session_info()
if session_info:
self.users.add_information_about_person(session_info)
log and log.info("session: %s" % session_info)
if log:
log.info("session: %s" % session_info)
return session_info
else:
log and log.info("No response")
if log:
log.info("No response")
return None
def logout_requests(self, subject_id, destination, entity_id,
@@ -493,7 +512,8 @@ class Saml2Client(object):
conversation.
"""
log and log.info("logout request for: %s" % subject_id)
if log:
log.info("logout request for: %s" % subject_id)
# find out which IdPs/AAs I should notify
entity_ids = self.users.issuers_of_info(subject_id)
@@ -505,15 +525,16 @@ class Saml2Client(object):
sign, log=None, return_to="/"):
# check time
if not_on_or_after(expire) == False: # I've run out of time
if not not_on_or_after(expire): # I've run out of time
# Do the local logout anyway
self.local_logout(subject_id)
return (0, "504 Gateway Timeout", [], [])
return 0, "504 Gateway Timeout", [], []
# for all where I can use the SOAP binding, do those first
not_done = entity_ids[:]
session_id = 0
response = False
for entity_id in entity_ids:
response = False
rstate = None
@@ -523,7 +544,8 @@ class Saml2Client(object):
if not destination:
continue
log and log.info("destination to provider: %s" % destination)
if log:
log.info("destination to provider: %s" % destination)
request = self.logout_requests(subject_id, destination,
entity_id, reason, expire, log)
@@ -544,14 +566,17 @@ class Saml2Client(object):
self.config["cert_file"],
log=log)
if response:
log and log.info("Verifying response")
if log:
log.info("Verifying response")
response = self.logout_response(response, log)
if response:
not_done.remove(entity_id)
log and log.info("OK response from %s" % destination)
if log:
log.info("OK response from %s" % destination)
else:
log and log.info(
if log:
log.info(
"NOT OK response from %s" % destination)
else:
@@ -579,13 +604,13 @@ class Saml2Client(object):
rstate)
code = "302 Found"
return (session_id, code, head, body)
return session_id, code, head, body
if not_done != []:
if not_done:
# upstream should try later
raise LogoutError("%s" % (entity_ids,))
return (0, "", [], response)
return 0, "", [], response
def local_logout(self, subject_id):
""" Remove the user from the cache, equals local logout
@@ -603,15 +628,18 @@ class Saml2Client(object):
:return: 4-tuple of (session_id of the last sent logout request,
response message, response headers and message)
"""
log and log.info("state: %s" % (self.state,))
if log:
log.info("state: %s" % (self.state,))
status = self.state[response.in_response_to]
log and log.info("status: %s" % (status,))
if log:
log.info("status: %s" % (status,))
issuer = response.issuer()
log and log.info("issuer: %s" % issuer)
if log:
log.info("issuer: %s" % issuer)
del self.state[response.in_response_to]
if status["entity_ids"] == [issuer]: # done
self.local_logout(status["subject_id"])
return (0, "200 Ok", [("Content-type","text/html")], [])
return 0, "200 Ok", [("Content-type","text/html")], []
else:
status["entity_ids"].remove(issuer)
return self._logout(status["subject_id"],
@@ -641,14 +669,16 @@ class Saml2Client(object):
"single_logout_service",
binding=binding)[0]
except Exception:
log and log.info("Not supposed to handle this!")
if log:
log.info("Not supposed to handle this!")
return None
try:
response = LogoutResponse(self.sec, return_addr, debug=True,
log=log)
except Exception, exc:
log and log.info("%s" % exc)
if log:
log.info("%s" % exc)
return None
if binding == BINDING_HTTP_REDIRECT:
@@ -710,7 +740,7 @@ class Saml2Client(object):
status)
if log:
log.info("RESPONSE: %s" % response)
log.info("RESPONSE: {0:>s}".format(response))
if 'RelayState' in get:
rstate = get['RelayState']

View File

@@ -104,7 +104,7 @@ class Config(dict):
res = []
for spec in self["service"][typ]["endpoints"][service]:
if isinstance(spec, basestring):
if binding == None or binding == DEFAULT_BINDING[service]:
if binding is None or binding == DEFAULT_BINDING[service]:
res.append(spec)
elif isinstance(spec, tuple):
if binding:

View File

@@ -44,7 +44,7 @@ class Cache(object):
if not entities:
entities = self.entities(subject_id)
if not entities:
return ({}, [])
return {}, []
res = {}
oldees = []
@@ -61,7 +61,7 @@ class Cache(object):
res[key] = list(tmp)
except KeyError:
res[key] = vals
return (res, oldees)
return res, oldees
def get_info(self, item):
""" Get session information about a subject gotten from a
@@ -174,7 +174,7 @@ class Cache(object):
def update(self, subject_id, entity_id, ava):
res = self._cache.get(_key(subject_id, entity_id))
if res == None:
if res is None:
raise KeyError("No such subject")
else:
info = self.get_info(res)

View File

@@ -115,7 +115,7 @@ class MetaData(object):
if afd:
members = [member.text.strip() for member in afd.affiliate_member]
if members != []:
if members:
entity[tag] = members
def _sp_metadata(self, entity_descr, entity, tag):
@@ -229,7 +229,7 @@ class MetaData(object):
if attr_serv.binding == BINDING_SOAP:
aserv.append(attr_serv)
if aserv == []:
if not aserv:
continue
taad.attribute_service = aserv
@@ -243,7 +243,7 @@ class MetaData(object):
aads.append(taad)
if aads != []:
if aads:
entity[tag] = aads
def clear_from_source(self, source):
@@ -295,7 +295,7 @@ class MetaData(object):
except KeyError:
self._import[source] = [entity_descr.entity_id]
# have I seen this entity_id before ? If so log and ignore it
# have I seen this entity_id before ? If so if log: ignore it
if entity_descr.entity_id in self.entity:
print >> sys.stderr, \
"Duplicated Entity descriptor (entity id: '%s')" % \
@@ -372,7 +372,7 @@ class MetaData(object):
self.import_metadata(content, (url, cert))
return True
else:
self.log and self.log.info("Response status: %s" % response.status)
self.if log: self.log.info("Response status: %s" % response.status)
return False
def idp_services(self, entity_id, typ, binding=None):
@@ -541,14 +541,14 @@ class MetaData(object):
try:
return self._wants[entity_id]
except KeyError:
return ([], [])
return [], []
@keep_updated
def attribute_consumer(self, entity_id):
try:
ssos = self.entity[entity_id]["sp_sso"]
except KeyError:
return ([], [])
return [], []
required = []
optional = []
@@ -560,7 +560,7 @@ class MetaData(object):
else:
optional.append(attr)
return (required, optional)
return required, optional
def _orgname(self, org, lang="en"):
if not org:
@@ -594,8 +594,10 @@ class MetaData(object):
for entity_id, edict in self.entity.items():
if "idp_sso" in edict:
#idp_aa_check self._valid(entity_id)
name = None
if "organization" in edict:
name = self._orgname(edict["organization"],"en")
if not name:
name = self._location(edict["idp_sso"])[0]
idps[entity_id] = (name, edict["idp_sso"])

View File

@@ -41,7 +41,7 @@ class Population(object):
def subjects(self):
"""Returns the name id's for all the persons in the cache"""
return self.cache.subjects();
return self.cache.subjects()
def remove_person(self, subject_id):
self.cache.delete(subject_id)

View File

@@ -52,7 +52,7 @@ class Request(object):
except TypeError:
raise
except Exception, excp:
self.log and self.log.info("EXCEPTION: %s", excp)
self.if log: self.log.info("EXCEPTION: %s", excp)
if not self.message:
if self.log:

View File

@@ -68,6 +68,19 @@ def authn_response(conf, entity_id, return_addr, outstanding_queries=None,
return_addr, outstanding_queries, log, timeslack,
debug)
# comes in over SOAP so synchronous
def attribute_response(conf, entity_id, return_addr, log=None, timeslack=0,
debug=0):
sec = security_context(conf)
if not timeslack:
try:
timeslack = int(conf["timeslack"])
except KeyError:
pass
return AttributeResponse(sec, conf.attribute_converters, entity_id,
return_addr, log, timeslack, debug)
class StatusResponse(object):
def __init__(self, sec_context, return_addr=None, log=None, timeslack=0,
debug=0, request_id=0):
@@ -140,7 +153,7 @@ class StatusResponse(object):
except SignatureError:
raise
except Exception, excp:
self.log and self.log.info("EXCEPTION: %s", excp)
self.if log: self.log.info("EXCEPTION: %s", excp)
print "<", self.response
@@ -216,6 +229,33 @@ class LogoutResponse(StatusResponse):
debug)
self.signature_check = self.sec.correctly_signed_logout_response
class AttributeResponse(StatusResponse):
def __init__(self, sec_context, attribute_converters, entity_id,
return_addr=None, log=None, timeslack=0, debug=0):
StatusResponse.__init__(self, sec_context, return_addr, log, timeslack,
debug)
self.entity_id = entity_id
self.attribute_converters = attribute_converters
def get_identity(self):
# The assertion can contain zero or one attributeStatements
if not self.assertion.attribute_statement:
self.log.error("Missing Attribute Statement")
ava = {}
else:
assert len(self.assertion.attribute_statement) == 1
if self.debug:
self.log.info("Attribute Statement: %s" % (
self.assertion.attribute_statement[0],))
for aconv in self.attribute_converters():
self.log.info(
"Converts name format: %s" % (aconv.name_format,))
ava = to_local(self.attribute_converters(),
self.assertion.attribute_statement[0])
return ava
class AuthnResponse(StatusResponse):
""" This is where all the profile complience is checked.
@@ -281,7 +321,7 @@ class AuthnResponse(StatusResponse):
self.timeslack)
validate_before(condition.not_before, self.timeslack)
except Exception, excp:
self.log and self.log.error("Exception on condition: %s" % (excp,))
self.if log: self.log.error("Exception on condition: %s" % (excp,))
if not lax:
raise
else:
@@ -357,7 +397,7 @@ class AuthnResponse(StatusResponse):
subjconf.append(subject_confirmation)
if subjconf == []:
if not subjconf:
raise Exception("No valid subject confirmation")
subject.subject_confirmation = subjconf
@@ -374,7 +414,7 @@ class AuthnResponse(StatusResponse):
self.log.info("assertion context: %s" % (self.context,))
self.log.info("assertion keys: %s" % (assertion.keyswv()))
self.log.info("outstanding_queries: %s" % (
self.outstanding_queries))
self.outstanding_queries,))
if self.context == "AuthNReq":
self.authn_statement_ok()

View File

@@ -122,7 +122,7 @@ def parse_attribute_map(filenames):
forward[(name, name_format)] = friendly_name
backward[friendly_name] = (name, name_format)
return (forward, backward)
return forward, backward
def identity_attribute(form, attribute, forward_map=None):
if form == "friendly":
@@ -214,7 +214,7 @@ def response_factory(sign=False, encrypt=False, **kwargs):
def _attrval(val, typ=""):
if isinstance(val, list) or isinstance(val, set):
attrval = [saml.AttributeValue(text=v) for v in val]
elif val == None:
elif val is None:
attrval = None
else:
attrval = [saml.AttributeValue(text=val)]
@@ -241,7 +241,7 @@ def do_ava(val, typ=""):
ava = saml.AttributeValue()
ava.set_text(val)
attrval = [ava]
elif val == None:
elif val is None:
attrval = None
else:
raise OtherError("strange value type on: %s" % val)

View File

@@ -80,7 +80,7 @@ def _verify_value_type(typ, val):
if typ == XSD + "float" or typ == XSD + "double":
return float(val)
if typ == XSD + "boolean":
if (val.lower() == "true" or val.lower() == "false"):
if val.lower() == "true" or val.lower() == "false":
pass
else:
raise ValueError("Faulty boolean value")
@@ -126,7 +126,7 @@ class AttributeValueBase(SamlBase):
val = str(val)
if not typ:
self.set_type("xs:float")
elif val == None:
elif val is None:
val = ""
else:
raise ValueError

View File

@@ -93,6 +93,7 @@ class Identifier(object):
try:
return self._get_remote("persistent", entity_id, subject_id)
except KeyError:
temp_id = "xyz"
while True:
temp_id = sid()
try:
@@ -147,10 +148,11 @@ class Identifier(object):
:param userid: The local persistent identifier for the subject.
:return: The created identifier,
"""
temp_id = sid()
while True:
temp_id = sid()
try:
_ = self._get_local("transient", sp_entity_id, temp_id)
temp_id = sid()
except KeyError:
break
self._store("transient", sp_entity_id, userid, temp_id)
@@ -232,6 +234,7 @@ class Server(object):
# subject information is store in database
# default database is a shelve database which is OK in some setups
dbspec = self.conf["subject_data"]
idb = None
if isinstance(dbspec, basestring):
idb = shelve.open(dbspec, writeback=True)
else: # database spec is a a 2-tuple (type, address)
@@ -241,11 +244,12 @@ class Server(object):
elif typ == "memcached":
idb = memcache.Client(addr)
if idb != None:
if idb is not None:
self.ident = Identifier(idb, self.conf.vo_conf, self.debug,
self.log)
else:
raise Exception("Couldn't open identity database: %s" % (dbspec))
raise Exception("Couldn't open identity database: %s" %
(dbspec,))
else:
self.ident = None
@@ -289,9 +293,9 @@ class Server(object):
try:
consumer_url = self.metadata.consumer_url(sp_entity_id)
except KeyError:
self.log and self.log.info(
self.if log: self.log.info(
"Failed to find consumer URL for %s" % sp_entity_id)
self.log and self.log.info(
self.if log: self.log.info(
"entities: %s" % self.metadata.entity.keys())
raise UnknownPrincipal(sp_entity_id)
@@ -347,7 +351,7 @@ class Server(object):
subject = attribute_query.subject_id()
attribute = attribute_query.attribute()
return (subject, attribute, attribute_query.message)
return subject, attribute, attribute_query.message
# ------------------------------------------------------------------------
@@ -599,7 +603,7 @@ class Server(object):
self.log.info("binding wanted: %s" % (binding,))
raise
self.log and self.log.info("Endpoint: %s" % (slo))
self.if log: self.log.info("Endpoint: %s" % slo)
req = LogoutRequest(self.sec, slo)
if binding == BINDING_SOAP:
lreq = soap.parse_soap_enveloped_saml_logout_request(text)
@@ -647,7 +651,7 @@ class Server(object):
if not destination:
self.log and self.log.error("Not way to return a response !!!")
self.if log: self.log.error("Not way to return a response !!!")
return ("412 Precondition Failed",
[("Content-type", "text/html")],
["No return way defined"])
@@ -693,7 +697,7 @@ class Server(object):
to_sign = [(class_name(response), mid)]
response = signed_instance_factory(response, self.sec, to_sign)
self.log and self.log.info("Response: %s" % (response,))
self.if log: self.log.info("Response: %s" % (response,))
if binding == BINDING_HTTP_REDIRECT:
(headers, message) = http_redirect_message(response,
destination,
@@ -703,4 +707,4 @@ class Server(object):
(headers, message) = http_post_message(response, destination,
typ="SAMLResponse")
return (rcode, headers, message)
return rcode, headers, message

View File

@@ -388,7 +388,7 @@ class SecurityContext(object):
self.debug = 0
def correctly_signed(self, xml, must=False):
self.log and self.log.info("verify correct signature")
self.if log: self.log.info("verify correct signature")
return self.correctly_signed_response(xml, must)
def decrypt(self, enctext):
@@ -397,7 +397,7 @@ class SecurityContext(object):
:param enctext: The encrypted text as a string
:return: The decrypted text
"""
self.log and self.log.info("input len: %d" % len(enctext))
self.if log: self.log.info("input len: %d" % len(enctext))
_, fil = make_temp("%s" % enctext, decode=False)
ntf = NamedTemporaryFile()
@@ -415,7 +415,8 @@ class SecurityContext(object):
p_err = pof.stderr.read()
if self.debug:
self.log.debug("Decrypt result: %s" % (p_out, p_err))
self.log.debug("Decrypt result (out): %s" % (p_out))
self.log.debug("Decrypt result (err): %s" % (p_err))
ntf.seek(0)
return ntf.read()

View File

@@ -133,7 +133,7 @@ class SOAPClient(object):
response = self.server.post(soap_message,
{"content-type": "application/soap+xml"})
if response:
self.log and self.log.info("SOAP response: %s" % response)
self.if log: self.log.info("SOAP response: %s" % response)
return parse_soap_enveloped_saml_response(response)
else:
return False

View File

@@ -66,7 +66,7 @@ def _verify_value_type(typ, val):
if typ == XSD + "float" or typ == XSD + "double":
return float(val)
if typ == XSD + "boolean":
if (val.lower() == "true" or val.lower() == "false"):
if val.lower() == "true" or val.lower() == "false":
pass
else:
raise ValueError("Faulty boolean value")
@@ -112,7 +112,7 @@ class AttributeValueBase(SamlBase):
val = str(val)
if not typ:
self.set_type("xs:float")
elif val == None:
elif val is None:
val = ""
else:
raise ValueError

View File

@@ -46,7 +46,7 @@
},
"key_file" : "test.key",
"cert_file" : "test.pem",
"xmlsec_binary" : "/opt/local/bin/xmlsec1",
"xmlsec_binary" : "/usr/local/bin/xmlsec1",
"metadata": {
"local": ["sp_0.metadata"],
},

View File

@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='UTF-8'?>
<ns0:EntitiesDescriptor xmlns:ns0="urn:oasis:names:tc:SAML:2.0:metadata"><ns0:EntityDescriptor entityID="urn:mace:umu.se:saml:roland:sp"><ns0:SPSSODescriptor AuthnRequestsSigned="false" WantAssertionsSigned="true" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"><ns0:KeyDescriptor><ns1:KeyInfo xmlns:ns1="http://www.w3.org/2000/09/xmldsig#"><ns1:X509Data><ns1:X509Certificate>MIICsDCCAhmgAwIBAgIJAJrzqSSwmDY9MA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
<ns0:EntitiesDescriptor xmlns:ns0="urn:oasis:names:tc:SAML:2.0:metadata"><ns0:EntityDescriptor entityID="http://www.example.com/roland/sp"><ns0:SPSSODescriptor AuthnRequestsSigned="false" WantAssertionsSigned="true" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"><ns0:KeyDescriptor><ns1:KeyInfo xmlns:ns1="http://www.w3.org/2000/09/xmldsig#"><ns1:X509Data><ns1:X509Certificate>MIICsDCCAhmgAwIBAgIJAJrzqSSwmDY9MA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMDkxMDA2MTk0OTQxWhcNMDkxMTA1MTk0OTQxWjBF
MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50
@@ -14,4 +14,4 @@ mDY9MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAJSrKOEzHO7TL5cy6
h3qh+3+JAk8HbGBW+cbX6KBCAw/mzU8flK25vnWwXS3dv2FF3Aod0/S7AWNfKib5
U/SA9nJaz/mWeF9S0farz9AQFc8/NSzAzaVq7YbM4F6f6N2FRl7GikdXRCed45j6
mrPzGzk3ECbupFnqyREH3+ZPSdk=
</ns1:X509Certificate></ns1:X509Data></ns1:KeyInfo></ns0:KeyDescriptor><ns0:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://localhost:8087/" index="0" /><ns0:AttributeConsumingService><ns0:ServiceName ns1:lang="en" xmlns:ns1="http:#www.w3.org/XML/1998/namespace">Rolands SP</ns0:ServiceName><ns0:RequestedAttribute FriendlyName="surName" Name="urn:oid:2.5.4.4" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true" /><ns0:RequestedAttribute FriendlyName="givenName" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true" /><ns0:RequestedAttribute FriendlyName="mail" Name="urn:oid:0.9.2342.19200300.100.1.3" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true" /><ns0:RequestedAttribute FriendlyName="title" Name="urn:oid:2.5.4.12" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" /></ns0:AttributeConsumingService></ns0:SPSSODescriptor></ns0:EntityDescriptor></ns0:EntitiesDescriptor>
</ns1:X509Certificate></ns1:X509Data></ns1:KeyInfo></ns0:KeyDescriptor><ns0:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="location" /><ns0:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="http://localhost:8087/" index="1" /><ns0:AttributeConsumingService index="1"><ns0:ServiceName xml:lang="en">Rolands SP</ns0:ServiceName><ns0:ServiceDescription xml:lang="en">Roland own test SP</ns0:ServiceDescription><ns0:RequestedAttribute Name="surName" isRequired="true" /><ns0:RequestedAttribute FriendlyName="givenName" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true" /><ns0:RequestedAttribute FriendlyName="mail" Name="urn:oid:0.9.2342.19200300.100.1.3" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true" /><ns0:RequestedAttribute FriendlyName="title" Name="urn:oid:2.5.4.12" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false" /></ns0:AttributeConsumingService></ns0:SPSSODescriptor></ns0:EntityDescriptor></ns0:EntitiesDescriptor>

View File

@@ -165,7 +165,6 @@ def test_sp_metadata():
assert _eq(md.wants('urn:mace:umu.se:saml:roland:sp')[1].keys(),
["title"])
KALMAR2_URL = "https://kalmar2.org/simplesaml/module.php/aggregator/?id=kalmarcentral2&set=saml2"
KALMAR2_CERT = "kalmar2.pem"

View File

@@ -27,9 +27,12 @@ sp1 = {
"urn-mace-swami.se-swamid-test-1.0-metadata.xml"],
},
"virtual_organization" : {
"http://vo.example.org/biomed":{
"nameid_format" : "urn:oid:2.16.756.1.2.5.1.1.1-NameID",
"common_identifier": "swissEduPersonUniqueID",
"coip":{
"nameid_format" : "urn:oasis:names:tc:SAML:2.0:nameid-format:transient",
"common_identifier": "eduPersonPrincipalName",
"attribute_auth": [
"https://coip-test.sunet.se/idp/shibboleth",
]
}
}
}

View File

@@ -460,4 +460,18 @@ class TestServerLogout():
assert len(headers) == 1
assert headers[0][0] == "Location"
assert message == ['']
# class TestSign():
# def test_1(self):
# IDP = server.Server("restrictive_idp.config", debug=1)
# ava = { "givenName": ["Derek"], "surName": ["Jeter"],
# "mail": ["derek@nyy.mlb.com"]}
#
# authn_resp = IDP.authn_response(ava,
# "id1", "http://local:8087/",
# "urn:mace:example.com:saml:roland:sp",
# samlp.NameIDPolicy(format=saml.NAMEID_FORMAT_TRANSIENT,
# allow_create="true"),
# "foba0001@example.com", sign=True)
# print authn_resp
# assert False

View File

@@ -69,7 +69,6 @@ class TestClient:
req = self.client.create_attribute_query("id1",
"E8042FB4-4D5B-48C3-8E14-8EDD852790DD",
"https://idp.example.com/idp/",
self.client.issuer(),
nameid_format=saml.NAMEID_FORMAT_PERSISTENT)
reqstr = "%s" % req.to_string()
xmlsec_vers = xmlsec_version(self.client.config["xmlsec_binary"])
@@ -91,7 +90,6 @@ class TestClient:
req = self.client.create_attribute_query("id1",
"E8042FB4-4D5B-48C3-8E14-8EDD852790DD",
"https://idp.example.com/idp/",
self.client.issuer(),
attribute={
("urn:oid:2.5.4.42",
"urn:oasis:names:tc:SAML:2.0:attrname-format:uri",
@@ -135,7 +133,6 @@ class TestClient:
req = self.client.create_attribute_query("id1",
"_e7b68a04488f715cda642fbdd90099f5",
"https://aai-demo-idp.switch.ch/idp/shibboleth",
self.client.issuer(),
nameid_format=saml.NAMEID_FORMAT_TRANSIENT )
assert isinstance(req, samlp.AttributeQuery)
@@ -152,7 +149,6 @@ class TestClient:
req = self.client.attribute_query(
"_e7b68a04488f715cda642fbdd90099f5",
"https://aai-demo-idp.switch.ch/idp/shibboleth",
self.client.issuer(),
nameid_format=saml.NAMEID_FORMAT_TRANSIENT)
# since no one is answering on the other end

View File

@@ -71,7 +71,7 @@ def base_init(imports):
line.append("%sSamlBase.__init__(self, " % (INDENT+INDENT))
for attr in BASE_ELEMENT:
line.append("%s%s=%s," % (indent4, attr, attr))
line.append("%s)" % (indent4))
line.append("%s)" % indent4)
else:
# TODO have to keep apart which properties comes from which superior
for sup, elems in imports.items():
@@ -80,7 +80,7 @@ def base_init(imports):
lattr.extend(BASE_ELEMENT)
for attr in lattr:
line.append("%s%s=%s," % (indent4, attr, attr))
line.append("%s)" % (indent4))
line.append("%s)" % indent4)
return line
def initialize(attributes):
@@ -106,7 +106,7 @@ def _mod_typ(prop):
typ = prop.ref
mod = None
return (mod, typ)
return mod, typ
def _mod_cname(prop, cdict):
if hasattr(prop, "scoped"):
@@ -122,7 +122,7 @@ def _mod_cname(prop, cdict):
else:
cname = typ
return (mod, cname)
return mod, cname
def leading_uppercase(string):
try:
@@ -270,7 +270,7 @@ class PyObj(object):
else:
args.append((prop.pyname, prop.pyname, None))
return (args, child, inh)
return args, child, inh
def _superiors(self, cdict):
imps = {}
@@ -290,7 +290,7 @@ class PyObj(object):
superior = []
sups = []
return (superior, sups, imps)
return superior, sups, imps
def class_definition(self, target_namespace, cdict=None, ignore=None):
line = []
@@ -427,7 +427,7 @@ class PyElement(PyObj):
if not mod:
cname = leading_uppercase(typ)
if not cdict[cname].done:
return ([cdict[cname]], [])
return [cdict[cname]], []
except ValueError:
pass
except TypeError: # could be a ref then or a PyObj instance
@@ -438,8 +438,8 @@ class PyElement(PyObj):
else:
cname = leading_uppercase(self.ref)
if not cdict[cname].done:
return ([cdict[cname]], [])
return ([], [])
return [cdict[cname]], []
return [], []
def _local_class(self, typ, cdict, child, target_namespace, ignore):
if typ in cdict and not cdict[typ].done:
@@ -524,7 +524,7 @@ class PyElement(PyObj):
if mod:
#self.superior = ["%s.%s" % (mod, typ)]
if verify_import(self.root.modul[mod], typ):
return (req, text)
return req, text
else:
raise Exception(
"Import attempted on %s from %s module failed - wasn't there" % (
@@ -538,19 +538,19 @@ class PyElement(PyObj):
raise MissingPrerequisite(self.ref)
self.done = True
return (req, text)
return req, text
def _do(obj, target_namespace, cdict, prep):
try:
(req, text) = obj.text(target_namespace, cdict)
except MissingPrerequisite:
return ([], None)
return [], None
if text == None:
if text is None:
if req:
#prep = prepend(req, prep)
prep.append(req)
return (prep, None)
return prep, None
else:
obj.done = True
if req:
@@ -592,7 +592,7 @@ class PyType(PyObj):
if not self.properties and not self.type \
and not self.superior:
self.done = True
return ([], self.class_definition(target_namespace, cdict))
return [], self.class_definition(target_namespace, cdict)
req = []
inherited_properties = []
@@ -613,7 +613,7 @@ class PyType(PyObj):
if isinstance(res, tuple):
return res
if self.properties[1] == []:
if not self.properties[1]:
inherited_properties = reqursive_superior(supc, cdict)
if inherited_properties:
@@ -649,7 +649,7 @@ class PyType(PyObj):
if isinstance(res, tuple):
return res
return (req, self.class_definition(target_namespace, cdict, ignore))
return req, self.class_definition(target_namespace, cdict, ignore)
def undefined(self, cdict):
undef = ([], [])
@@ -685,7 +685,7 @@ class PyAttribute(PyObj):
if not cdict[self.type.name].done:
raise MissingPrerequisite(self.type.name)
return ([], []) # Means this elements definition is empty
return [], [] # Means this elements definition is empty
def spec(self):
if isinstance(self.type, PyObj):
@@ -718,7 +718,7 @@ class PyGroup(object):
self.done = False
def text(self, _target_namespace, _dict, _child, _ignore):
return ([], [])
return [], []
def undefined(self, _cdict):
undef = ([], [])
@@ -802,7 +802,7 @@ def _namespace_and_tag(obj, param, top):
namespace = ""
tag = param
return (namespace, tag)
return namespace, tag
# -----------------------------------------------------------------------------
@@ -824,9 +824,9 @@ class Simple(object):
argv_copy = sd_copy(argv)
rval = self.repr(top, sup, argv_copy, True, parent)
if rval:
return ([rval], [])
return [rval], []
else:
return ([], [])
return [], []
def repr(self, _top=None, _sup=None, _argv=None, _child=True, _parent=""):
return None
@@ -849,7 +849,7 @@ class Attribute(Simple):
def repr(self, top=None, sup=None, _argv=None, _child=True, _parent=""):
# default, fixed, use, type
if (DEBUG):
if DEBUG:
print "#ATTR", self.__dict__
external = False
@@ -921,7 +921,7 @@ class Attribute(Simple):
except AttributeError:
pass
if (DEBUG):
if DEBUG:
print "#--ATTR py_attr:%s" % (objekt,)
return objekt
@@ -1021,15 +1021,15 @@ class Complex(object):
def collect(self, top, sup, argv=None, parent=""):
if self._own or self._inherited:
return (self._own, self._inherited)
return self._own, self._inherited
if (DEBUG):
if DEBUG:
print self.__dict__
print "#-- %d parts" % len(self.parts)
self._extend(top, sup, argv, parent)
return (self._own, self._inherited)
return self._own, self._inherited
def do_child(self, elem):
for child in elem:
@@ -1106,7 +1106,7 @@ class Element(Complex):
else:
xns = namespace
return (namespace, name, ctyp, xns, ref)
return namespace, name, ctyp, xns, ref
def collect(self, top, sup, argv=None, parent=""):
""" means this element is part of a larger object, hence a property of
@@ -1114,10 +1114,10 @@ class Element(Complex):
try:
argv_copy = sd_copy(argv)
return ([self.repr(top, sup, argv_copy, parent=parent)], [])
return [self.repr(top, sup, argv_copy, parent=parent)], []
except AttributeError, exc:
print "!!!!", exc
return ([], [])
return [], []
def elements(self, top):
(_namespace, name, ctyp, xns, _) = self.klass(top)
@@ -1162,7 +1162,7 @@ class Element(Complex):
else:
objekt.ref = (namespace, superkl)
except AttributeError, exc:
if (DEBUG):
if DEBUG:
print "#===>", exc
typ = self.type
@@ -1203,7 +1203,7 @@ class Element(Complex):
parent=self.name)
objekt.scoped = True
else:
if (DEBUG):
if DEBUG:
print "$", self
raise
@@ -1267,9 +1267,9 @@ class ComplexContent(Complex):
class Extension(Complex):
def collect(self, top, sup, argv=None, parent=""):
if self._own or self._inherited:
return (self._own, self._inherited)
return self._own, self._inherited
if (DEBUG):
if DEBUG:
print "#!!!", self.__dict__
try:
@@ -1294,7 +1294,7 @@ class Extension(Complex):
self._extend(top, sup, argv, parent, base)
return (self._own, self._inherited)
return self._own, self._inherited
class Choice(Complex):
def collect(self, top, sup, argv=None, parent=""):
@@ -1409,7 +1409,7 @@ class Group(Complex):
raise Exception("Missing namespace definition")
except AttributeError, exc:
print "!!!!", exc
return ([], [])
return [], []
def repr(self, top=None, sup=None, argv=None, _child=True, parent=""):
if self.py_class:
@@ -1445,7 +1445,7 @@ class AttributeGroup(Complex):
return cti.collect(top, sup)
except AttributeError:
if self._own or self._inherited:
return (self._own, self._inherited)
return self._own, self._inherited
argv_copy = sd_copy(argv)
@@ -1453,7 +1453,7 @@ class AttributeGroup(Complex):
if isinstance(prop, Attribute):
self._own.append(prop.repr(top, sup, argv_copy, parent))
return (self._own, self._inherited)
return self._own, self._inherited
def repr(self, top=None, sup=None, _argv=None, _child=True, parent=""):
if self.py_class:
@@ -1482,7 +1482,7 @@ def pyify_0(name):
res = res.replace("-","_")
if res in ["class"]:
res = res+"_"
res += "_"
return res
def pyify(name):
@@ -1557,7 +1557,7 @@ def sort_elements(els):
partres.sort()
res.extend(partres)
return (res, els)
return res, els
def output(elem, target_namespace, eldict, ignore=[]):
done = 0