Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
27087eb
Merge pull request #225 from Syncano/release-v5.3.0
opalczynski Jul 26, 2016
a03fd8c
Merge pull request #226 from Syncano/master
opalczynski Jul 26, 2016
90c4333
[LIB-821] add retry-after handling;
opalczynski Aug 9, 2016
3801a26
[LIB-821] correct isort issues;
opalczynski Aug 9, 2016
49fa010
Merge pull request #227 from Syncano/LIB-821
opalczynski Aug 9, 2016
12cda74
[LIB-837][WIP] working on custom sockets in LIB
opalczynski Aug 10, 2016
460006f
[LIB-837] Add missing docs about custom_sockets; move utils to anothe…
opalczynski Aug 11, 2016
5eca906
[LIB-837] add missing fields in doc string;
opalczynski Aug 11, 2016
cb5f0ab
[readme_changes] Some readme changes
23doors Aug 12, 2016
9a7c280
Merge pull request #229 from Syncano/readme_changes
23doors Aug 12, 2016
c0f75cb
[LIB-837] correct documentation; add possibility to read all endpoint…
opalczynski Aug 12, 2016
e108b5a
[LIB-837] Correct after tests;
opalczynski Aug 12, 2016
5eab464
[LIB-837] another portion of corrects;
opalczynski Aug 12, 2016
1afcd9f
[LIB-837] correct tests again;
opalczynski Aug 12, 2016
48eb08e
[LIB-837] change tests instead of doing a magic in ModelField;
opalczynski Aug 12, 2016
4e2ee33
Language updates
MariuszWisniewski Aug 12, 2016
fe52e7a
[ci skip] readme
MariuszWisniewski Aug 12, 2016
7bc974a
[ci skip] Endpoints readme update
MariuszWisniewski Aug 15, 2016
bc71ad1
[LIB-837] revert ModelField on script in script endpoint model;
opalczynski Aug 16, 2016
327a3fc
[LIB-837] correct data passing on run methods;
opalczynski Aug 16, 2016
d50344b
[LIB-837] correct custom socket behaviour;
opalczynski Aug 16, 2016
c2ffd3a
Merge branch 'LIB-837' of github.com:Syncano/syncano-python into LIB-837
opalczynski Aug 16, 2016
42e4373
[LIB-837] corrects after qa;
opalczynski Aug 16, 2016
04c5ef6
[LIB-837] corrects after qa;
opalczynski Aug 16, 2016
9f5adba
[LIB-837] correct docs examples, polish the tests;
opalczynski Aug 16, 2016
69f3a11
[LIB-837] remove default custom socket in setupclass;
opalczynski Aug 16, 2016
3d1f4dd
[LIB-837] remove default custom socket in setupclass;
opalczynski Aug 16, 2016
d982fd0
[LIB-837] final test correction;
opalczynski Aug 16, 2016
8662e42
Update language
devintyler Aug 16, 2016
2ff6c68
[LIB-819] - Add support for creating objects through DataEndpoint
ilu2112 Aug 18, 2016
0864163
[LIB-837] add possibility to directly point instance name when gettin…
opalczynski Aug 18, 2016
9246b98
[LIB-837] change interface: publish to install in custom socket context;
opalczynski Aug 19, 2016
31c51b9
Merge branch 'LIB-837' of github.com:Syncano/syncano-python into LIB-837
opalczynski Aug 19, 2016
14f6ff7
[LIB-837] add status badges to README
opalczynski Aug 19, 2016
2372986
[LIB-837] small changes after CORE change;
opalczynski Aug 22, 2016
515e50b
[LIB-837] correct SocketEndpoint behaviour (run mainly);
opalczynski Aug 22, 2016
16795dd
[LIB-837] correct run in CustomSocket;
opalczynski Aug 22, 2016
b8c252f
[LIB-837] add possiblity to install from url;
opalczynski Aug 23, 2016
3cf2465
[LIB-837] update documentation for installing socket from url;
opalczynski Aug 23, 2016
ef39be6
[LIB-837] fixes after qa;
opalczynski Aug 24, 2016
38e94ad
Merge pull request #230 from Syncano/LIB-819
opalczynski Aug 24, 2016
6ab2429
Merge pull request #228 from Syncano/LIB-837
opalczynski Aug 24, 2016
21ddeaf
[RELEASE v5.4] bump the version;
opalczynski Aug 24, 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
28 changes: 15 additions & 13 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
Syncano
=======

Python QuickStart Guide
-----------------------
Build Status
------------

You can find quick start on installing and using Syncano's Python library in our [documentation](http://docs.syncano.com/docs/python).
**Master**

For more detailed information on how to use Syncano and its features - our [Developer Manual](http://docs.syncano.com/docs/getting-started-with-syncano) should be very helpful.
.. image:: https://circleci.com/gh/Syncano/syncano-python/tree/master.svg?style=svg&circle-token=738c379fd91cc16b82758e6be89d0c21926655e0
:target: https://circleci.com/gh/Syncano/syncano-python/tree/master

In case you need help working with the library - email us at libraries@syncano.com - we will be happy to help!
**Develop**

You can also find library reference hosted on GitHub pages [here](http://syncano.github.io/syncano-python/).
.. image:: https://circleci.com/gh/Syncano/syncano-python/tree/develop.svg?style=svg&circle-token=738c379fd91cc16b82758e6be89d0c21926655e0
:target: https://circleci.com/gh/Syncano/syncano-python/tree/develop

Backwards incompatible changes
------------------------------
Python QuickStart Guide
-----------------------

You can find quick start on installing and using Syncano's Python library in our `documentation <http://docs.syncano.io/docs/python>`_.

Version 4.x and 5.x is designed for new release of Syncano platform and
is **not compatible** with any previous releases.
For more detailed information on how to use Syncano and its features - our `Developer Manual <http://docs.syncano.io/docs/getting-started-with-syncano>`_ should be very helpful.

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:
In case you need help working with the library - email us at libraries@syncano.com - we will be happy to help!

``pip install syncano==0.6.2 --pre``
You can also find library reference hosted on GitHub pages `here <http://syncano.github.io/syncano-python/>`_.
276 changes: 276 additions & 0 deletions docs/source/custom_sockets.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,276 @@
.. _custom-sockets:

=========================
Custom Sockets in Syncano
=========================

``Syncano`` gives its users the ability to create Custom Sockets. What this means is that users can define very specific
endpoints in their Syncano application, and use them exactly like they would any other Syncano
module (Classes, Scripts, etc), using standard API calls.
Currently, Custom Sockets allow only one dependency - Scripts. Under the hood,
each API call executes a Script, and the result of this execution is returned as a result of the
API call.

Creating a custom Socket
------------------------

To create a custom Socket follow these steps::

import syncano
from syncano.models import CustomSocket, Endpoint, ScriptCall, ScriptDependency, RuntimeChoices
from syncano.connection import Connection

# 1. Initialize a custom Socket.
custom_socket = CustomSocket(name='my_custom_socket') # this will create an object in place (do API call)

# 2. Define endpoints.
my_endpoint = Endpoint(name='my_endpoint') # no API call here
my_endpoint.add_call(ScriptCall(name='custom_script'), methods=['GET'])
my_endpoint.add_call(ScriptCall(name='another_custom_script'), methods=['POST'])

# What happened here:
# - We defined a new endpoint that will be visible under the name `my_endpoint`
# - You will be able to call this endpoint (execute attached `call`),
# by sending a request, using any defined method to the following API route:
# <host>://<api_version>/instances/<instance_name>/endpoints/sockets/my_endpoint/
# - To get details for that endpoint, you need to send a GET request to following API route:
# <host>://<api_version>/instances/<instance_name>/sockets/my_custom_socket/endpoints/my_endpoint/
#
# Following the example above - we defined two calls on our endpoint with the `add_call` method
# The first one means that using a GET method will call the `custom_script` Script,
# and second one means that using a POST method will call the `another_custom_script` Script.
# At the moment, only Scripts are available as endpoint calls.
#
# As a general rule - to get endpoint details (but not call them), use following API route:
# <host>://<api_version>/instances/<instance_name>/sockets/my_custom_socket/endpoints/<endpoint>/
# and to run your endpoints (e.g. execute Script connected to them), use following API route:
# <host>://<api_version>/instances/<instance_name>/endpoints/sockets/<endpoint>/

# 3. After creation of the endpoint, add it to your custom_socket.
custom_socket.add_endpoint(my_endpoint)

# 4. Define dependency.
# 4.1 Using a new Script - define a new source code.
custom_socket.add_dependency(
ScriptDependency(
Script(
runtime_name=RuntimeChoices.PYTHON_V5_0,
source='print("custom_script")'
),
name='custom_script'
)
)
# 4.2 Using an existing Script.
another_custom_script = Script.please.get(id=2)
custom_socket.add_dependency(
ScriptDependency(
another_custom_script,
name='another_custom_script',
)
)

# 4.3 Using an existing ScriptEndpoint.
script_endpoint = ScriptEndpoint.please.get(name='script_endpoint_name')
custom_socket.add_dependency(
script_endpoint
)

# 5. Install custom_socket.
custom_socket.install() # this will make an API call and create a script;

It may take some time to set up the Socket, so you can check the status.
It's possible to check the custom Socket status::

# Reload will refresh object using Syncano API.
custom_socket.reload()
print(custom_socket.status)
# and
print(custom_socket.status_info)

Updating the custom Socket
--------------------------

To update custom Socket, use::

custom_socket = CustomSocket.please.get(name='my_custom_socket')

# to remove endpoint/dependency

custom_socket.remove_endpoint(endpoint_name='my_endpoint')
custom_socket.remove_dependency(dependency_name='custom_script')

# or to add a new endpoint/dependency:

custom_socket.add_endpoint(new_endpoint) # see above code for endpoint examples;
custom_socket.add_dependency(new_dependency) # see above code for dependency examples;

# save changes on Syncano

custom_socket.update()


Running custom Socket
-------------------------

To run a custom Socket use::

# this will run `my_endpoint` - and call `custom_script` using GET method;
result = custom_socket.run(method='GET', endpoint_name='my_endpoint')


Read all endpoints in a custom Socket
-----------------------------------

To get the all defined endpoints in a custom Socket run::

endpoints = custom_socket.get_endpoints()

for endpoint in endpoints:
print(endpoint.name)
print(endpoint.calls)

To run a particular endpoint::

endpoint.run(method='GET')
# or:
endpoint.run(method='POST', data={'name': 'test_name'})

Data will be passed to the API call in the request body.

Read all endpoints
------------------

To get all endpoints that are defined in all custom Sockets::

socket_endpoint_list = SocketEndpoint.get_all_endpoints()

Above code will return a list with SocketEndpoint objects. To run an endpoint,
choose one endpoint first, e.g.:

endpoint = socket_endpoint_list[0]

and now run it::

endpoint.run(method='GET')
# or:
endpoint.run(method='POST', data={'custom_data': 1})

Custom Sockets endpoints
------------------------

Each custom socket requires defining at least one endpoint. This endpoint is defined by name and
a list of calls. Each call is defined by its name and a list of methods. `name` is used as an
identification for the dependency, eg. if `name` is equal to 'my_script' - the ScriptEndpoint with name 'my_script'
will be used (if it exists and Script source and passed runtime match) -- otherwise a new one will be created.
There's a special wildcard method: `methods=['*']` - this allows you to execute the provided custom Socket
with any request method (GET, POST, PATCH, etc.).

To add an endpoint to a chosen custom_socket use::

my_endpoint = Endpoint(name='my_endpoint') # no API call here
my_endpoint.add_call(ScriptCall(name='custom_script'), methods=['GET'])
my_endpoint.add_call(ScriptCall(name='another_custom_script'), methods=['POST'])

custom_socket.add_endpoint(my_endpoint)

Custom Socket dependency
------------------------

Each custom socket has a dependency -- meta information for an endpoint: which resource
should be used to return the API call results. These dependencies are bound to the endpoints call object.
Currently the only supported dependency is a Script.

**Using new Script**

::

custom_socket.add_dependency(
ScriptDependency(
Script(
runtime_name=RuntimeChoices.PYTHON_V5_0,
source='print("custom_script")'
),
name='custom_script'
)
)


**Using defined Script**

::

another_custom_script = Script.please.get(id=2)
custom_socket.add_dependency(
ScriptDependency(
another_custom_script,
name='another_custom_script'
)
)

**Using defined Script endpoint**

::

script_endpoint = ScriptEndpoint.please.get(name='script_endpoint_name')
custom_socket.add_dependency(
script_endpoint
)

You can overwrite the Script name in the following way::

script_endpoint = ScriptEndpoint.please.get(name='script_endpoint_name')
custom_socket.add_dependency(
script_endpoint,
name='custom_name'
)

Custom Socket recheck
---------------------

The creation of a Socket can fail - this can happen, for example, when an endpoint name is already taken by another
custom Socket. To check the creation status use::

print(custom_socket.status)
print(custom_socket.status_info)

You can also re-check a Socket. This mean that all dependencies will be checked - if some of them are missing
(e.g. some were deleted by mistake), they will be created again. If the endpoints and dependencies do not meet
the criteria - an error will be returned in the status field.

Custom Socket - install from url
--------------------------------

To install a socket from url use::

CustomSocket(name='new_socket_name').install_from_url(url='https://...')

If instance name was not provided in connection arguments, do::

CustomSocket(name='new_socket_name').install_from_url(url='https://...', instance_name='instance_name')

Custom Socket - raw format
--------------------------

If you prefer raw JSON format for creating Sockets, the Python library allows you to do so::::

CustomSocket.please.create(
name='my_custom_socket_3',
endpoints={
"my_endpoint_3": {
"calls":
[
{"type": "script", "name": "my_script_3", "methods": ["POST"]}
]
}
},
dependencies=[
{
"type": "script",
"runtime_name": "python_library_v5.0",
"name": "my_script_3",
"source": "print(3)"
}
]
)

The disadvantage of this method is that the internal structure of the JSON file must be known by the developer.
1 change: 1 addition & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Contents:

getting_started
interacting
custom_sockets
refs/syncano


Expand Down
7 changes: 7 additions & 0 deletions docs/source/refs/syncano.models.custom_sockets.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
syncano.models.custom_sockets
=============================

.. automodule:: syncano.models.custom_sockets
:members:
:undoc-members:
:show-inheritance:
7 changes: 7 additions & 0 deletions docs/source/refs/syncano.models.custom_sockets_utils.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
syncano.models.custom_sockets_utils
===================================

.. automodule:: syncano.models.custom_sockets_utils
:members:
:undoc-members:
:show-inheritance:
7 changes: 7 additions & 0 deletions docs/source/refs/syncano.models.geo.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
syncano.models.geo
==================

.. automodule:: syncano.models.geo
:members:
:undoc-members:
:show-inheritance:
7 changes: 7 additions & 0 deletions docs/source/refs/syncano.models.hosting.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
syncano.models.hosting
======================

.. automodule:: syncano.models.hosting
:members:
:undoc-members:
:show-inheritance:
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ def readme():
version=__version__,
description='Python Library for syncano.com api',
long_description=readme(),
author='Daniel Kopka',
author_email='daniel.kopka@syncano.com',
author='Syncano',
author_email='support@syncano.io',
url='http://syncano.com',
packages=find_packages(exclude=['tests']),
zip_safe=False,
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.3.0'
__version__ = '5.4.0'
__author__ = "Daniel Kopka, Michal Kobus, and Sebastian Opalczynski"
__credits__ = ["Daniel Kopka",
"Michal Kobus",
Expand Down
6 changes: 6 additions & 0 deletions syncano/connection.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import json
import time
from copy import deepcopy

import requests
Expand Down Expand Up @@ -267,6 +268,11 @@ def make_request(self, method_name, path, **kwargs):

url = self.build_url(path)
response = method(url, **params)

while response.status_code == 429: # throttling;
retry_after = response.headers.get('retry-after', 1)
time.sleep(float(retry_after))
response = method(url, **params)
content = self.get_response_content(url, response)

if files:
Expand Down
Loading