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)
A Calendar subscribe server for python

cn-holiday-ics-server A calendar subscribe server 直接使用我搭建的服务 订阅节假日:https://cdxy.fun:9999/holiday 订阅调休上班:https://cdxy.fun:9999/workday 节假日和调休上班在一起的版本:h

CD 11 Nov 12, 2022
IPE is a simple tool for analyzing IP addresses. With IPE you can find out the server region, city, country, longitude and latitude and much more in seconds.

IPE is a simple tool for analyzing IP addresses. With IPE you can find out the server region, city, country, longitude and latitude and much more in seconds.

Paul 0 Jun 11, 2022
An open source bias lighting program which syncs up colored lights to the contents of your screen.

About Firelight Firelight is an open source bias lighting program which syncs up colored lights to the contents of your screen or TV, providing an imm

Roshan 18 Dec 18, 2022
league-connection is a python package to communicate to riot client and league client

league-connection is a python package to communicate to riot client and league client.

Sandbox 1 Sep 13, 2022
GitHub action for sspanel automatically checks in to get free traffic quota

SSPanel_Checkin This is a dish chicken script for automatic check-in of sspanel for GitHub action, It is only applicable when there is no verification

FeedCatWithFish 7 Apr 28, 2022
IP Rover - An Excellent OSINT tool to get information of any ip address

IP Rover - An Excellent OSINT tool to get information of any ip address. All details are explained in below screenshot

Saad 20 Dec 16, 2022
Heroku Cloudflare App Domain

Heroku Cloudflare App Domain Creating branded herokuapp.com-like domains using Cloudflare, based on the app name (eg my-app-prod.example.com). Feature

Torchbox 2 Oct 04, 2022
Use Raspberry Pi and CircuitSetup's power monitor hardware to publish electrical usage to MQTT

This repo has code and notes for whole home electrical power monitoring using a Raspberry Pi and CircuitSetup modules. Beyond just collecting data, it

Eric Tsai 10 Jul 25, 2022
Pteronode - Script for managing Pterodactyl nodes

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

9 Sep 28, 2022
The module that allows the collection of data sampling, which is transmitted with WebSocket via WIFI or serial port for CSV file.

The module that allows the collection of data sampling, which is transmitted with WebSocket via WIFI or serial port for CSV file.

Nelson Wenner 2 Apr 01, 2022
This tool will scans your wi-fi/wlan and show you the connected clients

This tool will scans your wi-fi/wlan and show you the connected clients

VENKAT SAI SAGAR 3 Mar 24, 2022
The best way to send tokens into a specific server, which can be used for discord bots, and some tools..

XTRA420 The simplified version of sending tokens into a server, the basic and fastest way.. When using this, you have the option to use proxies (http)

07v 1 Nov 30, 2021
A Python Packages to make own chat room

Chathon A Python packages for make own chat room Install PyPI pip install chathon

1 Dec 10, 2021
snappi-trex is a snappi plugin that allows executing scripts written using snappi with Cisco's TRex Traffic Generator

snappi-trex snappi-trex is a snappi plugin that allows executing scripts written using snappi with Cisco's TRex Traffic Generator Design snappi-trex c

Open Traffic Generator 14 Sep 07, 2022
Vent domain information retrieval tool, which is capable of retrieving customer information

Vent domain information retrieval tool, which is capable of retrieving customer information. This tool has been created for the purpose of complete education, Iam not responsible for any illegal acti

Md. Ridwanul Islam Muntakim 25 Dec 09, 2022
Anonymously Reverse shell over Tor Network using Hidden Services without portfortwarding

Anonymously Reverse shell over Tor Network using Hidden Services without portfortwarding Tor ağı ile Dark Web servislerini kullanarak anonim biçimde p

249 Dec 29, 2022
Tool written on Python that locate all up host on your subnet

HOSTSCAN Easy to use command line network host scanner. From noob to noobs. Dependencies Nmap 7.92 or superior Python 3.9 or superior All requirements

NexCreep 4 Feb 27, 2022
This tool extracts Credit card numbers, NTLM(DCE-RPC, HTTP, SQL, LDAP, etc), Kerberos (AS-REQ Pre-Auth etype 23), HTTP Basic, SNMP, POP, SMTP, FTP, IMAP, etc from a pcap file or from a live interface.

This tool extracts Credit card numbers, NTLM(DCE-RPC, HTTP, SQL, LDAP, etc), Kerberos (AS-REQ Pre-Auth etype 23), HTTP Basic, SNMP, POP, SMTP, FTP, IMAP, etc from a pcap file or from a live interface

1.6k Jan 01, 2023
A fully automated, accurate, and extensive scanner for finding log4j RCE CVE-2021-44228

log4j-scan A fully automated, accurate, and extensive scanner for finding vulnerable log4j hosts Features Support for lists of URLs. Fuzzing for more

FullHunt 3.2k Jan 02, 2023
This script aims to make the dynamic public ip of your local server, public.

EZ DDNS CLOUDFLARE This script aims to make the dynamic ip of your local server, public. It does this by regularly updating cloudflare's dns record. B

3 Feb 13, 2022