Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 2 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ You can also find library reference hosted on GitHub pages [here](http://syncano
Backwards incompatible changes
------------------------------

Version 4.0 is designed for new release of Syncano platform and
it's **not compatible** with any previous releases.
Version 4.x and 5.x is designed for new release of Syncano platform and
is **not compatible** with any previous releases.

Code from `0.6.x` release is avalable on [stable/0.6.x](https://github.com/Syncano/syncano-python/tree/stable/0.6.x) branch
and it can be installed directly from pip via:
Expand Down
2 changes: 1 addition & 1 deletion syncano/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import os

__title__ = 'Syncano Python'
__version__ = '5.1.0'
__version__ = '5.2.0'
__author__ = "Daniel Kopka, Michal Kobus, and Sebastian Opalczynski"
__credits__ = ["Daniel Kopka",
"Michal Kobus",
Expand Down
4 changes: 4 additions & 0 deletions syncano/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,7 @@ class SyncanoDoesNotExist(SyncanoException):

class RevisionMismatchException(SyncanoRequestError):
"""Revision do not match with expected one"""


class UserNotFound(SyncanoRequestError):
"""Special error to handle user not found case."""
84 changes: 69 additions & 15 deletions syncano/models/accounts.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@

from syncano.exceptions import SyncanoRequestError, SyncanoValueError, UserNotFound

from . import fields
from .base import Model
Expand Down Expand Up @@ -37,7 +37,7 @@ class Meta:
'path': '/admins/{id}/',
},
'list': {
'methods': ['get'],
'methods': ['get', 'post'],
'path': '/admins/',
}
}
Expand Down Expand Up @@ -76,7 +76,7 @@ class Meta:
'path': '/objects/{id}/',
},
'list': {
'methods': ['get'],
'methods': ['get', 'post'],
'path': '/objects/',
}
}
Expand All @@ -100,7 +100,8 @@ class User(Model):
password = fields.StringField(read_only=False, required=True)
user_key = fields.StringField(read_only=True, required=False)

profile = fields.ModelField('Profile', read_only=False, default={})
profile = fields.ModelField('Profile', read_only=False, default={},
just_pk=False, is_data_object_mixin=True)

links = fields.LinksField()
created_at = fields.DateTimeField(read_only=True, required=False)
Expand All @@ -117,29 +118,64 @@ class Meta:
'methods': ['post'],
'path': '/users/{id}/reset_key/',
},
'auth': {
'methods': ['post'],
'path': '/user/auth/',
},
'list': {
'methods': ['get'],
'methods': ['get', 'post'],
'path': '/users/',
},
'groups': {
'methods': ['get', 'post'],
'methods': ['get', 'post', 'delete'],
'path': '/users/{id}/groups/',
}
}

def reset_key(self):
properties = self.get_endpoint_data()
endpoint = self._meta.resolve_endpoint('reset_key', properties)
http_method = 'POST'
endpoint = self._meta.resolve_endpoint('reset_key', properties, http_method)
connection = self._get_connection()
return connection.request(http_method, endpoint)

def auth(self, username=None, password=None):
properties = self.get_endpoint_data()
http_method = 'POST'
endpoint = self._meta.resolve_endpoint('auth', properties, http_method)
connection = self._get_connection()
return connection.request('POST', endpoint)

if not (username and password):
raise SyncanoValueError('You need provide username and password.')

data = {
'username': username,
'password': password
}

return connection.request(http_method, endpoint, data=data)

def _user_groups_method(self, group_id=None, method='GET'):
properties = self.get_endpoint_data()
endpoint = self._meta.resolve_endpoint('groups', properties)
if group_id is not None:
endpoint = self._meta.resolve_endpoint('groups', properties, method)

if group_id is not None and method != 'POST':
endpoint += '{}/'.format(group_id)
connection = self._get_connection()
return connection.request(method, endpoint)

data = {}
if method == 'POST':
data = {'group': group_id}

response = connection.request(method, endpoint, data=data)

if method == 'DELETE': # no response here;
return

if 'objects' in response:
return [Group(**group_response['group']) for group_response in response['objects']]

return Group(**response['group'])

def add_to_group(self, group_id):
return self._user_groups_method(group_id, method='POST')
Expand Down Expand Up @@ -180,7 +216,7 @@ class Meta:
'path': '/groups/{id}/',
},
'list': {
'methods': ['get'],
'methods': ['get', 'post'],
'path': '/groups/',
},
'users': {
Expand All @@ -191,11 +227,29 @@ class Meta:

def _group_users_method(self, user_id=None, method='GET'):
properties = self.get_endpoint_data()
endpoint = self._meta.resolve_endpoint('users', properties)
if user_id is not None:
endpoint = self._meta.resolve_endpoint('users', properties, method)
if user_id is not None and method != 'POST':
endpoint += '{}/'.format(user_id)
connection = self._get_connection()
return connection.request(method, endpoint)

data = {}
if method == 'POST':
data = {'user': user_id}

try:
response = connection.request(method, endpoint, data=data)
except SyncanoRequestError as e:
if e.status_code == 404:
raise UserNotFound(e.status_code, 'User not found.')
raise

if method == 'DELETE':
return

if 'objects' in response:
return [User(**user_response['user']) for user_response in response['objects']]

return User(**response['user'])

def list_users(self):
return self._group_users_method()
Expand Down
23 changes: 17 additions & 6 deletions syncano/models/archetypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ def save(self, **kwargs):
if 'put' in methods:
method = 'PUT'

endpoint = self._meta.resolve_endpoint(endpoint_name, properties)
endpoint = self._meta.resolve_endpoint(endpoint_name, properties, method)
if 'expected_revision' in kwargs:
data.update({'expected_revision': kwargs['expected_revision']})
request = {'data': data}
Expand Down Expand Up @@ -171,9 +171,10 @@ def delete(self, **kwargs):
raise SyncanoValidationError('Method allowed only on existing model.')

properties = self.get_endpoint_data()
endpoint = self._meta.resolve_endpoint('detail', properties)
http_method = 'DELETE'
endpoint = self._meta.resolve_endpoint('detail', properties, http_method)
connection = self._get_connection(**kwargs)
connection.request('DELETE', endpoint)
connection.request(http_method, endpoint)
if self.__class__.__name__ == 'Instance': # avoid circular import;
registry.clear_used_instance()
self._raw_data = {}
Expand All @@ -185,9 +186,10 @@ def reload(self, **kwargs):
raise SyncanoValidationError('Method allowed only on existing model.')

properties = self.get_endpoint_data()
endpoint = self._meta.resolve_endpoint('detail', properties)
http_method = 'GET'
endpoint = self._meta.resolve_endpoint('detail', properties, http_method)
connection = self._get_connection(**kwargs)
response = connection.request('GET', endpoint)
response = connection.request(http_method, endpoint)
self.to_python(response)

def validate(self):
Expand Down Expand Up @@ -225,10 +227,19 @@ def to_python(self, data):
:type data: dict
:param data: Raw data
"""

for field in self._meta.fields:
field_name = field.name

if field.mapping is not None and self.pk:
# some explanation needed here:
# When data comes from Syncano Platform the 'class' field is there
# so to map correctly the 'class' value to the 'class_name' field
# the mapping is required.
# But. When DataEndpoint (and probably others models with mapping) is created from
# syncano LIB directly: DataEndpoint(class_name='some_class')
# the data dict has only 'class_name' key - not the 'class',
# later the transition between class_name and class is made in to_native on model;
if field.mapping is not None and field.mapping in data and self.is_new():
field_name = field.mapping

if field_name in data:
Expand Down
78 changes: 78 additions & 0 deletions syncano/models/backups.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# -*- coding: utf-8 -*-
from . import fields
from .base import Model
from .instances import Instance


class Backup(Model):
"""
OO wrapper around backups `link <http://docs.syncano.com/docs/full-backups>`_.

:ivar label: :class:`~syncano.models.fields.StringField`
:ivar description: :class:`~syncano.models.fields.StringField`
:ivar instance: :class:`~syncano.models.fields.StringField`
:ivar size: :class:`~syncano.models.fields.IntegerField`
:ivar status: :class:`~syncano.models.fields.StringField`
:ivar status_info: :class:`~syncano.models.fields.StringField`
:ivar author: :class:`~syncano.models.fields.ModelField`
:ivar details: :class:`~syncano.models.fields.JSONField`
:ivar updated_at: :class:`~syncano.models.fields.DateTimeField`
:ivar created_at: :class:`~syncano.models.fields.DateTimeField`
:ivar links: :class:`~syncano.models.fields.HyperlinkedField`
"""

label = fields.StringField(read_only=True)
description = fields.StringField(read_only=True)

instance = fields.StringField(read_only=True)
size = fields.IntegerField(read_only=True)
status = fields.StringField(read_only=True)
status_info = fields.StringField(read_only=True)
author = fields.ModelField('Admin')
details = fields.JSONField(read_only=True)

updated_at = fields.DateTimeField(read_only=True, required=False)
created_at = fields.DateTimeField(read_only=True, required=False)
links = fields.LinksField()

class Meta:
parent = Instance
endpoints = {
'detail': {
'methods': ['get', 'delete'],
'path': '/backups/full/{id}/',
},
'list': {
'methods': ['post', 'get'],
'path': '/backups/full/',
},
}

def schedule_restore(self):
restore = Restore(backup=self.id).save()
return restore


class Restore(Model):

author = fields.ModelField('Admin')
status = fields.StringField(read_only=True)
status_info = fields.StringField(read_only=True)
updated_at = fields.DateTimeField(read_only=True, required=False)
created_at = fields.DateTimeField(read_only=True, required=False)
links = fields.LinksField()
backup = fields.StringField()
archive = fields.StringField(read_only=True)

class Meta:
parent = Instance
endpoints = {
'list': {
'methods': ['get', 'post'],
'path': '/restores/',
},
'detail': {
'methods': ['get'],
'path': '/restores/{id}/',
}
}
2 changes: 2 additions & 0 deletions syncano/models/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@
from .traces import * # NOQA
from .push_notification import * # NOQA
from .geo import * # NOQA
from .backups import * # NOQA
from .data_views import DataEndpoint as EndpointData # NOQA
9 changes: 5 additions & 4 deletions syncano/models/channels.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ class Meta:

def poll(self, room=None, last_id=None, callback=None, error=None, timeout=None):
properties = self.get_endpoint_data()
endpoint = self._meta.resolve_endpoint('poll', properties)
endpoint = self._meta.resolve_endpoint('poll', properties, http_method='GET')
connection = self._get_connection()

thread = PollThread(connection, endpoint, callback, error, timeout=timeout,
Expand All @@ -148,10 +148,11 @@ def poll(self, room=None, last_id=None, callback=None, error=None, timeout=None)

def publish(self, payload, room=None):
properties = self.get_endpoint_data()
endpoint = self._meta.resolve_endpoint('publish', properties)
http_method = 'POST'
endpoint = self._meta.resolve_endpoint('publish', properties, http_method)
connection = self._get_connection()
request = {'data': Message(payload=payload, room=room).to_native()}
response = connection.request('POST', endpoint, **request)
response = connection.request(http_method, endpoint, **request)
return Message(**response)


Expand Down Expand Up @@ -189,7 +190,7 @@ class Meta:
'path': '/history/{pk}/',
},
'list': {
'methods': ['get'],
'methods': ['get', 'post'],
'path': '/history/',
},
}
2 changes: 1 addition & 1 deletion syncano/models/classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ def _set_up_object_class(cls, model):

@classmethod
def _get_instance_name(cls, kwargs):
return kwargs.get('instance_name')
return kwargs.get('instance_name') or registry.instance_name

@classmethod
def _get_class_name(cls, kwargs):
Expand Down
Loading