Swagger Petstore - 1.0.0

This is a sample server Petstore server. You can find out more about Swagger at http://swagger.io or on irc.freenode.net, #swagger. For this sample, you can use the api key special-key to test the authorization filters.


In [ ]:
!pip install dicttoxml

In [ ]:
import json
from dicttoxml import dicttoxml

In [ ]:
PETS = {}
PET_STATUS_INDEX = {}
TAG_INDEX = {}
ORDERS = {}
ORDER_STATUS_INDEX = {}
JSON = 'application/json'
XML = 'application/xml'
content_type = JSON

In [ ]:
class MissingField(Exception):
    def __init__(self, type_name, field):
        self.msg = '{} is missing required field "{}"'.format(type_name, field)
        
        
class InvalidValue(Exception):
    def __init__(self, name, type_name):
        self.msg = '{} is not a {}'.format(name, type_name)
        
class NotFound(Exception):
    def __init__(self, type_name, id):
        self.msg = 'There is no {} with id {}'.format(type_name, id)


def print_response(content, content_type=JSON):
    if content_type == JSON:
        print(json.dumps(content))
    elif content_type == XML:
        print(dicttoxml(content).decode('UTF-8'))

def split_query_param(param):
    values = []
    for paramValue in param:
        values += paramValue.split(',')
    values = map(lambda x: x.strip(), values)
    return list(values)

def create_error_response(code, error_type, message):
    return {
        'code' : code,
        'type' : error_type,
        'message' : message
    }
        
# Pet APIs
def validate_pet(pet):
    fields = ['id', 'category', 'name', 'photoUrls', 'tags', 'status']
    for field in fields:
        if field not in pet:
            raise MissingField('Pet', field)
            
def persist_pet(pet):
    validate_pet(pet)
    PETS[pet['id']] = pet
    index_pet(pet)
    return pet


def get_pet_by_id(pet_id):
    try:
        pet_id = int(pet_id)
        if not pet_id in PETS:
            raise NotFound('Pet', pet_id)
        else:
            return PETS[pet_id]
    except ValueError:
        raise InvalidValue('Pet id', 'int')

def delete_pet_by_id(pet_id):
    try:
        pet_id = int(pet_id)
        if not pet_id in PETS:
            raise NotFound('Pet', pet_id)
        else:
            pet = PETS[pet_id]
            del PETS[pet_id]
            return pet
    except ValueError:
        raise InvalidValue('Pet id', 'int')

def index_pet(pet):
    # Index the status of the pet
    pet_status = pet['status']
    if pet_status not in PET_STATUS_INDEX:
        PET_STATUS_INDEX[pet_status] = set()
    PET_STATUS_INDEX[pet_status].add(pet['id'])
    
    # index the tags of the pet
    for tag in pet['tags']:
        tag = tag.strip()
        if tag not in STATUS_INDEX:
            TAG_INDEX[tag] = set()
        TAG_INDEX[tag].add(pet['id'])
        
def collect_pets_by_id(petIds):
    petIds = set(petIds)
    petList = []
    for petId in petIds:
        petList.append(PETS[petId])
    return petList

# Order APIs
def validate_order(order):
    fields = ['id', 'petId', 'quantity', 'shipDate', 'status', 'complete']
    for field in fields:
        if field not in order:
            raise MissingField('Order', field)

def persist_order(order):
    validate_order(order)
    ORDERS[order['id']] = order
    
def get_order_by_id(order_id):
    try:
        order_id = int(order_id)
        if not order_id in ORDERS:
            raise NotFound('Order', order_id)
        else:
            return ORDERS[order_id]
    except ValueError:
        raise InvalidValue('Order id', 'int')

def delete_order_by_id(order_id):
    try:
        order_id = int(order_id)
        if not order_id in ORDERS:
            raise NotFound('Order', order_id)
        else:
            order = ORDERS[order_id]
            del ORDERS[order_id]
            return order
    except ValueError:
        raise InvalidValue('Order id', 'int')

POST /pet

Add a new pet to the store

Body Parameters:

  • body (required) - Pet object that needs to be added to the store

In [ ]:
REQUEST = json.dumps({
        'body' : {
            'id': 1,
            'category' : { 
                'id' : 1,
                'name' : 'cat'
            },
            'name': 'fluffy',
            'photoUrls': [],
            'tags': ['cat', 'siamese'],
            'status': 'available'
        }
    })

In [ ]:
# POST /pet 
try:
    req = json.loads(REQUEST)
    pet = req['body']
    persist_pet(pet)
    response = pet
except MissingField as e:
    response = create_error_response(405, 'Invalid Pet', e.msg)
except ValueError as e:
    response = create_error_response(405, 'Invalid Pet', 'Could not parse json')
finally:
    print_response(response, content_type)

PUT /pet

Update an existing pet

Body Parameters:

  • body (required) - Pet object that needs to be added to the store

In [ ]:
REQUEST = json.dumps({
        'body' : {
            'id': 1,
            'category' : { 
                'id' : 1,
                'name' : 'cat'
            },
            'name': 'fluffy',
            'photoUrls': [],
            'tags': ['cat', 'siamese'],
            'status': 'available'
        }
    })

In [ ]:
# PUT /pet 
try:
    req = json.loads(REQUEST)
    new_pet = req['body']
    current_pet = get_pet_by_id(new_pet['id'])
    persist_pet(new_pet)
    response = new_pet
except InvalidValue as e:
    response = create_error_response(400, 'Invalid ID', e.msg)
except ValueError as e:
    response = create_error_response(400, 'Invalid Pet', 'Could not parse json')
except NotFound as e:
    response = create_error_response(404, 'Not Found', e.msg) 
except MissingField as e:
    response = create_error_response(405, 'Invalid Pet', e.msg)
finally:
    print_response(response, content_type)

GET /pet/findByStatus

Finds Pets by status

Multiple status values can be provided with comma seperated strings

Query Parameters:

  • status (required) - Status values that need to be considered for filter

In [ ]:
REQUEST = json.dumps({
        'args' : {
            'status' : ['available , unavailable']
        }
    })

In [ ]:
# GET /pet/findByStatus 
req = json.loads(REQUEST)
status_list = split_query_param(req['args']['status'])
pet_ids = []
for status in status_list:
    if status in PET_STATUS_INDEX:
        pet_ids += PET_STATUS_INDEX[status]
pet_list = collect_pets_by_id(pet_ids)
print_response(pet_list, content_type)

GET /pet/findByTags

Finds Pets by tags

Muliple tags can be provided with comma seperated strings. Use tag1, tag2, tag3 for testing.

Query Parameters:

  • tags (required) - Tags to filter by

In [ ]:
REQUEST = json.dumps({
        'args' : {
            'tags' : ['cat , dog, horse']
        }
    })

In [ ]:
# GET /pet/findByTags 
req = json.loads(REQUEST)
tag_list = split_query_param(req['args']['tags'])
pet_ids = []
for tag in tag_list:
    if tag in TAG_INDEX:
        pet_ids += TAG_INDEX[tag]
pet_list = collect_pets_by_id(pet_ids)
print_response(pet_list, content_type)

GET /pet/:petId

Find pet by ID

Returns a single pet

Path Parameters:

  • petId (required) - ID of pet to return

In [ ]:
REQUEST = json.dumps({
        'path' : {
            'petId' : 1
        }
    })

In [ ]:
# GET /pet/:petId 
try:
    req = json.loads(REQUEST)
    pet_id = req['path']['petId']
    response = get_pet_by_id(pet_id)
except InvalidValue as e:
    response = create_error_response(400, 'Invalid ID', e.msg)
except NotFound as e:
    response = create_error_response(404, 'Not Found', e.msg)    
finally:
    print_response(response, content_type)

POST /pet/:petId

Updates a pet in the store with form data

Path Parameters:

  • petId (required) - ID of pet that needs to be updated

Form Parameters:

  • name (optional) - Updated name of the pet
  • status (optional) - Updated status of the pet

In [ ]:
REQUEST = json.dumps({
        'path' : {
            'petId' : 1
        },
        'body' : {
            'name' : ['new name']
        }
    })

In [ ]:
# POST /pet/:petId 
try:
    req = json.loads(REQUEST)
    pet_updates = req['body']
    pet_id = req['path']['petId']
    old_pet = get_pet_by_id(pet_id)
    props = ['name', 'status']
    for prop in props:
        if prop in pet_updates:
            old_pet[prop] = pet_updates[prop][0]
    response = persist_pet(old_pet)
except InvalidValue as e:
    response = create_error_response(400, 'Invalid ID', e.msg)
except NotFound as e:
    response = create_error_response(404, 'Not Found', e.msg)    
finally:
    print_response(response, content_type)

DELETE /pet/:petId

Deletes a pet

Path Parameters:

  • petId (required) - Pet id to delete

In [ ]:
REQUEST = json.dumps({
        'path' : {
            'petId' : '1'
        }
    })

In [ ]:
# DELETE /pet/:petId
try:
    req = json.loads(REQUEST)
    pet_id = req['path']['petId']
    response = delete_pet_by_id(pet_id)
except InvalidValue as e:
    response = create_error_response(400, 'Invalid ID', e.msg)
except NotFound as e:
    response = create_error_response(404, 'Not Found', e.msg)    
finally:
    print_response(response, content_type)

Store Endpoints

GET /store/inventory

Returns pet inventories by status

Returns a map of status codes to quantities


In [ ]:
# GET /store/inventory 
status_counts = {}
for status in ORDER_STATUS_INDEX:
    status_counts[status] = len(set(ORDER_STATUS_INDEX[status]))
    
print_response(status_counts, content_type)

POST /store/order

Place an order for a pet

Body Parameters:

  • body (required) - order placed for purchasing the pet

In [ ]:
REQUEST = json.dumps({
        'body' : {
            'id' : 1,
            'petId' : 1,
            'quantity' : 1,
            'shipDate' : '12/30/2015',
            'status' : 'placed',
            'complete' : False
        }
    })

In [ ]:
# POST /store/order 
try:
    req = json.loads(REQUEST)
    order = req['body']
    persist_order(order)
    response = order
except MissingField as e:
    response = create_error_response(400, 'Invalid Order', e.msg)
except ValueError as e:
    response = create_error_response(400, 'Invalid Order', 'Could not parse json')
finally:
    print_response(response, content_type)

GET /store/order/:orderId

Find purchase order by ID

For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions

Path Parameters:

  • orderId (required) - ID of pet that needs to be fetched

In [ ]:
REQUEST = json.dumps({
        'path' : {
            'orderId' : 1
        }
    })

In [ ]:
# GET /store/order/:orderId
try:
    req = json.loads(REQUEST)
    order_id = req['path']['orderId']
    response = get_order_by_id(order_id)
except InvalidValue as e:
    response = create_error_response(400, 'Invalid ID', e.msg)
except NotFound as e:
    response = create_error_response(404, 'Not Found', e.msg)    
finally:
    print_response(response, content_type)

DELETE /store/order/:orderId

Delete purchase order by ID

For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors

Path Parameters:

  • orderId (required) - ID of the order that needs to be deleted

In [ ]:
REQUEST = json.dumps({
        'path' : {
            'orderId' : 1
        }
    })

In [ ]:
# DELETE /store/order/:orderId 
try:
    req = json.loads(REQUEST)
    order_id = req['path']['orderId']
    response = delete_order_by_id(order_id)
except InvalidValue as e:
    response = create_error_response(400, 'Invalid ID', e.msg)
except NotFound as e:
    response = create_error_response(404, 'Not Found', e.msg)    
finally:
    print_response(response, content_type)

Initialization

Sets all stores to empty dictionaries, so when the app starts there is no initial state.


In [ ]:
PETS = {}
STATUS_INDEX = {}
TAG_INDEX = {}
ORDERS = {}