{"id":13936579,"url":"https://github.com/noisyboiler/wampy","last_synced_at":"2026-01-16T11:26:13.930Z","repository":{"id":53136646,"uuid":"54590516","full_name":"noisyboiler/wampy","owner":"noisyboiler","description":"Websocket RPC and Pub/Sub for Python applications and microservices","archived":false,"fork":false,"pushed_at":"2021-05-21T16:34:11.000Z","size":1223,"stargazers_count":129,"open_issues_count":1,"forks_count":24,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-07-19T23:22:57.333Z","etag":null,"topics":["pubsub","python","rpc","wamp","wamp-client","wamp-protocol","wampy","websocket"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/noisyboiler.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-03-23T20:21:48.000Z","updated_at":"2025-01-19T07:46:09.000Z","dependencies_parsed_at":"2022-09-16T17:20:44.053Z","dependency_job_id":null,"html_url":"https://github.com/noisyboiler/wampy","commit_stats":null,"previous_names":[],"tags_count":49,"template":false,"template_full_name":null,"purl":"pkg:github/noisyboiler/wampy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noisyboiler%2Fwampy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noisyboiler%2Fwampy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noisyboiler%2Fwampy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noisyboiler%2Fwampy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/noisyboiler","download_url":"https://codeload.github.com/noisyboiler/wampy/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noisyboiler%2Fwampy/sbom","scorecard":{"id":693278,"data":{"date":"2025-08-11","repo":{"name":"github.com/noisyboiler/wampy","commit":"7bc1859f7acd501d152f3f3ca05672b501b407e3"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Code-Review","score":0,"reason":"Found 1/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Mozilla Public License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 8 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-22T02:51:45.884Z","repository_id":53136646,"created_at":"2025-08-22T02:51:45.884Z","updated_at":"2025-08-22T02:51:45.884Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28478252,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-16T06:30:42.265Z","status":"ssl_error","status_checked_at":"2026-01-16T06:30:16.248Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["pubsub","python","rpc","wamp","wamp-client","wamp-protocol","wampy","websocket"],"created_at":"2024-08-07T23:02:48.339Z","updated_at":"2026-01-16T11:26:13.791Z","avatar_url":"https://github.com/noisyboiler.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"![Travis](https://travis-ci.org/noisyboiler/wampy.svg?branch=master)\n![Python36](https://img.shields.io/badge/python-3.6-blue.svg)\n![Python37](https://img.shields.io/badge/python-3.7-blue.svg)\n![Python37](https://img.shields.io/badge/python-3.7.3-blue.svg)\n![Python38](https://img.shields.io/badge/python-3.8-blue.svg)\n\n![image](./coverage.svg)\n\nwampy\n=====\n\n*[whomp-ee]*\n\nFor a background as to what WAMP is, please see\n[here](https://medium.com/@noisyboiler/the-web-application-messaging-protocol-d8efe95aeb67).\n\nThis is a Python implementation of\n[WAMP](http://wamp-proto.org/static/rfc/draft-oberstet-hybi-crossbar-wamp.html)\nusing [Gevent](http://www.gevent.org/), but you can also configure\n**wampy** to use [eventlet](http://eventlet.net/), if that is how your\napplication does async. **Wampy** is is a light-weight alternative to\n[autobahn](https://github.com/crossbario/autobahn-python).\n\nWith **wampy**, you can quickly and easily create your own **WAMP**\nclients, whether this is in a web app, a microservice, a script or just\nin a Python shell. You can integrate **wampy** into your existing\napplications without having to re-write or re-design anything.\n\n**wampy** tries to provide an intuitive API for your **WAMP** messaging.\n\nSee [ReadTheDocs](http://wampy.readthedocs.io/en/latest/) for more\ndetailed documentation, but the README here is detailed enough to get\ngoing.\n\nwampy features\n--------------\n\n-   Remote Procedure Calls over websockets\n-   Publish and Subscribe over websockets\n-   Open Source and Open *Thoughts* - see\n    [internals](https://github.com/noisyboiler/wampy/wiki/Internal-Architecture)\n    and then the entire WIKI\n-   Use **wampy** as a microservice/app, or in your Flask or nameko\n    apps, or in scripts.... or just in a Python shell!\n-   Client Authentication (Ticket and WCA)\n-   Transport Layer Security\n-   CLI for easy and rapid development\n-   Pytest fixtures to use when testing your projects, including a\n    Crossbar.io fixture that tears down between each test\n-   [nameko](https://github.com/nameko) integration with\n    [namekowwamp](https://github.com/noisyboiler/nameko-wamp)\n-   [Flask](https://github.com/pallets/flask) integration with\n    [flaskwwamp](https://github.com/noisyboiler/flask-wamp)\n-   Compatible with gevent, eventlet and asyncio\n-   Alpha features (see below)\n\nQuickStart - Connect and Go!\n----------------------------\n\nIf you've already got access to a running **Router** which has other\n**Peers** connected, then stay here. If not, jump to the next section.\nIf you're still here...\n\n    pip install wampy\n\n...and then open a Python shell.\n\nThe example here assumes a **Peer** connected to a **Router** on\n`localhost`, port `8080`, that has registered a remote procedure called\n`get_foobar`, and you want to *call* that procedure.\n\n    from wampy.peers import Client\n\n    with Client() as client:\n        response = client.rpc.get_foobar()\n\n    # do something with the response here\n\nThe same example here, but the **Router** is on a *remote* host.\n\n    from wampy.peers import Client\n\n    with Client(url=\"ws://example.com:8080\") as client:\n        response = client.rpc.get_foobar()\n\n    # do something with the response here\n\nThe WAMP Session is \"context managed\", meaning it begins as you enter,\nand ends as you exit the scope of the client instance.\n\nSee [ReadTheDocs](http://wampy.readthedocs.io/en/latest/) for much more\ndetail on this.\n\nRunning and Calling a wampy Application\n---------------------------------------\n\nBefore any messaging can happen you need a **Router**. Messages are then\nrouted between **Clients** over an administrative domain on the\n**Router** called a **Realm**.\n\nFor the quickest of starts I suggest that you use **Crossbar.io** and\nstart it up on the default host and port, and with the default **realm**\nand **roles**. See the [Crossbar.io\ndocs](http://crossbar.io/docs/Quick-Start/) for the instructions on this\nor alternatively run with **wampy's** testing setup.\n\nNote, if you already have Crossbar installed and running you do *not*\nneed these steps, because the dev requirements also include Crossbar.\n\n    $ make dev-install\n\n    $ crossbar start --config ./wampy/testing/configs/crossbar.json\n\nwampy RPC\n---------\n\nNow open your preferred text editor and we'll write a few lines of\nPython constructing a simple **WAMP** service that takes a decimal\nnumber and returns the binary representation of it - wowzers!\n\n    from wampy.peers.clients import Client\n    from wampy.roles import callee\n\n    class BinaryNumberService(Client):\n\n        @callee\n        def get_binary_number(self, number):\n            return bin(number)\n\nSave this module somewhere on your Python path and we'll use a **wampy**\ncommand line interface tool to start the service.\n\n    $ wampy run path.to.your.module.including.module_name:BinaryNumberService\n\nFor example, running one of the **wampy** example applications against\nthe Router suggested previously:\n\n    $ wampy run docs.examples.services:DateService --config ./wampy/testing/configs/crossbar.json\n\nActually - no need to panic! The `BinaryNumberService` example already\nexists in the **wampy** examples so put that text editor away if you\nlike. Just execute from the command line:\n\n    $ wampy run docs.examples.services:BinaryNumberService --config ./wampy/testing/configs/crossbar.json\n\nNow, open a Python console in a new terminal, allowing the\n`BinaryNumberService` to run uninterupted in your original terminal (but\nonce you're done with it `Ctrl-C` is required).\n\n    In [1]: from wampy.peers.clients import Client\n\n    In [2]: with Client(url=\"ws://localhost:8080\") as client:\n                result = client.rpc.get_binary_number(number=100)\n\n    In [3]: result\n    Out[3]: u'0b1100100'\n\nwampy RPC for Crossbar.io\n-------------------------\n\nThe RPC pattern above was inspired by the\n[nameko](https://github.com/nameko) project, but this pattern may not\nfeel intuitive for those familiar with **Crossbar.io**, the primary\nRouter used by **wampy**.\n\nFor this reason there also exists the `CallProxy` object which\nimplements the `call` API by more loosely wrapping **wampy's** `Call`\nMessage. In this pattern, applications and their endpoints are\nidentified by dot delimented strings rather than a single API name, e.g.\n\n    \"com.example.endpoint\"\n\nJust like the `rpc` API, the `call` API is directly available on every\n**wampy** client. Lets look at the two examples side by side.\n\n    \u003e\u003e\u003e client.rpc.get_foo_bar(eggs, foo=bar, spam=ham)\n    \u003e\u003e\u003e client.call(\"get_foo_bar\", eggs, foo=bar, spam=ham)\n\nNoted these are very similar and achieve the same, but the intention\nhere is for the `call` API to behave more like a classic **Crossbar.io**\napplication and the `rpc` to be used in\n[namekowwamp](https://github.com/noisyboiler/nameko-wamp).\n\nThe `call` API however does allow calls of the form...\n\n    \u003e\u003e\u003e client.call(\"com.myapp.foo.bar\", eggs, foo=bar, spam=ham) \n\n...which you will not be able to do with the `rpc` API.\n\nPublishing and Subscribing is equally as simple\n-----------------------------------------------\n\nTo demonstrate, first of all you need a **Subscriber**. You can either\ncreate one yourself in a Python module (as a subclass of a **wampy**\n`Client`) or use the example `Client` already for you in\n`docs.examples.services`.\n\nHere we use the said example service, but all a **Subscriber** is is a\n**wampy** `Client` with a method decorated by `subscribe`. Take a look\nand see for yourself in the\n[examples](https://github.com/noisyboiler/wampy/blob/master/docs/examples/services.py#L26).\n\nLet's start up that example service.\n\n    $ wampy run docs.examples.services:SubscribingService --config ./wampy/testing/configs/crossbar.json\n\nNow we have a service running that subscribes to the topic \"foo\".\n\nIn another terminal, with a **wampy** virtualenv, you can create a\n**Publisher** - which is no different to any other **wampy** Client.\n\n    In [1]: from wampy.peers import Client\n\n    In [2]: with Client() as client:\n                result = client.publish(topic=\"foo\", message=\"spam\")\n\nHopefully you'll see any message you send printed to the screen where\nthe example service is running. You'll also see the meta data that\n**wampy** chooses to send.\n\nPlease note. **wampy** believes in explicit `kwargs` and not bare\n`args`, so you can only publish keyword arguments. Bare arguments don't\ntell readers enough about the call, so even though **WAMP** supports\nthem, **wampy** does not.\n\nIt doesn't matter what the `kwargs` are they will be published, but you\nmight find a call like this is not supported by subscribers of other\n**WAMP** implementations (sorry) e.g.\n\n    In [1]: from wampy.peers import Client\n\n    In [2]: with Client() as client:\n                client.publish(\n                    topic=\"foo\",\n                    ham=\"spam\",\n                    birds={'foo_bird': 1, 'bar_bird': 2},\n                    message=\"hello world\",\n                )\n\nNotice `topic` is *always* first, followed by `kwargs`. Happy to explore\nhow implementations like\n[autobahn](https://github.com/crossbario/autobahn-python) can be\nsupported here.\n\nSee [ReadTheDocs](http://wampy.readthedocs.io/en/latest/) for more\ndetailed documentation.\n\nHave Fun With Wampy\n===================\n\nYou can simply import a wampy client into a Python shell and start\ncreating WAMP apps. Open a few shells and start clients running! Or\nstart an example app and open a shell and start calling it. Don't forget\nto start Crossbar first though!\n\n    $ make install\n\n    $ crossbar start --config ./wampy/testing/configs/crossbar.json\n\nExtensions\n==========\n\nWampy is a \"simple\" WAMP client and so it can easily be integrated with\nother frameworks. The current extensions are:\n\n\u003e -   [Flask-WAMP](https://github.com/noisyboiler/flask-wamp)\n\u003e -   [nameko-wamp](https://github.com/noisyboiler/nameko-wamp)\n\nExtensions for other Python Frameworks are encouraged!\n\nAsync Networking\n================\n\nThe default backend for async networking is **gevent**, but you can\nswitch this to **eventlet** if that is what your applications already\nuse.\n\n    $ export WAMPY_ASYNC_NAME=eventlet\n\nSwapping back is easy.\n\n    $ export WAMPY_ASYNC_NAME=gevent\n\n\nGevent is officially supported but eventlet no longer is, sorry. There\nwere issues with Eventlet and Python 3.7 that I cannot currently work\naround.\n\nAsync.io would require a complete re-write, and if you're already using\nthe standard library and want to use **wampy** that is *not* a problem -\njust roll with the default gevent - as the two event loops can run side\nby side.\n\nWhy does wampy support both eventlet and gevent? Because wampy is not a\nframework like Flask or nameko, and wampy tries to make as few\nassumptions about the process it is running in as possible. Wampy is\nintended to be integrated into existing Python apps as an easy way to\nsend and receive WAMP messages, and if your app is already committed to\na paritcular async architecture, then wampy may not be usable unless he\ncan switch between them freely. And do remember: both options are\ncompatible with the core asyncio library, so don't be put off if your\napp uses this.\n\nAlpha Features\n==============\n\nWebSocket Client -\\\u003e Server Pings\n---------------------------------\n\nDisabled by default, but by setting the environment variable\n**DEFAULT\\_HEARTBEAT\\_SECONDS** you can tell wampy to start Pinging the\nRouter/Broker, i.e. Crossbar.\n\n    $ export DEFAULT_HEARTBEAT_SECONDS=5\n\nThere is also **HEARTBEAT\\_TIMEOUT\\_SECONDS** (defaults to 2 seconds)\nwhich on missed will incrmeent a missed Pong counter. That's it for now;\nWIP.\n\nWAMP Call TimeOuts\n------------------\n\nWAMP advacned protocol describes an RPC timeout which **wampy**\nimplements but Crossbar as yet does not. See\n\u003chttps://github.com/crossbario/crossbar/issues/299\u003e. wampy does pass\nyour preferred value to the Router/Broker in the Call Message, but the\nactual timeout is implemented by wampy, simply cutting the request off\nat the head. Sadly this does mean the server still may return a value\nfor you and your app will have to handle this. We send the Cancel\nMessage too, but there are issues here as well: Work In Progress.\n\nRunning the tests\n=================\n\n    $ pip install --editable .[dev]\n    $ py.test ./test -v\n\nBuild the docs\n==============\n\n    $ pip install -r rtd_requirements.txt\n    $ sphinx-build -E -b html ./docs/ ./docs/_build/\n\n**If you like this project, then Thank You, and you're welcome to get\ninvolved.**\n\nContributing\n============\n\nFirstly. thank you everyone who does. And *everyone* is welcome to. And\nthanks for reading the\n[CONTRIBUTING](https://github.com/noisyboiler/wampy/blob/master/CONTRIBUTING.md)\nguidelines. And for adding yourselves to the\n[CONTRIBUTORS](https://github.com/noisyboiler/wampy/blob/master/CONTRIBUTORS.txt)\nlist on your PR - you should! Many thanks. It's also great to hear how\neveryone uses wampy, so please do share how with me on your PR in\ncomments.\n\nThen, please read about the\n[internals](https://github.com/noisyboiler/wampy/wiki/Internal-Architecture).\n\nFinally.... get coding!!\n\nThanks!\n\n#### TroubleShooting\n\nCrossbar.io is used by the test runner and has many dependencies.\n\n##### Mac OS\n\n`snappy/snappymodule.cc:31:10: fatal error: 'snappy-c.h' file not found   #include \u003csnappy-c.h\u003e`\n\nFix by brew install snappy\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnoisyboiler%2Fwampy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnoisyboiler%2Fwampy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnoisyboiler%2Fwampy/lists"}