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.
Files changed (302) hide show
  1. {pyro5-5.16 → pyro5-5.17}/PKG-INFO +6 -2
  2. {pyro5-5.16 → pyro5-5.17}/Pyro5/__init__.py +1 -1
  3. {pyro5-5.16 → pyro5-5.17}/Pyro5/client.py +13 -6
  4. {pyro5-5.16 → pyro5-5.17}/Pyro5/configure.py +2 -0
  5. {pyro5-5.16 → pyro5-5.17}/Pyro5/core.py +38 -26
  6. {pyro5-5.16 → pyro5-5.17}/Pyro5/errors.py +1 -1
  7. {pyro5-5.16 → pyro5-5.17}/Pyro5/nameserver.py +20 -16
  8. {pyro5-5.16 → pyro5-5.17}/Pyro5/protocol.py +9 -6
  9. {pyro5-5.16 → pyro5-5.17}/Pyro5/serializers.py +2 -2
  10. {pyro5-5.16 → pyro5-5.17}/Pyro5/server.py +20 -18
  11. {pyro5-5.16 → pyro5-5.17}/Pyro5/socketutil.py +10 -4
  12. {pyro5-5.16 → pyro5-5.17}/Pyro5/svr_existingconn.py +2 -2
  13. {pyro5-5.16 → pyro5-5.17}/Pyro5/svr_multiplex.py +2 -2
  14. {pyro5-5.16 → pyro5-5.17}/Pyro5/svr_threads.py +7 -9
  15. {pyro5-5.16 → pyro5-5.17}/Pyro5.egg-info/PKG-INFO +6 -2
  16. {pyro5-5.16 → pyro5-5.17}/Pyro5.egg-info/SOURCES.txt +0 -46
  17. {pyro5-5.16 → pyro5-5.17}/Readme.rst +5 -1
  18. {pyro5-5.16 → pyro5-5.17}/examples/distributed-computing3/Readme.txt +1 -1
  19. {pyro5-5.16 → pyro5-5.17}/examples/exceptions/Readme.txt +1 -1
  20. {pyro5-5.16 → pyro5-5.17}/tests/test_core.py +15 -0
  21. {pyro5-5.16 → pyro5-5.17}/tests/test_daemon.py +129 -0
  22. {pyro5-5.16 → pyro5-5.17}/tests/test_naming.py +31 -0
  23. {pyro5-5.16 → pyro5-5.17}/tests/test_serialize.py +51 -0
  24. {pyro5-5.16 → pyro5-5.17}/tests/test_server.py +8 -0
  25. pyro5-5.16/.gitattributes +0 -7
  26. pyro5-5.16/.github/workflows/main-ci.yml +0 -40
  27. pyro5-5.16/Makefile +0 -39
  28. pyro5-5.16/docs/Makefile +0 -130
  29. pyro5-5.16/docs/make.bat +0 -170
  30. pyro5-5.16/docs/source/_static/css/customize.css +0 -14
  31. pyro5-5.16/docs/source/_static/flammable.png +0 -0
  32. pyro5-5.16/docs/source/_static/pyro-large.png +0 -0
  33. pyro5-5.16/docs/source/_static/pyro.png +0 -0
  34. pyro5-5.16/docs/source/_static/tf_pyrotaunt.png +0 -0
  35. pyro5-5.16/docs/source/api/api.rst +0 -6
  36. pyro5-5.16/docs/source/api/callcontext.rst +0 -5
  37. pyro5-5.16/docs/source/api/client.rst +0 -5
  38. pyro5-5.16/docs/source/api/compatibility.rst +0 -5
  39. pyro5-5.16/docs/source/api/config.rst +0 -14
  40. pyro5-5.16/docs/source/api/core.rst +0 -5
  41. pyro5-5.16/docs/source/api/echoserver.rst +0 -5
  42. pyro5-5.16/docs/source/api/errors.rst +0 -24
  43. pyro5-5.16/docs/source/api/httpgateway.rst +0 -5
  44. pyro5-5.16/docs/source/api/nameserver.rst +0 -9
  45. pyro5-5.16/docs/source/api/protocol.rst +0 -13
  46. pyro5-5.16/docs/source/api/server.rst +0 -6
  47. pyro5-5.16/docs/source/api/socketserver.rst +0 -60
  48. pyro5-5.16/docs/source/api/socketutil.rst +0 -5
  49. pyro5-5.16/docs/source/api.rst +0 -24
  50. pyro5-5.16/docs/source/changelog.rst +0 -167
  51. pyro5-5.16/docs/source/clientcode.rst +0 -531
  52. pyro5-5.16/docs/source/commandline.rst +0 -77
  53. pyro5-5.16/docs/source/conf.py +0 -236
  54. pyro5-5.16/docs/source/config.rst +0 -140
  55. pyro5-5.16/docs/source/docutils.conf +0 -2
  56. pyro5-5.16/docs/source/errors.rst +0 -138
  57. pyro5-5.16/docs/source/index.rst +0 -61
  58. pyro5-5.16/docs/source/install.rst +0 -64
  59. pyro5-5.16/docs/source/intro.rst +0 -310
  60. pyro5-5.16/docs/source/license.rst +0 -37
  61. pyro5-5.16/docs/source/nameserver.rst +0 -629
  62. pyro5-5.16/docs/source/pyrolite.rst +0 -15
  63. pyro5-5.16/docs/source/security.rst +0 -126
  64. pyro5-5.16/docs/source/servercode.rst +0 -824
  65. pyro5-5.16/docs/source/tipstricks.rst +0 -738
  66. pyro5-5.16/docs/source/tutorials.rst +0 -198
  67. pyro5-5.16/mypy.ini +0 -10
  68. pyro5-5.16/requirements.txt +0 -1
  69. pyro5-5.16/test-requirements.txt +0 -4
  70. pyro5-5.16/tox.ini +0 -14
  71. {pyro5-5.16 → pyro5-5.17}/LICENSE +0 -0
  72. {pyro5-5.16 → pyro5-5.17}/MANIFEST.in +0 -0
  73. {pyro5-5.16 → pyro5-5.17}/Pyro5/api.py +0 -0
  74. {pyro5-5.16 → pyro5-5.17}/Pyro5/callcontext.py +0 -0
  75. {pyro5-5.16 → pyro5-5.17}/Pyro5/compatibility/Pyro4.py +0 -0
  76. {pyro5-5.16 → pyro5-5.17}/Pyro5/compatibility/__init__.py +0 -0
  77. {pyro5-5.16 → pyro5-5.17}/Pyro5/nsc.py +0 -0
  78. {pyro5-5.16 → pyro5-5.17}/Pyro5/utils/__init__.py +0 -0
  79. {pyro5-5.16 → pyro5-5.17}/Pyro5/utils/echoserver.py +0 -0
  80. {pyro5-5.16 → pyro5-5.17}/Pyro5/utils/httpgateway.py +0 -0
  81. {pyro5-5.16 → pyro5-5.17}/Pyro5.egg-info/dependency_links.txt +0 -0
  82. {pyro5-5.16 → pyro5-5.17}/Pyro5.egg-info/entry_points.txt +0 -0
  83. {pyro5-5.16 → pyro5-5.17}/Pyro5.egg-info/requires.txt +0 -0
  84. {pyro5-5.16 → pyro5-5.17}/Pyro5.egg-info/top_level.txt +0 -0
  85. {pyro5-5.16 → pyro5-5.17}/Pyro5.egg-info/zip-safe +0 -0
  86. {pyro5-5.16 → pyro5-5.17}/certs/client_cert.pem +0 -0
  87. {pyro5-5.16 → pyro5-5.17}/certs/client_key.pem +0 -0
  88. {pyro5-5.16 → pyro5-5.17}/certs/readme.txt +0 -0
  89. {pyro5-5.16 → pyro5-5.17}/certs/server_cert.pem +0 -0
  90. {pyro5-5.16 → pyro5-5.17}/certs/server_key.pem +0 -0
  91. {pyro5-5.16 → pyro5-5.17}/examples/attributes/Readme.txt +0 -0
  92. {pyro5-5.16 → pyro5-5.17}/examples/attributes/client.py +0 -0
  93. {pyro5-5.16 → pyro5-5.17}/examples/attributes/server.py +0 -0
  94. {pyro5-5.16 → pyro5-5.17}/examples/autoproxy/Readme.txt +0 -0
  95. {pyro5-5.16 → pyro5-5.17}/examples/autoproxy/client.py +0 -0
  96. {pyro5-5.16 → pyro5-5.17}/examples/autoproxy/server.py +0 -0
  97. {pyro5-5.16 → pyro5-5.17}/examples/autoproxy/thingy.py +0 -0
  98. {pyro5-5.16 → pyro5-5.17}/examples/autoreconnect/Readme.txt +0 -0
  99. {pyro5-5.16 → pyro5-5.17}/examples/autoreconnect/client.py +0 -0
  100. {pyro5-5.16 → pyro5-5.17}/examples/autoreconnect/clientNS.py +0 -0
  101. {pyro5-5.16 → pyro5-5.17}/examples/autoreconnect/server.py +0 -0
  102. {pyro5-5.16 → pyro5-5.17}/examples/autoreconnect/serverNS.py +0 -0
  103. {pyro5-5.16 → pyro5-5.17}/examples/autoretry/Readme.txt +0 -0
  104. {pyro5-5.16 → pyro5-5.17}/examples/autoretry/client.py +0 -0
  105. {pyro5-5.16 → pyro5-5.17}/examples/autoretry/server.py +0 -0
  106. {pyro5-5.16 → pyro5-5.17}/examples/banks/Readme.txt +0 -0
  107. {pyro5-5.16 → pyro5-5.17}/examples/banks/banks.py +0 -0
  108. {pyro5-5.16 → pyro5-5.17}/examples/banks/client.py +0 -0
  109. {pyro5-5.16 → pyro5-5.17}/examples/banks/server.py +0 -0
  110. {pyro5-5.16 → pyro5-5.17}/examples/batchedcalls/Readme.txt +0 -0
  111. {pyro5-5.16 → pyro5-5.17}/examples/batchedcalls/client.py +0 -0
  112. {pyro5-5.16 → pyro5-5.17}/examples/batchedcalls/server.py +0 -0
  113. {pyro5-5.16 → pyro5-5.17}/examples/benchmark/Readme.txt +0 -0
  114. {pyro5-5.16 → pyro5-5.17}/examples/benchmark/bench.py +0 -0
  115. {pyro5-5.16 → pyro5-5.17}/examples/benchmark/client.py +0 -0
  116. {pyro5-5.16 → pyro5-5.17}/examples/benchmark/connections.py +0 -0
  117. {pyro5-5.16 → pyro5-5.17}/examples/benchmark/server.py +0 -0
  118. {pyro5-5.16 → pyro5-5.17}/examples/blob-dispatch/Readme.txt +0 -0
  119. {pyro5-5.16 → pyro5-5.17}/examples/blob-dispatch/client/client.py +0 -0
  120. {pyro5-5.16 → pyro5-5.17}/examples/blob-dispatch/client/customdata.py +0 -0
  121. {pyro5-5.16 → pyro5-5.17}/examples/blob-dispatch/dispatcher/dispatcher.py +0 -0
  122. {pyro5-5.16 → pyro5-5.17}/examples/blob-dispatch/listeners/customdata.py +0 -0
  123. {pyro5-5.16 → pyro5-5.17}/examples/blob-dispatch/listeners/listener.py +0 -0
  124. {pyro5-5.16 → pyro5-5.17}/examples/blob-dispatch/listeners/main.py +0 -0
  125. {pyro5-5.16 → pyro5-5.17}/examples/callback/Readme.txt +0 -0
  126. {pyro5-5.16 → pyro5-5.17}/examples/callback/client.py +0 -0
  127. {pyro5-5.16 → pyro5-5.17}/examples/callback/client2.py +0 -0
  128. {pyro5-5.16 → pyro5-5.17}/examples/callback/server.py +0 -0
  129. {pyro5-5.16 → pyro5-5.17}/examples/callback/server2.py +0 -0
  130. {pyro5-5.16 → pyro5-5.17}/examples/callcontext/Readme.txt +0 -0
  131. {pyro5-5.16 → pyro5-5.17}/examples/callcontext/client.py +0 -0
  132. {pyro5-5.16 → pyro5-5.17}/examples/callcontext/server.py +0 -0
  133. {pyro5-5.16 → pyro5-5.17}/examples/chatbox/Readme.txt +0 -0
  134. {pyro5-5.16 → pyro5-5.17}/examples/chatbox/client.py +0 -0
  135. {pyro5-5.16 → pyro5-5.17}/examples/chatbox/server.py +0 -0
  136. {pyro5-5.16 → pyro5-5.17}/examples/circular/Readme.txt +0 -0
  137. {pyro5-5.16 → pyro5-5.17}/examples/circular/chain.py +0 -0
  138. {pyro5-5.16 → pyro5-5.17}/examples/circular/client.py +0 -0
  139. {pyro5-5.16 → pyro5-5.17}/examples/circular/servA.py +0 -0
  140. {pyro5-5.16 → pyro5-5.17}/examples/circular/servB.py +0 -0
  141. {pyro5-5.16 → pyro5-5.17}/examples/circular/servC.py +0 -0
  142. {pyro5-5.16 → pyro5-5.17}/examples/custom-serialization/Readme.txt +0 -0
  143. {pyro5-5.16 → pyro5-5.17}/examples/custom-serialization/client.py +0 -0
  144. {pyro5-5.16 → pyro5-5.17}/examples/custom-serialization/mycustomclasses.py +0 -0
  145. {pyro5-5.16 → pyro5-5.17}/examples/custom-serialization/server.py +0 -0
  146. {pyro5-5.16 → pyro5-5.17}/examples/diffie-hellman/Readme.txt +0 -0
  147. {pyro5-5.16 → pyro5-5.17}/examples/diffie-hellman/client.py +0 -0
  148. {pyro5-5.16 → pyro5-5.17}/examples/diffie-hellman/diffiehellman.py +0 -0
  149. {pyro5-5.16 → pyro5-5.17}/examples/diffie-hellman/server.py +0 -0
  150. {pyro5-5.16 → pyro5-5.17}/examples/disconnects/Readme.txt +0 -0
  151. {pyro5-5.16 → pyro5-5.17}/examples/disconnects/client.py +0 -0
  152. {pyro5-5.16 → pyro5-5.17}/examples/disconnects/server.py +0 -0
  153. {pyro5-5.16 → pyro5-5.17}/examples/distributed-computing/Readme.txt +0 -0
  154. {pyro5-5.16 → pyro5-5.17}/examples/distributed-computing/client.py +0 -0
  155. {pyro5-5.16 → pyro5-5.17}/examples/distributed-computing/dispatcher.py +0 -0
  156. {pyro5-5.16 → pyro5-5.17}/examples/distributed-computing/worker.py +0 -0
  157. {pyro5-5.16 → pyro5-5.17}/examples/distributed-computing/workitem.py +0 -0
  158. {pyro5-5.16 → pyro5-5.17}/examples/distributed-computing2/Readme.txt +0 -0
  159. {pyro5-5.16 → pyro5-5.17}/examples/distributed-computing2/alice.zip +0 -0
  160. {pyro5-5.16 → pyro5-5.17}/examples/distributed-computing2/client.py +0 -0
  161. {pyro5-5.16 → pyro5-5.17}/examples/distributed-computing2/servers.py +0 -0
  162. {pyro5-5.16 → pyro5-5.17}/examples/distributed-computing3/client.py +0 -0
  163. {pyro5-5.16 → pyro5-5.17}/examples/distributed-computing3/worker.py +0 -0
  164. {pyro5-5.16 → pyro5-5.17}/examples/distributed-mandelbrot/Readme.txt +0 -0
  165. {pyro5-5.16 → pyro5-5.17}/examples/distributed-mandelbrot/client_asciizoom.py +0 -0
  166. {pyro5-5.16 → pyro5-5.17}/examples/distributed-mandelbrot/client_graphics.py +0 -0
  167. {pyro5-5.16 → pyro5-5.17}/examples/distributed-mandelbrot/launch_servers.sh +0 -0
  168. {pyro5-5.16 → pyro5-5.17}/examples/distributed-mandelbrot/normal.py +0 -0
  169. {pyro5-5.16 → pyro5-5.17}/examples/distributed-mandelbrot/normal_graphics.py +0 -0
  170. {pyro5-5.16 → pyro5-5.17}/examples/distributed-mandelbrot/server.py +0 -0
  171. {pyro5-5.16 → pyro5-5.17}/examples/echoserver/Readme.txt +0 -0
  172. {pyro5-5.16 → pyro5-5.17}/examples/echoserver/client.py +0 -0
  173. {pyro5-5.16 → pyro5-5.17}/examples/eventloop/Readme.txt +0 -0
  174. {pyro5-5.16 → pyro5-5.17}/examples/eventloop/client.py +0 -0
  175. {pyro5-5.16 → pyro5-5.17}/examples/eventloop/server_multiplexed.py +0 -0
  176. {pyro5-5.16 → pyro5-5.17}/examples/eventloop/server_threads.py +0 -0
  177. {pyro5-5.16 → pyro5-5.17}/examples/exceptions/client.py +0 -0
  178. {pyro5-5.16 → pyro5-5.17}/examples/exceptions/excep.py +0 -0
  179. {pyro5-5.16 → pyro5-5.17}/examples/exceptions/server.py +0 -0
  180. {pyro5-5.16 → pyro5-5.17}/examples/filetransfer/Readme.txt +0 -0
  181. {pyro5-5.16 → pyro5-5.17}/examples/filetransfer/client.py +0 -0
  182. {pyro5-5.16 → pyro5-5.17}/examples/filetransfer/server.py +0 -0
  183. {pyro5-5.16 → pyro5-5.17}/examples/gui_eventloop/Readme.txt +0 -0
  184. {pyro5-5.16 → pyro5-5.17}/examples/gui_eventloop/client.py +0 -0
  185. {pyro5-5.16 → pyro5-5.17}/examples/gui_eventloop/gui_nothreads.py +0 -0
  186. {pyro5-5.16 → pyro5-5.17}/examples/gui_eventloop/gui_threads.py +0 -0
  187. {pyro5-5.16 → pyro5-5.17}/examples/handshake/Readme.txt +0 -0
  188. {pyro5-5.16 → pyro5-5.17}/examples/handshake/client.py +0 -0
  189. {pyro5-5.16 → pyro5-5.17}/examples/handshake/server.py +0 -0
  190. {pyro5-5.16 → pyro5-5.17}/examples/http/Readme.txt +0 -0
  191. {pyro5-5.16 → pyro5-5.17}/examples/http/client.js +0 -0
  192. {pyro5-5.16 → pyro5-5.17}/examples/http/client.py +0 -0
  193. {pyro5-5.16 → pyro5-5.17}/examples/hugetransfer/Readme.txt +0 -0
  194. {pyro5-5.16 → pyro5-5.17}/examples/hugetransfer/client.py +0 -0
  195. {pyro5-5.16 → pyro5-5.17}/examples/hugetransfer/server.py +0 -0
  196. {pyro5-5.16 → pyro5-5.17}/examples/instancemode/Readme.txt +0 -0
  197. {pyro5-5.16 → pyro5-5.17}/examples/instancemode/client.py +0 -0
  198. {pyro5-5.16 → pyro5-5.17}/examples/instancemode/server.py +0 -0
  199. {pyro5-5.16 → pyro5-5.17}/examples/maxsize/Readme.txt +0 -0
  200. {pyro5-5.16 → pyro5-5.17}/examples/maxsize/client.py +0 -0
  201. {pyro5-5.16 → pyro5-5.17}/examples/messagebus/Readme.txt +0 -0
  202. {pyro5-5.16 → pyro5-5.17}/examples/messagebus/manytopics_publisher.py +0 -0
  203. {pyro5-5.16 → pyro5-5.17}/examples/messagebus/manytopics_subscriber.py +0 -0
  204. {pyro5-5.16 → pyro5-5.17}/examples/messagebus/messagebus/__init__.py +0 -0
  205. {pyro5-5.16 → pyro5-5.17}/examples/messagebus/messagebus/messagebus.py +0 -0
  206. {pyro5-5.16 → pyro5-5.17}/examples/messagebus/messagebus/server.py +0 -0
  207. {pyro5-5.16 → pyro5-5.17}/examples/messagebus/publisher.py +0 -0
  208. {pyro5-5.16 → pyro5-5.17}/examples/messagebus/subscriber.py +0 -0
  209. {pyro5-5.16 → pyro5-5.17}/examples/messagebus/subscriber_manual_consume.py +0 -0
  210. {pyro5-5.16 → pyro5-5.17}/examples/nameserverstress/Readme.txt +0 -0
  211. {pyro5-5.16 → pyro5-5.17}/examples/nameserverstress/stress.py +0 -0
  212. {pyro5-5.16 → pyro5-5.17}/examples/nonameserver/Readme.txt +0 -0
  213. {pyro5-5.16 → pyro5-5.17}/examples/nonameserver/client.py +0 -0
  214. {pyro5-5.16 → pyro5-5.17}/examples/nonameserver/server.py +0 -0
  215. {pyro5-5.16 → pyro5-5.17}/examples/ns-metadata/Readme.txt +0 -0
  216. {pyro5-5.16 → pyro5-5.17}/examples/ns-metadata/example.py +0 -0
  217. {pyro5-5.16 → pyro5-5.17}/examples/ns-metadata/resources.py +0 -0
  218. {pyro5-5.16 → pyro5-5.17}/examples/oneway/Readme.txt +0 -0
  219. {pyro5-5.16 → pyro5-5.17}/examples/oneway/client.py +0 -0
  220. {pyro5-5.16 → pyro5-5.17}/examples/oneway/client2.py +0 -0
  221. {pyro5-5.16 → pyro5-5.17}/examples/oneway/server.py +0 -0
  222. {pyro5-5.16 → pyro5-5.17}/examples/oneway/server2.py +0 -0
  223. {pyro5-5.16 → pyro5-5.17}/examples/privilege-separation/Readme.txt +0 -0
  224. {pyro5-5.16 → pyro5-5.17}/examples/privilege-separation/drop_privs_client.py +0 -0
  225. {pyro5-5.16 → pyro5-5.17}/examples/privilege-separation/drop_privs_server.py +0 -0
  226. {pyro5-5.16 → pyro5-5.17}/examples/privilege-separation/elevated_client.py +0 -0
  227. {pyro5-5.16 → pyro5-5.17}/examples/privilege-separation/elevated_server.py +0 -0
  228. {pyro5-5.16 → pyro5-5.17}/examples/resourcetracking/Readme.txt +0 -0
  229. {pyro5-5.16 → pyro5-5.17}/examples/resourcetracking/client.py +0 -0
  230. {pyro5-5.16 → pyro5-5.17}/examples/resourcetracking/server.py +0 -0
  231. {pyro5-5.16 → pyro5-5.17}/examples/robots/Readme.txt +0 -0
  232. {pyro5-5.16 → pyro5-5.17}/examples/robots/client.py +0 -0
  233. {pyro5-5.16 → pyro5-5.17}/examples/robots/gameserver.py +0 -0
  234. {pyro5-5.16 → pyro5-5.17}/examples/robots/remote.py +0 -0
  235. {pyro5-5.16 → pyro5-5.17}/examples/robots/robot.py +0 -0
  236. {pyro5-5.16 → pyro5-5.17}/examples/servertypes/Readme.txt +0 -0
  237. {pyro5-5.16 → pyro5-5.17}/examples/servertypes/client.py +0 -0
  238. {pyro5-5.16 → pyro5-5.17}/examples/servertypes/server.py +0 -0
  239. {pyro5-5.16 → pyro5-5.17}/examples/shoppingcart/Readme.txt +0 -0
  240. {pyro5-5.16 → pyro5-5.17}/examples/shoppingcart/clients.py +0 -0
  241. {pyro5-5.16 → pyro5-5.17}/examples/shoppingcart/shoppingcart.py +0 -0
  242. {pyro5-5.16 → pyro5-5.17}/examples/shoppingcart/shopserver.py +0 -0
  243. {pyro5-5.16 → pyro5-5.17}/examples/socketpair/pair-fork.py +0 -0
  244. {pyro5-5.16 → pyro5-5.17}/examples/socketpair/pair-thread.py +0 -0
  245. {pyro5-5.16 → pyro5-5.17}/examples/socketpair/readme.txt +0 -0
  246. {pyro5-5.16 → pyro5-5.17}/examples/ssl/Readme.txt +0 -0
  247. {pyro5-5.16 → pyro5-5.17}/examples/ssl/client.py +0 -0
  248. {pyro5-5.16 → pyro5-5.17}/examples/ssl/server.py +0 -0
  249. {pyro5-5.16 → pyro5-5.17}/examples/stockquotes/Readme.txt +0 -0
  250. {pyro5-5.16 → pyro5-5.17}/examples/stockquotes/phase1/stockmarket.py +0 -0
  251. {pyro5-5.16 → pyro5-5.17}/examples/stockquotes/phase1/viewer.py +0 -0
  252. {pyro5-5.16 → pyro5-5.17}/examples/stockquotes/phase2/stockmarket.py +0 -0
  253. {pyro5-5.16 → pyro5-5.17}/examples/stockquotes/phase2/viewer.py +0 -0
  254. {pyro5-5.16 → pyro5-5.17}/examples/stockquotes/phase3/stockmarket.py +0 -0
  255. {pyro5-5.16 → pyro5-5.17}/examples/stockquotes/phase3/viewer.py +0 -0
  256. {pyro5-5.16 → pyro5-5.17}/examples/streaming/Readme.txt +0 -0
  257. {pyro5-5.16 → pyro5-5.17}/examples/streaming/client.py +0 -0
  258. {pyro5-5.16 → pyro5-5.17}/examples/streaming/server.py +0 -0
  259. {pyro5-5.16 → pyro5-5.17}/examples/thirdpartylib/Readme.txt +0 -0
  260. {pyro5-5.16 → pyro5-5.17}/examples/thirdpartylib/awesome_thirdparty_library.py +0 -0
  261. {pyro5-5.16 → pyro5-5.17}/examples/thirdpartylib/client.py +0 -0
  262. {pyro5-5.16 → pyro5-5.17}/examples/thirdpartylib/server.py +0 -0
  263. {pyro5-5.16 → pyro5-5.17}/examples/thirdpartylib/server2.py +0 -0
  264. {pyro5-5.16 → pyro5-5.17}/examples/threadproxysharing/Readme.txt +0 -0
  265. {pyro5-5.16 → pyro5-5.17}/examples/threadproxysharing/client.py +0 -0
  266. {pyro5-5.16 → pyro5-5.17}/examples/timeout/Readme.txt +0 -0
  267. {pyro5-5.16 → pyro5-5.17}/examples/timeout/client.py +0 -0
  268. {pyro5-5.16 → pyro5-5.17}/examples/timeout/server.py +0 -0
  269. {pyro5-5.16 → pyro5-5.17}/examples/timezones/Readme.txt +0 -0
  270. {pyro5-5.16 → pyro5-5.17}/examples/timezones/client.py +0 -0
  271. {pyro5-5.16 → pyro5-5.17}/examples/timezones/server.py +0 -0
  272. {pyro5-5.16 → pyro5-5.17}/examples/unixdomainsock/Readme.txt +0 -0
  273. {pyro5-5.16 → pyro5-5.17}/examples/unixdomainsock/abstract_namespace_server.py +0 -0
  274. {pyro5-5.16 → pyro5-5.17}/examples/unixdomainsock/client.py +0 -0
  275. {pyro5-5.16 → pyro5-5.17}/examples/unixdomainsock/server.py +0 -0
  276. {pyro5-5.16 → pyro5-5.17}/examples/usersession/Readme.txt +0 -0
  277. {pyro5-5.16 → pyro5-5.17}/examples/usersession/client.py +0 -0
  278. {pyro5-5.16 → pyro5-5.17}/examples/usersession/database.py +0 -0
  279. {pyro5-5.16 → pyro5-5.17}/examples/usersession/server.py +0 -0
  280. {pyro5-5.16 → pyro5-5.17}/examples/warehouse/Readme.txt +0 -0
  281. {pyro5-5.16 → pyro5-5.17}/examples/warehouse/phase1/person.py +0 -0
  282. {pyro5-5.16 → pyro5-5.17}/examples/warehouse/phase1/visit.py +0 -0
  283. {pyro5-5.16 → pyro5-5.17}/examples/warehouse/phase1/warehouse.py +0 -0
  284. {pyro5-5.16 → pyro5-5.17}/examples/warehouse/phase2/person.py +0 -0
  285. {pyro5-5.16 → pyro5-5.17}/examples/warehouse/phase2/visit.py +0 -0
  286. {pyro5-5.16 → pyro5-5.17}/examples/warehouse/phase2/warehouse.py +0 -0
  287. {pyro5-5.16 → pyro5-5.17}/examples/warehouse/phase3/person.py +0 -0
  288. {pyro5-5.16 → pyro5-5.17}/examples/warehouse/phase3/visit.py +0 -0
  289. {pyro5-5.16 → pyro5-5.17}/examples/warehouse/phase3/warehouse.py +0 -0
  290. {pyro5-5.16 → pyro5-5.17}/setup.cfg +0 -0
  291. {pyro5-5.16 → pyro5-5.17}/setup.py +0 -0
  292. {pyro5-5.16 → pyro5-5.17}/tests/support.py +0 -0
  293. {pyro5-5.16 → pyro5-5.17}/tests/test_api.py +0 -0
  294. {pyro5-5.16 → pyro5-5.17}/tests/test_client.py +0 -0
  295. {pyro5-5.16 → pyro5-5.17}/tests/test_echoserver.py +0 -0
  296. {pyro5-5.16 → pyro5-5.17}/tests/test_errors.py +0 -0
  297. {pyro5-5.16 → pyro5-5.17}/tests/test_httpgateway.py +0 -0
  298. {pyro5-5.16 → pyro5-5.17}/tests/test_protocol.py +0 -0
  299. {pyro5-5.16 → pyro5-5.17}/tests/test_pyro4compat.py +0 -0
  300. {pyro5-5.16 → pyro5-5.17}/tests/test_server_timeout.py +0 -0
  301. {pyro5-5.16 → pyro5-5.17}/tests/test_socketutil.py +0 -0
  302. {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.16
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 Python 3.9 and newer, and Pypy3
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.
@@ -4,7 +4,7 @@ Pyro package. Some generic init stuff to set up logging etc.
4
4
  Pyro - Python Remote Objects. Copyright by Irmen de Jong (irmen@razorvine.net).
5
5
  """
6
6
 
7
- __version__ = "5.16"
7
+ __version__ = "5.17"
8
8
  __author__ = "Irmen de Jong"
9
9
 
10
10
 
@@ -88,7 +88,7 @@ class Proxy(object):
88
88
  def __del__(self):
89
89
  if hasattr(self, "_pyroConnection"):
90
90
  try:
91
- self._pyroRelease()
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
- raise data # if you see this in your traceback, you should probably inspect the remote traceback as well
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(conn):
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
- conn = socketutil.SocketConnection(sock, uri.object)
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(conn)
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)
@@ -93,6 +93,8 @@ class Configuration:
93
93
  envvalue = True
94
94
  else:
95
95
  raise ValueError("invalid boolean value: %s%s=%s" % (prefix, item, envvalue))
96
+ elif valuetype is type(None):
97
+ envvalue = str(envvalue)
96
98
  else:
97
99
  try:
98
100
  envvalue = valuetype(envvalue)
@@ -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
- raise self.exception
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
- try:
219
- socket.gethostbyaddr("127.0.1.1")
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
- for _ in range(3):
240
- try:
241
- for bcaddr in config.BROADCAST_ADDRS:
242
- try:
243
- sock.sendto(b"GET_NSURI", 0, (bcaddr, port))
244
- except socket.error as x:
245
- err = getattr(x, "errno", x.args[0])
246
- # handle some errno's that some platforms like to throw:
247
- if err not in socketutil.ERRNO_EADDRNOTAVAIL and err not in socketutil.ERRNO_EADDRINUSE:
248
- raise
249
- data, _ = sock.recvfrom(100)
250
- sock.close()
251
- text = data.decode("iso-8859-1")
252
- log.debug("located NS: %s", text)
253
- proxy = client.Proxy(text)
254
- return proxy
255
- except socket.timeout:
256
- continue
257
- with contextlib.suppress(OSError, socket.error):
258
- sock.shutdown(socket.SHUT_RDWR)
259
- sock.close()
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 occured remotely (Pyro) - Remote traceback:"]
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 or frozenset()))
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 in self.storage and name != core.NAMESERVER_NAME:
336
+ if name and name != core.NAMESERVER_NAME:
337
337
  with self.lock:
338
- del self.storage[name]
339
- return 1
338
+ if name in self.storage:
339
+ del self.storage[name]
340
+ return 1
341
+ return 0
340
342
  if prefix:
341
- items = list(self.list(prefix=prefix).keys())
342
- if core.NAMESERVER_NAME in items:
343
- items.remove(core.NAMESERVER_NAME)
344
- self.storage.remove_items(items)
345
- return len(items)
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
- items = list(self.list(regex=regex).keys())
348
- if core.NAMESERVER_NAME in items:
349
- items.remove(core.NAMESERVER_NAME)
350
- self.storage.remove_items(items)
351
- return len(items)
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([8 + len(v) for v in annotations.values()])
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
- header_data = struct.pack(_header_format, b"PYRO", PROTOCOL_VERSION, msgtype, serializer_id, flags, seq,
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
- assert i == self.annotations_size
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
- (text, msg.type, msg.flags, msg.serializer_id, msg.seq, num_anns, corr_id, bytes(msg.data)))
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: " + classname)
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.split(":")[1])
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" % protocol.PROTOCOL_VERSION)
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
- if config.ITER_STREAM_LINGER > 0:
528
- # client goes away, keep streams around for a bit longer (allow reconnect)
529
- for streamId in list(self.streaming_responses):
530
- info = self.streaming_responses.get(streamId, None)
531
- if info and info[0] is conn:
532
- _, timestamp, _, stream = info
533
- self.streaming_responses[streamId] = (None, timestamp, time.time(), stream)
534
- else:
535
- # client goes away, close any streams it had open as well
536
- for streamId in list(self.streaming_responses):
537
- info = self.streaming_responses.get(streamId, None)
538
- if info and info[0] is conn:
539
- del self.streaming_responses[streamId]
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={} method={} exception={}"
863
- .format(client_sock, method.__qualname__, repr(exception)))
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
- return get_interface("4.2.2.2").ip
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
- err = ConnectionClosedError("receiving: not enough data")
158
- err.partialData = data # store the message that was received until now
159
- raise err
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 " + str(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" % x)
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: " + str(x))
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" % x)
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" % x)
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
- with _client_disconnect_lock:
60
- try:
61
- self.daemon._clientDisconnect(self.csock)
62
- except Exception as x:
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: " + reason)
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.16
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 Python 3.9 and newer, and Pypy3
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