Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
77a1580
Merge pull request #196 from Syncano/release-v5.1.0
opalczynski May 13, 2016
caa0529
Update README.rst
MariuszWisniewski May 17, 2016
b021de2
Merge pull request #197 from Syncano/readme-update
MariuszWisniewski May 17, 2016
4f20f47
[LIB-743] Add string field filtering
opalczynski May 25, 2016
12a61a0
[LIB-743] corrects after tests
opalczynski May 25, 2016
82494c0
[LIB-672] Add mixin fro handling the array fields operations;
opalczynski May 25, 2016
c8d516b
[LIB-672] add test for manager methods: add, remove, addunique
opalczynski May 27, 2016
b2fc933
[LIB-672] add test for manager methods: add, remove, addunique
opalczynski May 27, 2016
618b25d
[LIB-732] correct new object initialization - use registry.intance_na…
opalczynski May 27, 2016
4571819
[LIB-732] add test;
opalczynski May 27, 2016
9069c4c
Merge pull request #200 from Syncano/LIB-732
opalczynski Jun 1, 2016
217d448
Merge pull request #199 from Syncano/LIB-672
opalczynski Jun 1, 2016
0b458e1
Merge pull request #198 from Syncano/LIB-743
opalczynski Jun 1, 2016
357ee5e
Support for user auth(). (#202)
mkucharz Jun 2, 2016
d938dcd
[LIB-656] add cache_key support for data endpoints and script endpoints;
opalczynski Jun 7, 2016
2565cb8
[LIB-656] add cache_key support for data endpoints and script endpoints;
opalczynski Jun 7, 2016
f600cf3
[LIB-656] add cache_key support for data endpoints and script endpoints;
opalczynski Jun 7, 2016
18ed55b
[LIB-656] add cache_key support for data endpoints and script endpoints;
opalczynski Jun 7, 2016
41751ce
[LIB-656] add cache_key support for data endpoints and script endpoints;
opalczynski Jun 7, 2016
7f98de2
[LIB-656] add cache_key support for data endpoints and script endpoints;
opalczynski Jun 7, 2016
8c13787
[LIB-656] query on data endpoints is not required;
opalczynski Jun 7, 2016
35755db
[LIB-656] query on data endpoints is not required;
opalczynski Jun 7, 2016
c3029a1
[LIB-175] add special error if user is not found;
opalczynski Jun 7, 2016
9f2dbfb
[LIB-175] add tests
opalczynski Jun 7, 2016
162a356
[LIB-175] correct tests
opalczynski Jun 7, 2016
f7349b4
[LIB-175] correct tests
opalczynski Jun 7, 2016
9a66243
[LIB-656] remove obsolete comment
opalczynski Jun 7, 2016
8f44705
[LIB-667][WIP] saving a user saves now user_profile;
opalczynski Jun 7, 2016
4c4c8ef
Merge pull request #207 from Syncano/LIB-175
opalczynski Jun 8, 2016
cbb519f
Merge pull request #206 from Syncano/LIB-656
opalczynski Jun 8, 2016
eff5040
[LIB-667] add is_data_object_mixin on ModelField - DataObjects are dy…
opalczynski Jun 8, 2016
230e7f9
[LIB-667] rework to_native on ModelField
opalczynski Jun 8, 2016
7e5ba1c
[LIB-667] add one more test - save directly on profile; add validatio…
opalczynski Jun 8, 2016
c0f327d
[LIB-667] correct test
opalczynski Jun 8, 2016
52827fc
[LIB-667] correct ifo-logic
opalczynski Jun 8, 2016
5115dde
[LIB-667] merge with develop branch to resolve conflicts
opalczynski Jun 8, 2016
ed36c73
Merge pull request #208 from Syncano/LIB-667
opalczynski Jun 8, 2016
77ea467
[LIB-642][WIP] add query paramter to DataEndpoints
opalczynski Jun 9, 2016
8732964
[LIB-642] add tests, correct mapping in model archetypes;
opalczynski Jun 13, 2016
b688157
[LIB-642] correct mapping handling;
opalczynski Jun 13, 2016
b21bcdd
[LIB-642] remove not needed code - moved this to build_query on manag…
opalczynski Jun 13, 2016
71ecc3d
Merge pull request #210 from Syncano/LIB-642
opalczynski Jun 15, 2016
0dca019
[LIB-769] add proper user and group endpoints handling;
opalczynski Jun 16, 2016
4300e19
[LIB-769] Fix tests
opalczynski Jun 16, 2016
327ef61
[LIB-758] add Backup and PartialBackup models; with full CRUD;
opalczynski Jun 16, 2016
3be4dc0
[LIB-758] test fix; add prefix to instance name;
opalczynski Jun 16, 2016
ddd2792
[LIB-758] correct prefix to instance name;
opalczynski Jun 16, 2016
9b177a3
[LIB-758] correct create test;
opalczynski Jun 16, 2016
f6f95de
[LIB-758] small fixes;
opalczynski Jun 16, 2016
884b516
[LIB-758] remove partial backup for this PR; partial will be forgoten;
opalczynski Jun 16, 2016
33cdb10
Merge pull request #212 from Syncano/LIB-758
opalczynski Jun 19, 2016
8b84795
Merge pull request #211 from Syncano/LIB-769
opalczynski Jun 19, 2016
478e325
[LIB-783] - move logic checking available endpoint request methods to…
ilu2112 Jun 28, 2016
d84dbab
[LIB-783] - move logic checking available endpoint request methods t…
ilu2112 Jun 28, 2016
0303de2
[LIB-783] - check available http methods for endpoint calls: apply ch…
ilu2112 Jun 28, 2016
88d118c
[LIB-783] - tests
ilu2112 Jun 28, 2016
35de4a6
[LIB-783] - fix user integration tests
ilu2112 Jun 28, 2016
1a80368
[LIB-757] - add possibility to restore backups
ilu2112 Jun 28, 2016
cf361ba
[LIB-757] - remove obsolete blank lines
ilu2112 Jun 28, 2016
3a1d0b6
[LIB-757] - test
ilu2112 Jun 28, 2016
5d8a1ce
[LIB-757] - improve test
ilu2112 Jun 29, 2016
4a62a9a
[LIB-757] - make backup restore synchronous
ilu2112 Jun 29, 2016
b7606bc
[LIB-783] - Pass method type to resolve_endpoint as named parameter.
ilu2112 Jun 30, 2016
d84be9d
[LIB-757] - Remove unused imports.
ilu2112 Jun 30, 2016
114d1e8
Merge pull request #213 from Syncano/LIB-783
ilu2112 Jul 4, 2016
a0997f4
Merge pull request #214 from Syncano/LIB-757
ilu2112 Jul 6, 2016
80ac517
[LIB-800] - Add possibility to define global config
ilu2112 Jul 6, 2016
293a547
Resolve isort issues.
ilu2112 Jul 6, 2016
eda493e
[LIB-800] - Add config validation before sending request to API.
ilu2112 Jul 7, 2016
f4c2aec
[LIB-802] - Add possibility to use template on DataEndpoint - on get()
ilu2112 Jul 7, 2016
8624d23
[LIB-800] -Improve tests.
ilu2112 Jul 7, 2016
f2d77ce
Merge pull request #215 from Syncano/LIB-800
ilu2112 Jul 9, 2016
e2d09b6
[LIB-802] - Remove obsolete blank lines in the code.
ilu2112 Jul 9, 2016
ec692c6
Merge pull request #216 from Syncano/LIB-802
ilu2112 Jul 12, 2016
039f386
[LIB-BC] add backward compatibility import EndpointData
opalczynski Jul 19, 2016
06a1481
[LIB-BC] add backward compatibility import EndpointData
opalczynski Jul 19, 2016
6f53e45
Merge pull request #217 from Syncano/LIB-backward-compatibility
opalczynski Jul 19, 2016
9c45225
[RELEASE v5.2.0] Bump the version
opalczynski Jul 19, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions syncano/models/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -572,10 +572,16 @@ def validate(self, value, model_instance):
except (ValueError, TypeError):
raise SyncanoValueError('Expected an array')

if not isinstance(value, list):
if isinstance(value, dict):
if len(value) != 1 or len(set(value.keys()).intersection(['_add', '_remove', '_addunique'])) != 1:
raise SyncanoValueError('Wrong value: one operation at the time.')

elif not isinstance(value, list):
raise SyncanoValueError('Expected an array')

for element in value:
value_to_check = value if isinstance(value, list) else value.values()[0]

for element in value_to_check:
if not isinstance(element, six.string_types + (bool, int, float)):
raise SyncanoValueError(
'Currently supported types for array items are: string types, bool, float and int')
Expand Down
4 changes: 2 additions & 2 deletions syncano/models/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from syncano.connection import ConnectionMixin
from syncano.exceptions import SyncanoRequestError, SyncanoValidationError, SyncanoValueError
from syncano.models.bulk import ModelBulkCreate, ObjectBulkCreate
from syncano.models.manager_mixins import IncrementMixin, clone
from syncano.models.manager_mixins import ArrayOperationsMixin, IncrementMixin, clone

from .registry import registry

Expand Down Expand Up @@ -874,7 +874,7 @@ def run(self, *args, **kwargs):
return registry.ScriptEndpointTrace(**response)


class ObjectManager(IncrementMixin, Manager):
class ObjectManager(IncrementMixin, ArrayOperationsMixin, Manager):
"""
Custom :class:`~syncano.models.manager.Manager`
class for :class:`~syncano.models.base.Object` model.
Expand Down
154 changes: 154 additions & 0 deletions syncano/models/manager_mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,157 @@ def _check_field_type_for_increment(cls, model, field_name):
return True

return False


class ArrayOperationsMixin(object):

@clone
def add(self, field_name, value, **kwargs):
"""
A manager method that will add a values to the array field.

Usage::

data_object = Object.please.add(
field_name='array',
value=[10],
class_name='arr_test',
id=155
)

Consider example:

data_object.array = [1]

after running::

data_object = Object.please.add(
field_name='array',
value=[3],
id=data_object.id,
)

data_object.array will be equal: [1, 3]

and after::

data_object = Object.please.add(
field_name='array',
value=[1],
id=data_object.id,
)

data_object.array will be equal: [1, 3, 1]

:param field_name: the array field name to which elements will be added;
:param value: the list of values to add;
:param kwargs: class_name and id usually;
:return: the processed data object;
"""
self.properties.update(kwargs)
model = self.model.get_subclass_model(**self.properties)

self.array_validate(field_name, value, model)
return self.array_process(field_name, value, operation_type='add')

def remove(self, field_name, value, **kwargs):
"""
A manager method that will remove a values from the array field.

Usage::

data_object = Object.please.remove(
field_name='array',
value=[10],
class_name='arr_test',
id=155
)

:param field_name: the array field name from which elements will be removed;
:param value: the list of values to remove;
:param kwargs: class_name and id usually;
:return: the processed data object;
"""
self.properties.update(kwargs)
model = self.model.get_subclass_model(**self.properties)

self.array_validate(field_name, value, model)
return self.array_process(field_name, value, operation_type='remove')

def add_unique(self, field_name, value, **kwargs):
"""
A manager method that will add an unique values to the array field.

Usage::

data_object = Object.please.add_unique(
field_name='array',
value=[10],
class_name='arr_test',
id=155
)

The main distinction between add and add unique is that: add unique will not repeat elements.
Consider example::

data_object.array = [1]

after running::

data_object = Object.please.add_unique(
field_name='array',
value=[1],
id=data_object.id,
)

data_object.array will be equal: [1]

But if only add will be run the result will be as follow:

data_object.array will be equal: [1, 1]

:param field_name: field_name: the array field name to which elements will be added unique;
:param value: the list of values to add unique;
:param kwargs: class_name and id usually;
:return: the processed data object;
"""
self.properties.update(kwargs)
model = self.model.get_subclass_model(**self.properties)

self.array_validate(field_name, value, model)
return self.array_process(field_name, value, operation_type='add_unique')

@classmethod
def array_validate(cls, field_name, value, model):

fields = {field.name: field for field in model._meta.fields}
if field_name not in fields:
raise SyncanoValueError('Object has not specified field.')

from syncano.models import ArrayField
if not isinstance(fields[field_name], ArrayField):
raise SyncanoValueError('Field must be of array type')

if not isinstance(value, list):
raise SyncanoValueError('List of values expected')

def array_process(self, field_name, value, operation_type, **kwargs):
self.endpoint = 'detail'
self.method = self.get_allowed_method('PATCH', 'PUT', 'POST')
self.data = kwargs.copy()

if operation_type == 'add':
array_data = {'_add': value}
elif operation_type == 'remove':
array_data = {'_remove': value}
elif operation_type == 'add_unique':
array_data = {'_addunique': value}
else:
raise SyncanoValueError('Operation not supported')

self.data.update(
{field_name: array_data}
)

response = self.request()
return response
55 changes: 55 additions & 0 deletions tests/integration_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ def setUpClass(cls):
{'type': 'float', 'name': 'cost'},
{'type': 'boolean', 'name': 'available'},
{'type': 'datetime', 'name': 'published_at'},
{'type': 'array', 'name': 'array'},
{'type': 'file', 'name': 'cover'},
{'type': 'reference', 'name': 'author',
'order_index': True, 'filter_index': True, 'target': cls.author.name},
Expand Down Expand Up @@ -369,6 +370,60 @@ def test_increment_and_decrement_on_float(self):

self.assertEqual(decremented_book.cost, 8.4)

def test_add_array(self):
book = self.model.please.create(
instance_name=self.instance.name, class_name=self.book.name,
name='test', description='test', quantity=10, cost=10.5,
published_at=datetime.now(), available=True, array=[10])

book = Object.please.add(
'array',
[11],
class_name=self.book.name,
id=book.id
)

self.assertEqual(book.array, [10, 11])

def test_remove_array(self):
book = self.model.please.create(
instance_name=self.instance.name, class_name=self.book.name,
name='test', description='test', quantity=10, cost=10.5,
published_at=datetime.now(), available=True, array=[10])

book = Object.please.remove(
'array',
[10],
class_name=self.book.name,
id=book.id
)

self.assertEqual(book.array, [])

def test_addunique_array(self):
book = self.model.please.create(
instance_name=self.instance.name, class_name=self.book.name,
name='test', description='test', quantity=10, cost=10.5,
published_at=datetime.now(), available=True, array=[10])

book = Object.please.add_unique(
'array',
[10],
class_name=self.book.name,
id=book.id
)

self.assertEqual(book.array, [10])

book = Object.please.add_unique(
'array',
[11],
class_name=self.book.name,
id=book.id
)

self.assertEqual(book.array, [10, 11])


class ScriptIntegrationTest(InstanceMixin, IntegrationTest):
model = Script
Expand Down