From 60d16934689776070ced26738f91c2c3735c35a4 Mon Sep 17 00:00:00 2001 From: Max Tepkeev Date: Wed, 5 Nov 2014 19:05:45 +0300 Subject: [PATCH] issue #64 --- CHANGELOG.rst | 5 +++-- redmine/resources.py | 3 +++ tests/test_managers.py | 9 +++++++++ tests/test_redmine.py | 15 +++++++-------- tests/test_resources.py | 8 ++++++++ tests/test_resultsets.py | 8 ++++++++ 6 files changed, 38 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index a404899..02b9d2c 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,7 +1,7 @@ Changelog --------- -1.0.2 (2014-10-XX) +1.0.2 (2014-11-XX) ++++++++++++++++++ - Fixed: `Issue #55 `__ (TypeError was @@ -9,7 +9,8 @@ Changelog a list) - Fixed: `Issue #59 `__ (Raise ForbiddenError when a 403 is encountered) (thanks to `Rick Harris `__) -- Fixed: `Issue #64 `__ (Make the Redmine class picklable) (thanks to `Rick Harris `__) +- Fixed: `Issue #64 `__ (Redmine and Resource + classes weren't picklable) (thanks to `Rick Harris `__) 1.0.1 (2014-09-23) ++++++++++++++++++ diff --git a/redmine/resources.py b/redmine/resources.py index 817e5d6..4b096d7 100644 --- a/redmine/resources.py +++ b/redmine/resources.py @@ -140,6 +140,9 @@ def __setitem__(self, item, value): def __getattr__(self, item): """Returns the requested attribute and makes a conversion if needed""" + if item.startswith('_'): + raise AttributeError + if item in self._attributes: # If item shouldn't be converted let's return it as it is if item in self._unconvertible: diff --git a/tests/test_managers.py b/tests/test_managers.py index 22bfc8a..b96169d 100644 --- a/tests/test_managers.py +++ b/tests/test_managers.py @@ -226,6 +226,15 @@ def test_update_validation_exception(self): def test_delete_validation_exception(self): self.assertRaises(ValidationError, lambda: self.redmine.wiki_page.delete('Foo')) + def test_manager_is_picklable(self): + import pickle + project = self.redmine.project + project.url = 'foo' + project.params = {'foo': 'bar'} + unpickled_project = pickle.loads(pickle.dumps(project)) + self.assertEqual(project.url, unpickled_project.url) + self.assertEqual(project.params['foo'], unpickled_project.params['foo']) + @mock.patch('requests.put') @mock.patch('requests.post') def test_create_validation_exception_via_put(self, mock_post, mock_put): diff --git a/tests/test_redmine.py b/tests/test_redmine.py index 12a35ab..242c741 100644 --- a/tests/test_redmine.py +++ b/tests/test_redmine.py @@ -164,11 +164,10 @@ def test_auth(self): self.response.json = json_response({'user': {'firstname': 'John', 'lastname': 'Smith', 'id': 1}}) self.assertEqual(self.redmine.auth().firstname, 'John') - def test_getattr_on_under_attribute(self): - """ - Attributes that begin with an underscore should not be treated as a - `Resource`. The impetus of this was to make `Redmine` picklable by - preventing the `__getstate__` access from being treated a `Resource`. - """ - with self.assertRaises(AttributeError): - self.redmine.__getstate__ + def test_redmine_is_picklable(self): + import pickle + redmine = pickle.loads(pickle.dumps(self.redmine)) + self.assertEqual(redmine.key, self.redmine.key) + self.assertEqual(redmine.username, self.redmine.username) + self.assertEqual(redmine.password, self.redmine.password) + self.assertEqual(redmine.requests, self.redmine.requests) diff --git a/tests/test_resources.py b/tests/test_resources.py index 029c29e..1d36fa7 100644 --- a/tests/test_resources.py +++ b/tests/test_resources.py @@ -251,6 +251,14 @@ def test_setting_custom_field_raises_exception_if_not_list_of_dicts(self): with self.assertRaises(CustomFieldValueError): project.custom_fields = 'foo' + def test_resource_is_picklable(self): + import pickle + self.response.json = json_response(responses['project']['get']) + project = self.redmine.project.get(1) + unpickled_project = pickle.loads(pickle.dumps(project)) + self.assertEqual(project.id, unpickled_project.id) + self.assertEqual(project.name, unpickled_project.name) + def test_project_version(self): self.assertEqual(self.redmine.project.resource_class.redmine_version, '1.0') diff --git a/tests/test_resultsets.py b/tests/test_resultsets.py index 2bdbd7e..90d393f 100644 --- a/tests/test_resultsets.py +++ b/tests/test_resultsets.py @@ -156,6 +156,14 @@ def test_values_resourceset_update_method(self): self.assertEqual(projects[1]['name'], 'FooBar') self.assertEqual(projects[2]['name'], 'FooBar') + def test_resourceset_is_picklable(self): + import pickle + projects = self.redmine.project.all() + unpickled_projects = pickle.loads(pickle.dumps(projects)) + self.assertEqual(projects[0]['name'], unpickled_projects[0]['name']) + self.assertEqual(projects[1]['name'], unpickled_projects[1]['name']) + self.assertEqual(projects[2]['name'], unpickled_projects[2]['name']) + def test_values_resourceset_delete_method(self): self.assertEqual(self.redmine.project.all().values().delete(), True)