Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
24 changes: 13 additions & 11 deletions syncano/models/accounts.py
Original file line number Diff line number Diff line change
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 Down Expand Up @@ -123,24 +123,26 @@ class Meta:
'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('POST', endpoint)
return connection.request(http_method, endpoint)

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

if not (username and password):
Expand All @@ -151,11 +153,11 @@ def auth(self, username=None, password=None):
'password': password
}

return connection.request('POST', endpoint, data=data)
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)
endpoint = self._meta.resolve_endpoint('groups', properties, method)

if group_id is not None and method != 'POST':
endpoint += '{}/'.format(group_id)
Expand Down Expand Up @@ -214,7 +216,7 @@ class Meta:
'path': '/groups/{id}/',
},
'list': {
'methods': ['get'],
'methods': ['get', 'post'],
'path': '/groups/',
},
'users': {
Expand All @@ -225,7 +227,7 @@ class Meta:

def _group_users_method(self, user_id=None, method='GET'):
properties = self.get_endpoint_data()
endpoint = self._meta.resolve_endpoint('users', properties)
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()
Expand Down
12 changes: 7 additions & 5 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
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/',
},
}
15 changes: 9 additions & 6 deletions syncano/models/data_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,24 +66,27 @@ class Meta:

def rename(self, new_name):
properties = self.get_endpoint_data()
endpoint = self._meta.resolve_endpoint('rename', properties)
http_method = 'POST'
endpoint = self._meta.resolve_endpoint('rename', properties, http_method)
connection = self._get_connection()
return connection.request('POST',
return connection.request(http_method,
endpoint,
data={'new_name': new_name})

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

def get(self, cache_key=None, **kwargs):
connection = self._get_connection()
properties = self.get_endpoint_data()
query = Object.please._build_query(query_data=kwargs, class_name=self.class_name)

endpoint = self._meta.resolve_endpoint('get', properties)
http_method = 'GET'
endpoint = self._meta.resolve_endpoint('get', properties, http_method)

kwargs = {}
params = {}
Expand All @@ -96,7 +99,7 @@ def get(self, cache_key=None, **kwargs):
kwargs = {'params': params}

while endpoint is not None:
response = connection.request('GET', endpoint, **kwargs)
response = connection.request(http_method, endpoint, **kwargs)
endpoint = response.get('next')
for obj in response['objects']:
yield obj
20 changes: 12 additions & 8 deletions syncano/models/incentives.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,15 @@ def run(self, **payload):
raise SyncanoValidationError('Method allowed only on existing model.')

properties = self.get_endpoint_data()
endpoint = self._meta.resolve_endpoint('run', properties)
http_method = 'POST'
endpoint = self._meta.resolve_endpoint('run', properties, http_method)
connection = self._get_connection(**payload)
request = {
'data': {
'payload': json.dumps(payload)
}
}
response = connection.request('POST', endpoint, **request)
response = connection.request(http_method, endpoint, **request)
response.update({'instance_name': self.instance_name, 'script_id': self.id})
return ScriptTrace(**response)

Expand Down Expand Up @@ -268,7 +269,8 @@ def run(self, cache_key=None, **payload):
raise SyncanoValidationError('Method allowed only on existing model.')

properties = self.get_endpoint_data()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In:

    def resolve_endpoint(self, name, properties):
        endpoint = self.get_endpoint(name)

        for name in endpoint['properties']:
            if name not in properties:
                raise SyncanoValueError('Request property "{0}" is required.'.format(name))

        return endpoint['path'].format(**properties)

is get_endpoint which is:

    def get_endpoint(self, name):
        if name not in self.endpoints:
            raise SyncanoValueError('Invalid path name: "{0}".'.format(name))
        return self.endpoints[name]

Maybe we should add check in resolve_endpoint for that? Would be much cleaner. What do you think?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@opalczynski Fine :)

endpoint = self._meta.resolve_endpoint('run', properties)
http_method = 'POST'
endpoint = self._meta.resolve_endpoint('run', properties, http_method)
connection = self._get_connection(**payload)

params = {}
Expand All @@ -279,7 +281,7 @@ def run(self, cache_key=None, **payload):
if params:
kwargs.update({'params': params})

response = connection.request('POST', endpoint, **kwargs)
response = connection.request(http_method, endpoint, **kwargs)

if isinstance(response, dict) and 'result' in response and 'stdout' in response['result']:
response.update({'instance_name': self.instance_name,
Expand All @@ -296,10 +298,11 @@ def reset_link(self):
>>> se.reset_link()
"""
properties = self.get_endpoint_data()
endpoint = self._meta.resolve_endpoint('reset', properties)
http_method = 'POST'
endpoint = self._meta.resolve_endpoint('reset', properties, http_method)
connection = self._get_connection()

response = connection.request('POST', endpoint)
response = connection.request(http_method, endpoint)
self.public_link = response['public_link']


Expand Down Expand Up @@ -345,10 +348,11 @@ class Meta:
def render(self, context=None):
context = context or {}
properties = self.get_endpoint_data()
endpoint = self._meta.resolve_endpoint('render', properties)
http_method = 'POST'
endpoint = self._meta.resolve_endpoint('render', properties, http_method)

connection = self._get_connection()
return connection.request('POST', endpoint, data={'context': context})
return connection.request(http_method, endpoint, data={'context': context})

def rename(self, new_name):
rename_path = self.links.rename
Expand Down
20 changes: 14 additions & 6 deletions syncano/models/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import six
from syncano.connection import ConnectionMixin
from syncano.exceptions import SyncanoValueError
from syncano.exceptions import SyncanoValidationError, SyncanoValueError
from syncano.models.registry import registry
from syncano.utils import camelcase_to_underscore

Expand Down Expand Up @@ -133,15 +133,23 @@ def get_endpoint_methods(self, name):
endpoint = self.get_endpoint(name)
return endpoint['methods']

def resolve_endpoint(self, name, properties):
endpoint = self.get_endpoint(name)
def resolve_endpoint(self, endpoint_name, properties, http_method=None):
if http_method and not self.is_http_method_available(http_method, endpoint_name):
raise SyncanoValidationError(
'HTTP method {0} not allowed for endpoint "{1}".'.format(http_method, endpoint_name)
)
endpoint = self.get_endpoint(endpoint_name)

for name in endpoint['properties']:
if name not in properties:
raise SyncanoValueError('Request property "{0}" is required.'.format(name))
for endpoint_name in endpoint['properties']:
if endpoint_name not in properties:
raise SyncanoValueError('Request property "{0}" is required.'.format(endpoint_name))

return endpoint['path'].format(**properties)

def is_http_method_available(self, http_method_name, endpoint_name):
available_methods = self.get_endpoint_methods(endpoint_name)
return http_method_name.lower() in available_methods

def get_endpoint_query_params(self, name, params):
properties = self.get_endpoint_properties(name)
return {k: v for k, v in six.iteritems(params) if k not in properties}
Expand Down
4 changes: 2 additions & 2 deletions syncano/models/push_notification.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ class Meta:
'path': '/push_notifications/gcm/messages/{id}/',
},
'list': {
'methods': ['get'],
'methods': ['get', 'post'],
'path': '/push_notifications/gcm/messages/',
}
}
Expand Down Expand Up @@ -244,7 +244,7 @@ class Meta:
'path': '/push_notifications/apns/messages/{id}/',
},
'list': {
'methods': ['get'],
'methods': ['get', 'post'],
'path': '/push_notifications/apns/messages/',
}
}
Expand Down
8 changes: 4 additions & 4 deletions syncano/models/traces.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class Meta:
'path': '/traces/{id}/',
},
'list': {
'methods': ['get'],
'methods': ['get', 'post'],
'path': '/traces/',
}
}
Expand Down Expand Up @@ -71,7 +71,7 @@ class Meta:
'path': '/traces/{id}/',
},
'list': {
'methods': ['get'],
'methods': ['get', 'post'],
'path': '/traces/',
}
}
Expand Down Expand Up @@ -109,7 +109,7 @@ class Meta:
'path': '/traces/{id}/',
},
'list': {
'methods': ['get'],
'methods': ['get', 'post'],
'path': '/traces/',
}
}
Expand Down Expand Up @@ -144,7 +144,7 @@ class Meta:
'path': '/traces/{id}/',
},
'list': {
'methods': ['get'],
'methods': ['get', 'post'],
'path': '/traces/',
}
}
12 changes: 11 additions & 1 deletion tests/test_options.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import unittest

from syncano.exceptions import SyncanoValueError
from syncano.exceptions import SyncanoValidationError, SyncanoValueError
from syncano.models import Field, Instance
from syncano.models.options import Options

Expand Down Expand Up @@ -149,3 +149,13 @@ def test_get_path_properties(self):
path = '/{a}/{b}-{c}/dummy-{d}/'
properties = self.options.get_path_properties(path)
self.assertEqual(properties, ['a', 'b'])

def test_resolve_endpoint_with_missing_http_method(self):
properties = {'instance_name': 'test'}
with self.assertRaises(SyncanoValidationError):
self.options.resolve_endpoint('list', properties, 'DELETE')

def test_resolve_endpoint_with_specified_http_method(self):
properties = {'instance_name': 'test', 'a': 'a', 'b': 'b'}
path = self.options.resolve_endpoint('dummy', properties, 'GET')
self.assertEqual(path, '/v1.1/instances/test/v1.1/dummy/a/b/')