Pyro5 5.16__tar.gz → 5.17__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyro5-5.16 → pyro5-5.17}/PKG-INFO +6 -2
- {pyro5-5.16 → pyro5-5.17}/Pyro5/__init__.py +1 -1
- {pyro5-5.16 → pyro5-5.17}/Pyro5/client.py +13 -6
- {pyro5-5.16 → pyro5-5.17}/Pyro5/configure.py +2 -0
- {pyro5-5.16 → pyro5-5.17}/Pyro5/core.py +38 -26
- {pyro5-5.16 → pyro5-5.17}/Pyro5/errors.py +1 -1
- {pyro5-5.16 → pyro5-5.17}/Pyro5/nameserver.py +20 -16
- {pyro5-5.16 → pyro5-5.17}/Pyro5/protocol.py +9 -6
- {pyro5-5.16 → pyro5-5.17}/Pyro5/serializers.py +2 -2
- {pyro5-5.16 → pyro5-5.17}/Pyro5/server.py +20 -18
- {pyro5-5.16 → pyro5-5.17}/Pyro5/socketutil.py +10 -4
- {pyro5-5.16 → pyro5-5.17}/Pyro5/svr_existingconn.py +2 -2
- {pyro5-5.16 → pyro5-5.17}/Pyro5/svr_multiplex.py +2 -2
- {pyro5-5.16 → pyro5-5.17}/Pyro5/svr_threads.py +7 -9
- {pyro5-5.16 → pyro5-5.17}/Pyro5.egg-info/PKG-INFO +6 -2
- {pyro5-5.16 → pyro5-5.17}/Pyro5.egg-info/SOURCES.txt +0 -46
- {pyro5-5.16 → pyro5-5.17}/Readme.rst +5 -1
- {pyro5-5.16 → pyro5-5.17}/examples/distributed-computing3/Readme.txt +1 -1
- {pyro5-5.16 → pyro5-5.17}/examples/exceptions/Readme.txt +1 -1
- {pyro5-5.16 → pyro5-5.17}/tests/test_core.py +15 -0
- {pyro5-5.16 → pyro5-5.17}/tests/test_daemon.py +129 -0
- {pyro5-5.16 → pyro5-5.17}/tests/test_naming.py +31 -0
- {pyro5-5.16 → pyro5-5.17}/tests/test_serialize.py +51 -0
- {pyro5-5.16 → pyro5-5.17}/tests/test_server.py +8 -0
- pyro5-5.16/.gitattributes +0 -7
- pyro5-5.16/.github/workflows/main-ci.yml +0 -40
- pyro5-5.16/Makefile +0 -39
- pyro5-5.16/docs/Makefile +0 -130
- pyro5-5.16/docs/make.bat +0 -170
- pyro5-5.16/docs/source/_static/css/customize.css +0 -14
- pyro5-5.16/docs/source/_static/flammable.png +0 -0
- pyro5-5.16/docs/source/_static/pyro-large.png +0 -0
- pyro5-5.16/docs/source/_static/pyro.png +0 -0
- pyro5-5.16/docs/source/_static/tf_pyrotaunt.png +0 -0
- pyro5-5.16/docs/source/api/api.rst +0 -6
- pyro5-5.16/docs/source/api/callcontext.rst +0 -5
- pyro5-5.16/docs/source/api/client.rst +0 -5
- pyro5-5.16/docs/source/api/compatibility.rst +0 -5
- pyro5-5.16/docs/source/api/config.rst +0 -14
- pyro5-5.16/docs/source/api/core.rst +0 -5
- pyro5-5.16/docs/source/api/echoserver.rst +0 -5
- pyro5-5.16/docs/source/api/errors.rst +0 -24
- pyro5-5.16/docs/source/api/httpgateway.rst +0 -5
- pyro5-5.16/docs/source/api/nameserver.rst +0 -9
- pyro5-5.16/docs/source/api/protocol.rst +0 -13
- pyro5-5.16/docs/source/api/server.rst +0 -6
- pyro5-5.16/docs/source/api/socketserver.rst +0 -60
- pyro5-5.16/docs/source/api/socketutil.rst +0 -5
- pyro5-5.16/docs/source/api.rst +0 -24
- pyro5-5.16/docs/source/changelog.rst +0 -167
- pyro5-5.16/docs/source/clientcode.rst +0 -531
- pyro5-5.16/docs/source/commandline.rst +0 -77
- pyro5-5.16/docs/source/conf.py +0 -236
- pyro5-5.16/docs/source/config.rst +0 -140
- pyro5-5.16/docs/source/docutils.conf +0 -2
- pyro5-5.16/docs/source/errors.rst +0 -138
- pyro5-5.16/docs/source/index.rst +0 -61
- pyro5-5.16/docs/source/install.rst +0 -64
- pyro5-5.16/docs/source/intro.rst +0 -310
- pyro5-5.16/docs/source/license.rst +0 -37
- pyro5-5.16/docs/source/nameserver.rst +0 -629
- pyro5-5.16/docs/source/pyrolite.rst +0 -15
- pyro5-5.16/docs/source/security.rst +0 -126
- pyro5-5.16/docs/source/servercode.rst +0 -824
- pyro5-5.16/docs/source/tipstricks.rst +0 -738
- pyro5-5.16/docs/source/tutorials.rst +0 -198
- pyro5-5.16/mypy.ini +0 -10
- pyro5-5.16/requirements.txt +0 -1
- pyro5-5.16/test-requirements.txt +0 -4
- pyro5-5.16/tox.ini +0 -14
- {pyro5-5.16 → pyro5-5.17}/LICENSE +0 -0
- {pyro5-5.16 → pyro5-5.17}/MANIFEST.in +0 -0
- {pyro5-5.16 → pyro5-5.17}/Pyro5/api.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/Pyro5/callcontext.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/Pyro5/compatibility/Pyro4.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/Pyro5/compatibility/__init__.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/Pyro5/nsc.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/Pyro5/utils/__init__.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/Pyro5/utils/echoserver.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/Pyro5/utils/httpgateway.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/Pyro5.egg-info/dependency_links.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/Pyro5.egg-info/entry_points.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/Pyro5.egg-info/requires.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/Pyro5.egg-info/top_level.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/Pyro5.egg-info/zip-safe +0 -0
- {pyro5-5.16 → pyro5-5.17}/certs/client_cert.pem +0 -0
- {pyro5-5.16 → pyro5-5.17}/certs/client_key.pem +0 -0
- {pyro5-5.16 → pyro5-5.17}/certs/readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/certs/server_cert.pem +0 -0
- {pyro5-5.16 → pyro5-5.17}/certs/server_key.pem +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/attributes/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/attributes/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/attributes/server.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/autoproxy/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/autoproxy/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/autoproxy/server.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/autoproxy/thingy.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/autoreconnect/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/autoreconnect/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/autoreconnect/clientNS.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/autoreconnect/server.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/autoreconnect/serverNS.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/autoretry/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/autoretry/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/autoretry/server.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/banks/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/banks/banks.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/banks/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/banks/server.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/batchedcalls/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/batchedcalls/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/batchedcalls/server.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/benchmark/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/benchmark/bench.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/benchmark/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/benchmark/connections.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/benchmark/server.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/blob-dispatch/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/blob-dispatch/client/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/blob-dispatch/client/customdata.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/blob-dispatch/dispatcher/dispatcher.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/blob-dispatch/listeners/customdata.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/blob-dispatch/listeners/listener.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/blob-dispatch/listeners/main.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/callback/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/callback/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/callback/client2.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/callback/server.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/callback/server2.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/callcontext/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/callcontext/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/callcontext/server.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/chatbox/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/chatbox/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/chatbox/server.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/circular/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/circular/chain.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/circular/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/circular/servA.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/circular/servB.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/circular/servC.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/custom-serialization/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/custom-serialization/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/custom-serialization/mycustomclasses.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/custom-serialization/server.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/diffie-hellman/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/diffie-hellman/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/diffie-hellman/diffiehellman.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/diffie-hellman/server.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/disconnects/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/disconnects/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/disconnects/server.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/distributed-computing/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/distributed-computing/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/distributed-computing/dispatcher.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/distributed-computing/worker.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/distributed-computing/workitem.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/distributed-computing2/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/distributed-computing2/alice.zip +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/distributed-computing2/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/distributed-computing2/servers.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/distributed-computing3/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/distributed-computing3/worker.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/distributed-mandelbrot/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/distributed-mandelbrot/client_asciizoom.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/distributed-mandelbrot/client_graphics.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/distributed-mandelbrot/launch_servers.sh +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/distributed-mandelbrot/normal.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/distributed-mandelbrot/normal_graphics.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/distributed-mandelbrot/server.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/echoserver/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/echoserver/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/eventloop/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/eventloop/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/eventloop/server_multiplexed.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/eventloop/server_threads.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/exceptions/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/exceptions/excep.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/exceptions/server.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/filetransfer/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/filetransfer/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/filetransfer/server.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/gui_eventloop/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/gui_eventloop/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/gui_eventloop/gui_nothreads.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/gui_eventloop/gui_threads.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/handshake/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/handshake/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/handshake/server.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/http/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/http/client.js +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/http/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/hugetransfer/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/hugetransfer/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/hugetransfer/server.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/instancemode/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/instancemode/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/instancemode/server.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/maxsize/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/maxsize/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/messagebus/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/messagebus/manytopics_publisher.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/messagebus/manytopics_subscriber.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/messagebus/messagebus/__init__.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/messagebus/messagebus/messagebus.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/messagebus/messagebus/server.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/messagebus/publisher.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/messagebus/subscriber.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/messagebus/subscriber_manual_consume.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/nameserverstress/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/nameserverstress/stress.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/nonameserver/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/nonameserver/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/nonameserver/server.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/ns-metadata/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/ns-metadata/example.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/ns-metadata/resources.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/oneway/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/oneway/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/oneway/client2.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/oneway/server.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/oneway/server2.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/privilege-separation/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/privilege-separation/drop_privs_client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/privilege-separation/drop_privs_server.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/privilege-separation/elevated_client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/privilege-separation/elevated_server.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/resourcetracking/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/resourcetracking/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/resourcetracking/server.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/robots/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/robots/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/robots/gameserver.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/robots/remote.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/robots/robot.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/servertypes/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/servertypes/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/servertypes/server.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/shoppingcart/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/shoppingcart/clients.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/shoppingcart/shoppingcart.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/shoppingcart/shopserver.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/socketpair/pair-fork.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/socketpair/pair-thread.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/socketpair/readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/ssl/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/ssl/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/ssl/server.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/stockquotes/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/stockquotes/phase1/stockmarket.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/stockquotes/phase1/viewer.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/stockquotes/phase2/stockmarket.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/stockquotes/phase2/viewer.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/stockquotes/phase3/stockmarket.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/stockquotes/phase3/viewer.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/streaming/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/streaming/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/streaming/server.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/thirdpartylib/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/thirdpartylib/awesome_thirdparty_library.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/thirdpartylib/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/thirdpartylib/server.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/thirdpartylib/server2.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/threadproxysharing/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/threadproxysharing/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/timeout/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/timeout/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/timeout/server.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/timezones/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/timezones/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/timezones/server.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/unixdomainsock/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/unixdomainsock/abstract_namespace_server.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/unixdomainsock/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/unixdomainsock/server.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/usersession/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/usersession/client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/usersession/database.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/usersession/server.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/warehouse/Readme.txt +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/warehouse/phase1/person.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/warehouse/phase1/visit.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/warehouse/phase1/warehouse.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/warehouse/phase2/person.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/warehouse/phase2/visit.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/warehouse/phase2/warehouse.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/warehouse/phase3/person.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/warehouse/phase3/visit.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/examples/warehouse/phase3/warehouse.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/setup.cfg +0 -0
- {pyro5-5.16 → pyro5-5.17}/setup.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/tests/support.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/tests/test_api.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/tests/test_client.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/tests/test_echoserver.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/tests/test_errors.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/tests/test_httpgateway.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/tests/test_protocol.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/tests/test_pyro4compat.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/tests/test_server_timeout.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/tests/test_socketutil.py +0 -0
- {pyro5-5.16 → pyro5-5.17}/tests/test_threadpool.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: Pyro5
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.17
|
|
4
4
|
Summary: Remote object communication library, fifth major version
|
|
5
5
|
Home-page: https://github.com/irmen/Pyro5
|
|
6
6
|
Author: Irmen de Jong
|
|
@@ -62,7 +62,7 @@ New code should use Pyro5 if at all possible.
|
|
|
62
62
|
Features
|
|
63
63
|
--------
|
|
64
64
|
|
|
65
|
-
- written in 100% Python so extremely portable, supported on
|
|
65
|
+
- written in 100% Python so extremely portable, supported on CPython 3 and Pypy 3
|
|
66
66
|
- works between different system architectures and operating systems.
|
|
67
67
|
- able to communicate between different Python versions transparently.
|
|
68
68
|
- defaults to a safe serializer (`serpent <https://pypi.python.org/pypi/serpent>`_) that supports many Python data types.
|
|
@@ -81,6 +81,10 @@ Features
|
|
|
81
81
|
- you can define timeouts on network communications to prevent a call blocking forever if there's something wrong.
|
|
82
82
|
- remote exceptions will be raised in the caller, as if they were local. You can extract detailed remote traceback information.
|
|
83
83
|
- http gateway available for clients wanting to use http+json (such as browser scripts).
|
|
84
|
+
- custom handshake data can be exchanged during connection setup.
|
|
85
|
+
- message annotations support attaching custom metadata to every call.
|
|
86
|
+
- correlation ids on every call for end-to-end request tracing.
|
|
87
|
+
- SerializedBlob for efficient transfer of large serialized data blobs.
|
|
84
88
|
- stable network communication code that has worked reliably on many platforms for over a decade.
|
|
85
89
|
- can hook onto existing sockets created for instance with socketpair() to communicate efficiently between threads or sub-processes.
|
|
86
90
|
- possibility to integrate Pyro's event loop into your own (or third party) event loop.
|
|
@@ -88,7 +88,7 @@ class Proxy(object):
|
|
|
88
88
|
def __del__(self):
|
|
89
89
|
if hasattr(self, "_pyroConnection"):
|
|
90
90
|
try:
|
|
91
|
-
self.
|
|
91
|
+
self._pyroConnection.close()
|
|
92
92
|
except Exception:
|
|
93
93
|
pass
|
|
94
94
|
|
|
@@ -272,7 +272,10 @@ class Proxy(object):
|
|
|
272
272
|
raise errors.ProtocolError("result of call is an iterator, but the server is not configured to allow streaming")
|
|
273
273
|
return _StreamResultIterator(streamId, self)
|
|
274
274
|
if msg.flags & protocol.FLAGS_EXCEPTION:
|
|
275
|
-
|
|
275
|
+
try:
|
|
276
|
+
raise data # if you see this in your traceback, you should probably inspect the remote traceback as well
|
|
277
|
+
finally:
|
|
278
|
+
del data
|
|
276
279
|
else:
|
|
277
280
|
return data
|
|
278
281
|
except (errors.CommunicationError, KeyboardInterrupt):
|
|
@@ -296,7 +299,8 @@ class Proxy(object):
|
|
|
296
299
|
Connects this proxy to the remote Pyro daemon. Does connection handshake.
|
|
297
300
|
Returns true if a new connection was made, false if an existing one was already present.
|
|
298
301
|
"""
|
|
299
|
-
def connect_and_handshake(
|
|
302
|
+
def connect_and_handshake():
|
|
303
|
+
conn = None
|
|
300
304
|
try:
|
|
301
305
|
if self._pyroConnection is not None:
|
|
302
306
|
return False # already connected
|
|
@@ -312,7 +316,11 @@ class Proxy(object):
|
|
|
312
316
|
timeout=self.__pyroTimeout,
|
|
313
317
|
nodelay=config.SOCK_NODELAY,
|
|
314
318
|
sslContext=sslContext)
|
|
315
|
-
|
|
319
|
+
try:
|
|
320
|
+
conn = socketutil.SocketConnection(sock, uri.object)
|
|
321
|
+
except Exception:
|
|
322
|
+
sock.close()
|
|
323
|
+
raise
|
|
316
324
|
# Do handshake.
|
|
317
325
|
serializer = serializers.serializers[self._pyroSerializer or config.SERIALIZER]
|
|
318
326
|
data = {"handshake": self._pyroHandshake, "object": uri.object}
|
|
@@ -366,14 +374,13 @@ class Proxy(object):
|
|
|
366
374
|
return False # already connected
|
|
367
375
|
uri = core.resolve(self._pyroUri)
|
|
368
376
|
# socket connection (normal or Unix domain socket)
|
|
369
|
-
conn = None
|
|
370
377
|
log.debug("connecting to %s", uri)
|
|
371
378
|
connect_location = uri.sockname or (uri.host, uri.port)
|
|
372
379
|
if connected_socket:
|
|
373
380
|
self._pyroConnection = socketutil.SocketConnection(connected_socket, uri.object, True)
|
|
374
381
|
self._pyroLocalSocket = connected_socket.getsockname()
|
|
375
382
|
else:
|
|
376
|
-
connect_and_handshake(
|
|
383
|
+
connect_and_handshake()
|
|
377
384
|
# obtain metadata if this feature is enabled, and the metadata is not known yet
|
|
378
385
|
if not self._pyroMethods and not self._pyroAttrs:
|
|
379
386
|
self._pyroGetMetadata(uri.object)
|
|
@@ -10,6 +10,7 @@ import contextlib
|
|
|
10
10
|
import ipaddress
|
|
11
11
|
import socket
|
|
12
12
|
import random
|
|
13
|
+
import platform
|
|
13
14
|
import serpent
|
|
14
15
|
from typing import Union, Optional
|
|
15
16
|
from . import config, errors, socketutil, serializers
|
|
@@ -152,7 +153,13 @@ class _ExceptionWrapper(object):
|
|
|
152
153
|
self.exception = exception
|
|
153
154
|
|
|
154
155
|
def raiseIt(self):
|
|
155
|
-
|
|
156
|
+
try:
|
|
157
|
+
err = self.exception.__class__(*self.exception.args)
|
|
158
|
+
if hasattr(self.exception, '_pyroTraceback'):
|
|
159
|
+
err._pyroTraceback = self.exception._pyroTraceback
|
|
160
|
+
raise err
|
|
161
|
+
finally:
|
|
162
|
+
del err
|
|
156
163
|
|
|
157
164
|
def __serialized_dict__(self):
|
|
158
165
|
"""serialized form as a dictionary"""
|
|
@@ -215,11 +222,15 @@ def locate_ns(host: Union[str, ipaddress.IPv4Address, ipaddress.IPv6Address] = "
|
|
|
215
222
|
else:
|
|
216
223
|
# Some systems have 127.0.1.1 in the hosts file assigned to the hostname,
|
|
217
224
|
# so try this too (only if it's actually used as a valid ip address)
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
hosts = [config.NS_HOST] if config.NS_HOST == "127.0.1.1" else [config.NS_HOST, "127.0.1.1"]
|
|
221
|
-
except socket.error:
|
|
225
|
+
# Skip this check on Windows to avoid slow DNS lookup timeout (5+ seconds)
|
|
226
|
+
if platform.system() == "Windows":
|
|
222
227
|
hosts = [config.NS_HOST]
|
|
228
|
+
else:
|
|
229
|
+
try:
|
|
230
|
+
socket.gethostbyaddr("127.0.1.1")
|
|
231
|
+
hosts = [config.NS_HOST] if config.NS_HOST == "127.0.1.1" else [config.NS_HOST, "127.0.1.1"]
|
|
232
|
+
except socket.error:
|
|
233
|
+
hosts = [config.NS_HOST]
|
|
223
234
|
for host in hosts:
|
|
224
235
|
uristring = "PYRO:%s@%s:%d" % (NAMESERVER_NAME, host, port or config.NS_PORT)
|
|
225
236
|
log.debug("locating the NS: %s", uristring)
|
|
@@ -236,27 +247,28 @@ def locate_ns(host: Union[str, ipaddress.IPv4Address, ipaddress.IPv6Address] = "
|
|
|
236
247
|
port = config.NS_BCPORT
|
|
237
248
|
log.debug("broadcast locate")
|
|
238
249
|
sock = socketutil.create_bc_socket(reuseaddr=config.SOCK_REUSE, timeout=0.7)
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
250
|
+
try:
|
|
251
|
+
for _ in range(3):
|
|
252
|
+
try:
|
|
253
|
+
for bcaddr in config.BROADCAST_ADDRS:
|
|
254
|
+
try:
|
|
255
|
+
sock.sendto(b"GET_NSURI", 0, (bcaddr, port))
|
|
256
|
+
except socket.error as x:
|
|
257
|
+
err = getattr(x, "errno", x.args[0])
|
|
258
|
+
# handle some errno's that some platforms like to throw:
|
|
259
|
+
if err not in socketutil.ERRNO_EADDRNOTAVAIL and err not in socketutil.ERRNO_EADDRINUSE:
|
|
260
|
+
raise
|
|
261
|
+
data, _ = sock.recvfrom(100)
|
|
262
|
+
text = data.decode("iso-8859-1")
|
|
263
|
+
log.debug("located NS: %s", text)
|
|
264
|
+
proxy = client.Proxy(text)
|
|
265
|
+
return proxy
|
|
266
|
+
except socket.timeout:
|
|
267
|
+
continue
|
|
268
|
+
finally:
|
|
269
|
+
with contextlib.suppress(OSError, socket.error):
|
|
270
|
+
sock.shutdown(socket.SHUT_RDWR)
|
|
271
|
+
sock.close()
|
|
260
272
|
log.debug("broadcast locate failed, try direct connection on NS_HOST")
|
|
261
273
|
else:
|
|
262
274
|
log.debug("skipping broadcast lookup")
|
|
@@ -70,7 +70,7 @@ def get_pyro_traceback(ex_type=None, ex_value=None, ex_tb=None):
|
|
|
70
70
|
you do not supply the objects yourself."""
|
|
71
71
|
|
|
72
72
|
def formatRemoteTraceback(remote_tb_lines):
|
|
73
|
-
result = [" +--- This exception
|
|
73
|
+
result = [" +--- This exception occurred remotely (Pyro) - Remote traceback:"]
|
|
74
74
|
for line in remote_tb_lines:
|
|
75
75
|
if line.endswith("\n"):
|
|
76
76
|
line = line[:-1]
|
|
@@ -37,7 +37,7 @@ class MemoryStorage(dict):
|
|
|
37
37
|
|
|
38
38
|
def __setitem__(self, key, value):
|
|
39
39
|
uri, metadata = value
|
|
40
|
-
super(MemoryStorage, self).__setitem__(key, (uri, metadata
|
|
40
|
+
super(MemoryStorage, self).__setitem__(key, (uri, metadata if metadata is not None else frozenset()))
|
|
41
41
|
|
|
42
42
|
def optimized_prefix_list(self, prefix, return_metadata=False):
|
|
43
43
|
return None
|
|
@@ -315,7 +315,7 @@ class NameServer(object):
|
|
|
315
315
|
with self.lock:
|
|
316
316
|
if safe and name in self.storage:
|
|
317
317
|
raise NamingError("name already registered: " + name)
|
|
318
|
-
self.storage[name] = uri, set(metadata) if metadata else None
|
|
318
|
+
self.storage[name] = uri, set(metadata) if metadata is not None else None
|
|
319
319
|
|
|
320
320
|
def set_metadata(self, name, metadata):
|
|
321
321
|
"""update the metadata for an existing registration"""
|
|
@@ -327,28 +327,32 @@ class NameServer(object):
|
|
|
327
327
|
with self.lock:
|
|
328
328
|
try:
|
|
329
329
|
uri, old_meta = self.storage[name]
|
|
330
|
-
self.storage[name] = uri, set(metadata) if metadata else None
|
|
330
|
+
self.storage[name] = uri, set(metadata) if metadata is not None else None
|
|
331
331
|
except KeyError:
|
|
332
332
|
raise NamingError("unknown name: " + name)
|
|
333
333
|
|
|
334
334
|
def remove(self, name=None, prefix=None, regex=None):
|
|
335
335
|
"""Remove a registration. returns the number of items removed."""
|
|
336
|
-
if name and name
|
|
336
|
+
if name and name != core.NAMESERVER_NAME:
|
|
337
337
|
with self.lock:
|
|
338
|
-
|
|
339
|
-
|
|
338
|
+
if name in self.storage:
|
|
339
|
+
del self.storage[name]
|
|
340
|
+
return 1
|
|
341
|
+
return 0
|
|
340
342
|
if prefix:
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
343
|
+
with self.lock:
|
|
344
|
+
items = list(self.list(prefix=prefix).keys())
|
|
345
|
+
if core.NAMESERVER_NAME in items:
|
|
346
|
+
items.remove(core.NAMESERVER_NAME)
|
|
347
|
+
self.storage.remove_items(items)
|
|
348
|
+
return len(items)
|
|
346
349
|
if regex:
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
350
|
+
with self.lock:
|
|
351
|
+
items = list(self.list(regex=regex).keys())
|
|
352
|
+
if core.NAMESERVER_NAME in items:
|
|
353
|
+
items.remove(core.NAMESERVER_NAME)
|
|
354
|
+
self.storage.remove_items(items)
|
|
355
|
+
return len(items)
|
|
352
356
|
return 0
|
|
353
357
|
|
|
354
358
|
# noinspection PyNoneFunctionAssignment
|
|
@@ -75,12 +75,11 @@ class SendingMessage:
|
|
|
75
75
|
self.seq = seq
|
|
76
76
|
self.serializer_id = serializer_id
|
|
77
77
|
annotations = annotations or {}
|
|
78
|
-
annotations_size = sum(
|
|
78
|
+
annotations_size = sum(8 + len(v) for v in annotations.values())
|
|
79
79
|
flags &= ~FLAGS_COMPRESSED
|
|
80
80
|
if config.COMPRESSION and len(payload) > 100:
|
|
81
81
|
payload = zlib.compress(payload, 4)
|
|
82
82
|
flags |= FLAGS_COMPRESSED
|
|
83
|
-
self.flags = flags
|
|
84
83
|
total_size = len(payload) + annotations_size
|
|
85
84
|
if total_size > config.MAX_MESSAGE_SIZE:
|
|
86
85
|
raise errors.ProtocolError("message too large ({:d}, max={:d})".format(total_size, config.MAX_MESSAGE_SIZE))
|
|
@@ -89,7 +88,8 @@ class SendingMessage:
|
|
|
89
88
|
self.corr_id = current_context.correlation_id.bytes
|
|
90
89
|
else:
|
|
91
90
|
self.corr_id = _empty_correlation_id
|
|
92
|
-
|
|
91
|
+
self.flags = flags
|
|
92
|
+
header_data = struct.pack(_header_format, b"PYRO", PROTOCOL_VERSION, msgtype, serializer_id, self.flags, seq,
|
|
93
93
|
len(payload), annotations_size, self.corr_id, 0, _magic_number)
|
|
94
94
|
annotation_data = []
|
|
95
95
|
for k, v in annotations.items():
|
|
@@ -158,9 +158,12 @@ class ReceivingMessage:
|
|
|
158
158
|
while i < self.annotations_size:
|
|
159
159
|
annotation_id = bytes(payload[i:i+4]).decode("ascii")
|
|
160
160
|
length = int.from_bytes(payload[i+4:i+8], "big")
|
|
161
|
+
if length < 0 or i + 8 + length > self.annotations_size:
|
|
162
|
+
raise errors.ProtocolError("annotation chunk length exceeds remaining data")
|
|
161
163
|
self.annotations[annotation_id] = payload[i+8:i+8+length] # note: it stores a memoryview!
|
|
162
164
|
i += 8 + length
|
|
163
|
-
|
|
165
|
+
if i != self.annotations_size:
|
|
166
|
+
raise errors.ProtocolError("annotation parsing did not consume all annotation data")
|
|
164
167
|
self.data = payload[self.annotations_size:]
|
|
165
168
|
else:
|
|
166
169
|
self.data = payload
|
|
@@ -175,8 +178,8 @@ def log_wiredata(logger, text, msg):
|
|
|
175
178
|
num_anns = len(msg.annotations) if hasattr(msg, "annotations") else 0
|
|
176
179
|
corr_bytes = bytes(msg.corr_id) if hasattr(msg, "corr_id") else _empty_correlation_id
|
|
177
180
|
corr_id = uuid.UUID(bytes=corr_bytes)
|
|
178
|
-
logger.debug("%s: msgtype=%d flags=0x%x ser=%d seq=%d num_annotations=%s corr_id=%s\ndata=%r"
|
|
179
|
-
|
|
181
|
+
logger.debug("%s: msgtype=%d flags=0x%x ser=%d seq=%d num_annotations=%s corr_id=%s\ndata=%r",
|
|
182
|
+
text, msg.type, msg.flags, msg.serializer_id, msg.seq, num_anns, corr_id, bytes(msg.data))
|
|
180
183
|
|
|
181
184
|
|
|
182
185
|
def recv_stub(connection, accepted_msgtypes=None):
|
|
@@ -231,7 +231,7 @@ class SerializerBase(object):
|
|
|
231
231
|
exceptiontype = getattr(sqlite3, short_classname)
|
|
232
232
|
if issubclass(exceptiontype, BaseException):
|
|
233
233
|
return SerializerBase.make_exception(exceptiontype, data)
|
|
234
|
-
log.warning("unsupported serialized class: "
|
|
234
|
+
log.warning("unsupported serialized class: %s", classname)
|
|
235
235
|
raise errors.SerializeError("unsupported serialized class: " + classname)
|
|
236
236
|
|
|
237
237
|
@staticmethod
|
|
@@ -422,7 +422,7 @@ class MsgpackSerializer(SerializerBase):
|
|
|
422
422
|
return msgpack.packb(data, use_bin_type=True, default=self.default)
|
|
423
423
|
|
|
424
424
|
def loadsCall(self, data):
|
|
425
|
-
return msgpack.unpackb(self._convertToBytes(data), raw=False, object_hook=self.object_hook)
|
|
425
|
+
return msgpack.unpackb(self._convertToBytes(data), raw=False, object_hook=self.object_hook, ext_hook=self.ext_hook)
|
|
426
426
|
|
|
427
427
|
def loads(self, data):
|
|
428
428
|
return msgpack.unpackb(self._convertToBytes(data), raw=False, object_hook=self.object_hook, ext_hook=self.ext_hook)
|
|
@@ -241,7 +241,7 @@ class Daemon(object):
|
|
|
241
241
|
natport_for_loc = natport
|
|
242
242
|
if natport == 0:
|
|
243
243
|
# expose internal port number as NAT port as well. (don't use port because it could be 0 and will be chosen by the OS)
|
|
244
|
-
natport_for_loc = int(self.locationStr.
|
|
244
|
+
natport_for_loc = int(self.locationStr.rsplit(":", 1)[1])
|
|
245
245
|
# The NAT-location (str of the form ``nathost:natportnumber``) on which the Daemon is exposed for use with NAT-routing
|
|
246
246
|
self.natLocationStr = "%s:%d" % (nathost, natport_for_loc) if nathost else None
|
|
247
247
|
if self.natLocationStr:
|
|
@@ -250,10 +250,11 @@ class Daemon(object):
|
|
|
250
250
|
pyroObject._pyroId = core.DAEMON_NAME
|
|
251
251
|
# Dictionary from Pyro object id to the actual Pyro object registered by this id
|
|
252
252
|
self.objectsById = {pyroObject._pyroId: pyroObject}
|
|
253
|
-
log.debug("pyro protocol version: %d"
|
|
253
|
+
log.debug("pyro protocol version: %d", protocol.PROTOCOL_VERSION)
|
|
254
254
|
self._pyroInstances = {} # pyro objects for instance_mode=single (singletons, just one per daemon)
|
|
255
255
|
self.streaming_responses = {} # stream_id -> (client, creation_timestamp, linger_timestamp, stream)
|
|
256
256
|
self.housekeeper_lock = threading.Lock()
|
|
257
|
+
self._disconnect_lock = threading.Lock()
|
|
257
258
|
self.create_single_instance_lock = threading.Lock()
|
|
258
259
|
self.__mustshutdown.clear()
|
|
259
260
|
self.methodcall_error_handler = _default_methodcall_error_handler
|
|
@@ -524,19 +525,20 @@ class Daemon(object):
|
|
|
524
525
|
raise # re-raise if flagged as callback, communication or security error.
|
|
525
526
|
|
|
526
527
|
def _clientDisconnect(self, conn):
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
528
|
+
with self._disconnect_lock:
|
|
529
|
+
if config.ITER_STREAM_LINGER > 0:
|
|
530
|
+
# client goes away, keep streams around for a bit longer (allow reconnect)
|
|
531
|
+
for streamId in list(self.streaming_responses):
|
|
532
|
+
info = self.streaming_responses.get(streamId, None)
|
|
533
|
+
if info and info[0] is conn:
|
|
534
|
+
_, timestamp, _, stream = info
|
|
535
|
+
self.streaming_responses[streamId] = (None, timestamp, time.time(), stream)
|
|
536
|
+
else:
|
|
537
|
+
# client goes away, close any streams it had open as well
|
|
538
|
+
for streamId in list(self.streaming_responses):
|
|
539
|
+
info = self.streaming_responses.get(streamId, None)
|
|
540
|
+
if info and info[0] is conn:
|
|
541
|
+
del self.streaming_responses[streamId]
|
|
540
542
|
self.clientDisconnect(conn) # user overridable hook
|
|
541
543
|
|
|
542
544
|
def _housekeeping(self):
|
|
@@ -667,7 +669,7 @@ class Daemon(object):
|
|
|
667
669
|
raise errors.DaemonError("an object or class is already registered with that id")
|
|
668
670
|
# set some pyro attributes
|
|
669
671
|
obj_or_class._pyroId = objectId
|
|
670
|
-
obj_or_class._pyroDaemon = self
|
|
672
|
+
obj_or_class._pyroDaemon = weakref.proxy(self)
|
|
671
673
|
# register a custom serializer for the type to automatically return proxies
|
|
672
674
|
# we need to do this for all known serializers
|
|
673
675
|
for ser in serializers.serializers.values():
|
|
@@ -859,8 +861,8 @@ def _default_methodcall_error_handler(daemon: Daemon, client_sock: socketutil.So
|
|
|
859
861
|
method: Callable, vargs: Sequence[Any], kwargs: Dict[str, Any],
|
|
860
862
|
exception: Exception) -> None:
|
|
861
863
|
"""The default routine called to process a exception raised in the user code of a method call"""
|
|
862
|
-
log.debug("exception occurred in method call user code: client
|
|
863
|
-
|
|
864
|
+
log.debug("exception occurred in method call user code: client=%s method=%s exception=%r",
|
|
865
|
+
client_sock, method.__qualname__, exception)
|
|
864
866
|
|
|
865
867
|
|
|
866
868
|
# register the special serializers for the pyro objects
|
|
@@ -79,7 +79,10 @@ def get_ip_address(hostname: str, workaround127: bool = False, version: int = No
|
|
|
79
79
|
raise ValueError("unknown value for argument ipVersion.")
|
|
80
80
|
ip = socket.getaddrinfo(hostname or socket.gethostname(), 80, family, socket.SOCK_STREAM, socket.SOL_TCP)[0][4][0]
|
|
81
81
|
if workaround127 and (ip.startswith("127.") or ip == "0.0.0.0"):
|
|
82
|
-
|
|
82
|
+
try:
|
|
83
|
+
return get_interface("4.2.2.2").ip
|
|
84
|
+
except OSError:
|
|
85
|
+
pass # network unreachable, fall through to return loopback address
|
|
83
86
|
return ipaddress.ip_address(ip)
|
|
84
87
|
|
|
85
88
|
try:
|
|
@@ -154,9 +157,12 @@ def receive_data(sock: socket.socket, size: int) -> bytes:
|
|
|
154
157
|
data.extend(chunk)
|
|
155
158
|
msglen += len(chunk)
|
|
156
159
|
if len(data) != size:
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
+
try:
|
|
161
|
+
err = ConnectionClosedError("receiving: not enough data")
|
|
162
|
+
err.partialData = data # store the message that was received until now
|
|
163
|
+
raise err
|
|
164
|
+
finally:
|
|
165
|
+
del err
|
|
160
166
|
return data # yay, complete
|
|
161
167
|
except socket.timeout:
|
|
162
168
|
raise TimeoutError("receiving: timeout")
|
|
@@ -24,7 +24,7 @@ class SocketServer_ExistingConnection(object):
|
|
|
24
24
|
raise socket.error("SSL configured for Pyro but existing socket is not a SSL socket")
|
|
25
25
|
self.daemon = daemon
|
|
26
26
|
self.sock = connected_socket
|
|
27
|
-
log.info("starting server on user-supplied connected socket "
|
|
27
|
+
log.info("starting server on user-supplied connected socket %s", connected_socket)
|
|
28
28
|
sn = connected_socket.getsockname()
|
|
29
29
|
if hasattr(socket, "AF_UNIX") and connected_socket.family == socket.AF_UNIX:
|
|
30
30
|
self.locationStr = "./u:" + (sn or "<<not-bound>>")
|
|
@@ -86,7 +86,7 @@ class SocketServer_ExistingConnection(object):
|
|
|
86
86
|
return False
|
|
87
87
|
except errors.TimeoutError as x:
|
|
88
88
|
# for timeout errors we're not really interested in detailed traceback info
|
|
89
|
-
log.warning("error during handleRequest: %s"
|
|
89
|
+
log.warning("error during handleRequest: %s", x)
|
|
90
90
|
return False
|
|
91
91
|
except Exception:
|
|
92
92
|
# other error occurred, close the connection, but also log a warning
|
|
@@ -87,7 +87,7 @@ class SocketServer_Multiplex(object):
|
|
|
87
87
|
try:
|
|
88
88
|
self.daemon._clientDisconnect(s)
|
|
89
89
|
except Exception as x:
|
|
90
|
-
log.warning("Error in clientDisconnect: "
|
|
90
|
+
log.warning("Error in clientDisconnect: %s", x)
|
|
91
91
|
self.selector.unregister(s)
|
|
92
92
|
s.close()
|
|
93
93
|
self.daemon._housekeeping()
|
|
@@ -174,7 +174,7 @@ class SocketServer_Multiplex(object):
|
|
|
174
174
|
return False
|
|
175
175
|
except errors.TimeoutError as x:
|
|
176
176
|
# for timeout errors we're not really interested in detailed traceback info
|
|
177
|
-
log.warning("error during handleRequest: %s"
|
|
177
|
+
log.warning("error during handleRequest: %s", x)
|
|
178
178
|
return False
|
|
179
179
|
except Exception:
|
|
180
180
|
# other error occurred, close the connection, but also log a warning
|
|
@@ -17,7 +17,6 @@ import contextlib
|
|
|
17
17
|
from . import config, socketutil, errors
|
|
18
18
|
|
|
19
19
|
log = logging.getLogger("Pyro5.threadpoolserver")
|
|
20
|
-
_client_disconnect_lock = threading.Lock()
|
|
21
20
|
|
|
22
21
|
|
|
23
22
|
class ClientConnectionJob(object):
|
|
@@ -46,7 +45,7 @@ class ClientConnectionJob(object):
|
|
|
46
45
|
break
|
|
47
46
|
except errors.TimeoutError as x:
|
|
48
47
|
# for timeout errors we're not really interested in detailed traceback info
|
|
49
|
-
log.warning("error during handleRequest: %s"
|
|
48
|
+
log.warning("error during handleRequest: %s", x)
|
|
50
49
|
break
|
|
51
50
|
except Exception:
|
|
52
51
|
# other errors log a warning, break this loop and close the client connection
|
|
@@ -56,11 +55,10 @@ class ClientConnectionJob(object):
|
|
|
56
55
|
log.warning(msg)
|
|
57
56
|
break
|
|
58
57
|
finally:
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
log.warning("Error in clientDisconnect: " + str(x))
|
|
58
|
+
try:
|
|
59
|
+
self.daemon._clientDisconnect(self.csock)
|
|
60
|
+
except Exception as x:
|
|
61
|
+
log.warning("Error in clientDisconnect: %s", x)
|
|
64
62
|
self.csock.close()
|
|
65
63
|
|
|
66
64
|
def handleConnection(self):
|
|
@@ -77,7 +75,7 @@ class ClientConnectionJob(object):
|
|
|
77
75
|
return False
|
|
78
76
|
|
|
79
77
|
def denyConnection(self, reason):
|
|
80
|
-
log.warning("client connection was denied: "
|
|
78
|
+
log.warning("client connection was denied: %s", reason)
|
|
81
79
|
# return failed handshake
|
|
82
80
|
self.daemon._handshake(self.csock, denied_reason=reason)
|
|
83
81
|
self.csock.close()
|
|
@@ -308,11 +306,11 @@ class Pool(object):
|
|
|
308
306
|
def close(self):
|
|
309
307
|
if not self.closed:
|
|
310
308
|
log.debug("closing down")
|
|
309
|
+
self.closed = True
|
|
311
310
|
for w in list(self.busy):
|
|
312
311
|
w.process(None)
|
|
313
312
|
for w in list(self.idle):
|
|
314
313
|
w.process(None)
|
|
315
|
-
self.closed = True
|
|
316
314
|
time.sleep(0.1)
|
|
317
315
|
idle, self.idle = self.idle, set()
|
|
318
316
|
busy, self.busy = self.busy, set()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: Pyro5
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.17
|
|
4
4
|
Summary: Remote object communication library, fifth major version
|
|
5
5
|
Home-page: https://github.com/irmen/Pyro5
|
|
6
6
|
Author: Irmen de Jong
|
|
@@ -62,7 +62,7 @@ New code should use Pyro5 if at all possible.
|
|
|
62
62
|
Features
|
|
63
63
|
--------
|
|
64
64
|
|
|
65
|
-
- written in 100% Python so extremely portable, supported on
|
|
65
|
+
- written in 100% Python so extremely portable, supported on CPython 3 and Pypy 3
|
|
66
66
|
- works between different system architectures and operating systems.
|
|
67
67
|
- able to communicate between different Python versions transparently.
|
|
68
68
|
- defaults to a safe serializer (`serpent <https://pypi.python.org/pypi/serpent>`_) that supports many Python data types.
|
|
@@ -81,6 +81,10 @@ Features
|
|
|
81
81
|
- you can define timeouts on network communications to prevent a call blocking forever if there's something wrong.
|
|
82
82
|
- remote exceptions will be raised in the caller, as if they were local. You can extract detailed remote traceback information.
|
|
83
83
|
- http gateway available for clients wanting to use http+json (such as browser scripts).
|
|
84
|
+
- custom handshake data can be exchanged during connection setup.
|
|
85
|
+
- message annotations support attaching custom metadata to every call.
|
|
86
|
+
- correlation ids on every call for end-to-end request tracing.
|
|
87
|
+
- SerializedBlob for efficient transfer of large serialized data blobs.
|
|
84
88
|
- stable network communication code that has worked reliably on many platforms for over a decade.
|
|
85
89
|
- can hook onto existing sockets created for instance with socketpair() to communicate efficiently between threads or sub-processes.
|
|
86
90
|
- possibility to integrate Pyro's event loop into your own (or third party) event loop.
|
|
@@ -1,15 +1,8 @@
|
|
|
1
|
-
.gitattributes
|
|
2
1
|
LICENSE
|
|
3
2
|
MANIFEST.in
|
|
4
|
-
Makefile
|
|
5
3
|
Readme.rst
|
|
6
|
-
mypy.ini
|
|
7
|
-
requirements.txt
|
|
8
4
|
setup.cfg
|
|
9
5
|
setup.py
|
|
10
|
-
test-requirements.txt
|
|
11
|
-
tox.ini
|
|
12
|
-
.github/workflows/main-ci.yml
|
|
13
6
|
Pyro5/__init__.py
|
|
14
7
|
Pyro5/api.py
|
|
15
8
|
Pyro5/callcontext.py
|
|
@@ -43,45 +36,6 @@ certs/client_key.pem
|
|
|
43
36
|
certs/readme.txt
|
|
44
37
|
certs/server_cert.pem
|
|
45
38
|
certs/server_key.pem
|
|
46
|
-
docs/Makefile
|
|
47
|
-
docs/make.bat
|
|
48
|
-
docs/source/api.rst
|
|
49
|
-
docs/source/changelog.rst
|
|
50
|
-
docs/source/clientcode.rst
|
|
51
|
-
docs/source/commandline.rst
|
|
52
|
-
docs/source/conf.py
|
|
53
|
-
docs/source/config.rst
|
|
54
|
-
docs/source/docutils.conf
|
|
55
|
-
docs/source/errors.rst
|
|
56
|
-
docs/source/index.rst
|
|
57
|
-
docs/source/install.rst
|
|
58
|
-
docs/source/intro.rst
|
|
59
|
-
docs/source/license.rst
|
|
60
|
-
docs/source/nameserver.rst
|
|
61
|
-
docs/source/pyrolite.rst
|
|
62
|
-
docs/source/security.rst
|
|
63
|
-
docs/source/servercode.rst
|
|
64
|
-
docs/source/tipstricks.rst
|
|
65
|
-
docs/source/tutorials.rst
|
|
66
|
-
docs/source/_static/flammable.png
|
|
67
|
-
docs/source/_static/pyro-large.png
|
|
68
|
-
docs/source/_static/pyro.png
|
|
69
|
-
docs/source/_static/tf_pyrotaunt.png
|
|
70
|
-
docs/source/_static/css/customize.css
|
|
71
|
-
docs/source/api/api.rst
|
|
72
|
-
docs/source/api/callcontext.rst
|
|
73
|
-
docs/source/api/client.rst
|
|
74
|
-
docs/source/api/compatibility.rst
|
|
75
|
-
docs/source/api/config.rst
|
|
76
|
-
docs/source/api/core.rst
|
|
77
|
-
docs/source/api/echoserver.rst
|
|
78
|
-
docs/source/api/errors.rst
|
|
79
|
-
docs/source/api/httpgateway.rst
|
|
80
|
-
docs/source/api/nameserver.rst
|
|
81
|
-
docs/source/api/protocol.rst
|
|
82
|
-
docs/source/api/server.rst
|
|
83
|
-
docs/source/api/socketserver.rst
|
|
84
|
-
docs/source/api/socketutil.rst
|
|
85
39
|
examples/attributes/Readme.txt
|
|
86
40
|
examples/attributes/client.py
|
|
87
41
|
examples/attributes/server.py
|