Hello community, here is the log from the commit of package python-ana for openSUSE:Factory checked in at 2019-06-12 13:15:47 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-ana (Old) and /work/SRC/openSUSE:Factory/.python-ana.new.4811 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-ana" Wed Jun 12 13:15:47 2019 rev:4 rq:708982 version:0.06 Changes: -------- --- /work/SRC/openSUSE:Factory/python-ana/python-ana.changes 2018-12-12 17:24:49.415156073 +0100 +++ /work/SRC/openSUSE:Factory/.python-ana.new.4811/python-ana.changes 2019-06-12 13:15:50.744719375 +0200 @@ -1,0 +2,24 @@ +Mon Jun 10 14:19:34 UTC 2019 - Andreas Färber <afaer...@suse.de> + +- Update to v0.06 +* LICENSE and README.md files are now included in the tarball +* Repo URL is deprecated but no new one known (gh#zardus/ana#13) +- Don't overwrite tarball files with local copies + +------------------------------------------------------------------- +Thu Jun 6 12:58:58 UTC 2019 - pgaj...@suse.com + +- revert to previous behaviour: in case LICENSE, test.py or + test_pickle.p are shipped in future upstream version, do not + abort build (but also do not overwrite them) + +------------------------------------------------------------------- +Thu Jun 6 07:33:30 UTC 2019 - pgaj...@suse.com + +- run tests +- added sources + https://github.com/zardus/ana/issues/13 + + test.py + + test_pickle.p + +------------------------------------------------------------------- Old: ---- LICENSE ana-0.05.tar.gz New: ---- ana-0.06.tar.gz test.py test_pickle.p ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-ana.spec ++++++ --- /var/tmp/diff_new_pack.cApDJB/_old 2019-06-12 13:15:52.312717731 +0200 +++ /var/tmp/diff_new_pack.cApDJB/_new 2019-06-12 13:15:52.352717689 +0200 @@ -1,7 +1,7 @@ # # spec file for package python-ana # -# 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,15 +18,18 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-ana -Version: 0.05 +Version: 0.06 Release: 0 Summary: The Python "ana" module License: BSD-2-Clause Group: Development/Languages/Python Url: https://github.com/zardus/ana Source: https://files.pythonhosted.org/packages/source/a/ana/ana-%{version}.tar.gz -Source1: https://github.com/zardus/ana/raw/master/LICENSE +# https://github.com/zardus/ana/issues/13 +Source2: https://raw.githubusercontent.com/zardus/ana/master/test.py +Source3: https://raw.githubusercontent.com/zardus/ana/master/test_pickle.p BuildRequires: %{python_module future} +BuildRequires: %{python_module nose} BuildRequires: %{python_module setuptools} BuildRequires: fdupes BuildRequires: python-rpm-macros @@ -41,7 +44,8 @@ %prep %setup -q -n ana-%{version} -[ -e LICENSE ] || cp %{SOURCE1} LICENSE +[ -e test.py ] || cp %{SOURCE2} test.py +[ -e test_pickle.p ] || cp %{SOURCE3} test_pickle.p %build %python_build @@ -50,9 +54,13 @@ %python_install %python_expand %fdupes %{buildroot}%{$python_sitelib} +%check +%python_expand nosetests-%{$python_bin_suffix} -v + %files %{python_files} %defattr(-,root,root,-) %license LICENSE +%doc README.md %{python_sitelib}/* %changelog ++++++ ana-0.05.tar.gz -> ana-0.06.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ana-0.05/LICENSE new/ana-0.06/LICENSE --- old/ana-0.05/LICENSE 1970-01-01 01:00:00.000000000 +0100 +++ new/ana-0.06/LICENSE 2018-05-31 09:48:43.000000000 +0200 @@ -0,0 +1,24 @@ +Copyright (c) 2015, The Regents of the University of California +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ana-0.05/PKG-INFO new/ana-0.06/PKG-INFO --- old/ana-0.05/PKG-INFO 2018-03-28 01:18:31.000000000 +0200 +++ new/ana-0.06/PKG-INFO 2019-06-06 23:01:13.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.0 Name: ana -Version: 0.05 +Version: 0.06 Summary: UNKNOWN Home-page: UNKNOWN Author: UNKNOWN diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ana-0.05/README.md new/ana-0.06/README.md --- old/ana-0.05/README.md 1970-01-01 01:00:00.000000000 +0100 +++ new/ana-0.06/README.md 2018-05-31 09:48:43.000000000 +0200 @@ -0,0 +1,149 @@ +# ANA + +ANA is a project to provide easy distributed data storage for stuff. +It provides every object with a UUID and, when pickled, will first serialize the object's state to a central location and then "pickle" the object into just its UUID. +This is really handy when you have to distribute objects in some distributed system, and you'd rather not pickle the whole object every time you need to send it. + +ANA violates some of pickle's assumptions. +Users of pickle often have an implicit assumption that the objects they unpickle will be different (identity-wise) than the objects that they pickle. +This is not the case with ANA; in fact, it has an object cache specifically to avoid this. +Furthermore, depending on the mode of operation, ANA might store the objects centrally, by UUID, where it will be accessed by other instances of ANA. +Because of these things, the objects serialized with ANA should be immutable, if you know what's good for you. + +## Usage + +To use ANA, simply subclass `ana.Storable` and implement `_ana_getstate` and `_ana_setstate`. +These should function identically to how you would normally implement `__getstate__` and `__setstate__` for pickle. + +Here's an example: + +```python +import ana +import pickle + +class A(ana.Storable): + def __init__(self, n): + self.n = n + l.debug("Initialized %s", self) + + def __repr__(self): + return "<A %d>" % self.n + + def _ana_getstate(self): + return self.n + + def _ana_setstate(self, s): + self.n = s + +# create an instance +a = A(10) + +# First, this instance will be pickled more or less normally. +# For example, the following will actually contain the state, +# and deserializing it will create a new object. +a_pickled = pickle.dumps(a) +b = pickle.loads(a_pickled) +assert b is not a + +# Now, let's try assigning this guy a UUID +a.make_uuid() + +# Now, when the object is unpickled, the identity is preserved. +a_pickled = pickle.dumps(a) +b = pickle.loads(a_pickled) +assert b is a + +# There are also functions that provide easy storing and loading +# in advanced situations. These these require an actual storage +# datalayer (see below) other than SimpleDataLayer. +a_uuid = a.uuid +a.ana_store() +b = A.ana_load(a_uuid) # note that this is a class method +assert b is a +``` + +Have fun! + +## JSON + +ANA has the capability to serialize to a literal format such as JSON, out of the box. +By default, it does it's best to serialize any collections in what's returned by `_ana_getstate`, which is often enough. +If something more complex is needed, a `Storable` can overload `_ana_getliteral`, which is then called instead of `_ana_getstate`. + +Since the list of already-serialized UUIDs may be client-dependent (for an ANA instance that serves multiple clients), this functionality receives, and updates, a set of which UUIDs have already been serialized. +Furthermore, it assigns a UUID to every ANA-serializable object. + +With the example `A` class, we would do the following: + +```python +a = A(10) + +# start with an empty set +serialized = set() + +# serialize to literal +a_literal = a.to_literal(serialized) + +# the object is marked as serialized +assert a.ana_uuid in serialized + +# the dictionary has a list of objects and the root node +assert a_literal == { + 'objects': { + a.ana_uuid: { 'class': a.__class__.__name__, 'object': a._get_state() } + }, + 'value': { 'ana_uuid': a.ana_uuid } +} + +# in this case, the literal value would be, with an example UUID: +assert a.ana_uuid == "142be0d1-e3b4-4d7e-a2ce-9842285f3b18" # let's pretend +assert a_literal == { + 'objects': { + '142be0d1-e3b4-4d7e-a2ce-9842285f3b18': { + 'class': 'A', + 'object': 10 + } + }, + 'value': { 'ana_uuid': '142be0d1-e3b4-4d7e-a2ce-9842285f3b18' } +} + +# if you serialize this again, with the same serialized set, ANA is +# smart enough to avoid re-serializing objects +assert a.to_literal(serialized) == { + 'objects': { } + 'value': { 'ana_uuid': '142be0d1-e3b4-4d7e-a2ce-9842285f3b18' } +} + +# furthermore, object trees are properly handled +b = A(20) +a.n = b +serialized = set() + +assert b.ana_uuid == "fbda537c-38f0-4db7-b5f2-3e3d8afe7c1f" # some more pretending +assert a.to_literal(serialized) == { + 'objects': { + '142be0d1-e3b4-4d7e-a2ce-9842285f3b18': { + 'class': 'A', + 'object': { 'ana_uuid': 'fbda537c-38f0-4db7-b5f2-3e3d8afe7c1f' + }, + 'fbda537c-38f0-4db7-b5f2-3e3d8afe7c1f': { + 'class': 'A', + 'object': 20 + } + } + 'value': { 'ana_uuid': '142be0d1-e3b4-4d7e-a2ce-9842285f3b18' } +} +``` + +This can then be serialized out to JSON with something like `json.dumps(a_literal)`! + +## Storage Backends + +There are several storage backends for ANA: + +| Backend | Description | +|---------|-------------| +| Simple (default) | This backend is basically a pickle passthrough, and serialization just works normally through pickle. | +| Dict | With this backend, the pickled states are held in a dict. The dict can be a distributed storage structure (i.e., redis or something). This can be initialized as: ana.set_dl(ana.DictDataLayer(the_dict={}))` | +| Directory | With this backend, states are pickled into a directory. This can be created by passing the `pickle_dir` option to ana.set_dl(), like so: `ana.set_dl(ana.DirDataLayer("/dev/shm/ana_storage"))` | +| MongoDB | With this backend, states are pickled into mongodb. This can be created by passing the `mongo_args`, `mongo_db`, and `mongo_collection` options to `ana.set_dl(ana.MongoDataLayer(mongo_args, mongo_db=mongo_db, mongo_collection=mongo_collection))`. These are passed into pymongo, like so: `pymongo.MongoClient(*mongo_args)[mongo_db][mongo_collection]` | diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ana-0.05/setup.py new/ana-0.06/setup.py --- old/ana-0.05/setup.py 2018-03-28 01:17:53.000000000 +0200 +++ new/ana-0.06/setup.py 2019-06-06 23:00:54.000000000 +0200 @@ -1,2 +1,2 @@ from distutils.core import setup -setup(name='ana', version='0.05', install_requires=['future'], packages=['ana']) +setup(name='ana', version='0.06', install_requires=['future'], packages=['ana']) ++++++ test.py ++++++ import os import gc import ana import nose import pickle import logging l = logging.getLogger("ana.test") class A(ana.Storable): def __init__(self, n): nose.tools.assert_false(hasattr(self, 'n')) self.n = n l.debug("%s.__init__", self) def __repr__(self): return "<A %s>" % str(self.n) def _ana_getstate(self): l.debug("%s._ana_getstate", self) return (self.n,) def _ana_setstate(self, s): self.n = s[0] l.debug("%s._ana_setstate", self) def _ana_getliteral(self): return { 'n': self.n } def test_simple(): ana.set_dl(ana.SimpleDataLayer()) one = A(1) one.make_uuid() o = pickle.dumps(one) one_copy = pickle.loads(o) assert one is one_copy two = A(1) t = pickle.dumps(one) two_copy = pickle.loads(t) assert two_copy is not two assert pickle.load(open(os.path.join(os.path.dirname(__file__), 'test_pickle.p'), 'rb')).n == 1337 def write_a1337(): a1337 = A(1337) a1337.make_uuid() pickle.dump(a1337, open(os.path.join(os.path.dirname(__file__), 'test_pickle.p'), 'w')) def test_dict(): ana.set_dl(ana.DictDataLayer()) l.debug("Initializing 1") one = A(1) l.debug("Initializing 2") two = A(2) one.make_uuid() l.debug("Copying 1") one_p = pickle.dumps(one) one_copy = pickle.loads(one_p) l.debug("Copying 2") two_p = pickle.dumps(two) two_copy = pickle.loads(two_p) nose.tools.assert_is(one_copy, one) nose.tools.assert_is_not(two_copy, two) nose.tools.assert_equal(str(two_copy), str(two)) nose.tools.assert_is(one, A.ana_load(one.ana_store())) nose.tools.assert_is(two, A.ana_load(two.ana_store())) two_copy2 = pickle.loads(pickle.dumps(two)) nose.tools.assert_equal(str(two_copy2), str(two)) l.debug("Initializing 3") three = A(3) three_str = str(three) l.debug("Storing 3") three_uuid = three.ana_store() l.debug("Deleting 3") del three gc.collect() nose.tools.assert_false(three_uuid in ana.get_dl().uuid_cache) l.debug("Loading 3") three_copy = A.ana_load(three_uuid) nose.tools.assert_equal(three_copy.ana_uuid, three_uuid) #pylint:disable=no-member nose.tools.assert_equal(str(three_copy), three_str) known = set() first_json = three_copy.to_literal(known) nose.tools.assert_true(three_copy.ana_uuid in first_json['objects']) nose.tools.assert_equal(first_json['objects'][three_copy.ana_uuid]['object']['n'], three_copy.n) nose.tools.assert_equal(first_json['value']['ana_uuid'], three_copy.ana_uuid) second_json = three_copy.to_literal(known) nose.tools.assert_false(three_copy.ana_uuid in second_json['objects']) nose.tools.assert_equal(second_json['value']['ana_uuid'], three_copy.ana_uuid) def test_dir(): ana.dl = ana.DirDataLayer(pickle_dir="/tmp/test_ana") one = A(1) nose.tools.assert_is(one, A.ana_load(one.ana_store())) nose.tools.assert_true(os.path.exists("/tmp/test_ana/%s.p" % one.ana_uuid)) uuid = one.ana_uuid old_id = id(one) del one gc.collect() ana.dl = ana.DirDataLayer(pickle_dir="/tmp/test_ana") two = A.ana_load(uuid) nose.tools.assert_equals(uuid, two.ana_uuid) nose.tools.assert_not_equals(old_id, id(two)) # reset the datalayer to make sure we handle it properly ana.set_dl(ana.DictDataLayer()) try: two = A.ana_load(uuid) assert False except KeyError: pass two.ana_store() del two three = A.ana_load(uuid) assert uuid, three.ana_uuid if __name__ == '__main__': import sys logging.getLogger("ana.test").setLevel(logging.DEBUG) logging.getLogger("ana.storable").setLevel(logging.DEBUG) logging.getLogger("ana.datalayer").setLevel(logging.DEBUG) logging.getLogger("ana.d").setLevel(logging.DEBUG) if len(sys.argv) > 1: globals()['test_%s' % sys.argv[1]]() else: test_simple() test_dict() test_dir() ++++++ test_pickle.p ++++++ cana.d D p0 (S'bcf9e574-7901-4292-8873-5423edb1ca1c' p1 ctest A p2 (I1337 tp3 tp4 Rp5 .