[![travis build](https://img.shields.io/travis/jvrana/**Pillowtalk**.svg)](https://travis-ci.org/jvrana/**Pillowtalk**)
[![Coverage Status](https://coveralls.io/repos/github/jvrana/**Pillowtalk**/badge.svg?branch=master)](https://coveralls.io/github/jvrana/**Pillowtalk**?branch=master)


![pillow_talk_icon](images/pillowtalk_icon_medium.png?raw=true)
# **Pillowtalk**

Creates intuitive python wrappers for APIs. **Pillowtalk** talks to APIs and handles all of the model relationships behind the scenes, providing a clean and easy-to-use wrapper for your models.

# Why another package?

While there are plenty of excellent libraries for creating APIs, but creating intuitive wrappers for these APIs isn't entirely straightforward. **Pillowtalk** cleanly captures the underlying database relationships APIs may be providing making it easy to write python models. It provides a wrapper for making intuitive live API calls using your python models and the underlying relationships you specified.

In future versions, **pillowtalk** will be able to create and update your code based on a list of JSON files and *guess* at the underlying relationships between models. From there, **pillowtalk** will automatically generate or update python models. This means changes to some API can trigger an automatic update to your python wrapper to that API!

# Features and Examples

## Minimalistic models with relationships

e.g. Person with ONE Address; Address has MANY people
```python
class MyBase(PillowtalkBase):
    @classmethod
    def find(cls, id):
         ...
         
    def where(cls, data):
         ...

@add_schema
class Person(MyBase):
    FIELDS = ["id", "name"]
    RELATIONSHIPS = [
      One("address", "find Person.address_id <> Address.id")
    ]
      
@add_schema
class Address(MyBase):
    FIELDS = ["id", "str"]
    RELATIONSHIPS = [
      Many("people", "where Address.id <> Person.address_id")
    ]
```

Intuitive calls uses live API connection to deserialize data to your models

```python
# address.people doesn't exist yet
address = Address.find(3)

# calling .people causes a api call using "where" and deserialization of data
people = address.people # returns a list of People objects found through "where"

# returned is a list of Person objects!
assert type(people[0]) is Person 
```


Handling impartial data

```python
person = {
  "id": 5,
  "name": "Joe",
  "address": {"id": 4}
}

p = Person.load(person_data)

# a.address will magically return Address object even though data is enveloped in a json.
# we do not specifically have to handle deserialization of impartial data since the
# relationship between Person.address_id <> Address.id was already defined.
a = p.address
assert type(a) is Address
assert person.address_id == 4 # this wasn't defined explicitly but it is inferred from "address": {"id": 4}
```

## More examples and magic to come!
    Other things include:
        * Magic chaining in relationships
        * Session managing suggestions
        * automatically creating model skeletons from list of JSON
        * model relationships through associations
        * examples of connecting to MySQL or SQLlite
        * examples of using CLI through hug
        
