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)
This application aims to read all wifi passwords and visualizes the complexity in graph formation by taking into account several criteria and help you generate new random passwords.

This application aims to read all wifi passwords and visualizes the complexity in graph formation by taking into account several criteria and help you generate new random passwords.

Njomza Rexhepi 0 May 29, 2022
E4GL3OS1NT - Simple Information Gathering Tool

E4GL30S1NT Features userrecon - username reconnaissance facedumper - dump facebook information mailfinder - find email with specific name godorker - d

C0MPL3XDEV 195 Dec 21, 2022
Converts from PC formatted MAC addresses (hardware addresses) to Cisco format or vice-versa

MAC-Converter Converts from PC formatted MAC addresses (hardware addresses) to Cisco format or vice-versa Stores the results to a file in the same dir

Stew Alexander 0 Dec 24, 2022
Python Program to connect to different VPN servers autoatically using Windscribe VPN.

AutomateVPN What is VPN ? VPN stands for Virtual Private Network , it is a technology that creates a safe and encrypted connectionover a less secure n

Vivek 1 Oct 27, 2021
This program ingests a Cisco "sh ip arp" as a text file and produces the list of vendors seen in the file

IP-ARP-Vendor_lookup This program ingests a Cisco "sh ip arp" as a text file and produces the list of vendors seen in the file Why? Answers the questi

Stew Alexander 1 Dec 24, 2022
A simple and lightweight server that allows clients to connect and launch a shell remotely through a browser.

carrotsh A simple and lightweight server that allows clients to connect and launch a shell remotely through a browser. Uses xterm.js for the frontend

V9 31 Dec 27, 2022
This repository contain sample code of gRPC Communication between Python and GoLang

This repository contain sample code of gRPC Communication between Python and GoLang, the Server is running on GoLang while Python is running the client

Abdullahi Muhammad 2 Nov 29, 2021
Initial code of an A3C network

A3C-network Initial code of an A3C network Open the python file named as "APL452 Project Report2" The following libraries and packages have been insta

Ayush Tanwar 0 Jun 11, 2022
A library of functions that can be used to manage the download of claims from the LBRY network.

lbrytools A library of functions that can be used to manage the download of claims from the LBRY network. It includes methods to download claims by UR

13 Dec 03, 2022
A repository to spoof ARP table of any devices and successfully establish Man in the Middle(MITM) attack using Python3 in Linux

arp_spoofer A repository to spoof ARP table of any devices and successfully establish Man in the Middle(MITM) attack using Python3 in Linux Usage: git

Surya Das N 1 Oct 30, 2021
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
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
Qtas(Quite a Storage)is an experimental distributed storage system developed by Q-team in BJFU Advanced Computer Network sources.

Qtas(Quite a Storage)is a experimental distributed storage system developed by Q-team in BJFU Advanced Computer Network sources.

Jiaming Zhang 3 Jan 12, 2022
A Scapy implementation of SMS-SUBMIT and (U)SIM Application Toolkit command packets.

A Scapy implementation of SMS-SUBMIT and (U)SIM Application Toolkit command packets.

mnemonic 83 Dec 11, 2022
Simple Port Scanner With Socket Module In Python 3x

PortScanner Simple Port Scanner With Socket Module In Python 3x How To Install Requirements Of This Port Scanner sudo apt install python3;sudo apt ins

1 Nov 23, 2021
WARP+ uses Cloudflare’s virtual private backbone, known as Argo, to achieve higher speeds and ensure your connection is encrypted across the long haul of the Internet

WARP+ uses Cloudflare’s virtual private backbone, known as Argo, to achieve higher speeds and ensure your connection is encrypted across the long haul of the Internet

Rivane Rasetiansyah 3 Apr 01, 2022
A simple, configurable application and set of services to monitor multiple raspberry pi's on a network.

rpi-info-monitor A simple, configurable application and set of services to monitor multiple raspberry pi's on a network. It can be used in a terminal

Kevin Kirchhoff 11 May 22, 2022
A collection of domains, wildcards and substrings designed for dnscrypt-proxy filter method.

A collection of domains, wildcards and substrings designed for dnscrypt-proxy filter method.

3 Oct 25, 2022
Very simple FTP client, sync folder to FTP server, use python, opensource

ftp-sync-python Opensource, A way to safe your data, avoid lost data by Virus, Randsomware Some functions: Upload a folder automatically to FTP server

4 Sep 13, 2022
Simple client for the Sirah Matisse Commander TCP server.

Simple client for the Sirah Matisse Commander TCP server.

Nelson Darkwah Oppong 1 Nov 02, 2021