A transport agnostic sync/async RPC library that focuses on exposing services with a well-defined API using popular protocols.

Overview

WARNING: This is from spyne's development branch. This version is not released yet! Latest stable release can be found in the 2_13 branch.

If you like and use Spyne, star it on Github!

About

Spyne aims to save the protocol implementers the hassle of implementing their own remote procedure call api and the application programmers the hassle of jumping through hoops just to expose their services using multiple protocols and transports.

In other words, Spyne is a framework for building distributed solutions that strictly follow the MVC pattern, where Model = spyne.model, View = spyne.protocol and Controller = user code.

Spyne comes with the implementations of popular transport, protocol and interface document standards along with a well-defined API that lets you build on existing functionality.

The following are the primary sources of information about spyne:

Requirements

Spyne source distribution is a collection of highly decoupled components, which makes it a bit difficult to put a simple list of requirements, as literally everything except pytz is optional.

Python version

Spyne 2.13 supports Python 2.7, 3.6, 3.7 and 3.8.

Libraries

Additionally the following software packages are needed for various subsystems of Spyne:

  • A Wsgi server of your choice is needed to wrap spyne.server.wsgi.WsgiApplication
  • lxml>=3.2.5 is needed for any xml-related protocol.
  • lxml>=3.4.1 is needed for any html-related protocol.
  • SQLAlchemy is needed for spyne.model.complex.TTableModel.
  • pyzmq is needed for spyne.client.zeromq.ZeroMQClient and spyne.server.zeromq.ZeroMQServer.
  • Werkzeug is needed for using spyne.protocol.http.HttpRpc under a wsgi transport.
  • PyParsing is needed for using HttpPattern's with spyne.protocol.http.HttpRpc.
  • Twisted is needed for anything in spyne.server.twisted and spyne.client.twisted.
  • Django (tested with 1.8 and up) is needed for anything in spyne.server.django.
  • Pyramid is needed for spyne.server.pyramid.PyramidApplication.
  • msgpack>=1.0.0 is needed for spyne.protocol.msgpack.
  • PyYaml is needed for spyne.protocol.yaml.
  • simplejson is used when found for spyne.protocol.json.

You are advised to add these as requirements to your own projects, as these are only optional dependencies of Spyne, thus not handled in its setup script.

Installing

You first need to have package manager (pip, easy_install) installed. Spyne ships with a setuptools bootstrapper, so if setup.py refuses to run because it can't find setuptools, do:

bin/distribute_setup.py

You can add append --user to get it installed with $HOME/.local as prefix.

You can get spyne via pypi:

easy_install [--user] spyne

or you can clone the latest master tree from Github:

git clone git://github.com/arskom/spyne.git

To install from source distribution, you can run the setup script as usual:

python setup.py install [--user]

If you want to make any changes to the Spyne code, just use

python setup.py develop [--user]

so that you can painlessly test your patches.

Finally, to run the tests, you need to first install every single library that Spyne integrates with, along with additional packages like pytest or tox that are only needed when running Spyne testsuite. An up-to-date list is maintained in the requirements/ directory, in separate files for both Python 2.7 and >=3.6. To install everything, run:

pip install [--user] -r requirements/test_requirements.txt

If you are still stuck on Python 2.x however, you should use:

pip install [--user] -r requirements/test_requirements_py27.txt

Assuming all dependencies are installed without any issues, the following command will run the whole test suite:

python setup.py test

Spyne's test harness has evolved a lot in the 10+ years the project has been active. It has 3 main stages: Traditional unit tests, tests that perform end-to-end testing by starting actual daemons that listen on real TCP sockets on hard-coded ports, and finally Django tests that are managed by tox. Naively running pytest etc in the root directory will fail as their auto-discovery mechanism was not implemented with Spyne's requirements in mind.

Getting Support

Official support channels are as follows:

Please don't use the issue tracker for asking questions. It's a database that holds the most important information for the project, so we must avoid cluttering it as much as possible.

Contributing

If you feel like helping out, see the CONTRIBUTING.rst file in the Spyne source distribution for starting points and general guidelines.

Comments
  • Value error __class__ is not in list during spyne import

    Value error __class__ is not in list during spyne import

    Hello,

    I had a working SOAP service working under Django 1.7 / Python 2.7 / Spyne 2.11. I am migrating my full application to Python 3.4 and as far as I understand, XML related features should work on Py3.

    The application crashes during the import of DjangoView when processing the request (Django starts ok)

    • Exception returned is Value error __class__ is not in list.
    • Exception location is spyne\util\odict.py in __delitem__, line 68

    The code in odict.py:

        def __delitem__(self, key):
            if not isinstance(key, int):
                key = self.__list.index(key) # ouch.
    

    My urls.py:

        from django.conf.urls import patterns, url
        from spyne.server.django import DjangoView
        from soap.views import app
    
        urlpatterns = patterns(
            '',
            url(r'^test/', DjangoView.as_view(application=app), name='test-service'),
        )
    

    Any idea on this ? I really appreciate Spyne and would not like to have to seek a new SOAP framework or reimplement everything manually.

    Defect 
    opened by penoux 40
  • Default value for nillable violates XMLSchema

    Default value for nillable violates XMLSchema

    Why does nillable attribute is True by default? According to XMLSchema, elements aren't nillable by default. Database columns aren't null by default.

    Do you think it's good idea to make it configurable?

    Invalid 
    opened by DXist 39
  • Schema parser struggles with additional namespaces

    Schema parser struggles with additional namespaces

    The Office OpenXML schemas are spread out across multiple files. parse_schema_file seems to struggle with the various namespaces in use. It also struggles with the encoding declaration of the file which is weird, because lxml doesn't when I read it. I wonder if that's because it's using fromstring(file.read()) rather than parse(file, parser)?

    schema = parse_schema_file("openpyxl/tests/schemas/sml.xsd")
    Traceback (most recent call last):
      File "/Applications/WingIDE.app/Contents/Resources/src/debug/tserver/_sandbox.py", line 1, in <module>
        # Used internally for debug sandbox under external interpreter
      File "/Users/charlieclark/Projects/openpyxl/lib/python3.4/site-packages/spyne/util/xml.py", line 153, in parse_schema_file
        .parse_schema(elt)
      File "/Users/charlieclark/Projects/openpyxl/lib/python3.4/site-packages/spyne/interface/xml_schema/parser.py", line 545, in parse_schema
        file_name = self.files[imp.namespace]
    builtins.KeyError: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'
    
    Defect 
    opened by Themanwithoutaplan 33
  • Programmer control of sequence declaration in WSDL

    Programmer control of sequence declaration in WSDL

    I have been bitten once again by me changing something apparently innocuous in my type definitions (adding a nillable I think), and then breaking every client that generates compiled code from the WSDL. (This means just about everyone who doesn't use python-suds).

    We have discussed before: https://github.com/arskom/spyne/issues/233#issuecomment-18737172

    So, here is a patch that fixes it - at the expense of breaking all existing servers in this way one final time, of course.

    The patch works by automagically assigning every subclass of ModelBase a unique number called declare_order. The number is incremented each time a new subclass is created.

    ComplexModelBase inserts fields into _type_info in ascending order of declare_order. The WSDL already generated it's sequence in the order things were put into _type_info, so if you create a new type for every field in a ComplexModel like this:

    class MyStruct(ComplexModel):
      y = Unicode()
      x = Double()
    

    Then the WSDL generated by Spyne will match the declared order of the fields in Python (ie y will be declared then x) - like just about every other SOAP implementation on the planet.

    If you don't generate new types then the fallback is to use the names. So in this case in the WSDL x would be declared before y, because that is the sort order of the names. Not perfect, but it will be stable across revisions of Spyne, and python.

    opened by rstuart 33
  • Test mandatory input elements validation

    Test mandatory input elements validation

    test_mandatory_element_attributes fails

    UPDATE This pull request was initiates to solve this question http://stackoverflow.com/questions/19514045/how-to-describe-element-attributes-with-spyne/19519355

    opened by satyrius 22
  • Django with Python 3.4 WSDL is wrong type (bytes, not string)

    Django with Python 3.4 WSDL is wrong type (bytes, not string)

    With Django 1.6.5 and Python 3.4.1 attempting to generate WSDL results in the following error:

    sequence item 0: expected str instance, bytes found

    The reason for this is that xml.etree.tostring() returns a bytes object, not a string object unless you specify the encoding as "unicode". Since the encoding is specified as UTF-8 a bytes object is returned. Django expects responses to be strings, not bytes objects.

    Adding the line

    self.__wsdl = self.__wsdl.decode("utf-8")

    at the end of the build_interface_document() method in interface/wsdl/wsdl11.py resolves the issue. I'm not sure if this is a desirable solution, however.

    opened by anthony-tuininga 18
  • Feature/transparent declared for python2

    Feature/transparent declared for python2

    This is an attempt to implement ordered class attributes for Python 2.

    See https://github.com/arskom/spyne/pull/313 for solution that requires class customization.

    For statically defined classes there is inspect magic, that tries to find class code object.

    Those users who create classes dynamically have to specify class attributes as odict instance.

    opened by DXist 18
  • Feature/django mapper

    Feature/django mapper

    This pull request provides initial support for mapping Django models to spyne complex types.

    Revised version of https://github.com/arskom/spyne/pull/269

    opened by DXist 18
  • Fix collections.abc imports

    Fix collections.abc imports

    • Abstract base classes are no longer exposed in the top-level collections module in Python 3.9: https://docs.python.org/3.9/whatsnew/3.9.html#removed
    • Consolidate docstrings in util.oset.new
    • Remove unnecessary list call in util.oset.new

    Attempt to fix these warnings:

    /app/venv/lib/python3.8/site-packages/spyne/util/oset/new.py:10: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated since Python 3.3, and in 3.9 it will stop working
      class oset(collections.MutableSet):
    /app/venv/lib/python3.8/site-packages/spyne/protocol/dictdoc/hier.py:29: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated since Python 3.3, and in 3.9 it will stop working
      from collections import defaultdict, Iterable as AbcIterable
    
    opened by antonagestam 17
  • Invalid output conversion

    Invalid output conversion

    rpclib is doing invalid output conversion of floats - if your function is supposed to return float and you will return string, value in XML is invalid (see that quotes):

    <tns:testfResult>'1.1'</tns:testfResult>
    

    server example:

    import logging
    
    from rpclib.application import Application
    from rpclib.decorator import srpc
    from rpclib.decorator import rpc
    from rpclib.interface.wsdl import Wsdl11
    from rpclib.protocol.soap import Soap11
    from rpclib.service import ServiceBase
    from rpclib.model.primitive import Integer
    from rpclib.model.primitive import String
    from rpclib.model.primitive import Float
    from rpclib.model.complex import Array
    from rpclib.model.complex import ComplexModel
    from rpclib.server.wsgi import WsgiApplication
    
    class tests(ServiceBase):
    
      @rpc(_returns=Float)
      def testf(ctx):
        return "1.1"
    
    if __name__ == '__main__':
      from wsgiref.simple_server import make_server
    
      logging.basicConfig(level=logging.DEBUG)
      logging.getLogger('rpclib.protocol.xml').setLevel(logging.DEBUG)
    
      application = Application([tests], 'tests', interface=Wsdl11(), in_protocol=Soap11(validator="soft"), out_protocol=Soap11())
    
      host = "127.0.0.1"
      port = 8080
    
      server = make_server(host, port, WsgiApplication(application))
    
      print "listening to http://%s:%s" % (host, port)
      print "wsdl is at: http://%s:%s/?wsdl" % (host, port)
    
      server.serve_forever()
    
    Invalid 
    opened by azurit 17
  • soap:address is duplicated

    soap:address is duplicated

    I use python3.7 and spyne 2.13.10 (build from source)

    I set up services as the Application takes many services on registration.

    def create_spyne_app():
        from spyne import ServiceBase
        from .controllers import soap
    
        services = set()
        for module in _import_submodules_from_package(soap):
            for name, service in inspect.getmembers(module, lambda x: inspect.isclass(x) and issubclass(x, ServiceBase)):
                if service is not ServiceBase:
                    services.add(service)
    
        print(services)
        # from soap to soap protocol
        return WsgiApplication(
                   Application(services,
                       tns='spyne.example.flask',
                       in_protocol=Soap11(validator='lxml'),
                       out_protocol=Soap11()
               ))
    
    ...
    
    # init with flask
    
        app.wsgi_app = DispatcherMiddleware(app.wsgi_app, {
            "/LeapServiceWS/services": create_spyne_app(),
            })
    
    

    Then I access to http://localhost:5000/LeapServiceWS/services/?wsdl I got <wsdlsoap11:address location="http://localhost:5000/LeapServiceWS/services/HelloWorldService/"/> duplicated in each service tag

    ...
    <wsdl:service name="CustomerAccountListInq">
    <wsdl:port name="Application" binding="tns:Application">
    <wsdlsoap11:address location="http://localhost:5000/LeapServiceWS/services/HelloWorldService/"/>
    </wsdl:port>
    </wsdl:service>
    <wsdl:service name="HelloWorldService">
    <wsdl:port name="Application" binding="tns:Application">
    <wsdlsoap11:address location="http://localhost:5000/LeapServiceWS/services/HelloWorldService/"/>
    </wsdl:port>
    </wsdl:service>
    ..
    

    then I went to http://localhost:5000/LeapServiceWS/services/HelloWordService/?wsdl which specific service and I got another service description also.

    ...
    <wsdl:service name="CustomerAccountListInq">
    <wsdl:port name="Application" binding="tns:Application">
    <wsdlsoap11:address location="http://localhost:5000/LeapServiceWS/services/HelloWordService/"/>
    </wsdl:port>
    </wsdl:service>
    <wsdl:service name="HelloWorldService">
    <wsdl:port name="Application" binding="tns:Application">
    <wsdlsoap11:address location="http://localhost:5000/LeapServiceWS/services/HelloWordService/"/>
    </wsdl:port>
    </wsdl:service>
    ...
    

    so I am not sure this is expected behavior of Soap ? not sure how to solve or I need to register with different wsgi app ?

    Invalid 
    opened by jingz 16
  • First draft to show how to make syntactically nicer with type annotations

    First draft to show how to make syntactically nicer with type annotations

    Just the initial example - dont want to go too far down the rabbit hole if there's no appetite. Open to thoughts

    Example

    class HelloWorldService(ServiceBase):
        @typed_rpc
        def say_hello(
            self,
            name: Unicode,
            times: UnsignedInteger32,
            a: Iterable(Decimal),
            b: Iterable(Iterable(Decimal)),
        ) -> Iterable(Unicode):
            for _ in range(times):
                yield f"Hello, {name}"
    

    Example 2

    class HelloWorldService(ServiceBase):
        @typed_rpc(_is_async=True)
        def say_hello(
            self,
            name: Unicode,
            times: UnsignedInteger32,
            a: Iterable(Decimal),
            b: Iterable(Iterable(Decimal)),
        ) -> Iterable(Unicode):
            for _ in range(times):
                yield f"Hello, {name}"
    
    Enhancement 
    opened by ghandic 2
  • Bugfix/return client errors

    Bugfix/return client errors

    Handle 2 cases where bad client data cause a 500 Internal Server Error, rather than the nicer soap11env:Client.XMLSyntaxError.

    Case 1: Client does not send body in its request. This causes an empty generator to be passed to _parse_xml_string, which causes an unhandled StopIteration exception.

    Case 2: Client sends badly encoded data in its request. This causes a badly encoded byte string to be passed to _parse_xml_string, which causes a UnicodeDecodeError when we try to decode it.

    opened by sashawood 1
  • add GitHub URL for PyPi

    add GitHub URL for PyPi

    opened by andriyor 1
  • only old docs available

    only old docs available

    Please update the documentation for 2.13 The link to documentation http://spyne.io/docs/ only gives docs for 2.10 and incomplete docs for 2.13.

    What is needed to update those for the latest release?

    Documentation 
    opened by maurerle 1
Releases(spyne-2.14.0)
Equibles Stocks API for Python

Equibles Stocks API for Python Requirements. Python 2.7 and 3.4+ Installation & Usage pip install If the python package is hosted on Github, you can i

Equibles 3 Apr 15, 2022
MoreIP 一款基于Python的面向 MacOS/Linux 用户用于查询IP/域名信息的日常渗透小工具

MoreIP 一款基于Python的面向 MacOS/Linux 用户用于查询IP/域名信息的日常渗透小工具

xq17 9 Sep 21, 2022
A Python server and client app that tracks player session times and server status

MC Outpost A Python server and client application that tracks player session times and server status About MC Outpost provides a session graph and ser

Grant Scrits 0 Jul 23, 2021
Visualize the electric field of a point charge network.

ElectriPy ⚡ Visualize the electric field of a point charges network. 🔌 Installation Install ElectriPy package: $ pip install electripy You are all d

Dylan Tintenfich 29 Aug 29, 2022
Best discord webhook spammer using proxy (support all proxy type)

Best discord webhook spammer using proxy (support all proxy type)

Iтѕ_Ѵιcнч#1337 25 Nov 01, 2022
Tool that creates a complete copy of your server

Discord-Server-Cloner Tool that creates a complete copy of your server Setup: Open run.bat If the file closes, open cmd And write: pip install -r requ

DEEM 3 Dec 13, 2021
A Network tool kit for scanning active IP addresses and open ports

Network scanner A small project that I wrote on the fly for (IT351) Computer Networks University Course to identify and label the devices in my networ

Mohamed Abdelrahman 10 Nov 07, 2022
Una simple herramienta para rastrear IP programada en Python

Spyrod-v2 Una simple herramienta para rastrear IP programada en Python Instalacion apt install git -y cd $HOME git clone https://github.com/Euronymou5

15 Dec 08, 2022
Python tutorial for implementing Oxylabs' Residential Proxies with AIOHTTP

Integrating Oxylabs' Residential Proxies with AIOHTTP Requirements for the Integration For the integration to work you'll need to install aiohttp libr

Oxylabs.io 6 Sep 14, 2022
A Simple but Powerful cross-platform port scanning & and network automation tool.

DEDMAP is a Simple but Powerful, Clever and Flexible Cross-Platform Port Scanning tool made with ease to use and convenience in mind. Both TCP

Anurag Mondal 30 Dec 16, 2022
simple subdomain finder

Subdomain-finder Simple SubDomain finder using python which is easy to use just download and run it Wordlist you can use your own wordlist but here i

AsjadOwO 5 Sep 24, 2021
A Project to resolve hostname and receive IP

hostname-resolver A Project to resolve hostname and receive IP Installation git clone https://github.com/ihapiw/hostname-resolver.git Head into the ho

iHapiW 5 Sep 12, 2022
DNS monitoring system built with Python.

DNS monitoring system built with Python.

Andressa Cabistani 7 Sep 28, 2021
Netwalk is a Python library to discover, parse, analyze and change Cisco switched networks

Netwalk is a Python library born out of a large remadiation project aimed at making network device discovery and management as fast and painless as possible.

38 Nov 07, 2022
Simple P2P application for sending files over open and forwarded network ports.

FileShareV2 A major overhaul to the V1 (now deprecated) FileShare application. V2 brings major improvements in both UI and performance. V2 is now base

Michael Wang 1 Nov 23, 2021
Socialhome is best described as a federated personal profile with social networking functionality

Description Socialhome is best described as a federated personal profile with social networking functionality. Users can create rich content using Mar

Jason Robinson 332 Dec 30, 2022
mitm6 is a pentesting tool that exploits the default configuration of Windows to take over the default DNS server.

mitm6 is a pentesting tool that exploits the default configuration of Windows to take over the default DNS server.

Fox-IT 1.3k Jan 05, 2023
Jogo da forca simples com conexão entre cliente e servidor utilizando TCP.

JogoDaForcaTCP Um jogo da forca simples com conexão entre cliente e servidor utilizando o protocólo TCP. Como jogar: Habilite a porta 20000, inicie o

Kelvin Santos 1 Dec 01, 2021
Pteronode - Script for managing Pterodactyl nodes

pteronode Script for managing Pterodactyl nodes Pteronode allows you to create s

9 Sep 28, 2022
CORS Bypass Proxy Cloud Function

CORS Bypass Proxy Cloud Function

Elayamani K 1 Oct 23, 2021