1 Extending kamaki.clients
2 ========================
4 By default, kamaki clients are REST clients (they manage HTTP requests and
5 responses to communicate with services).
10 All service clients consist of a subclass of the Client class and implement
11 separate client functionalities as member methods. There is also an error class
12 to raise exceptions that can be handled by kamaki interfaces.
14 .. code-block:: python
16 # ${KAMAKI_PATH}/kamaki/clients/mynewclient.py
18 from kamaki.clients import Client, ClientError
20 class MyNewClient(Client):
21 """MyNewClient Description Here"""
23 def my_first_method(self, **args):
24 """Method description"""
29 except SomeKnownException as e1:
30 raise ClientError('MyError: %s' % e1)
31 except SomeOtherException as e2:
32 raise ClientError('MyError: %s' % e2)
34 def my_second_method(self, **params):
35 """Method description"""
38 Custom clients can use a set of convenience methods for easy HTTP requests
40 .. code-block:: python
42 def get(self, path, **kwargs)
43 def head(self, path, **kwargs)
44 def post(self, path, **kwargs)
45 def put(self, path, **kwargs)
46 def delete(self, path, **kwargs)
47 def copy(self, path, **kwargs)
48 def move(self, path, **kwargs)
50 How to use your client
51 ----------------------
53 External applications must instantiate a MyNewClient object.
55 .. code-block:: python
57 from kamaki.clients import ClientError
58 from kamaki.clients.mynewclient import MyNewClient
62 cl = MyNewClient(args)
63 cl.my_first_method(other_args)
64 except ClientError as cle:
65 print('Client Error: %s' % cle)
71 Kamaki clients may handle multiple requests at once, using threads. In that
72 case, users might implement their own thread handling mechanism, use an
73 external solution or take advantage of the mechanism featured in kamaki.clients
75 .. code-block:: python
77 from threading import enumerate
78 from kamaki.clients import SilentEvent
81 class MyNewClient(Client):
84 def _single_threaded_method(self, **args):
89 def multithread_method(self):
91 self._init_thread_limit()
92 while some_condition or thread_list:
94 event = SilentEvent(self._single_threaded_method, **args)
96 thread_list.append(event)
97 thread_list = self._watch_thread_limit(thread_list)
102 The kamaki.clients package contains a set of fine-grained unit-tests for all
105 .. note:: unit tests require the optional python-mock package, version 1.X or
111 To run the tests, the kamaki source code has to be downloaded.
113 .. code-block:: console
115 $ git clone https://code.grnet.gr/git/kamaki
116 $ cd kamaki/kamaki/clients
118 In each package under kamaki.clients, there is a test module (test.py) where
119 the tests are implemented. To run all tests, run the test.py file from
122 .. code-block:: console
126 To test a specific class, add the class name as an argument. E.g. for the
129 .. code-block:: console
131 $ python test.py Client
133 To test a specific method in a class, apply an extra argument, e.g. for the
134 request method in the Client class:
136 .. code-block:: console
138 $ python test.py Client request
140 Each package contains a test module (test.py) which is also runnable from the
141 command line. E.g. in the pithos package there is a test module which
142 contains, among others, the **download** sub-test:
144 .. code-block:: console
148 # Run all kamaki.clients.pithos tests
151 # Run all kamaki.clients.pithos.PithoClient tests
152 $ python test.py Pithos
154 # Test kamaki.clients.pithos.PithosClient.download
155 $ python test.py Pithos download
157 To fully test a specific package, run test.py from the package location. E.g.
158 to test everything in kamaki.clients.pithos package:
160 .. code-block:: console
168 Each folder / package contains a test.py file, that represents the test module
169 of this package. All test modules contain a set of classes that extent the
170 TestCase class. They also contain a main method to run the tests.
172 By convention, testing classes are named as <Tested Class> where <Test Class>
173 is the name of the tested class or module. Methods not grouped in classes are
174 tested by classes named after their respective module.
176 For example, the kamaki.clients.pithos.PithosClient class is tested by the
177 kamaki.clients.pithos.test.PithosClient class, while the methods in
178 kamaki.clients.utils module are tested by the kamaki.clients.utils.test.Utils
184 After modifying or extending kamaki.clients method, classes, modules or
185 packages, it is a good practice to also modify or extend the corresponding
186 unit tests. What's more, it is recommended to modify or implement the testing
187 of new behavior before implementing the behavior itself. The aim for
188 kamaki.clients package is an 1 to 1 mapping between methods and their tests.
190 Modifying an existing method
191 """"""""""""""""""""""""""""
193 In case of an existing method modification, the programmer has to modify the
194 corresponding test as well. By convention, the test method is located in the
195 test module under the same package, in a TestCase subclass that is named with a
196 name similar to the package or class that contains the tested method.
198 Example 1: to modify the kamaki.clients.utils.filter_in method, the programmer
199 has to also adjust the kamaki.clients.utils.test.Utils.test_filter_in method.
201 Example 2: to modify the kamaki.clients.pithos.PithosRestClient.object_get, the
202 programmer has to also adjust the
203 kamaki.clients.pithos.test.PithosRestClient.test_object_get method.
208 Programmers who want to implement a new method in an existing class, are
209 encouraged to implement the corresponding unit test first. In order to do that,
210 they should find the testing class that is mapped to the class or module they
213 Example 1: To add a **list_special** method to
214 kamaki.clients.astakos.AstakosClient, extend the
215 kamaki.clients.astakos.test.AstakosClient class, as shown bellow:
217 .. code-block:: python
219 # file: ${kamaki}/kamaki/clients/astakos/__init__.py
221 class AstakosClient(TestCase):
223 def test_list_special(self):
224 """Test the list_special method"""
227 Example 2: To add a **get_random_int** method in kamaki.clients.utils module,
228 extend the kamaki.clients.utils.test.Utils test class, as shown bellow:
230 .. code-block:: python
232 # file: ${kamaki}/kamaki/clients/utils/__init__.py
234 class Utils(TestCase):
236 def test_get_random_int(self):
237 """Test the get_random_int method"""
240 Implementing a new class or module
241 """"""""""""""""""""""""""""""""""
243 Each class or module needs a seperate test sub-module. By convention, each
244 class or module under the kamaki.clients should be located in a separate
247 Example 1: To add a NewService class that implements the kamaki.clients.Client
250 * create a new_service package and implement the unit tests in the kamaki.clients.new_service.test module:
252 .. code-block:: console
254 $ mkdir new_service && touch new_service/test.py
256 * create the file that will hold the package code and implement the module there:
258 .. code-block:: console
260 $ touch new_service/__init__.py
262 * Create the test class and methods in kamaki.clients.new_service.test
264 .. code-block:: python
266 # file: ${kamaki}/kamaki/clients/new_service/test.py
267 from unittest import TestCase
269 class NewService(TestCase):
271 def test_method1(self):
274 * Create the NewService and its actual functionality in kamaki.clients.new_service
276 .. code-block:: python
278 # file: ${kamaki}/kamaki/clients/new_service/__init__.py
279 from kamaki.clients import Client
281 class NewService(Client):
283 def method1(self, ...):
286 * Expose the new tests to top test module, by importing the test class to kamaki.clients.test
288 ..code-block:: python
290 # file: ${kamaki}/kamaki/clients/test.py
292 from kamaki.clients.new_service.test import NewService
294 .. note:: If the new class or module is part of an existing sub-package, it is
295 acceptable to append its testing class in the existing test.py file of the
296 sub-package it belongs to. For example, the
297 kamaki.clients.pithos.PithosClient and
298 kamaki.clients.pithos.rest_api.PithosRestClient classes are tested by two
299 different classes (PithosClient and PithosRestClient respectively) in the
300 same module (kamaki.clients.pithos.test).