Hello community, here is the log from the commit of package python-Pyro4 for openSUSE:Factory checked in at 2019-03-19 09:58:09 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-Pyro4 (Old) and /work/SRC/openSUSE:Factory/.python-Pyro4.new.28833 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-Pyro4" Tue Mar 19 09:58:09 2019 rev:4 rq:682266 version:4.75 Changes: -------- --- /work/SRC/openSUSE:Factory/python-Pyro4/python-Pyro4.changes 2019-01-24 14:03:11.700066573 +0100 +++ /work/SRC/openSUSE:Factory/.python-Pyro4.new.28833/python-Pyro4.changes 2019-03-19 09:58:11.808107676 +0100 @@ -1,0 +2,12 @@ +Wed Mar 6 09:29:20 UTC 2019 - Tomáš Chvátal <[email protected]> + +- Update to 4.75: + * include LICENSE file in distribution + * avoid decode error when dealing with memoryview annotations + * serpent 1.27 required to avoid regression in previous version + * fixed marshal serializer problem that prevented it to even call register() in the name server. + * msgpack, json and marshal serializers now understand how to serialize array.array the same way serpent already did + * fixed distributed-mandelbrot example to actually run multiple concurrent calculations. + * missing API method doc added on NameServer.count() + +------------------------------------------------------------------- Old: ---- Pyro4-4.72.tar.gz New: ---- Pyro4-4.75.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-Pyro4.spec ++++++ --- /var/tmp/diff_new_pack.coxbTU/_old 2019-03-19 09:58:12.956107215 +0100 +++ /var/tmp/diff_new_pack.coxbTU/_new 2019-03-19 09:58:12.996107198 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-Pyro4 # -# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,36 +18,36 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-Pyro4 -Version: 4.72 +Version: 4.75 Release: 0 Summary: Distributed object middleware for Python (RPC) License: MIT Group: Development/Languages/Python -Url: https://github.com/irmen/Pyro4 +URL: https://github.com/irmen/Pyro4 Source: https://files.pythonhosted.org/packages/source/P/Pyro4/Pyro4-%{version}.tar.gz BuildRequires: %{python_module setuptools} BuildRequires: fdupes BuildRequires: python-rpm-macros +Requires: python-serpent >= 1.27 +Requires(post): update-alternatives +Requires(postun): update-alternatives +Recommends: ca-certificates +Recommends: python-cloudpickle >= 0.4.0 +Recommends: python-dill >= 0.2.6 +Recommends: python-msgpack-python >= 0.5.2 +BuildArch: noarch # SECTION test requirements BuildRequires: %{python_module cloudpickle >= 0.4.0} BuildRequires: %{python_module dill >= 0.2.6} -BuildRequires: %{python_module msgpack-python >= 0.4.6} -BuildRequires: %{python_module serpent >= 1.24} +BuildRequires: %{python_module msgpack-python >= 0.5.2} +BuildRequires: %{python_module pytest} +BuildRequires: %{python_module serpent >= 1.27} BuildRequires: ca-certificates BuildRequires: python-selectors34 # /SECTION -Requires: python-serpent >= 1.24 -Recommends: ca-certificates -Recommends: python-cloudpickle >= 0.4.0 -Recommends: python-dill >= 0.2.6 -Recommends: python-msgpack-python >= 0.4.6 %ifpython2 Requires: python-selectors34 %endif -BuildArch: noarch -Requires(post): update-alternatives -Requires(postun): update-alternatives - %python_subpackages %description @@ -61,10 +61,8 @@ building distributed applications. Pyro is a pure Python library and runs on many different platforms and Python versions. - %prep %setup -q -n Pyro4-%{version} -sed -i 's/\r$//' LICENSE %build %python_build @@ -79,6 +77,27 @@ %python_clone -a %{buildroot}%{_bindir}/pyro4-nsc %python_clone -a %{buildroot}%{_bindir}/pyro4-test-echoserver +%check +# testContextAndSock missing cert fixtures https://github.com/irmen/Pyro4/issues/216 +# socket tests require at least lo interface thus skip them +skip="testContextAndSock" +skip+=" or testGetIP or testAutoClean" +skip+=" or testBroadcast or testBCstart" +skip+=" or testStartNSfunc or testStartNSfunc" +skip+=" or testResolveWrongHmac" +skip+=" or testResolveAsymmetricHmacUsage" +skip+=" or testResolve" +skip+=" or testPyroname" +skip+=" or testLookupAndRegister" +skip+=" or testBCLookup0000" +skip+=" or testRefuseDottedNames" +skip+=" or testMulti" +skip+=" or testLookupUnixsockParsing" +skip+=" or testLookupInvalidHmac" +skip+=" or testLookupAndRegister" +skip+=" or testDaemonPyroObj" +%python_expand PYTHONPATH=%{buildroot}%{$python_sitelib}:./tests/PyroTests py.test-%{$python_bin_suffix} -v -k "not ($skip)" + %post %{python_install_alternative pyro4-check-config pyro4-flameserver pyro4-httpgateway pyro4-ns pyro4-nsc pyro4-test-echoserver} ++++++ Pyro4-4.72.tar.gz -> Pyro4-4.75.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pyro4-4.72/MANIFEST.in new/Pyro4-4.75/MANIFEST.in --- old/Pyro4-4.72/MANIFEST.in 2018-05-16 21:14:37.000000000 +0200 +++ new/Pyro4-4.75/MANIFEST.in 2018-08-16 09:50:01.000000000 +0200 @@ -1,5 +1,7 @@ include LICENSE include MANIFEST.in +include README.md +include tox.ini recursive-include tests * recursive-include examples * recursive-include docs * diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pyro4-4.72/PKG-INFO new/Pyro4-4.75/PKG-INFO --- old/Pyro4-4.72/PKG-INFO 2018-05-16 21:22:35.000000000 +0200 +++ new/Pyro4-4.75/PKG-INFO 2019-01-19 13:16:41.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: Pyro4 -Version: 4.72 +Version: 4.75 Summary: distributed object middleware for Python (RPC) Home-page: http://pyro4.readthedocs.io Author: Irmen de Jong diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pyro4-4.72/README.md new/Pyro4-4.75/README.md --- old/Pyro4-4.72/README.md 1970-01-01 01:00:00.000000000 +0100 +++ new/Pyro4-4.75/README.md 2018-09-04 00:11:22.000000000 +0200 @@ -0,0 +1,29 @@ +[](https://saythanks.io/to/irmen) +[](https://travis-ci.org/irmen/Pyro4) +[](https://pypi.python.org/pypi/Pyro4/) +[](https://anaconda.org/conda-forge/pyro4) +[](https://lgtm.com/projects/g/irmen/Pyro4/context:python) +[](https://lgtm.com/projects/g/irmen/Pyro4/alerts) + +PYRO - Python Remote Objects +============================ + +Pyro enables you to build applications in which objects can talk +to each other over the network, with minimal programming effort. +You can just use normal Python method calls to call objects on +other machines. Pyro is a pure Python library so it +runs on many different platforms and Python versions. + + +Documentation can be found online at: http://pyro4.readthedocs.io +(or unformatted here in the repo at: docs/source/intro.rst) + + +This software is copyright (c) by Irmen de Jong ([email protected]). + +This software is released under the MIT software license. +This license, including disclaimer, is available in the 'LICENSE' file. + + +---- +_Are you interested in the most recent cutting edge Pyro version? Go try out Pyro5! https://github.com/irmen/Pyro5_ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pyro4-4.72/docs/source/_static/css/customize.css new/Pyro4-4.75/docs/source/_static/css/customize.css --- old/Pyro4-4.72/docs/source/_static/css/customize.css 1970-01-01 01:00:00.000000000 +0100 +++ new/Pyro4-4.75/docs/source/_static/css/customize.css 2018-09-04 00:08:33.000000000 +0200 @@ -0,0 +1,14 @@ +.wy-nav-content { + max-width: 1000px; +} + +/* override table width restrictions */ +.wy-table-responsive table td, .wy-table-responsive table th { + white-space: normal; +} + +.wy-table-responsive { + margin-bottom: 24px; + max-width: 100%; + overflow: visible; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pyro4-4.72/docs/source/changelog.rst new/Pyro4-4.75/docs/source/changelog.rst --- old/Pyro4-4.72/docs/source/changelog.rst 2018-05-16 21:14:37.000000000 +0200 +++ new/Pyro4-4.75/docs/source/changelog.rst 2019-01-19 13:14:23.000000000 +0100 @@ -2,6 +2,28 @@ Change Log ********** +**Pyro 4.75** + +- fixed distributed-mandelbrot example to actually run multiple concurrent calculations. +- CI build process now using more modern Python versions. +- missing API method doc added on NameServer.count() + + +**Pyro 4.74** + +- serpent 1.27 required to avoid regression in previous version +- fixed marshal serializer problem that prevented it to even call register() in the name server. + Its dumpsCall is now able to use the class_to_dict conversion for unmarshallable types + (in simple situations, not recursively). Previously, you would get a ValueError: unmarshallable object. +- msgpack, json and marshal serializers now understand how to serialize array.array the same way serpent already did + + +**Pyro 4.73** + +- include LICENSE file in distribution +- avoid decode error when dealing with memoryview annotations + + **Pyro 4.72** - (source files: normalized line endings to LF) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pyro4-4.72/docs/source/clientcode.rst new/Pyro4-4.75/docs/source/clientcode.rst --- old/Pyro4-4.72/docs/source/clientcode.rst 2018-05-16 21:14:37.000000000 +0200 +++ new/Pyro4-4.75/docs/source/clientcode.rst 2018-08-16 09:50:01.000000000 +0200 @@ -216,9 +216,12 @@ Changing the way your custom classes are (de)serialized ------------------------------------------------------- -.. note:: - The information in this paragraph is not relevant when using the pickle, cloudpickle or dill serialization protocols, - they have their own ways of serializing custom classes. +.. sidebar:: + Applicability + + The information in this paragraph does not apply to the pickle, cloudpickle or dill serialization protocols. + They have their own ways of serializing custom classes. + By default, custom classes are serialized into a dict. They are not deserialized back into instances of your custom class. This avoids possible security issues. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pyro4-4.72/docs/source/conf.py new/Pyro4-4.75/docs/source/conf.py --- old/Pyro4-4.72/docs/source/conf.py 2018-05-16 21:14:37.000000000 +0200 +++ new/Pyro4-4.75/docs/source/conf.py 2018-09-04 00:09:27.000000000 +0200 @@ -229,6 +229,8 @@ ] def setup(app): + # add custom css + app.add_stylesheet("css/customize.css") from sphinx.ext.autodoc import cut_lines # skip the copyright line in every module docstring (last line of docstring) app.connect('autodoc-process-docstring', cut_lines(pre=0, post=1, what=['module'])) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pyro4-4.72/docs/source/index.rst new/Pyro4-4.75/docs/source/index.rst --- old/Pyro4-4.72/docs/source/index.rst 2018-05-16 21:14:37.000000000 +0200 +++ new/Pyro4-4.75/docs/source/index.rst 2018-09-04 00:37:46.000000000 +0200 @@ -20,11 +20,10 @@ Pyro can be found on Pypi as `Pyro4 <http://pypi.python.org/pypi/Pyro4/>`_. Source on Github: https://github.com/irmen/Pyro4 -Contents --------- .. toctree:: :maxdepth: 2 + :caption: Contents of this manual: intro.rst install.rst diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pyro4-4.72/docs/source/install.rst new/Pyro4-4.75/docs/source/install.rst --- old/Pyro4-4.72/docs/source/install.rst 2018-05-16 21:14:37.000000000 +0200 +++ new/Pyro4-4.75/docs/source/install.rst 2018-08-16 09:50:01.000000000 +0200 @@ -62,7 +62,7 @@ Third party libraries that Pyro4 uses ------------------------------------- -`serpent <https://pypi.python.org/pypi/serpent>`_ - required, 1.24 or newer +`serpent <https://pypi.python.org/pypi/serpent>`_ - required, 1.27 or newer Should be installed automatically when you install Pyro4. `selectors34 <https://pypi.python.org/pypi/selectors34>`_ - required on Python 3.3 or older diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pyro4-4.72/docs/source/servercode.rst new/Pyro4-4.75/docs/source/servercode.rst --- old/Pyro4-4.72/docs/source/servercode.rst 2018-05-16 21:14:37.000000000 +0200 +++ new/Pyro4-4.75/docs/source/servercode.rst 2018-08-16 09:50:01.000000000 +0200 @@ -44,14 +44,13 @@ and decorate that with ``@expose``, if you want to provide a remotely accessible attribute. - classes as a whole (exposing a class has the effect of exposing every nonprivate method and property of the class automatically) -.. sidebar:: private members +Anything that isn't decorated with ``@expose`` is not remotely accessible. +.. important:: **Private methods and attributes**: In the spirit of being secure by default, Pyro doesn't allow remote access to anything of your class unless - explicitly told to do so. It will never allow remote access to 'private' members - (where private means that the name starts with a single or double underscore, - with a special exception for the regular 'dunder' names with double underscores such as ``__len__``) - -Anything that isn't decorated with ``@expose`` is not remotely accessible. + explicitly told to do so. It will never allow remote access to 'private' methods and attributes + (where 'private' means that their name starts with a single or double underscore). + There's a special exception for the regular 'dunder' names with double underscores such as ``__len__`` though. Here's a piece of example code that shows how a partially exposed Pyro class may look like:: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pyro4-4.72/examples/batchedcalls/client.py new/Pyro4-4.75/examples/batchedcalls/client.py --- old/Pyro4-4.72/examples/batchedcalls/client.py 2018-05-16 21:14:37.000000000 +0200 +++ new/Pyro4-4.75/examples/batchedcalls/client.py 2018-08-16 09:50:01.000000000 +0200 @@ -99,6 +99,6 @@ divisor -= 1 # this will raise the proper zerodivision exception once we're about # to process the batch result from the divide by 0 call. -except Exception: - print("An error occurred during the batch! (expected)") +except ZeroDivisionError: + print("A divide by zero error occurred during the batch! (expected)") print("".join(getPyroTraceback())) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pyro4-4.72/examples/blob-dispatch/Readme.txt new/Pyro4-4.75/examples/blob-dispatch/Readme.txt --- old/Pyro4-4.72/examples/blob-dispatch/Readme.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/Pyro4-4.75/examples/blob-dispatch/Readme.txt 2018-08-16 09:50:01.000000000 +0200 @@ -0,0 +1,15 @@ +This shows how you can pass through serialized arguments unchanged via Pyro4.core.SerializedBlob. +The idea is that you tell Pyro to NOT serialize/deserialize particular message contents, +because you'll be doing that yourself once it reaches the destination. This avoids a lot of +serializer overhead (which is quite expensive). + +This way it is possible to make efficient dispatchers/proxies/routing services for Pyro, +where only the actual receiving server at the end, deserializes the package once. + + +Run this example by: + +- make sure a Pyro name server is running. +- start a dispatcher from the dispatcher directory +- start one or more listeners from listeners/main.py +- start the client. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pyro4-4.72/examples/distributed-mandelbrot/Readme.txt new/Pyro4-4.75/examples/distributed-mandelbrot/Readme.txt --- old/Pyro4-4.72/examples/distributed-mandelbrot/Readme.txt 2018-05-16 21:14:37.000000000 +0200 +++ new/Pyro4-4.75/examples/distributed-mandelbrot/Readme.txt 2018-10-30 01:24:47.000000000 +0100 @@ -1,8 +1,13 @@ These examples are about calculating the Mandelbrot fractal set (z=z^2+c). + +NOTE: use the "launch_servers.sh" shell script to launch the name server + and a reasonable number of Pyro mandelbrot server processes. + + First, a few notes: - The ascii animation runs at 100x40 resolution so make sure your console window is large enough. -- The maximum iteration count is set to a quite high value to make the calculcations +- The maximum iteration count is set to a quite high value to make the calculations more time consuming. If you want you can change both maxiter values in server.py down to something more reasonable such as 256. - try using Pypy instead of CPython to improve the speed dramatically @@ -10,8 +15,6 @@ The 'normal' code simply runs the calculation in a single Python process. It calculates every frame of the animation in one go and prints it to the screen. -On my computer it runs at about 2.5 frames per second using CPython 3.5 -This is in a windows console and will only use one CPU core. The 'client_asciizoom' program uses Pyro to offload the calculations to whatever @@ -23,15 +26,10 @@ will just call every server once per frame. The calls will return a bunch of resulting lines that are merged into the final animation frame, which is then printed to the screen. -On my machine with 4 cpu cores, when starting 4 mandelbrot servers using CPython 3.5, -the animation now runs at about 7 fps instead of the previous 2.5. It uses all 4 cores of the machine -at about 80% load. I guess the rest is I/O time spent printing the frames to the console -(something that is not fast on windows). +The graphics version is interesting too because it actually creates a nice picture! -The graphics version is interesting too because it actually creates a nice picture! -The single core normal version takes 84 seconds on my machine. The Pyro -version only takes 22 seconds, when using 4 mandelbrot calculation servers. -It uses all 4 cores at nearly 100%, and indeed is almost 4 times faster. -It submits a single line to a mandelbrot server per call. +On my 8c/16t cpu the speedup of the distributed calculation of the graphical picture +is massive. The normal single core version takes 22 seconds, while the distributed version +only takes 2.6 seconds (and utilizes all cores of the cpu for nearly 100%). diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pyro4-4.72/examples/distributed-mandelbrot/client_graphics.py new/Pyro4-4.75/examples/distributed-mandelbrot/client_graphics.py --- old/Pyro4-4.72/examples/distributed-mandelbrot/client_graphics.py 2018-05-16 21:14:37.000000000 +0200 +++ new/Pyro4-4.75/examples/distributed-mandelbrot/client_graphics.py 2018-10-30 01:24:09.000000000 +0100 @@ -1,15 +1,8 @@ # mandelbrot fractal, z=z^2+c -from __future__ import print_function, division import time -try: - from queue import Queue, Empty -except ImportError: - from Queue import Queue, Empty -try: - import tkinter -except ImportError: - import Tkinter as tkinter -import Pyro4 +import tkinter +from concurrent import futures +from Pyro4 import Proxy, locateNS res_x = 1000 @@ -19,62 +12,40 @@ class MandelWindow(object): def __init__(self): self.root = tkinter.Tk() - self.root.title("Mandelbrot (Pyro multi core version)") + self.root.title("Mandelbrot (Pyro multi CPU core version)") canvas = tkinter.Canvas(self.root, width=res_x, height=res_y, bg="#000000") canvas.pack() self.img = tkinter.PhotoImage(width=res_x, height=res_y) canvas.create_image((res_x/2, res_y/2), image=self.img, state="normal") - with Pyro4.locateNS() as ns: + with locateNS() as ns: mandels = ns.list(metadata_any={"class:mandelbrot_calc_color"}) mandels = list(mandels.items()) print("{0} mandelbrot calculation servers found.".format(len(mandels))) if not mandels: raise ValueError("launch at least one mandelbrot calculation server before starting this") - self.mandels = [Pyro4.Proxy(uri) for _, uri in mandels] - for m in self.mandels: - m._pyroAsync() # set them to asynchronous mode - for proxy in self.mandels: - proxy._pyroBind() - self.lines = list(reversed(range(res_y))) - self.draw_data = Queue() - self.root.after(1000, self.draw_lines) + self.mandels = [uri for _, uri in mandels] + self.pool = futures.ThreadPoolExecutor(max_workers=len(self.mandels)) + self.tasks = [] + self.start_time = time.time() + for line in range(res_y): + self.tasks.append(self.calc_new_line(line)) + self.root.after(100, self.draw_results) tkinter.mainloop() - def draw_lines(self): - # start by putting each of the found servers to work on a single line, - # the other lines will be done in turn when the results come back. - for _ in range(len(self.mandels)): - self.calc_new_line() - self.start_time = time.time() - self.draw_results() - def draw_results(self): - # we do the drawing of the results in the gui main thread - # otherwise strange things may happen such as freezes - try: - while True: - y, pixeldata = self.draw_data.get(block=False) - if pixeldata: - self.img.put(pixeldata, (0, y)) - else: - # end reached - duration = time.time() - self.start_time - print("Calculation took: %.2f seconds" % duration) - break - except Empty: - self.root.after(100, self.draw_results) - - def calc_new_line(self): - y = self.lines.pop() - server = self.mandels[y % len(self.mandels)] # round robin server selection - server.calc_photoimage_line(y, res_x, res_y).then(self.process_result) - - def process_result(self, result): - self.draw_data.put(result) # drawing should be done by the main gui thread - if self.lines: - self.calc_new_line() - else: - self.draw_data.put((None, None)) # end-sentinel + for task in futures.as_completed(self.tasks): + y, pixeldata = task.result() + self.img.put(pixeldata, (0, y)) + self.root.update() + duration = time.time() - self.start_time + print("Calculation took: %.2f seconds" % duration) + + def calc_new_line(self, y): + def line_task(server_uri, y): + with Proxy(server_uri) as calcproxy: + return calcproxy.calc_photoimage_line(y, res_x, res_y) + uri = self.mandels[y % len(self.mandels)] # round robin server selection + return self.pool.submit(line_task, uri, y) if __name__ == "__main__": diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pyro4-4.72/examples/distributed-mandelbrot/launch_servers.sh new/Pyro4-4.75/examples/distributed-mandelbrot/launch_servers.sh --- old/Pyro4-4.72/examples/distributed-mandelbrot/launch_servers.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/Pyro4-4.75/examples/distributed-mandelbrot/launch_servers.sh 2018-10-30 01:21:29.000000000 +0100 @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +python -m Pyro4.naming & +sleep 0.5 + +NUM_CPUS=$(python -c "import os; print(os.cpu_count())") + +echo "Launching ${NUM_CPUS} mandelbrot server processes..." +for id in $(seq 1 ${NUM_CPUS}) +do + python server.py ${id} & +done + +sleep 1 +echo "" +echo "Now start a client." diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pyro4-4.72/examples/distributed-mandelbrot/server.py new/Pyro4-4.75/examples/distributed-mandelbrot/server.py --- old/Pyro4-4.72/examples/distributed-mandelbrot/server.py 2018-05-16 21:14:37.000000000 +0200 +++ new/Pyro4-4.75/examples/distributed-mandelbrot/server.py 2018-10-30 01:18:48.000000000 +0100 @@ -1,18 +1,8 @@ from __future__ import print_function, division -import math +import sys import Pyro4 -# A note about the abs(z) calls below not using abs(z), -# but instead squaring the imaginary and real components itself: -# -# This is because using abs(z) triggers a performance issue on pypy on windows, -# where it is much slower than it could have been. This seems to be an issue -# with the hypot() function in Microsoft's 32 bits runtime library. -# See bug report https://bitbucket.org/pypy/pypy/issues/2401 -# The problem doesn't occur on other Pypy implementations. - - @Pyro4.expose class Mandelbrot(object): maxiters = 500 @@ -40,7 +30,7 @@ def iterations(self, z): c = z for n in range(self.maxiters): - if z.real*z.real + z.imag*z.imag > 4: # abs(z) > 2 + if abs(z) > 2: return n z = z*z + c return self.maxiters @@ -63,25 +53,31 @@ zi *= res_y/res_x # aspect correction z = complex(zr, zi) c = z + iters = 0 for iters in range(self.maxiters+1): - if z.real*z.real + z.imag*z.imag > 4: # abs(z) > 2 + if abs(z) > 2: break z = z*z + c if iters >= self.maxiters: return 0, 0, 0 - abs_z = math.sqrt(z.real*z.real + z.imag*z.imag) # abs(z) r = (iters+32) % 255 - g = (iters - math.log(abs_z)) % 255 - b = (abs_z*iters) % 255 + g = iters % 255 + b = (iters+40) % 255 return int(r), int(g), int(b) if __name__ == "__main__": + # spawn a Pyro daemon process + # (can't use threads, because of the GIL) + if len(sys.argv) != 2: + raise SystemExit("give argument: server_id number") + + server_id = int(sys.argv[1]) with Pyro4.Daemon() as d: - uri_1 = d.register(Mandelbrot) - uri_2 = d.register(MandelbrotColorPixels) with Pyro4.locateNS() as ns: - ns.register(Mandelbrot._pyroId, uri_1, safe=True, metadata={"class:mandelbrot_calc"}) - ns.register(MandelbrotColorPixels._pyroId, uri_2, safe=True, metadata={"class:mandelbrot_calc_color"}) - print("Mandelbrot calculation server ready.") + mandel_server = d.register(Mandelbrot) + mandel_color_server = d.register(MandelbrotColorPixels) + ns.register("mandelbrot_"+str(server_id), mandel_server, safe=True, metadata={"class:mandelbrot_calc"}) + ns.register("mandelbrot_color_"+str(server_id), mandel_color_server, safe=True, metadata={"class:mandelbrot_calc_color"}) + print("Mandelbrot calculation server #{} ready.".format(server_id)) d.requestLoop() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pyro4-4.72/setup.cfg new/Pyro4-4.75/setup.cfg --- old/Pyro4-4.72/setup.cfg 2018-05-16 21:22:35.000000000 +0200 +++ new/Pyro4-4.75/setup.cfg 2019-01-19 13:16:41.000000000 +0100 @@ -1,3 +1,7 @@ +[metadata] +license = MIT +license_file = LICENSE + [bdist_rpm] doc_files = LICENSE docs/ @@ -14,7 +18,7 @@ [pycodestyle] max-line-length = 140 -ignore = E402,E731 +ignore = E402,E731,W504 exclude = .git,__pycache__,.tox,docs,tests,build,dist,examples [egg_info] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pyro4-4.72/setup.py new/Pyro4-4.75/setup.py --- old/Pyro4-4.72/setup.py 2018-05-16 21:14:37.000000000 +0200 +++ new/Pyro4-4.75/setup.py 2018-08-16 09:50:01.000000000 +0200 @@ -46,7 +46,7 @@ "packages": ['Pyro4', 'Pyro4.socketserver', 'Pyro4.test', 'Pyro4.utils'], "scripts": [], "platforms": "any", - "install_requires": ["serpent>=1.24"], + "install_requires": ["serpent>=1.27"], "extras_require": { ":python_version<'3.4'": ["selectors34"] }, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pyro4-4.72/src/Pyro4/constants.py new/Pyro4-4.75/src/Pyro4/constants.py --- old/Pyro4-4.72/src/Pyro4/constants.py 2018-05-16 21:17:34.000000000 +0200 +++ new/Pyro4-4.75/src/Pyro4/constants.py 2019-01-19 13:07:28.000000000 +0100 @@ -5,7 +5,7 @@ """ # Pyro version -VERSION = "4.72" +VERSION = "4.75" # standard object name for the Daemon object DAEMON_NAME = "Pyro.Daemon" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pyro4-4.72/src/Pyro4/core.py new/Pyro4-4.75/src/Pyro4/core.py --- old/Pyro4-4.72/src/Pyro4/core.py 2018-05-16 21:14:37.000000000 +0200 +++ new/Pyro4-4.75/src/Pyro4/core.py 2018-08-16 09:50:01.000000000 +0200 @@ -466,7 +466,7 @@ return msg data = serializer.deserializeData(msg.data, compressed=msg.flags & message.FLAGS_COMPRESSED) if msg.flags & message.FLAGS_ITEMSTREAMRESULT: - streamId = msg.annotations.get("STRM", b"").decode() + streamId = bytes(msg.annotations.get("STRM", b"")).decode() if not streamId: raise errors.ProtocolError("result of call is an iterator, but the server is not configured to allow streaming") return _StreamResultIterator(streamId, self) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pyro4-4.72/src/Pyro4/naming.py new/Pyro4-4.75/src/Pyro4/naming.py --- old/Pyro4-4.72/src/Pyro4/naming.py 2018-05-16 21:14:37.000000000 +0200 +++ new/Pyro4-4.75/src/Pyro4/naming.py 2018-12-02 20:45:18.000000000 +0100 @@ -79,6 +79,7 @@ self.lock = threading.RLock() def count(self): + """Returns the number of name registrations.""" return len(self.storage) def lookup(self, name, return_metadata=False): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pyro4-4.72/src/Pyro4/socketserver/existingconnectionserver.py new/Pyro4-4.75/src/Pyro4/socketserver/existingconnectionserver.py --- old/Pyro4-4.72/src/Pyro4/socketserver/existingconnectionserver.py 2018-05-16 21:14:37.000000000 +0200 +++ new/Pyro4-4.75/src/Pyro4/socketserver/existingconnectionserver.py 2018-09-03 12:21:49.000000000 +0200 @@ -8,7 +8,6 @@ import socket import sys import logging -import os import ssl from Pyro4 import socketutil, errors, util from Pyro4.configuration import config @@ -81,8 +80,6 @@ except (socket.error, errors.ConnectionClosedError, errors.SecurityError) as x: # client went away or caused a security error. # close the connection silently. - ex_t, ex_v, ex_tb = sys.exc_info() - tb = util.formatTraceback(ex_t, ex_v, ex_tb) try: peername = self.conn.sock.getpeername() log.debug("disconnected %s", peername) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pyro4-4.72/src/Pyro4/util.py new/Pyro4-4.75/src/Pyro4/util.py --- old/Pyro4-4.72/src/Pyro4/util.py 2018-05-16 21:14:37.000000000 +0200 +++ new/Pyro4-4.75/src/Pyro4/util.py 2018-09-03 12:27:25.000000000 +0200 @@ -4,6 +4,7 @@ Pyro - Python Remote Objects. Copyright by Irmen de Jong ([email protected]). """ +import array import sys import zlib import uuid @@ -225,7 +226,7 @@ if serpent_too: try: get_serializer_by_id(SerpentSerializer.serializer_id) - import serpent + import serpent # @todo not needed? def serpent_converter(obj, serializer, stream, level): d = converter(obj) @@ -243,7 +244,7 @@ del cls.__custom_class_to_dict_registry[clazz] try: get_serializer_by_id(SerpentSerializer.serializer_id) - import serpent + import serpent # @todo not needed? serpent.unregister_class(clazz) except errors.ProtocolError: pass @@ -532,13 +533,12 @@ serializer_id = 3 # never change this def dumpsCall(self, obj, method, vargs, kwargs): + vargs = [self.convert_obj_into_marshallable(value) for value in vargs] + kwargs = {key: self.convert_obj_into_marshallable(value) for key, value in kwargs.items()} return marshal.dumps((obj, method, vargs, kwargs)) def dumps(self, data): - try: - return marshal.dumps(data) - except (ValueError, TypeError): - return marshal.dumps(self.class_to_dict(data)) + return marshal.dumps(self.convert_obj_into_marshallable(data)) if sys.platform == "cli": def loadsCall(self, data): @@ -567,6 +567,22 @@ data = self._convertToBytes(data) return self.recreate_classes(marshal.loads(data)) + marshalable_types = (str, int, float, type(None), bool, complex, bytes, bytearray, + tuple, set, frozenset, list, dict) + if sys.version_info < (3, 0): + marshalable_types += (unicode,) + + def convert_obj_into_marshallable(self, obj): + if isinstance(obj, self.marshalable_types): + return obj + if isinstance(obj, array.array): + if obj.typecode == 'c': + return obj.tostring() + if obj.typecode == 'u': + return obj.tounicode() + return obj.tolist() + return self.class_to_dict(obj) + @classmethod def class_to_dict(cls, obj): if isinstance(obj, uuid.UUID): @@ -655,6 +671,12 @@ return obj.isoformat() if isinstance(obj, decimal.Decimal): return str(obj) + if isinstance(obj, array.array): + if obj.typecode == 'c': + return obj.tostring() + if obj.typecode == 'u': + return obj.tounicode() + return obj.tolist() return self.class_to_dict(obj) @classmethod @@ -707,6 +729,12 @@ return str(obj) if isinstance(obj, numbers.Number): return msgpack.ExtType(0x31, str(obj).encode("ascii")) # long + if isinstance(obj, array.array): + if obj.typecode == 'c': + return obj.tostring() + if obj.typecode == 'u': + return obj.tounicode() + return obj.tolist() return self.class_to_dict(obj) def object_hook(self, obj): @@ -797,19 +825,22 @@ else: ver = serpent.__version__ ver = tuple(map(int, ver.split("."))) - if ver < (1, 24): # serpent 1.24 required - raise RuntimeError("requires serpent 1.24 or better") + if ver < (1, 27): + raise RuntimeError("requires serpent 1.27 or later") _ser = SerpentSerializer() _serializers["serpent"] = _ser _serializers_by_id[_ser.serializer_id] = _ser except ImportError: log.warning("serpent serializer is not available") - pass try: import msgpack - _ser = MsgpackSerializer() - _serializers["msgpack"] = _ser - _serializers_by_id[_ser.serializer_id] = _ser + if msgpack.version < (0, 5, 2): + import warnings + warnings.warn("msgpack serializer unavailable. requires msgpack 0.5.2+, found " + str(msgpack.version)) + else: + _ser = MsgpackSerializer() + _serializers["msgpack"] = _ser + _serializers_by_id[_ser.serializer_id] = _ser except ImportError: pass del _ser diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pyro4-4.72/src/Pyro4/utils/httpgateway.py new/Pyro4-4.75/src/Pyro4/utils/httpgateway.py --- old/Pyro4-4.72/src/Pyro4/utils/httpgateway.py 2018-05-16 21:14:37.000000000 +0200 +++ new/Pyro4-4.75/src/Pyro4/utils/httpgateway.py 2018-08-16 09:50:01.000000000 +0200 @@ -117,7 +117,8 @@ <a href="http://pyro4.readthedocs.io/en/stable/tipstricks.html#pyro-via-http-and-json">Docs.</a> </p> </div> -<p><em>Note: performance isn't a key concern here; it is a stateless server. It does a name lookup and uses a new Pyro proxy for each request.</em></p> +<p><em>Note: performance isn't a key concern here; it is a stateless server. + It does a name lookup and uses a new Pyro proxy for each request.</em></p> <h2>Currently exposed contents of name server on {hostname}:</h2> <p>(Limited to 10 entries, exposed name pattern = '{ns_regex}')</p> {name_server_contents_list} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pyro4-4.72/src/Pyro4.egg-info/PKG-INFO new/Pyro4-4.75/src/Pyro4.egg-info/PKG-INFO --- old/Pyro4-4.72/src/Pyro4.egg-info/PKG-INFO 2018-05-16 21:22:35.000000000 +0200 +++ new/Pyro4-4.75/src/Pyro4.egg-info/PKG-INFO 2019-01-19 13:16:41.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: Pyro4 -Version: 4.72 +Version: 4.75 Summary: distributed object middleware for Python (RPC) Home-page: http://pyro4.readthedocs.io Author: Irmen de Jong diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pyro4-4.72/src/Pyro4.egg-info/SOURCES.txt new/Pyro4-4.75/src/Pyro4.egg-info/SOURCES.txt --- old/Pyro4-4.72/src/Pyro4.egg-info/SOURCES.txt 2018-05-16 21:22:35.000000000 +0200 +++ new/Pyro4-4.75/src/Pyro4.egg-info/SOURCES.txt 2019-01-19 13:16:41.000000000 +0100 @@ -1,7 +1,9 @@ LICENSE MANIFEST.in +README.md setup.cfg setup.py +tox.ini contrib/init.d/pyro4-nsd docs/Makefile docs/make.bat @@ -29,6 +31,7 @@ docs/source/_static/pyro-large.png docs/source/_static/pyro.png docs/source/_static/tf_pyrotaunt.png +docs/source/_static/css/customize.css docs/source/api/config.rst docs/source/api/constants.rst docs/source/api/core.rst @@ -73,6 +76,7 @@ examples/benchmark/client.py examples/benchmark/connections.py examples/benchmark/server.py +examples/blob-dispatch/Readme.txt examples/blob-dispatch/client/client.py examples/blob-dispatch/client/customdata.py examples/blob-dispatch/dispatcher/dispatcher.py @@ -122,6 +126,7 @@ examples/distributed-mandelbrot/Readme.txt examples/distributed-mandelbrot/client_asciizoom.py examples/distributed-mandelbrot/client_graphics.py +examples/distributed-mandelbrot/launch_servers.sh examples/distributed-mandelbrot/normal.py examples/distributed-mandelbrot/normal_graphics.py examples/distributed-mandelbrot/server.py diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pyro4-4.72/src/Pyro4.egg-info/requires.txt new/Pyro4-4.75/src/Pyro4.egg-info/requires.txt --- old/Pyro4-4.72/src/Pyro4.egg-info/requires.txt 2018-05-16 21:22:35.000000000 +0200 +++ new/Pyro4-4.75/src/Pyro4.egg-info/requires.txt 2019-01-19 13:16:41.000000000 +0100 @@ -1,4 +1,4 @@ -serpent>=1.24 +serpent>=1.27 [:python_version<'3.4'] selectors34 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pyro4-4.72/tests/PyroTests/test_serialize.py new/Pyro4-4.75/tests/PyroTests/test_serialize.py --- old/Pyro4-4.72/tests/PyroTests/test_serialize.py 2018-05-16 21:14:37.000000000 +0200 +++ new/Pyro4-4.75/tests/PyroTests/test_serialize.py 2018-08-16 09:50:01.000000000 +0200 @@ -4,6 +4,7 @@ Pyro - Python Remote Objects. Copyright by Irmen de Jong ([email protected]). """ +import array import sys import collections import copy @@ -28,7 +29,7 @@ def setUp(self): self.previous_serializer = config.SERIALIZER config.SERIALIZER = self.SERIALIZER - self.ser = Pyro4.util.get_serializer(config.SERIALIZER) + self.serializer = Pyro4.util.get_serializer(config.SERIALIZER) config.REQUIRE_EXPOSE = True def tearDown(self): @@ -36,30 +37,30 @@ def testSerItself(self): s = Pyro4.util.get_serializer(config.SERIALIZER) - p, _ = self.ser.serializeData(s) - s2 = self.ser.deserializeData(p) + p, _ = self.serializer.serializeData(s) + s2 = self.serializer.deserializeData(p) self.assertEqual(s, s2) self.assertTrue(s == s2) self.assertFalse(s != s2) def testSerUnicode(self): data = unicode("x") - self.ser.serializeData(data) - self.ser.serializeCall(data, unicode("method"), [], {}) + self.serializer.serializeData(data) + self.serializer.serializeCall(data, unicode("method"), [], {}) def testSerCompression(self): - d1, c1 = self.ser.serializeData("small data", compress=True) - d2, c2 = self.ser.serializeData("small data", compress=False) + d1, c1 = self.serializer.serializeData("small data", compress=True) + d2, c2 = self.serializer.serializeData("small data", compress=False) self.assertFalse(c1) self.assertEqual(d1, d2) bigdata = "x" * 1000 - d1, c1 = self.ser.serializeData(bigdata, compress=False) - d2, c2 = self.ser.serializeData(bigdata, compress=True) + d1, c1 = self.serializer.serializeData(bigdata, compress=False) + d2, c2 = self.serializer.serializeData(bigdata, compress=True) self.assertFalse(c1) self.assertTrue(c2) self.assertTrue(len(d2) < len(d1)) - self.assertEqual(bigdata, self.ser.deserializeData(d1, compressed=False)) - self.assertEqual(bigdata, self.ser.deserializeData(d2, compressed=True)) + self.assertEqual(bigdata, self.serializer.deserializeData(d1, compressed=False)) + self.assertEqual(bigdata, self.serializer.deserializeData(d2, compressed=True)) def testSerErrors(self): e1 = Pyro4.errors.NamingError(unicode("x")) @@ -69,19 +70,19 @@ e3 = Pyro4.errors.ProtocolError(unicode("x")) if sys.platform == "cli": Pyro4.util.fixIronPythonExceptionForPickle(e1, True) - p, _ = self.ser.serializeData(e1) - e = self.ser.deserializeData(p) + p, _ = self.serializer.serializeData(e1) + e = self.serializer.deserializeData(p) if sys.platform == "cli": Pyro4.util.fixIronPythonExceptionForPickle(e, False) self.assertIsInstance(e, Pyro4.errors.NamingError) self.assertEqual(repr(orig_e), repr(e)) self.assertEqual(["this is the remote traceback"], e._pyroTraceback, "remote traceback info should be present") - p, _ = self.ser.serializeData(e2) - e = self.ser.deserializeData(p) + p, _ = self.serializer.serializeData(e2) + e = self.serializer.deserializeData(p) self.assertIsInstance(e, Pyro4.errors.PyroError) self.assertEqual(repr(e2), repr(e)) - p, _ = self.ser.serializeData(e3) - e = self.ser.deserializeData(p) + p, _ = self.serializer.serializeData(e3) + e = self.serializer.deserializeData(p) self.assertIsInstance(e, Pyro4.errors.ProtocolError) self.assertEqual(repr(e3), repr(e)) @@ -89,8 +90,8 @@ ex = ZeroDivisionError("test error") ex._pyroTraceback = ["test traceback payload"] Pyro4.util.fixIronPythonExceptionForPickle(ex, True) # hack for ironpython - data, compressed = self.ser.serializeData(ex) - ex2 = self.ser.deserializeData(data, compressed) + data, compressed = self.serializer.serializeData(ex) + ex2 = self.serializer.deserializeData(data, compressed) Pyro4.util.fixIronPythonExceptionForPickle(ex2, False) # hack for ironpython self.assertEqual(ZeroDivisionError, type(ex2)) self.assertTrue(hasattr(ex2, "_pyroTraceback")) @@ -98,8 +99,8 @@ def testSerCoreOffline(self): uri = Pyro4.core.URI("PYRO:[email protected]:4444") - p, _ = self.ser.serializeData(uri) - uri2 = self.ser.deserializeData(p) + p, _ = self.serializer.serializeData(uri) + uri2 = self.serializer.deserializeData(p) self.assertEqual(uri, uri2) self.assertEqual("PYRO", uri2.protocol) self.assertEqual("9999", uri2.object) @@ -108,8 +109,8 @@ self.assertIsNone(uri2.sockname) uri = Pyro4.core.URI("PYRO:12345@./u:/tmp/socketname") - p, _ = self.ser.serializeData(uri) - uri2 = self.ser.deserializeData(p) + p, _ = self.serializer.serializeData(uri) + uri2 = self.serializer.deserializeData(p) self.assertEqual(uri, uri2) self.assertEqual("PYRO", uri2.protocol) self.assertEqual("12345", uri2.object) @@ -121,8 +122,8 @@ proxy._pyroTimeout = 42 proxy._pyroMaxRetries = 78 self.assertIsNone(proxy._pyroConnection) - p, _ = self.ser.serializeData(proxy) - proxy2 = self.ser.deserializeData(p) + p, _ = self.serializer.serializeData(proxy) + proxy2 = self.serializer.deserializeData(p) self.assertIsNone(proxy._pyroConnection) self.assertIsNone(proxy2._pyroConnection) self.assertEqual(proxy2._pyroUri, proxy._pyroUri) @@ -134,10 +135,10 @@ self.skipTest("marshal can't serialize custom objects") uri1 = Pyro4.core.URI("PYRO:[email protected]:111") uri2 = Pyro4.core.URI("PYRO:[email protected]:222") - _ = self.ser.serializeData(uri1) + _ = self.serializer.serializeData(uri1) data = [uri1, uri2] - p, _ = self.ser.serializeData(data) - [u1, u2] = self.ser.deserializeData(p) + p, _ = self.serializer.serializeData(data) + [u1, u2] = self.serializer.deserializeData(p) self.assertEqual(uri1, u1) self.assertEqual(uri2, u2) @@ -146,8 +147,8 @@ # but only to support serializing Pyro objects. # The serialized form of a Daemon should be empty (and thus, useless) with Pyro4.core.Daemon(port=0) as daemon: - d, _ = self.ser.serializeData(daemon) - d2 = self.ser.deserializeData(d) + d, _ = self.serializer.serializeData(daemon) + d2 = self.serializer.deserializeData(d) self.assertTrue(len(d2.__dict__) == 0, "deserialized daemon should be empty") self.assertTrue("Pyro4.core.Daemon" in repr(d2)) self.assertTrue("unusable" in repr(d2)) @@ -156,10 +157,10 @@ obj = pprint.PrettyPrinter(stream="dummy", width=42) obj.name = "hello" daemon.register(obj) - o, _ = self.ser.serializeData(obj) + o, _ = self.serializer.serializeData(obj) if self.SERIALIZER in ("pickle", "cloudpickle", "dill"): # only pickle, cloudpickle and dill can deserialize the PrettyPrinter class without the need of explicit deserialization function - o2 = self.ser.deserializeData(o) + o2 = self.serializer.deserializeData(o) self.assertEqual("hello", o2.name) self.assertEqual(42, o2._width) finally: @@ -167,15 +168,15 @@ def testPyroClasses(self): uri = Pyro4.core.URI("PYRO:object@host:4444") - s, c = self.ser.serializeData(uri) - x = self.ser.deserializeData(s, c) + s, c = self.serializer.serializeData(uri) + x = self.serializer.deserializeData(s, c) self.assertIsInstance(x, Pyro4.core.URI) self.assertEqual(uri, x) self.assertTrue("Pyro4.core.URI" in repr(uri)) self.assertEqual("PYRO:object@host:4444", str(uri)) uri = Pyro4.core.URI("PYRO:12345@./u:/tmp/socketname") - s, c = self.ser.serializeData(uri) - x = self.ser.deserializeData(s, c) + s, c = self.serializer.serializeData(uri) + x = self.serializer.deserializeData(s, c) self.assertIsInstance(x, Pyro4.core.URI) self.assertEqual(uri, x) proxy = Pyro4.core.Proxy(uri) @@ -187,8 +188,8 @@ proxy._pyroHandshake = "apples" proxy._pyroMaxRetries = 78 proxy._pyroSerializer = "serializer" - s, c = self.ser.serializeData(proxy) - x = self.ser.deserializeData(s, c) + s, c = self.serializer.serializeData(proxy) + x = self.serializer.deserializeData(s, c) self.assertIsInstance(x, Pyro4.core.Proxy) self.assertEqual(proxy._pyroUri, x._pyroUri) self.assertEqual(set("abc"), x._pyroAttrs) @@ -202,16 +203,16 @@ self.assertTrue("Pyro4.core.Proxy" in repr(x)) self.assertTrue("Pyro4.core.Proxy" in str(x)) daemon = Pyro4.core.Daemon() - s, c = self.ser.serializeData(daemon) - x = self.ser.deserializeData(s, c) + s, c = self.serializer.serializeData(daemon) + x = self.serializer.deserializeData(s, c) self.assertIsInstance(x, Pyro4.core.Daemon) self.assertTrue("Pyro4.core.Daemon" in repr(x)) self.assertTrue("unusable" in repr(x)) self.assertTrue("Pyro4.core.Daemon" in str(x)) self.assertTrue("unusable" in str(x)) wrapper = Pyro4.futures._ExceptionWrapper(ZeroDivisionError("divided by zero")) - s, c = self.ser.serializeData(wrapper) - x = self.ser.deserializeData(s, c) + s, c = self.serializer.serializeData(wrapper) + x = self.serializer.deserializeData(s, c) self.assertIsInstance(x, Pyro4.futures._ExceptionWrapper) self.assertEqual("divided by zero", str(x.exception)) self.assertTrue("ExceptionWrapper" in repr(x)) @@ -272,15 +273,15 @@ def testAutoProxyPartlyExposed(self): if self.SERIALIZER == "marshal": self.skipTest("marshal can't serialize custom objects") - self.ser.register_type_replacement(MyThingPartlyExposed, Pyro4.core.pyroObjectToAutoProxy) + self.serializer.register_type_replacement(MyThingPartlyExposed, Pyro4.core.pyroObjectToAutoProxy) t1 = MyThingPartlyExposed("1") t2 = MyThingPartlyExposed("2") with Pyro4.core.Daemon() as d: d.register(t1, "thingy1") d.register(t2, "thingy2") data = [t1, ["apple", t2]] - s, c = self.ser.serializeData(data) - data = self.ser.deserializeData(s, c) + s, c = self.serializer.serializeData(data) + data = self.serializer.deserializeData(s, c) self.assertEqual("apple", data[1][0]) p1 = data[0] p2 = data[1][1] @@ -295,15 +296,15 @@ def testAutoProxyFullExposed(self): if self.SERIALIZER == "marshal": self.skipTest("marshal can't serialize custom objects") - self.ser.register_type_replacement(MyThingPartlyExposed, Pyro4.core.pyroObjectToAutoProxy) + self.serializer.register_type_replacement(MyThingPartlyExposed, Pyro4.core.pyroObjectToAutoProxy) t1 = MyThingFullExposed("1") t2 = MyThingFullExposed("2") with Pyro4.core.Daemon() as d: d.register(t1, "thingy1") d.register(t2, "thingy2") data = [t1, ["apple", t2]] - s, c = self.ser.serializeData(data) - data = self.ser.deserializeData(s, c) + s, c = self.serializer.serializeData(data) + data = self.serializer.deserializeData(s, c) self.assertEqual("apple", data[1][0]) p1 = data[0] p2 = data[1][1] @@ -318,19 +319,19 @@ def testRegisterTypeReplacementSanity(self): if self.SERIALIZER == "marshal": self.skipTest("marshal can't serialize custom objects") - self.ser.register_type_replacement(int, lambda: None) + self.serializer.register_type_replacement(int, lambda: None) with self.assertRaises(ValueError): - self.ser.register_type_replacement(type, lambda: None) + self.serializer.register_type_replacement(type, lambda: None) with self.assertRaises(ValueError): - self.ser.register_type_replacement(42, lambda: None) + self.serializer.register_type_replacement(42, lambda: None) def testCustomClassFail(self): if self.SERIALIZER in ("pickle", "cloudpickle", "dill"): self.skipTest("pickle, cloudpickle and dill simply serialize custom classes") o = pprint.PrettyPrinter(stream="dummy", width=42) - s, c = self.ser.serializeData(o) + s, c = self.serializer.serializeData(o) try: - _ = self.ser.deserializeData(s, c) + _ = self.serializer.deserializeData(s, c) self.fail("error expected, shouldn't deserialize unknown class") except Pyro4.errors.ProtocolError: pass @@ -341,22 +342,22 @@ o = MyThingPartlyExposed("test") Pyro4.util.SerializerBase.register_class_to_dict(MyThingPartlyExposed, mything_dict) Pyro4.util.SerializerBase.register_dict_to_class("CUSTOM-Mythingymabob", mything_creator) - s, c = self.ser.serializeData(o) - o2 = self.ser.deserializeData(s, c) + s, c = self.serializer.serializeData(o) + o2 = self.serializer.deserializeData(s, c) self.assertIsInstance(o2, MyThingPartlyExposed) self.assertEqual("test", o2.name) # unregister the deserializer Pyro4.util.SerializerBase.unregister_dict_to_class("CUSTOM-Mythingymabob") try: - self.ser.deserializeData(s, c) + self.serializer.deserializeData(s, c) self.fail("must fail") except Pyro4.errors.ProtocolError: pass # ok # unregister the serializer Pyro4.util.SerializerBase.unregister_class_to_dict(MyThingPartlyExposed) - s, c = self.ser.serializeData(o) + s, c = self.serializer.serializeData(o) try: - self.ser.deserializeData(s, c) + self.serializer.deserializeData(s, c) self.fail("must fail") except Pyro4.errors.SerializeError as x: msg = str(x) @@ -365,54 +366,56 @@ def testData(self): data = [42, "hello"] - ser, compressed = self.ser.serializeData(data) + ser, compressed = self.serializer.serializeData(data) self.assertFalse(compressed) - data2 = self.ser.deserializeData(ser, compressed=False) + data2 = self.serializer.deserializeData(ser, compressed=False) self.assertEqual(data, data2) def testUnicodeData(self): data = u"euro\u20aclowbytes\u0000\u0001\u007f\u0080\u00ff" - ser, compressed = self.ser.serializeData(data) - data2 = self.ser.deserializeData(ser, compressed=compressed) + ser, compressed = self.serializer.serializeData(data) + data2 = self.serializer.deserializeData(ser, compressed=compressed) self.assertEqual(data, data2) def testUUID(self): data = uuid.uuid1() - ser, compressed = self.ser.serializeData(data) - data2 = self.ser.deserializeData(ser, compressed=compressed) + ser, compressed = self.serializer.serializeData(data) + data2 = self.serializer.deserializeData(ser, compressed=compressed) uuid_as_str = str(data) self.assertTrue(data2==data or data2==uuid_as_str) def testSet(self): data = {111, 222, 333} - ser, compressed = self.ser.serializeData(data) - data2 = self.ser.deserializeData(ser, compressed=compressed) + ser, compressed = self.serializer.serializeData(data) + data2 = self.serializer.deserializeData(ser, compressed=compressed) self.assertEqual(data, data2) def testCircular(self): data = [42, "hello", Pyro4.core.Proxy("PYRO:dummy@dummy:4444")] data.append(data) - ser, compressed = self.ser.serializeData(data) - data2 = self.ser.deserializeData(ser, compressed) + ser, compressed = self.serializer.serializeData(data) + data2 = self.serializer.deserializeData(ser, compressed) self.assertIs(data2, data2[3]) self.assertEqual(42, data2[0]) def testCallPlain(self): - ser, compressed = self.ser.serializeCall("object", "method", "vargs", "kwargs") + ser, compressed = self.serializer.serializeCall("object", "method", ("vargs1", "vargs2"), {"kwargs": 999}) self.assertFalse(compressed) - obj, method, vargs, kwargs = self.ser.deserializeCall(ser, compressed=False) + obj, method, vargs, kwargs = self.serializer.deserializeCall(ser, compressed=False) self.assertEqual("object", obj) self.assertEqual("method", method) - self.assertEqual("vargs", vargs) - self.assertEqual("kwargs", kwargs) + self.assertTrue(len(vargs) == 2) + self.assertTrue(vargs[0] == "vargs1") + self.assertTrue(vargs[1] == "vargs2") + self.assertDictEqual({"kwargs": 999}, kwargs) def testCallPyroObjAsArg(self): if self.SERIALIZER == "marshal": self.skipTest("marshal can't serialize custom objects") uri = Pyro4.core.URI("PYRO:555@localhost:80") - ser, compressed = self.ser.serializeCall("object", "method", [uri], {"thing": uri}) + ser, compressed = self.serializer.serializeCall("object", "method", [uri], {"thing": uri}) self.assertFalse(compressed) - obj, method, vargs, kwargs = self.ser.deserializeCall(ser, compressed=False) + obj, method, vargs, kwargs = self.serializer.deserializeCall(ser, compressed=False) self.assertEqual("object", obj) self.assertEqual("method", method) self.assertEqual([uri], vargs) @@ -422,9 +425,9 @@ if self.SERIALIZER == "marshal": self.skipTest("marshal can't serialize custom objects") e = ZeroDivisionError("hello") - ser, compressed = self.ser.serializeCall("object", "method", [e], {"thing": e}) + ser, compressed = self.serializer.serializeCall("object", "method", [e], {"thing": e}) self.assertFalse(compressed) - obj, method, vargs, kwargs = self.ser.deserializeCall(ser, compressed=False) + obj, method, vargs, kwargs = self.serializer.deserializeCall(ser, compressed=False) self.assertEqual("object", obj) self.assertEqual("method", method) self.assertIsInstance(vargs, list) @@ -435,25 +438,25 @@ def testSerializeException(self): e = ZeroDivisionError() - d, c = self.ser.serializeData(e) - e2 = self.ser.deserializeData(d, c) + d, c = self.serializer.serializeData(e) + e2 = self.serializer.deserializeData(d, c) self.assertIsInstance(e2, ZeroDivisionError) self.assertEqual("", str(e2)) e = ZeroDivisionError("hello") - d, c = self.ser.serializeData(e) - e2 = self.ser.deserializeData(d, c) + d, c = self.serializer.serializeData(e) + e2 = self.serializer.deserializeData(d, c) self.assertIsInstance(e2, ZeroDivisionError) self.assertEqual("hello", str(e2)) e = ZeroDivisionError("hello", 42) - d, c = self.ser.serializeData(e) - e2 = self.ser.deserializeData(d, c) + d, c = self.serializer.serializeData(e) + e2 = self.serializer.deserializeData(d, c) self.assertIsInstance(e2, ZeroDivisionError) self.assertIn(str(e2), ("('hello', 42)", "(u'hello', 42)")) e.custom_attribute = 999 if sys.platform == "cli": Pyro4.util.fixIronPythonExceptionForPickle(e, True) - ser, compressed = self.ser.serializeData(e) - e2 = self.ser.deserializeData(ser, compressed) + ser, compressed = self.serializer.serializeData(e) + e2 = self.serializer.deserializeData(ser, compressed) if sys.platform == "cli": Pyro4.util.fixIronPythonExceptionForPickle(e2, False) self.assertIsInstance(e2, ZeroDivisionError) @@ -463,22 +466,22 @@ def testSerializeSpecialException(self): self.assertIn("GeneratorExit", Pyro4.util.all_exceptions) e = GeneratorExit() - d, c = self.ser.serializeData(e) - e2 = self.ser.deserializeData(d, c) + d, c = self.serializer.serializeData(e) + e2 = self.serializer.deserializeData(d, c) self.assertIsInstance(e2, GeneratorExit) def testRecreateClasses(self): - self.assertEqual([1, 2, 3], self.ser.recreate_classes([1, 2, 3])) + self.assertEqual([1, 2, 3], self.serializer.recreate_classes([1, 2, 3])) d = {"__class__": "invalid"} try: - self.ser.recreate_classes(d) + self.serializer.recreate_classes(d) self.fail("error expected") except Pyro4.errors.ProtocolError: pass # ok d = {"__class__": "Pyro4.core.URI", "state": ['PYRO', '555', None, 'localhost', 80]} - uri = self.ser.recreate_classes(d) + uri = self.serializer.recreate_classes(d) self.assertEqual(Pyro4.core.URI("PYRO:555@localhost:80"), uri) - number, uri = self.ser.recreate_classes([1, {"uri": d}]) + number, uri = self.serializer.recreate_classes([1, {"uri": d}]) self.assertEqual(1, number) self.assertEqual(Pyro4.core.URI("PYRO:555@localhost:80"), uri["uri"]) @@ -491,7 +494,7 @@ config.PICKLE_PROTOCOL_VERSION = 2 try: u = Pyro4.core.URI("PYRO:obj@localhost:1234") - d, compr = self.ser.serializeData(u) + d, compr = self.serializer.serializeData(u) self.assertFalse(compr) import pickletools d = pickletools.optimize(d) @@ -506,75 +509,138 @@ f2 = 9876543212345.12345678987654321 f3 = 11223344.556677889988776655e33 floats = [f1, f2, f3] - d, compr = self.ser.serializeData(floats) - v = self.ser.deserializeData(d, compr) + d, compr = self.serializer.serializeData(floats) + v = self.serializer.deserializeData(d, compr) self.assertEqual(floats, v, "float precision must not be compromised in any serializer") def testSourceByteTypes_deserialize(self): # uncompressed - call_ser, _ = self.ser.serializeCall("object", "method", [1, 2, 3], {"kwarg": 42}, False) - ser, _ = self.ser.serializeData([4, 5, 6], False) - _, _, vargs, _ = self.ser.deserializeCall(bytearray(call_ser), False) + call_ser, _ = self.serializer.serializeCall("object", "method", [1, 2, 3], {"kwarg": 42}, False) + ser, _ = self.serializer.serializeData([4, 5, 6], False) + _, _, vargs, _ = self.serializer.deserializeCall(bytearray(call_ser), False) self.assertEqual([1, 2, 3], vargs) - d = self.ser.deserializeData(bytearray(ser), False) + d = self.serializer.deserializeData(bytearray(ser), False) self.assertEqual([4, 5, 6], d) if sys.version_info < (3, 0): - _, _, vargs, _ = self.ser.deserializeCall(buffer(call_ser), False) + _, _, vargs, _ = self.serializer.deserializeCall(buffer(call_ser), False) self.assertEqual([1, 2, 3], vargs) - d = self.ser.deserializeData(buffer(ser), False) + d = self.serializer.deserializeData(buffer(ser), False) self.assertEqual([4, 5, 6], d) # compressed - call_ser, _ = self.ser.serializeCall("object", "method", [1, 2, 3]*100, {"kwarg": 42}, True) - ser, _ = self.ser.serializeData([4, 5, 6]*100, True) - _, _, vargs, _ = self.ser.deserializeCall(bytearray(call_ser), True) + call_ser, _ = self.serializer.serializeCall("object", "method", [1, 2, 3] * 100, {"kwarg": 42}, True) + ser, _ = self.serializer.serializeData([4, 5, 6] * 100, True) + _, _, vargs, _ = self.serializer.deserializeCall(bytearray(call_ser), True) self.assertEqual(300, len(vargs)) - d = self.ser.deserializeData(bytearray(ser), True) + d = self.serializer.deserializeData(bytearray(ser), True) self.assertEqual(300, len(d)) if sys.version_info < (3, 0): - _, _, vargs, _ = self.ser.deserializeCall(buffer(call_ser), True) + _, _, vargs, _ = self.serializer.deserializeCall(buffer(call_ser), True) self.assertEqual(300, len(vargs)) - d = self.ser.deserializeData(buffer(ser), True) + d = self.serializer.deserializeData(buffer(ser), True) self.assertEqual(300, len(d)) @unittest.skipIf(sys.platform == "cli", "ironpython can't properly create memoryviews from serialized data") def testSourceByteTypes_deserialize_memoryview(self): # uncompressed - call_ser, _ = self.ser.serializeCall("object", "method", [1, 2, 3], {"kwarg": 42}, False) - ser, _ = self.ser.serializeData([4, 5, 6], False) - _, _, vargs, _ = self.ser.deserializeCall(memoryview(call_ser), False) + call_ser, _ = self.serializer.serializeCall("object", "method", [1, 2, 3], {"kwarg": 42}, False) + ser, _ = self.serializer.serializeData([4, 5, 6], False) + _, _, vargs, _ = self.serializer.deserializeCall(memoryview(call_ser), False) self.assertEqual([1, 2, 3], vargs) - d = self.ser.deserializeData(memoryview(ser), False) + d = self.serializer.deserializeData(memoryview(ser), False) self.assertEqual([4, 5, 6], d) # compressed - call_ser, _ = self.ser.serializeCall("object", "method", [1, 2, 3]*100, {"kwarg": 42}, True) - ser, _ = self.ser.serializeData([4, 5, 6]*100, True) - _, _, vargs, _ = self.ser.deserializeCall(memoryview(call_ser), True) + call_ser, _ = self.serializer.serializeCall("object", "method", [1, 2, 3] * 100, {"kwarg": 42}, True) + ser, _ = self.serializer.serializeData([4, 5, 6] * 100, True) + _, _, vargs, _ = self.serializer.deserializeCall(memoryview(call_ser), True) self.assertEqual(300, len(vargs)) - d = self.ser.deserializeData(memoryview(ser), True) + d = self.serializer.deserializeData(memoryview(ser), True) self.assertEqual(300, len(d)) def testSourceByteTypes_loads(self): - call_ser, _ = self.ser.serializeCall("object", "method", [1, 2, 3], {"kwarg": 42}, False) - ser, _ = self.ser.serializeData([4, 5, 6], False) - _, _, vargs, _ = self.ser.loadsCall(bytearray(call_ser)) + call_ser, _ = self.serializer.serializeCall("object", "method", [1, 2, 3], {"kwarg": 42}, False) + ser, _ = self.serializer.serializeData([4, 5, 6], False) + _, _, vargs, _ = self.serializer.loadsCall(bytearray(call_ser)) self.assertEqual([1, 2, 3], vargs) - d = self.ser.loads(bytearray(ser)) + d = self.serializer.loads(bytearray(ser)) self.assertEqual([4, 5, 6], d) if sys.version_info < (3, 0): - _, _, vargs, _ = self.ser.loadsCall(buffer(call_ser)) + _, _, vargs, _ = self.serializer.loadsCall(buffer(call_ser)) self.assertEqual([1, 2, 3], vargs) - d = self.ser.loads(buffer(ser)) + d = self.serializer.loads(buffer(ser)) self.assertEqual([4, 5, 6], d) @unittest.skipIf(sys.platform == "cli", "ironpython can't properly create memoryviews from serialized data") def testSourceByteTypes_loads_memoryview(self): - call_ser, _ = self.ser.serializeCall("object", "method", [1, 2, 3], {"kwarg": 42}, False) - ser, _ = self.ser.serializeData([4, 5, 6], False) - _, _, vargs, _ = self.ser.loadsCall(memoryview(call_ser)) + call_ser, _ = self.serializer.serializeCall("object", "method", [1, 2, 3], {"kwarg": 42}, False) + ser, _ = self.serializer.serializeData([4, 5, 6], False) + _, _, vargs, _ = self.serializer.loadsCall(memoryview(call_ser)) self.assertEqual([1, 2, 3], vargs) - d = self.ser.loads(memoryview(ser)) + d = self.serializer.loads(memoryview(ser)) self.assertEqual([4, 5, 6], d) + def testSerializeDumpsAndDumpsCall(self): + self.serializer.dumps(uuid.uuid4()) + self.serializer.dumps(Pyro4.URI("PYRO:test@test:4444")) + self.serializer.dumps(Pyro4.Proxy("PYRONAME:foobar")) + self.serializer.dumpsCall("obj", "method", (1, 2, 3), {"arg1": 999}) + self.serializer.dumpsCall("obj", "method", (1, 2, array.array('i', [1, 2, 3])), {"arg1": 999}) + self.serializer.dumpsCall("obj", "method", (1, 2, array.array('i', [1, 2, 3])), {"arg1": array.array('i', [1, 2, 3])}) + self.serializer.dumpsCall("obj", "method", (1, 2, Pyro4.URI("PYRO:test@test:4444")), {"arg1": 999}) + self.serializer.dumpsCall("obj", "method", (1, 2, Pyro4.URI("PYRO:test@test:4444")), {"arg1": Pyro4.URI("PYRO:test@test:4444")}) + self.serializer.dumpsCall("obj", "method", (1, 2, Pyro4.Proxy("PYRONAME:foobar")), {"arg1": 999}) + self.serializer.dumpsCall("obj", "method", (1, 2, Pyro4.Proxy("PYRONAME:foobar")), {"arg1": Pyro4.Proxy("PYRONAME:foobar")}) + + def testArrays(self): + if sys.version_info < (3, 0): + a1 = array.array('c', b"hello") + ser = self.serializer.dumps(a1) + a2 = self.serializer.loads(ser) + if type(a2) is array.array: + self.assertEqual(a1, a2) + else: + self.assertEqual(b"hello", a2) + a1 = array.array('u', unicode("hello")) + ser = self.serializer.dumps(a1) + a2 = self.serializer.loads(ser) + if type(a2) is array.array: + self.assertEqual(a1, a2) + else: + self.assertEqual(unicode("hello"), a2) + a1 = array.array('h', [222, 333, 444, 555]) + ser = self.serializer.dumps(a1) + a2 = self.serializer.loads(ser) + if type(a2) is array.array: + self.assertEqual(a1, a2) + else: + self.assertEqual([222, 333, 444, 555], a2) + + def testArrays2(self): + if sys.version_info < (3, 0): + a1 = array.array('c', b"hello") + ser = self.serializer.dumpsCall("obj", "method", [a1], {}) + a2 = self.serializer.loads(ser) + a2 = a2["params"][0] if self.SERIALIZER == "json" else a2[2][0] + if type(a2) is array.array: + self.assertEqual(a1, a2) + else: + self.assertEqual(b"hello", a2) + a1 = array.array('u', unicode("hello")) + ser = self.serializer.dumpsCall("obj", "method", [a1], {}) + a2 = self.serializer.loads(ser) + a2 = a2["params"][0] if self.SERIALIZER == "json" else a2[2][0] + if type(a2) is array.array: + self.assertEqual(a1, a2) + else: + self.assertEqual(unicode("hello"), a2) + a1 = array.array('h', [222, 333, 444, 555]) + ser = self.serializer.dumpsCall("obj", "method", [a1], {}) + a2 = self.serializer.loads(ser) + a2 = a2["params"][0] if self.SERIALIZER == "json" else a2[2][0] + if type(a2) is array.array: + self.assertEqual(a1, a2) + else: + self.assertEqual([222, 333, 444, 555], a2) + class SerializeTests_cloudpickle(SerializeTests_pickle): SERIALIZER = "cloudpickle" @@ -585,15 +651,15 @@ def testSerializeLambda(self): l = lambda x: x * x - ser, compressed = self.ser.serializeData(l) - l2 = self.ser.deserializeData(ser, compressed=compressed) + ser, compressed = self.serializer.serializeData(l) + l2 = self.serializer.deserializeData(ser, compressed=compressed) self.assertEqual(l2(3.), 9.) def testSerializeLocalFunction(self): def f(x): return x * x - ser, compressed = self.ser.serializeData(f) - f2 = self.ser.deserializeData(ser, compressed=compressed) + ser, compressed = self.serializer.serializeData(f) + f2 = self.serializer.deserializeData(ser, compressed=compressed) self.assertEqual(f2(3.), 9.) @@ -619,15 +685,15 @@ def testSerializeLambda(self): l = lambda x: x * x - ser, compressed = self.ser.serializeData(l) - l2 = self.ser.deserializeData(ser, compressed=compressed) + ser, compressed = self.serializer.serializeData(l) + l2 = self.serializer.deserializeData(ser, compressed=compressed) self.assertEqual(l2(3.), 9.) def testSerializeLocalFunction(self): def f(x): return x * x - ser, compressed = self.ser.serializeData(f) - f2 = self.ser.deserializeData(ser, compressed=compressed) + ser, compressed = self.serializer.serializeData(f) + f2 = self.serializer.deserializeData(ser, compressed=compressed) self.assertEqual(f2(3.), 9.) @@ -641,8 +707,8 @@ def testSet(self): # serpent serializes a set into a tuple on older python versions, so we override this data = {111, 222, 333} - ser, compressed = self.ser.serializeData(data) - data2 = self.ser.deserializeData(ser, compressed=compressed) + ser, compressed = self.serializer.serializeData(data) + data2 = self.serializer.deserializeData(ser, compressed=compressed) if serpent.can_use_set_literals: self.assertEqual(data, data2) else: @@ -651,8 +717,8 @@ def testDeque(self): # serpent converts a deque into a primitive list deq = collections.deque([1, 2, 3, 4]) - ser, compressed = self.ser.serializeData(deq) - data2 = self.ser.deserializeData(ser, compressed=compressed) + ser, compressed = self.serializer.serializeData(deq) + data2 = self.serializer.deserializeData(ser, compressed=compressed) self.assertEqual([1, 2, 3, 4], data2) @unittest.skipIf(sys.version_info < (2, 7), "ordereddict is in Python 2.7+") @@ -665,15 +731,15 @@ self.assertEqual("collections.OrderedDict", name) return collections.OrderedDict(values["items"]) Pyro4.util.SerializerBase.register_dict_to_class("collections.OrderedDict", recreate_OrderedDict) - ser, compressed = self.ser.serializeData(od) + ser, compressed = self.serializer.serializeData(od) self.assertIn(b"collections.OrderedDict", ser) self.assertIn(b"[('a',1),('b',2),('c',3)]", ser) - data2 = self.ser.deserializeData(ser, compressed=compressed) + data2 = self.serializer.deserializeData(ser, compressed=compressed) self.assertEqual(od, data2) def testUriSerializationWithoutSlots(self): u = Pyro4.core.URI("PYRO:obj@localhost:1234") - d, compr = self.ser.serializeData(u) + d, compr = self.serializer.serializeData(u) self.assertFalse(compr) result1 = b"# serpent utf-8 python3.2\n{'__class__':'Pyro4.core.URI','state':('PYRO','obj',None,'localhost',1234)}" result2 = b"# serpent utf-8 python3.2\n{'state':('PYRO','obj',None,'localhost',1234),'__class__':'Pyro4.core.URI'}" @@ -692,13 +758,13 @@ def testSet(self): # json serializes a set into a list, so we override this data = {111, 222, 333} - ser, compressed = self.ser.serializeData(data) - data2 = self.ser.deserializeData(ser, compressed=compressed) + ser, compressed = self.serializer.serializeData(data) + data2 = self.serializer.deserializeData(ser, compressed=compressed) self.assertEqual(list(data), data2) def testUriSerializationWithoutSlots(self): u = Pyro4.core.URI("PYRO:obj@localhost:1234") - d, compr = self.ser.serializeData(u) + d, compr = self.serializer.serializeData(u) self.assertFalse(compr) result1 = b'{"__class__": "Pyro4.core.URI", "state": ["PYRO", "obj", null, "localhost", 1234]}' result2 = b'{"state": ["PYRO", "obj", null, "localhost", 1234], "__class__": "Pyro4.core.URI"}' @@ -727,8 +793,8 @@ def testSet(self): # msgpack serializes a set into a list, so we override this data = {111, 222, 333} - ser, compressed = self.ser.serializeData(data) - data2 = self.ser.deserializeData(ser, compressed=compressed) + ser, compressed = self.serializer.serializeData(data) + data2 = self.serializer.deserializeData(ser, compressed=compressed) self.assertEqual(list(data), data2) @unittest.skip("msgpack is implementation dependent") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Pyro4-4.72/tox.ini new/Pyro4-4.75/tox.ini --- old/Pyro4-4.72/tox.ini 1970-01-01 01:00:00.000000000 +0100 +++ new/Pyro4-4.75/tox.ini 2018-08-16 09:50:01.000000000 +0200 @@ -0,0 +1,11 @@ +[tox] +envlist=py27,py34,py35,py36,py37,pypy + +[testenv] +deps=-rtest_requirements.txt +changedir=tests +commands=python -bb -tt -E -Wall run_testsuite.py --tox + +[testenv:pypy3] +# pypy3 doesn't have the -tt option +commands=pypy3 -E -Wall -bb run_testsuite.py --tox
