Writing your First SDK¶
Introduction¶
This tutorial will cover creating a simple SDK for managing a REST-ful API.
Note: The code for this tutorial is available in the ivanprjcts/my-first-sdk repository on GitHub.
Setting up a new environment¶
Before we do anything else we’ll create a new virtual environment, using virtualenv. This will make sure our package configuration is kept nicely isolated from any other projects we’re working on.
virtualenv env
source env/bin/activate
Now that we’re inside a virtualenv environment, we can install our package requirements.
pip install sdklib
Note: To exit the virtualenv environment at any time, just type deactivate.
Getting started¶
Okay, we’re ready to get coding. To get started, let’s create a new project to work with.
cd ~
mkdir my-first-sdk
cd my-first-sdk
Once that’s done we can create project structure that we’ll use to create a simple Web API Client SDK.
mkdir first_sdk tests
touch README.md first_sdk/__init__.py first_sdk/first_sdk.py tests/__init__.py tests/test_first_sdk.py
tree
.
├── README.md
├── first_sdk
│ ├── __init__.py
│ └── first_sdk.py
└── tests
├── __init__.py
└── test_first_sdk.py
My First SDK¶
We’ll need to edit our first_sdk/first_sdk.py file:
from sdklib.http import HttpSdk
from sdklib.util.parser import safe_add_end_slash, parse_args
class FirstSdk(HttpSdk):
"""
My First Sdk.
"""
DEFAULT_HOST = "http://mockapi.sdklib.org"
API_ITEMS_URL_PATH = "/items/"
def create_item(self, name, description=None):
"""
Create an item.
:param name: str
:param description: str (optional)
:return: SdkResponse
"""
params = parse_args(name=name, description=description)
return self.post(self.API_ITEMS_URL_PATH, body_params=params)
def get_items(self, item_id=None):
"""
Retrieve all items if 'item_id' is None. Otherwise, get specified item by 'item_id'.
:param item_id: str (optional)
:return: SdkResponse
"""
return self.get(self.API_ITEMS_URL_PATH + safe_add_end_slash(item_id))
def update_item(self, item_id, name, description=None):
"""
Update an item.
:param item_id: str
:param name: str
:param description: str (optional)
:return: SdkResponse
"""
params = parse_args(name=name, description=description)
return self.put(self.API_ITEMS_URL_PATH + item_id + '/', body_params=params)
def delete_item(self, item_id):
"""
Remove an item.
:param item_id: str
:return: SdkResponse
"""
return self.delete(self.API_ITEMS_URL_PATH + item_id + '/')
Okay, we’re ready to test.
Testing my First SDK¶
Let’s edit our tests/test_first_sdk.py file:
import unittest
from first_sdk.first_sdk import FirstSdk
class TestFirstSdk(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.api = FirstSdk()
@classmethod
def tearDownClass(cls):
pass
def test_crud_items(self):
"""
Test the creation, reading, update and deletion of an item.
"""
response = self.api.create_item("ItemName", "Some description")
self.assertEqual(response.status, 201)
item_id = response.data["pk"]
self.assertEqual("ItemName", response.data["name"])
self.assertEqual("Some description", response.data["description"])
response = self.api.get_items()
self.assertEqual(response.status, 200)
self.assertIn("results", response.data)
self.assertTrue(isinstance(response.data["results"], list))
response = self.api.get_items(item_id)
self.assertEqual(response.status, 200)
self.assertEqual("ItemName", response.data["name"])
self.assertEqual("Some description", response.data["description"])
response = self.api.update_item(item_id, "New name")
self.assertEqual(response.status, 200)
self.assertEqual("New name", response.data["name"])
self.assertEqual("Some description", response.data["description"])
response = self.api.delete_item(item_id)
self.assertEqual(response.status, 204)