NO LONGER BEING DEVELOPED
Branch | Build | Coverage |
---|---|---|
master | ||
development |
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.
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!
e.g. Person with ONE Address; Address has MANY people
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
# 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
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}
Pillowtalk comes with a SessionManager class. Lets say you have an api connector:
class MyAPI(object):
def __init__(*args, **kwargs):
self.__dict__.update(locals())
You can create a custom session manager easily by:
class MySession(SessionManager):
pass
You can register you connector by:
# initialize your connectors
myapi = MyAPI(login="username", password="password", url="myurl")
myapi2 = MyAPI(login="username", password="password", url="myurl_2")
# register it
MySession().register_connector(myapi, session_name="session1")
MySession().register_connector(myapi, session_name="session2")
You can access your apis from anywhere by:
# set to "session2"
MySession().set("session2")
# returns API associated with session1
MySession().session
# print the session_name
print(MySession().session_name) # prints "session2"
SessionManager instances are a Borg idioms and share their state between instances:
s1 = MySession()
s1.name = "something"
s2 = MySession()
s1.__dict__ == s2.__dict__
But not between other subclasses:
s1 = MySession()
s1.name = "something"
s1.name != SessionManager().name
SessionManager plays nicely with the pickle module. Save your sessions using pickle.dump
and reload
your sessions with pickle.load
. Loading will automatically update all of your session instances for your session class.
import pickle
# save session info
with open(filepath, 'wb') as f:
f.dump(MySession(), f)
# ...
# update session info
with open(filepath, 'rb') as f:
f.load(f)
Optionally, save
and load
methods are included for convenience:
MySession().save()
MySession().load()