From 12b3ea2e40083fe0b30b6a971a1b187e2c8ac39b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Opa=C5=82czy=C5=84ski?= Date: Thu, 25 Aug 2016 11:52:30 +0200 Subject: [PATCH 1/7] [LIB-849] fix for filtering; --- syncano/models/manager.py | 13 ++++++++++--- tests/integration_test_relations.py | 7 +++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/syncano/models/manager.py b/syncano/models/manager.py index 07d6d5c..c6ab313 100644 --- a/syncano/models/manager.py +++ b/syncano/models/manager.py @@ -972,9 +972,16 @@ def _build_query(self, query_data, **kwargs): if self.LOOKUP_SEPARATOR in field_name: model_name, field_name, lookup = self._get_lookup_attributes(field_name) - for field in model._meta.fields: - if field.name == field_name: - break + # if filter is made on relation field: relation__name__eq='test'; + if model_name: + for field in model._meta.fields: + if field.name == model_name: + break + # if filter is made on normal field: name__eq='test'; + else: + for field in model._meta.fields: + if field.name == field_name: + break self._validate_lookup(model, model_name, field_name, lookup, field) diff --git a/tests/integration_test_relations.py b/tests/integration_test_relations.py index 37348b6..7b01efc 100644 --- a/tests/integration_test_relations.py +++ b/tests/integration_test_relations.py @@ -90,3 +90,10 @@ def test_related_field_lookup_is(self): self.assertEqual(len(list(filtered_books)), 1) for book in filtered_books: self.assertEqual(book.title, self.niezwyciezony.title) + + def test_multiple_lookups(self): + filtered_books = self.books.objects.list().filter(authors__id__in=[self.prus.id], title__eq='Lalka') + + self.assertEqual(len(list(filtered_books)), 1) + for book in filtered_books: + self.assertEqual(book.title, self.niezwyciezony.title) From 165bd59ea476dc047664429d0900c23a434a1691 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Opa=C5=82czy=C5=84ski?= Date: Thu, 25 Aug 2016 12:03:22 +0200 Subject: [PATCH 2/7] [LIB-849] correct naming; --- tests/integration_test_relations.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/integration_test_relations.py b/tests/integration_test_relations.py index 7b01efc..980f69c 100644 --- a/tests/integration_test_relations.py +++ b/tests/integration_test_relations.py @@ -3,11 +3,11 @@ from tests.integration_test import InstanceMixin, IntegrationTest -class ResponseTemplateApiTest(InstanceMixin, IntegrationTest): +class RelationApiTest(InstanceMixin, IntegrationTest): @classmethod def setUpClass(cls): - super(ResponseTemplateApiTest, cls).setUpClass() + super(RelationApiTest, cls).setUpClass() # prapare data cls.author = Class.please.create(name="author", schema=[ @@ -92,7 +92,7 @@ def test_related_field_lookup_is(self): self.assertEqual(book.title, self.niezwyciezony.title) def test_multiple_lookups(self): - filtered_books = self.books.objects.list().filter(authors__id__in=[self.prus.id], title__eq='Lalka') + filtered_books = self.book.objects.list().filter(authors__id__in=[self.prus.id], title__eq='Lalka') self.assertEqual(len(list(filtered_books)), 1) for book in filtered_books: From 27ae02f40b5b65165afc24c142e3e70de693c60c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Opa=C5=82czy=C5=84ski?= Date: Thu, 25 Aug 2016 12:25:34 +0200 Subject: [PATCH 3/7] [LIB-849] correct naming; --- tests/integration_test_relations.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration_test_relations.py b/tests/integration_test_relations.py index 980f69c..052a424 100644 --- a/tests/integration_test_relations.py +++ b/tests/integration_test_relations.py @@ -96,4 +96,4 @@ def test_multiple_lookups(self): self.assertEqual(len(list(filtered_books)), 1) for book in filtered_books: - self.assertEqual(book.title, self.niezwyciezony.title) + self.assertEqual(book.title, self.lalka.title) From 962253e4db463a5522568d57b04ae236187c900f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Opa=C5=82czy=C5=84ski?= Date: Mon, 29 Aug 2016 13:57:28 +0200 Subject: [PATCH 4/7] [LIB-852] re-work hosting; add HostingFile models; add update_file method; --- syncano/models/hosting.py | 80 ++++++++++++++++++++++++++---- tests/integration_tests_hosting.py | 21 ++++++-- 2 files changed, 87 insertions(+), 14 deletions(-) diff --git a/syncano/models/hosting.py b/syncano/models/hosting.py index 39c32e7..92f6afe 100644 --- a/syncano/models/hosting.py +++ b/syncano/models/hosting.py @@ -1,4 +1,7 @@ # -*- coding: utf-8 -*- + +from syncano.exceptions import SyncanoRequestError + from . import fields from .base import Instance, Model, logger @@ -31,24 +34,51 @@ class Meta: } def upload_file(self, path, file): + """ + Upload a new file to the hosting. + :param path: the file path; + :param file: the file to be uploaded; + :return: the response from the API; + """ files_path = self.links.files data = {'path': path} connection = self._get_connection() - params = connection.build_params(params={}) - headers = params['headers'] - headers.pop('content-type') - response = connection.session.post(connection.host + files_path, headers=headers, + headers = self._prepare_header(connection) + response = connection.session.post('{}{}'.format(connection.host, files_path), headers=headers, data=data, files=[('file', file)]) if response.status_code != 201: logger.error(response.text) return - return response + return HostingFile(**response.json()) + + def update_file(self, path, file): + """ + Updates an existing file. + :param path: the file path; + :param file: the file to be uploaded; + :return: the response from the API; + """ + hosting_files = self._get_files() + is_found = False + for hosting_file in hosting_files: + if hosting_file.path == path: + is_found = True + break + + if not is_found: + raise SyncanoRequestError('File with path {} not found.'.format(path)) - def list_files(self): - files_path = self.links.files connection = self._get_connection() - response = connection.request('GET', files_path) - return [f['path'] for f in response['objects']] + headers = self._prepare_header(connection) + response = connection.session.patch('{}{}'.format(connection.host, hosting_file.links.self), headers=headers, + files=[('file', file)]) + if response.status_code != 200: + logger.error(response.text) + return + return HostingFile(**response.json()) + + def list_files(self): + return self._get_files() def set_default(self): default_path = self.links.set_default @@ -57,3 +87,35 @@ def set_default(self): response = connection.make_request('POST', default_path) self.to_python(response) return self + + def _prepare_header(self, connection): + params = connection.build_params(params={}) + headers = params['headers'] + headers.pop('content-type') + return headers + + def _get_files(self): + return [hfile for hfile in HostingFile.please.list(hosting_id=self.id)] + + +class HostingFile(Model): + """ + OO wrapper around hosting file. + """ + + path = fields.StringField(max_length=300) + file = fields.FileField() + links = fields.LinksField() + + class Meta: + parent = Hosting + endpoints = { + 'detail': { + 'methods': ['delete', 'get', 'put', 'patch'], + 'path': '/files/{id}/', + }, + 'list': { + 'methods': ['post', 'get'], + 'path': '/files/', + } + } diff --git a/tests/integration_tests_hosting.py b/tests/integration_tests_hosting.py index 8056ae1..1be56a5 100644 --- a/tests/integration_tests_hosting.py +++ b/tests/integration_tests_hosting.py @@ -25,12 +25,23 @@ def test_create_file(self): a_hosting_file.write('h1 {color: #541231;}') a_hosting_file.seek(0) - self.hosting.upload_file(path='styles/main.css', file=a_hosting_file) - - files_list = self.hosting.list_files() - - self.assertIn('styles/main.css', files_list) + hosting_file = self.hosting.upload_file(path='styles/main.css', file=a_hosting_file) + self.assertEqual(hosting_file.path, 'styles/main.css') def test_set_default(self): hosting = self.hosting.set_default() self.assertIn('default', hosting.domains) + + def test_update_file(self): + a_hosting_file = StringIO() + a_hosting_file.write('h1 {color: #541231;}') + a_hosting_file.seek(0) + + self.hosting.upload_file(path='styles/main.css', file=a_hosting_file) + + a_hosting_file = StringIO() + a_hosting_file.write('h2 {color: #541231;}') + a_hosting_file.seek(0) + + hosting_file = self.hosting.update_file(path='styles/main.css', file=a_hosting_file) + self.assertEqual(hosting_file.path, 'styles/main.css') From d7b0d83ced094cfba57c9eca7ba02e4f1e025e98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Opa=C5=82czy=C5=84ski?= Date: Mon, 29 Aug 2016 16:20:08 +0200 Subject: [PATCH 5/7] [LIB-852] allow to create file when updating non exsiting; --- syncano/models/hosting.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/syncano/models/hosting.py b/syncano/models/hosting.py index 92f6afe..377d7c5 100644 --- a/syncano/models/hosting.py +++ b/syncano/models/hosting.py @@ -60,13 +60,16 @@ def update_file(self, path, file): """ hosting_files = self._get_files() is_found = False + for hosting_file in hosting_files: if hosting_file.path == path: is_found = True break if not is_found: - raise SyncanoRequestError('File with path {} not found.'.format(path)) + # create if not found; + hosting_file = self.upload_file(path, file) + return hosting_file connection = self._get_connection() headers = self._prepare_header(connection) From 790ca62bb1d141fc1f84f58aed06791c5f6002b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Opa=C5=82czy=C5=84ski?= Date: Mon, 29 Aug 2016 16:25:08 +0200 Subject: [PATCH 6/7] [LIB-852] remove unused import; --- syncano/models/hosting.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/syncano/models/hosting.py b/syncano/models/hosting.py index 377d7c5..ab80819 100644 --- a/syncano/models/hosting.py +++ b/syncano/models/hosting.py @@ -1,7 +1,5 @@ # -*- coding: utf-8 -*- -from syncano.exceptions import SyncanoRequestError - from . import fields from .base import Instance, Model, logger From 0e21d15a81f92015c0e91339da6e69047600f0f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Opa=C5=82czy=C5=84ski?= Date: Tue, 30 Aug 2016 15:18:15 +0200 Subject: [PATCH 7/7] [RELEASE v5.4.1] bump the version; --- syncano/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/syncano/__init__.py b/syncano/__init__.py index e0c54af..311afea 100644 --- a/syncano/__init__.py +++ b/syncano/__init__.py @@ -2,7 +2,7 @@ import os __title__ = 'Syncano Python' -__version__ = '5.4.0' +__version__ = '5.4.1' __author__ = "Daniel Kopka, Michal Kobus, and Sebastian Opalczynski" __credits__ = ["Daniel Kopka", "Michal Kobus",