Skip to content
This repository

Application Registry and misc. fixes #157

Merged
merged 7 commits into from almost 2 years ago

1 participant

Burak Arslan
Burak Arslan
Owner
plq commented July 16, 2012

No description provided.

Burak Arslan plq merged commit bfcefd5 into from July 16, 2012
Burak Arslan plq closed this July 16, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
21  spyne/application.py
@@ -28,6 +28,7 @@
28 28
 from spyne.model.fault import Fault
29 29
 from spyne.interface import Interface
30 30
 from spyne._base import EventManager
  31
+from spyne.util.appreg import register_application
31 32
 
32 33
 
33 34
 class Application(object):
@@ -38,14 +39,14 @@ class Application(object):
38 39
                          the exposed services.
39 40
     :param tns:          The targetNamespace attribute of the exposed
40 41
                          service.
41  
-    :param interface:    Ignored.
42  
-    :param in_protocol:  A ProtocolBase instance that defines the input
43  
-                         protocol.
44  
-    :param out_protocol: A ProtocolBase instance that defines the output
45  
-                         protocol.
46 42
     :param name:         The optional name attribute of the exposed service.
47 43
                          The default is the name of the application class
48 44
                          which is, by default, 'Application'.
  45
+    :param in_protocol:  A ProtocolBase instance that defines the input
  46
+                         protocol. It's only optional for NullServer transport.
  47
+    :param out_protocol: A ProtocolBase instance that defines the output
  48
+                         protocol. It's only optional for NullServer transport.
  49
+    :param interface:    Ignored. Kept for backwards-compatibility purposes.
49 50
 
50 51
     Supported events:
51 52
         * method_call:
@@ -67,9 +68,8 @@ class Application(object):
67 68
 
68 69
     transport = None
69 70
 
70  
-    def __init__(self, services, tns, in_protocol, out_protocol, interface=None,
71  
-                                                                     name=None):
72  
-
  71
+    def __init__(self, services, tns, name=None,
  72
+                           in_protocol=None, out_protocol=None, interface=None):
73 73
         self.services = services
74 74
         self.tns = tns
75 75
         self.name = name
@@ -77,6 +77,8 @@ def __init__(self, services, tns, in_protocol, out_protocol, interface=None,
77 77
         if self.name is None:
78 78
             self.name = self.__class__.__name__.split('.')[-1]
79 79
 
  80
+        register_application(self)
  81
+
80 82
         self.event_manager = EventManager(self)
81 83
         self.error_handler = None
82 84
 
@@ -162,3 +164,6 @@ def reinitialize(self):
162 164
             if d.aux is not None and not id(d.aux) in aux_memo:
163 165
                 d.aux.initialize(server)
164 166
                 aux_memo.add(id(d.aux))
  167
+
  168
+    def __hash__(self):
  169
+        return hash(tuple([id(s) for s in self.services]))
2  spyne/auxproc/_base.py
@@ -32,7 +32,7 @@
32 32
 execution methods like persistent or non-persistent queueing, async execution
33 33
 in another thread, process or node.
34 34
 
35  
-Auxprocs define how an auxiliary method is going to be executed.
  35
+AuxProcs define how an auxiliary method is going to be executed.
36 36
 """
37 37
 
38 38
 import logging
5  spyne/model/_base.py
@@ -19,6 +19,7 @@
19 19
 
20 20
 import spyne.const.xml_ns
21 21
 
  22
+from decimal import Decimal
22 23
 
23 24
 """This module contains the ModelBase class and other building blocks for
24 25
 defining models.
@@ -217,7 +218,7 @@ def customize(cls, **kwargs):
217 218
         return type(cls_name, cls_bases, cls_dict)
218 219
 
219 220
     @staticmethod
220  
-    def _s_customize(cls, ** kwargs):
  221
+    def _s_customize(cls, **kwargs):
221 222
         """This function duplicates and customizes the class it belongs to. The
222 223
         original class remains unchanged.
223 224
 
@@ -238,6 +239,8 @@ class Annotations(cls.Annotations):
238 239
         for k, v in kwargs.items():
239 240
             if k in ("doc", "appinfo"):
240 241
                 setattr(Annotations, k, v)
  242
+            elif k == 'max_occurs' and v == 'unbounded':
  243
+                setattr(Attributes, k, Decimal('inf'))
241 244
             else:
242 245
                 setattr(Attributes, k, v)
243 246
 
2  spyne/model/complex.py
@@ -427,7 +427,7 @@ class Array(ComplexModel):
427 427
     the same name as the serialized class. It's contained in a Python list.
428 428
     """
429 429
 
430  
-    def __new__(cls, serializer, ** kwargs):
  430
+    def __new__(cls, serializer, **kwargs):
431 431
         retval = cls.customize(**kwargs)
432 432
 
433 433
         # hack to default to unbounded arrays when the user didn't specify
4  spyne/protocol/soap/soap11.py
@@ -326,6 +326,9 @@ def serialize(self, ctx, message):
326 326
 
327 327
             ctx.out_document.append(ctx.out_body_doc)
328 328
 
  329
+        if self.cleanup_namespaces:
  330
+            etree.cleanup_namespaces(ctx.out_document)
  331
+
329 332
         if self.log_messages:
330 333
             if message is self.REQUEST:
331 334
                 line_header = '%sRequest%s' % (LIGHT_GREEN, END_COLOR)
@@ -333,6 +336,7 @@ def serialize(self, ctx, message):
333 336
                 line_header = '%sResponse%s' % (LIGHT_RED, END_COLOR)
334 337
             logger.debug('%s %s' % (line_header, etree.tostring(ctx.out_document,
335 338
                                         xml_declaration=True, pretty_print=True)))
  339
+
336 340
         self.event_manager.fire_event('after_serialize', ctx)
337 341
 
338 342
     def fault_to_http_response_code(self, fault):
6  spyne/protocol/xml/model.py
@@ -135,6 +135,9 @@ def get_members_etree(prot, cls, inst, parent):
135 135
         except: # to guard against sqlalchemy throwing NoSuchColumnError
136 136
             subvalue = None
137 137
 
  138
+        # This is a tight loop, so enable this only when necessary.
  139
+        logger.debug("get %r(%r) from %r: %r" % (k, v, inst, subvalue))
  140
+
138 141
         if issubclass(v, XmlAttribute):
139 142
             v.marshall(k, subvalue, parent)
140 143
             continue
@@ -259,7 +262,8 @@ def enum_from_element(prot, cls, element):
259 262
 def fault_to_parent_element(prot, cls, value, tns, parent_elt, name=None):
260 263
     element = etree.SubElement(parent_elt, "{%s}Fault" % _ns_soap_env)
261 264
 
262  
-    etree.SubElement(element, 'faultcode').text = '%s:%s' % (_pref_soap_env, value.faultcode)
  265
+    etree.SubElement(element, 'faultcode').text = '%s:%s' % (_pref_soap_env,
  266
+                                                                value.faultcode)
263 267
     etree.SubElement(element, 'faultstring').text = value.faultstring
264 268
     etree.SubElement(element, 'faultactor').text = value.faultactor
265 269
     if value.detail != None:
5  spyne/server/null.py
@@ -17,7 +17,10 @@
17 17
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
18 18
 #
19 19
 
20  
-"""This module contains the NullServer class and its helper objects."""
  20
+"""This module contains the NullServer class and its helper objects.
  21
+
  22
+The name comes from the "null modem connection". Look it up.
  23
+"""
21 24
 
22 25
 import logging
23 26
 logger = logging.getLogger(__name__)
69  spyne/util/appreg.py
... ...
@@ -0,0 +1,69 @@
  1
+
  2
+#
  3
+# spyne - Copyright (C) Spyne contributors.
  4
+#
  5
+# This library is free software; you can redistribute it and/or
  6
+# modify it under the terms of the GNU Lesser General Public
  7
+# License as published by the Free Software Foundation; either
  8
+# version 2.1 of the License, or (at your option) any later version.
  9
+#
  10
+# This library is distributed in the hope that it will be useful,
  11
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
  12
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13
+# Lesser General Public License for more details.
  14
+#
  15
+# You should have received a copy of the GNU Lesser General Public
  16
+# License along with this library; if not, write to the Free Software
  17
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
  18
+#
  19
+
  20
+"""
  21
+Module that contains the Spyne Application Registry.
  22
+"""
  23
+
  24
+import logging
  25
+logger = logging.getLogger(__name__)
  26
+
  27
+_applications = {}
  28
+
  29
+from collections import namedtuple
  30
+
  31
+_ApplicationMetaData = namedtuple("_ApplicationMetaData", 
  32
+                                                  ['app', 'inst_stack', 'null'])
  33
+
  34
+def register_application(app):
  35
+    """Registers application in the registration was successful and False otherwise.
  36
+    """
  37
+
  38
+    key = (app.tns, app.name)
  39
+
  40
+    from spyne.server.null import NullServer
  41
+
  42
+    try:
  43
+        import traceback
  44
+        stack = traceback.format_stack()
  45
+    except ImportError:
  46
+        stack = None
  47
+
  48
+    prev = _applications.get(key, None)
  49
+    
  50
+    if prev is not None:
  51
+        if hash(prev.app) == hash(app):
  52
+            logger.debug("Application %r previously registered as %r is the same"
  53
+                        " as %r. Skipping." % (prev.app, key, app))
  54
+            prev.inst_stack.append(stack)
  55
+        else:
  56
+            logger.warning("Overwriting application %r(%r)." % (key, app))
  57
+
  58
+            if prev.inst_stack is not None:
  59
+                logger.debug("Stack trace of the instantiation:\n%s" %
  60
+                                                       ''.join(prev.inst_stack))
  61
+
  62
+    _applications[key] = _ApplicationMetaData(app=app, inst_stack=[stack],
  63
+                                                           null=NullServer(app))
  64
+
  65
+    logger.debug("Registering %r as %r" % (app, key))
  66
+
  67
+
  68
+def get_application(tns, name):
  69
+    return _applications.get((tns, name), None)
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.