Skip to content

Commit bd3bcd5

Browse files
committed
Add README. Include API usage.
1 parent edc5774 commit bd3bcd5

File tree

1 file changed

+281
-0
lines changed

1 file changed

+281
-0
lines changed

README.md

Lines changed: 281 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
1+
Introduction
2+
============
3+
4+
Slivka python client is a convenience wrapper around the popular [requests](https://requests.readthedocs.io/en/latest/) library for Python.
5+
It is designed to provide an interface for communicating with the slivka REST API using Python.
6+
7+
It includes:
8+
9+
- Programmatic access to slivka API with simple objects
10+
- Command-line interface
11+
- Interactive widgets for Jupyter notebooks
12+
13+
Installation
14+
============
15+
16+
The easiest way to install the slivka client is through the conda package manager.
17+
Install it from the *slivka* channel using
18+
19+
```
20+
conda install -c slivka slivka-client
21+
```
22+
23+
Alternatively, you can install it from sources. Clone the git repository to your
24+
machine and run
25+
26+
```
27+
python setup.py install
28+
```
29+
30+
After the installation has completed successfully, you can import slivka_client
31+
from Python or run `slivka-cli` command line tool.
32+
33+
Usage
34+
=====
35+
36+
To begin, import `slivka_client` library and create a `SlivkaClient` instance using the server URL.
37+
38+
```python
39+
import slivka_client
40+
41+
client = slivka_client.SlivkaClient("http://www.example.org/slivka/")
42+
```
43+
44+
> [!IMPORTANT]
45+
> Remember that locations typically end with a slash. Missing trailing slash may result
46+
> in resources not being located properly.
47+
48+
In order to verify the server was found successfully, you may query the version of slivka from the server.
49+
50+
```python
51+
>>> client.version
52+
Version(client='1.2.1b1', server='0.8.1', API='1.1')
53+
```
54+
55+
The version displays the current client version, server version and
56+
API compatibility version.
57+
58+
If you see an `HTTPError: 404` exception, check the URL the client tries to access and
59+
make sure the server is available under that address. The error may be caused by a missing
60+
trailing slash in the URL.
61+
62+
Services
63+
--------
64+
65+
A list of all available services can be retrieved using the `services` property of the `SlivkaClient` object.
66+
67+
```python
68+
>>> client.services
69+
[Service(...), Service(...), Service(...), ...]
70+
```
71+
72+
Each element of that list represents a single service. It contains its id, name, description, parameters, etc.
73+
The list is retrieved from the server only once and is cached to improve performance on subsequent access to the services.
74+
If you expect the services list to change on the server side you can force reloading them with the `reload_services()` method.
75+
76+
```python
77+
client.reload_services()
78+
```
79+
80+
For convenience, you can get a particular service by its id using the `get_service(id)` method or
81+
by a dictionary item access on a client object.
82+
83+
```python
84+
>>> client.get_service('example')
85+
Service(id='example', name='Example', ...)
86+
87+
>>> client['example']
88+
Service(id='example', name='Example', ...)
89+
```
90+
91+
The `Service` objects provide the following read-only properties:
92+
93+
<dl>
94+
<dt>id</dt>
95+
<dd>identifier of the service</dd>
96+
97+
<dt>url</dt>
98+
<dd>location of the service resource</dd>
99+
100+
<dt>name</dt>
101+
<dd>name of the service</dd>
102+
103+
<dt>description</dt>
104+
<dd>long description of the service</dd>
105+
106+
<dt>author</dt>
107+
<dd>one or more authors of the service</dd>
108+
109+
<dt>version</dt>
110+
<dd>version of the service</dd>
111+
112+
<dt>license</dt>
113+
<dd>license of the service<dd>
114+
115+
<dt>classifiers</dt>
116+
<dd>list of classifiers, tags or categories that help identify or group services</dd>
117+
118+
<dt>parameters</dt>
119+
<dd>list of service parameters represented as <code>Parameter</code> objects (explained below)</dd>
120+
121+
<dt>presets</dt>
122+
<dd>
123+
list of parameter presets offered for this service
124+
125+
<dl>
126+
<dt>Preset.id</dt>
127+
<dd>preset identifier</dd>
128+
<dt>Preset.name</dt>
129+
<dd>name of the preset</dd>
130+
<dt>Preset.description</dt>
131+
<dd>long description of the preset</dd>
132+
<dt>Preset.values</dt>
133+
<dd>dictionary of parameter value <code>Dict[str, Any]</code></dd>
134+
</dl>
135+
</dd>
136+
137+
<dt>status</dt>
138+
<dd>
139+
service operation status
140+
<dl>
141+
<dt>Status.status</dt>
142+
<dd>status name; one of: <em>OK</em>, <em>WARNING</em>, <em>DOWN</em></dd>
143+
<dt>Status.message</dt>
144+
<dd>error message</dd>
145+
<dt>Status.timestamp</dt>
146+
<dd>the time the status was last updated</dd>
147+
</dl>
148+
</dd>
149+
</dl>
150+
151+
### Parameters
152+
153+
Each object in the *parameters* list describes a parameter that can be provided
154+
for the service. For each parameter present in the list, you can provide one
155+
(sometimes multiple) value when submitting the job.
156+
All parameter objects offer the following read-only properties:
157+
158+
<dl>
159+
<dt>id</dt>
160+
<dd>parameter identifier; use it as a key in the data dictionary when submitting jobs.</dd>
161+
<dt>type</dt>
162+
<dd>
163+
parameter type; one of: <em>integer</em>, <em>decimal</em>, <em>text</em>, <em>flag</em>, <em>choice</em>, <em>file</em>, <em>undefined</em>, <em>unknown</em>
164+
</dd>
165+
<dt>name</dt>
166+
<dd>human-friendly name of the parameter</dd>
167+
<dt>description</dt>
168+
<dd>longer description of the parameter</dd>
169+
<dt>required</dt>
170+
<dd>if the parameter is required</dd>
171+
<dt>array</dt>
172+
<dd>if multiple values are allowed for the parameter</dd>
173+
<dt>default</dt>
174+
<dd>default value for the parameter that is used if none is provided</dd>
175+
</dl>
176+
177+
More specialised data structures exist for each type and provide additional properties
178+
specific to that type.
179+
180+
Starting jobs
181+
-------------
182+
183+
New jobs are submitted to the server using `submit_job()` method of the *Service*
184+
object. The method takes two arguments *data* and *files* which are both
185+
dictionaries containing parameter ids and corresponding values.
186+
The values are properly encoded and sent as a POST request to the server.
187+
Values for the parameters that require a file as an input need to be provided
188+
through the *files* argument to ensure the HTTP request includes the contents
189+
of the file.
190+
191+
Values provided in the *data* dictionary are converted to strings automatically.
192+
Values provided in the *files* dictionary can be open files or streams,
193+
in which case the content of the stream is sent to the server, or bytes, which are sent directly.
194+
195+
> [!IMPORTANT]
196+
> Files and streams should be opened in binary mode to avoid potential issues with
197+
> non-ascii characters.
198+
199+
On successful job submission the method returns a *Job* object containing
200+
submission data. This object is used to check job status and retrieve
201+
results.
202+
If the input parameter are not valid, the method throws a *SubmissionError*
203+
containing a list of errors encountered during input processing.
204+
205+
Example:
206+
207+
```python
208+
>>> service = client['example']
209+
>>> job = service.submit_job(
210+
... data={
211+
... 'param0': 13,
212+
... 'param1': 'foobar'
213+
... },
214+
... files={
215+
... 'input0': open("input-file.txt", "rb"),
216+
... 'input1': b"data data data data\n"
217+
... }
218+
... )
219+
```
220+
221+
Polling jobs and retrieving results
222+
-----------------------------------
223+
224+
The *Job* object returned by the `submit_job()` method provides the capability
225+
to inspect submission data and poll the status of the submitted job and
226+
retrieve result files from the server.
227+
228+
The 'id' property of the job object holds a server-generated identifier, uniquely denoting the job within the server's context.
229+
The job additionally holds *service*, *parameters* and *submission_time* information.
230+
231+
The current job status can be obtained using a *status* property which gets updated
232+
from the server every time it is accessed but no more frequently than once every five seconds.
233+
234+
The result files can be accessed with a *results* property. Just like *status*, the *results*
235+
is updated from the server every time it is accessed. It returns a list of *slivka_client.File*
236+
objects which can be used to inspect file metadata and download their content.
237+
238+
> [!NOTE]
239+
> If you lose the *Job* object either by deleting a variable or restarting
240+
> the Python interpreter, you can re-create that object using *Client.get_job()*
241+
> method providing it with the job id.
242+
243+
### File
244+
245+
The file objects you receive from the slivka client are not actual files you could
246+
read from. Instead, they are referencing the resources located on the server and can
247+
be dumped to actual files or streams instead using `dump()` method.
248+
The argument to the `dump()` method can be a stream or a file opened in either
249+
text or binary mode, or a file name. In case of streams or files, the result
250+
is downloaded from the server and appended to the stream. If a file name is
251+
provided, a new file is created, replacing the existing one if exists, and
252+
the content is written to that file.
253+
254+
Example:
255+
256+
```python
257+
>>> result = job.results[0]
258+
259+
>>> # dumping to open file
260+
>>> result.dump(open("out.txt", "w"))
261+
262+
>>> # dumping to in-memory stream
263+
>>> input_stream = io.BytesIO()
264+
>>> result.dump(input_stream)
265+
266+
>>> # creating new file
267+
>>> result.dump("out.txt")
268+
```
269+
270+
Additionally, the *File* object provides the following properties:
271+
272+
| Property | Description |
273+
|---------------|------------------------------------------------------------------|
274+
| *url* | Location of the resource |
275+
| *content_url* | Location of the file content |
276+
| *id* | Identifier of the file which can be used as input for other jobs |
277+
| *job_id* | Id of the job this file is a result of |
278+
| *path* | Real path and name of the file |
279+
| *label* | Name describing the file |
280+
| *media_type* | Media type of the file |
281+

0 commit comments

Comments
 (0)