![](https://seccdn.libravatar.org/avatar/e2145bc5cf53dda95c308a3c75e8fef3.jpg?s=120&d=mm&r=g)
Hello community, here is the log from the commit of package python-warlock for openSUSE:Factory checked in at 2013-02-25 20:42:06 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-warlock (Old) and /work/SRC/openSUSE:Factory/.python-warlock.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "python-warlock", Maintainer is "radmanic@suse.com" Changes: -------- --- /work/SRC/openSUSE:Factory/python-warlock/python-warlock.changes 2012-11-28 14:35:25.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.python-warlock.new/python-warlock.changes 2013-02-25 20:42:07.000000000 +0100 @@ -1,0 +2,7 @@ +Fri Feb 22 14:05:28 UTC 2013 - saschpe@suse.de + +- Update to version 0.8.1: + + Upstream provides no changelog +- LICENSE isn't part of upstream sources anymore + +------------------------------------------------------------------- Old: ---- warlock-0.6.0.tar.gz New: ---- warlock-0.8.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-warlock.spec ++++++ --- /var/tmp/diff_new_pack.fSqgBj/_old 2013-02-25 20:42:09.000000000 +0100 +++ /var/tmp/diff_new_pack.fSqgBj/_new 2013-02-25 20:42:09.000000000 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-warlock # -# Copyright (c) 2012 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -13,19 +13,22 @@ # published by the Open Source Initiative. # Please submit bugfixes or comments via http://bugs.opensuse.org/ +# Name: python-warlock -Version: 0.6.0 +Version: 0.8.1 Release: 0 -License: Apache-2.0 Summary: Python object model built on top of JSON schema -Url: http://github.com/bcwaldon/warlock +License: Apache-2.0 Group: Development/Languages/Python +Url: http://github.com/bcwaldon/warlock Source: http://pypi.python.org/packages/source/w/warlock/warlock-%{version}.tar.gz BuildRequires: python-devel BuildRequires: python-distribute +BuildRequires: python-jsonpatch BuildRequires: python-jsonschema +Requires: python-jsonpatch Requires: python-jsonschema BuildRoot: %{_tmppath}/%{name}-%{version}-build %if 0%{?suse_version} && 0%{?suse_version} <= 1110 @@ -51,7 +54,7 @@ %files %defattr(-,root,root,-) -%doc LICENSE README.md +%doc README.md %{python_sitelib}/* %changelog ++++++ warlock-0.6.0.tar.gz -> warlock-0.8.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/warlock-0.6.0/LICENSE new/warlock-0.8.1/LICENSE --- old/warlock-0.6.0/LICENSE 2012-07-27 20:15:34.000000000 +0200 +++ new/warlock-0.8.1/LICENSE 1970-01-01 01:00:00.000000000 +0100 @@ -1,176 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/warlock-0.6.0/PKG-INFO new/warlock-0.8.1/PKG-INFO --- old/warlock-0.6.0/PKG-INFO 2012-11-19 23:03:20.000000000 +0100 +++ new/warlock-0.8.1/PKG-INFO 2013-01-31 16:47:28.000000000 +0100 @@ -1,7 +1,7 @@ Metadata-Version: 1.0 Name: warlock -Version: 0.6.0 -Summary: Python object model built on top of JSON schema +Version: 0.8.1 +Summary: Python object model built on JSON schema and JSON patch. Home-page: http://github.com/bcwaldon/warlock Author: Brian Waldon Author-email: bcwaldon@gmail.com diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/warlock-0.6.0/README.md new/warlock-0.8.1/README.md --- old/warlock-0.6.0/README.md 2012-07-27 20:15:34.000000000 +0200 +++ new/warlock-0.8.1/README.md 2013-01-31 16:44:57.000000000 +0100 @@ -1,43 +1,46 @@ -# Warlock! +# Warlock -## Wat +Build self-validating python objects using JSON schemas. -Build self-validating python objects using JSON schemas +1) Create your schema -## How - -1) Build your schema - - >>> schema = { - 'name': 'Country', - 'properties': { - 'name': {'type': 'string'}, - 'abbreviation': {'type': 'string'}, - }, - 'additionalProperties': False, - } + >>> schema = { + 'name': 'Country', + 'properties': { + 'name': {'type': 'string'}, + 'abbreviation': {'type': 'string'}, + 'population': {'type': 'integer'}, + }, + 'additionalProperties': False, + } 2) Create a model >>> import warlock - >>> Country = warlock.model_factory(schema) + >>> Country = warlock.model_factory(schema) 3) Create an object using your model - >>> sweden = Country(name='Sweden', abbreviation='SE') + >>> sweden = Country(name='Sweden', abbreviation='SE') -4) Let the object validate itself! +4) Let the object validate itself >>> sweden.name = 5 Traceback (most recent call last): - File "<stdin>", line 1, in <module> + File "<stdin>", line 1, in <module> File "warlock/core.py", line 53, in __setattr__ - raise InvalidOperation() - warlock.core.InvalidOperation + raise InvalidOperation(msg) + warlock.core.InvalidOperation: Unable to set 'name' to '5' >>> sweden.overlord = 'Bears' Traceback (most recent call last): - File "<stdin>", line 1, in <module> + File "<stdin>", line 1, in <module> File "warlock/core.py", line 53, in __setattr__ - raise InvalidOperation() - warlock.core.InvalidOperation \ No newline at end of file + raise InvalidOperation(msg) + warlock.core.InvalidOperation: Unable to set 'overlord' to 'Bears' + +5) Generate a [JSON Patch document](http://tools.ietf.org/html/draft-ietf-appsawg-json-patch) to track changes + + >>> sweden.population=9453000 + >>> sweden.patch + '[{"path": "/population", "value": 9453000, "op": "add"}]' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/warlock-0.6.0/requirements.txt new/warlock-0.8.1/requirements.txt --- old/warlock-0.6.0/requirements.txt 2012-11-19 22:45:50.000000000 +0100 +++ new/warlock-0.8.1/requirements.txt 2013-01-21 18:27:49.000000000 +0100 @@ -1 +1,2 @@ jsonschema>=0.7,<1 +jsonpatch>=0.10,<=0.12 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/warlock-0.6.0/setup.py new/warlock-0.8.1/setup.py --- old/warlock-0.6.0/setup.py 2012-11-19 23:00:48.000000000 +0100 +++ new/warlock-0.8.1/setup.py 2013-01-31 16:46:08.000000000 +0100 @@ -1,3 +1,17 @@ +# Copyright 2012 Brian Waldon +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import setuptools @@ -6,13 +20,12 @@ raw_req = fap.read() fap.close() return raw_req.split('\n') - return ['jsonschema'] setuptools.setup( name='warlock', - version='0.6.0', - description='Python object model built on top of JSON schema', + version='0.8.1', + description='Python object model built on JSON schema and JSON patch.', author='Brian Waldon', author_email='bcwaldon@gmail.com', url='http://github.com/bcwaldon/warlock', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/warlock-0.6.0/test/test_core.py new/warlock-0.8.1/test/test_core.py --- old/warlock-0.6.0/test/test_core.py 2012-10-09 19:51:12.000000000 +0200 +++ new/warlock-0.8.1/test/test_core.py 2013-01-31 16:14:04.000000000 +0100 @@ -1,3 +1,17 @@ +# Copyright 2012 Brian Waldon +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import copy import unittest @@ -113,15 +127,27 @@ self.assertRaises(exc, sweden.clear) self.assertRaises(exc, sweden.pop, 0) self.assertRaises(exc, sweden.popitem) - self.assertRaises(exc, sweden.__delitem__, 'name') def test_dict_syntax(self): Country = warlock.model_factory(fixture) sweden = Country(name='Sweden', population=9379116) - self.assertEqual(sweden['name'], 'Sweden') + sweden['name'] = 'Finland' self.assertEqual(sweden['name'], 'Finland') + del sweden['name'] + self.assertRaises(AttributeError, getattr, sweden, 'name') + + def test_attr_syntax(self): + Country = warlock.model_factory(fixture) + sweden = Country(name='Sweden', population=9379116) + + sweden.name = 'Finland' + self.assertEqual(sweden.name, 'Finland') + + delattr(sweden, 'name') + self.assertRaises(AttributeError, getattr, sweden, 'name') + def test_changes(self): Country = warlock.model_factory(fixture) sweden = Country(name='Sweden', population=9379116) @@ -130,3 +156,47 @@ self.assertEqual(sweden.changes, {'name': 'Finland'}) sweden['name'] = 'Norway' self.assertEqual(sweden.changes, {'name': 'Norway'}) + + def test_patch_no_changes(self): + Country = warlock.model_factory(fixture) + sweden = Country(name='Sweden', population=9379116) + self.assertEqual(sweden.patch, '[]') + + def test_patch_alter_value(self): + Country = warlock.model_factory(fixture) + sweden = Country(name='Sweden', population=9379116) + sweden['name'] = 'Finland' + self.assertEqual( + sweden.patch, + '[{"path": "/name", "value": "Finland", "op": "replace"}]') + + def test_patch_drop_attribute(self): + Country = warlock.model_factory(fixture) + sweden = Country(name='Sweden', population=9379116) + del sweden['name'] + self.assertEqual(sweden.patch, '[{"path": "/name", "op": "remove"}]') + + def test_patch_reduce_operations(self): + Country = warlock.model_factory(fixture) + sweden = Country(name='Sweden', population=9379116) + + sweden['name'] = 'Finland' + self.assertEqual( + sweden.patch, + '[{"path": "/name", "value": "Finland", "op": "replace"}]') + + sweden['name'] = 'Norway' + self.assertEqual( + sweden.patch, + '[{"path": "/name", "value": "Norway", "op": "replace"}]') + + def test_patch_multiple_operations(self): + Country = warlock.model_factory(fixture) + sweden = Country(name='Sweden', population=9379116) + + sweden['name'] = 'Finland' + sweden['population'] = 5387000 + self.assertEqual( + sweden.patch, + '[{"path": "/name", "value": "Finland", "op": "replace"}, ' + '{"path": "/population", "value": 5387000, "op": "replace"}]') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/warlock-0.6.0/warlock/__init__.py new/warlock-0.8.1/warlock/__init__.py --- old/warlock-0.6.0/warlock/__init__.py 2012-07-27 20:15:34.000000000 +0200 +++ new/warlock-0.8.1/warlock/__init__.py 2013-01-31 16:37:47.000000000 +0100 @@ -1,5 +1,19 @@ +# Copyright 2012 Brian Waldon +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + """Public-facing Warlock API""" # pylint: disable=W0611 from warlock.core import model_factory -from warlock.core import InvalidOperation +from warlock.exceptions import InvalidOperation diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/warlock-0.6.0/warlock/core.py new/warlock-0.8.1/warlock/core.py --- old/warlock-0.6.0/warlock/core.py 2012-11-19 22:55:38.000000000 +0100 +++ new/warlock-0.8.1/warlock/core.py 2013-01-31 16:15:12.000000000 +0100 @@ -1,111 +1,35 @@ +# Copyright 2012 Brian Waldon +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + """Core Warlock functionality""" import copy -import jsonschema - - -class InvalidOperation(RuntimeError): - pass - +import model -class ValidationError(ValueError): - pass - -def model_factory(schema): +def model_factory(schema, base_class=model.Model): """Generate a model class based on the provided JSON Schema :param schema: dict representing valid JSON schema """ schema = copy.deepcopy(schema) - def validator(obj): - """Apply a JSON schema to an object""" - try: - jsonschema.validate(obj, schema) - except jsonschema.ValidationError as exc: - raise ValidationError(str(exc)) - - class Model(dict): - """Self-validating model for arbitrary objects""" - + class Model(base_class): def __init__(self, *args, **kwargs): - d = dict(*args, **kwargs) - - # we overload setattr so set this manually - self.__dict__['validator'] = validator - try: - self.validator(d) - except ValidationError as exc: - raise ValueError(str(exc)) - else: - dict.__init__(self, d) - - self.__dict__['changes'] = {} - - def __getattr__(self, key): - try: - return self.__getitem__(key) - except KeyError: - raise AttributeError(key) - - def __setitem__(self, key, value): - mutation = dict(self.items()) - mutation[key] = value - try: - self.validator(mutation) - except ValidationError: - msg = "Unable to set '%s' to '%s'" % (key, value) - raise InvalidOperation(msg) - - dict.__setitem__(self, key, value) - - self.__dict__['changes'][key] = value - - def __setattr__(self, key, value): - self.__setitem__(key, value) - - def clear(self): - raise InvalidOperation() - - def pop(self, key, default=None): - raise InvalidOperation() - - def popitem(self): - raise InvalidOperation() - - def __delitem__(self, key): - raise InvalidOperation() - - # NOTE(termie): This is kind of the opposite of what copy usually does - def copy(self): - return copy.deepcopy(dict(self)) - - def update(self, other): - mutation = dict(self.items()) - mutation.update(other) - try: - self.validator(mutation) - except ValidationError as exc: - raise InvalidOperation(str(exc)) - dict.update(self, other) - - def iteritems(self): - return copy.deepcopy(dict(self)).iteritems() - - def items(self): - return copy.deepcopy(dict(self)).items() - - def itervalues(self): - return copy.deepcopy(dict(self)).itervalues() - - def values(self): - return copy.deepcopy(dict(self)).values() - - @property - def changes(self): - return copy.deepcopy(self.__dict__['changes']) + self.__dict__['schema'] = schema + base_class.__init__(self, *args, **kwargs) Model.__name__ = str(schema['name']) return Model diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/warlock-0.6.0/warlock/exceptions.py new/warlock-0.8.1/warlock/exceptions.py --- old/warlock-0.6.0/warlock/exceptions.py 1970-01-01 01:00:00.000000000 +0100 +++ new/warlock-0.8.1/warlock/exceptions.py 2013-01-31 16:12:34.000000000 +0100 @@ -0,0 +1,23 @@ +# Copyright 2012 Brian Waldon +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" List of errors used in warlock """ + + +class InvalidOperation(RuntimeError): + pass + + +class ValidationError(ValueError): + pass diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/warlock-0.6.0/warlock/model.py new/warlock-0.8.1/warlock/model.py --- old/warlock-0.6.0/warlock/model.py 1970-01-01 01:00:00.000000000 +0100 +++ new/warlock-0.8.1/warlock/model.py 2013-01-31 16:12:44.000000000 +0100 @@ -0,0 +1,129 @@ +# Copyright 2012 Brian Waldon +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Self-validating model for arbitrary objects""" + +import copy + +import jsonpatch +import jsonschema + +import exceptions + + +class Model(dict): + def __init__(self, *args, **kwargs): + # we overload setattr so set this manually + d = dict(*args, **kwargs) + + try: + self.validate(d) + except exceptions.ValidationError as exc: + raise ValueError(str(exc)) + else: + dict.__init__(self, d) + + self.__dict__['changes'] = {} + self.__dict__['__original__'] = copy.deepcopy(d) + + def __setitem__(self, key, value): + mutation = dict(self.items()) + mutation[key] = value + try: + self.validate(mutation) + except exceptions.ValidationError: + msg = "Unable to set '%s' to '%s'" % (key, value) + raise exceptions.InvalidOperation(msg) + + dict.__setitem__(self, key, value) + + self.__dict__['changes'][key] = value + + def __delitem__(self, key): + mutation = dict(self.items()) + del mutation[key] + try: + self.validate(mutation) + except exceptions.ValidationError: + msg = "Unable to delete attribute '%s'" % (key) + raise exceptions.InvalidOperation(msg) + + dict.__delitem__(self, key) + + def __getattr__(self, key): + try: + return self.__getitem__(key) + except KeyError: + raise AttributeError(key) + + def __setattr__(self, key, value): + self.__setitem__(key, value) + + def __delattr__(self, key): + self.__delitem__(key) + + ### BEGIN dict compatibility methods ### + + def clear(self): + raise exceptions.InvalidOperation() + + def pop(self, key, default=None): + raise exceptions.InvalidOperation() + + def popitem(self): + raise exceptions.InvalidOperation() + + def copy(self): + return copy.deepcopy(dict(self)) + + def update(self, other): + mutation = dict(self.items()) + mutation.update(other) + try: + self.validate(mutation) + except exceptions.ValidationError as exc: + raise exceptions.InvalidOperation(str(exc)) + dict.update(self, other) + + def iteritems(self): + return copy.deepcopy(dict(self)).iteritems() + + def items(self): + return copy.deepcopy(dict(self)).items() + + def itervalues(self): + return copy.deepcopy(dict(self)).itervalues() + + def values(self): + return copy.deepcopy(dict(self)).values() + + ### END dict compatibility methods ### + + @property + def patch(self): + """Return a jsonpatch object representing the delta""" + original = self.__dict__['__original__'] + return jsonpatch.make_patch(original, dict(self)).to_string() + + @property + def changes(self): + """Dumber version of 'patch' method - this should be deprecated""" + return copy.deepcopy(self.__dict__['changes']) + + def validate(self, obj): + """Apply a JSON schema to an object""" + try: + jsonschema.validate(obj, self.schema) + except jsonschema.ValidationError as exc: + raise exceptions.ValidationError(str(exc)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/warlock-0.6.0/warlock.egg-info/PKG-INFO new/warlock-0.8.1/warlock.egg-info/PKG-INFO --- old/warlock-0.6.0/warlock.egg-info/PKG-INFO 2012-11-19 23:03:20.000000000 +0100 +++ new/warlock-0.8.1/warlock.egg-info/PKG-INFO 2013-01-31 16:47:28.000000000 +0100 @@ -1,7 +1,7 @@ Metadata-Version: 1.0 Name: warlock -Version: 0.6.0 -Summary: Python object model built on top of JSON schema +Version: 0.8.1 +Summary: Python object model built on JSON schema and JSON patch. Home-page: http://github.com/bcwaldon/warlock Author: Brian Waldon Author-email: bcwaldon@gmail.com diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/warlock-0.6.0/warlock.egg-info/SOURCES.txt new/warlock-0.8.1/warlock.egg-info/SOURCES.txt --- old/warlock-0.6.0/warlock.egg-info/SOURCES.txt 2012-11-19 23:03:20.000000000 +0100 +++ new/warlock-0.8.1/warlock.egg-info/SOURCES.txt 2013-01-31 16:47:28.000000000 +0100 @@ -1,4 +1,3 @@ -LICENSE MANIFEST.in README.md requirements.txt @@ -6,6 +5,8 @@ test/test_core.py warlock/__init__.py warlock/core.py +warlock/exceptions.py +warlock/model.py warlock.egg-info/PKG-INFO warlock.egg-info/SOURCES.txt warlock.egg-info/dependency_links.txt diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/warlock-0.6.0/warlock.egg-info/requires.txt new/warlock-0.8.1/warlock.egg-info/requires.txt --- old/warlock-0.6.0/warlock.egg-info/requires.txt 2012-11-19 23:03:20.000000000 +0100 +++ new/warlock-0.8.1/warlock.egg-info/requires.txt 2013-01-31 16:47:28.000000000 +0100 @@ -1 +1,2 @@ -jsonschema>=0.7,<1 \ No newline at end of file +jsonschema>=0.7,<1 +jsonpatch>=0.10,<=0.12 \ No newline at end of file -- To unsubscribe, e-mail: opensuse-commit+unsubscribe@opensuse.org For additional commands, e-mail: opensuse-commit+help@opensuse.org