Get a Newsletter REST API wrapper
Project description
ganapi
=======
The ganapi library presents a simple and easy to use interface to the Get a Newsletter's REST API.
Requirements
------------
* Python 2.7.6 tested
* requests 2.2.1
* httmock for tests
Installation
------------
Via PIP:
```bash
pip install ganapi
```
Usage
-----
Start by creating an instance of the ```Api``` object:
```python
from ganapi import Api
token = '...'
gan_api = Api(token)
```
Here ```token``` variable must contain a valid [API token](http://help.getanewsletter.com/en/support/api-token-2/) string.
#### The contact object
The instances of the Contact class represent the contact entities in the API.
They have the following fields:
*Required fields*
* ```email``` - contact's email. It's also a ***_lookup field_*** - required when updating or deleting the contact.
*Optional fields*
* ```attributes``` - list of the contact's [attributes](http://help.getanewsletter.com/en/support/attribute-overview/).
* ```first_name```
* ```last_name```
* ```lists``` - list of the newsletters for which this contact is subscribed to.
*Read-only fields*
* ```url``` - the contact's resource URL.
* ```active``` - true if the contact is active and can receive mails, false otherwise.
* ```updated``` - the date of the last change.
* ```created``` - the date of creation.
#### Retreiving a contact
You have to create an instance of the ```ContactManager``` class and then use it's ```get()``` method to retrieve the contact you need.
```python
from ganapi import ContactManager
contact_manager = ContactManager(gan_api)
contact = contact_manager.get('john.doe@example.com')
```
The manager methods will throw an ```HTTPError``` in case of HTTP error from the API, so it's a good idea to catch it.
```python
try:
contact = contact_manager.get('john.doe@example.com')
except HTTPError as e:
if e.response.code == 404:
print 'Contact not found!'
else:
print 'API error: ' + e
```
### Querying for contacts
You have to create an instance of the ```ContactManager``` class and then use it's ```query()``` method to retrieve the contacts you need.
```query()``` takes a dict of [url parameters](https://api.getanewsletter.com/v3/docs/contacts/#get-contacts) and will return a ```PaginatedResultSet``` with the first page of contacts in a list in PaginatedResultSet.entities.
```python
# Get PaginatedResultSet containing contacts with emails starting with name@.
queried_contacts = contact_manager.query({'search_email': 'name@'})
# list of contacts in current page(1)
queried_contacts.entities
# list of contacts in next page(2) if available and update PaginatedResultSet
queried_contacts.next()
# list of contacts in previous page(1) if available and update PaginatedResultSet
queried_contacts.prev()
```
#### Creating a contact
```python
contact = contact_manager.create()
contact.email = 'jane.doe@example.com'
contact.first_name = 'Jane'
contact.save()
```
This will create a new contact and save it. Again, it'll be a good idea to catch exceptions when calling the ```save()``` method. The API will respond with an error if the contact already exists.
One way to avoid it is to force the creation of the contact, overwriting the existing one:
```python
contact.overwrite()
```
Both ```save()``` and ```overwrite()``` will return the same contact object with it's read-only fields updated (e.g. ```created```, ```updated```).
```python
contact = contact.save()
print contact.created
```
#### Updating an existing contact
```python
# Get the contact.
contact = contact_manager.get('john.doe@example.com')
# Change some fields.
contact.first_name = 'John'
# Save it.
contact.save()
```
You can avoid making two calls to the API by forcing a *partial update*.
```python
contact = contact_manager.create()
contact.set_persisted()
contact.email = 'john.doe@example.com'
contact.first_name = 'John'
contact.save()
```
Calling ```set_persisted()``` on the contact object marks it like it's already existing and coming from the API. The calls to the ```save()``` method when a contact is maked as existing will do only a *partial update*, i.e. update only the supplied fields and skipping all the ```None``` fields.
Do not forget that ```email``` is a ***_lookup field_*** and required when updating or deleting the contact.
#### Deleting a contact
```python
contact.delete()
```
#### The list object
The instances of the List class represent the [lists](http://help.getanewsletter.com/en/support/lists-overview/) in the API. They have the following structure:
*Required fields*
* ```email``` - sender's email.
* ```name``` - name of the list.
* ```sender``` - sender's name.
*
*Optional fields*
* ```description```
*Lookup field*
* ```hash``` - the list's unique hash.
*Read-only fields*
* ```responders_count```
* ```subcribers```
* ```created```
* ```url```
* ```subscribers_count```
* ```active_subscribers_count```
* ```responders```
#### Retreiving, creating, updating and deleting a list
The CRUD operations on lists are no different from the operations on contacts:
```python
list_manager = ListManager(gan_api)
# Retrieve a list.
list = list_manager.get('hash')
# Update the list.
list.name = 'my list'
list = list.save()
print list.updated
# Create new list.
new_list = list_manager.create()
new_list.email = 'john.doe@example.com' # required fields
new_list.name = 'my new list'
new_list.sender = 'John Doe'
new_list.save()
# Partial update.
list = list_manager.create()
list.hash = 'hash' # lookup field
list.name = 'updated list'
list.save()
# Delete the list.
list.delete()
```
#### Subscribing a contact to a list
```python
contact.subscribe_to(list)
contact.save()
```
You can also create a new contact automatically subscribed.
```python
contact = contact_manager.create()
contact.email = 'john.doe@example.com'
contact.subscribe_to(list)
contact.save()
```
#### Unsubscribing a contact from a list
```python
contact.unsubscribe_from(list)
contact.save()
```
#### Deleting a contacts subscription from a list
```python
contact.delete_subscription_from(list)
contact.save()
```
#### The attribute object
The instances of the Attribute class represent the attribute entities in the API.
They have the following fields:
*Required fields*
* ```name``` - attribute name.
*Lookup field*
* ```code``` - the slugified attribute code. required when updating or deleting the attribute. *The name "A new attribute" code will be "a-new-attribute"*
*Read-only fields*
* ```url``` - the attribute resource URL.
* ```usage_count``` - number of usages.
#### Retreiving an attribute
You have to create an instance of the ```AttributeManager``` class and then use it's ```get()``` method to retrieve the attribute you need.
```python
from ganapi import AttributeManager
attribute_manager = AttributeManager(gan_api)
attribute = attribute_manager.get('code')
```
The manager methods will raise a ```HTTPError``` in case of HTTP error from the API, so it's a good idea to catch it.
```python
try:
attribute = attribute_manager.get('code')
except HttpError as e:
if e.response.code == 404:
print 'Attribute not found!'
else:
print 'API error: ' + e
```
#### Creating an attribute
```python
attribute = attribute_manager.create()
attribute.name = 'City'
attribute.save()
```
This will create a new attribute and save it. Again, it'll be a good idea to catch exceptions when calling the ```save()``` method. The API will respond with an error if the attribute already exists.
One way to avoid it is to force the creation of the attribute, overwriting the existing one:
```python
attribute.overwrite()
```
Both ```save()``` and ```overwrite()``` will return the same attribute object with it's read-only fields updated (e.g. ```url```, ```usage_count```).
```python
attribute = attribute.save()
print attribute.usage_count
```
#### Updating an existing attribute
```python
# Get the attribute.
attribute = attribute_manager.get('code')
# Change name field.
attribute.name = 'Changed!'
# Save it.
attribute.save()
```
You can avoid making two calls to the API by forcing a *partial update*.
```python
attribute = attribute_manager.create()
attribute.set_persisted()
attribute.code = 'code'
attribute.name = 'Changed!'
attribute.save()
```
Calling ```set_persisted()``` on the attribute object marks it like it's already existing and coming from the API. The calls to the ```save()``` method when a attribute is made as existing will do only a *partial update*, i.e. update only the supplied fields and skipping all the ```None``` fields.
Do not forget that ```code``` is a ***_lookup field_*** and required when updating or deleting the attribute.
#### Deleting an attribute
```python
attribute.delete()
```
### Get all entities of type
You can get all contacts, lists or attributes in a generator using the ```all()``` method on their manager.
*Parameters*
* ```start``` - start index (default: 0)
* ```stop``` stop index (default: float('inf'))
```python
# Print all contacts emails
all_contacts = contact_manager.all()
for contact in all_contacts:
print contact.email
# Get a generator starting on contact 100 stopping on contact 200
all_contacts = contact_manager.all(start=100, stop=200)
```
#### The PaginatedResultSet class
The instance of the PaginatedResultSet class represent the result of get from the API.
*Parameters*
* ```data``` - json of result from the ```query()``` method in the managers.
* ```manager``` - the manager using ```query()```.
*Properties*
* ```next_link``` - URL to get the next page of the results.
* ```previous_link``` - URL to get the previous page of the results.
* ```manager``` - ```EntityManager``` currently used.
* ```entities``` - List of ```Entity``` for the current result page.
* ```count``` - Total amount of entity results in all pages.
*Methods*
* ```prev()``` - replaces the instance with results from the previous page and returns entities.
* ```next()``` - replaces the instance with results from the next page and returns entities.
```next()``` and ```prev()``` will raise ```StopIteration``` if the end of the direction has been reached.
They will raise ```HTTPError``` in case of HTTP error from the API,
=======
The ganapi library presents a simple and easy to use interface to the Get a Newsletter's REST API.
Requirements
------------
* Python 2.7.6 tested
* requests 2.2.1
* httmock for tests
Installation
------------
Via PIP:
```bash
pip install ganapi
```
Usage
-----
Start by creating an instance of the ```Api``` object:
```python
from ganapi import Api
token = '...'
gan_api = Api(token)
```
Here ```token``` variable must contain a valid [API token](http://help.getanewsletter.com/en/support/api-token-2/) string.
#### The contact object
The instances of the Contact class represent the contact entities in the API.
They have the following fields:
*Required fields*
* ```email``` - contact's email. It's also a ***_lookup field_*** - required when updating or deleting the contact.
*Optional fields*
* ```attributes``` - list of the contact's [attributes](http://help.getanewsletter.com/en/support/attribute-overview/).
* ```first_name```
* ```last_name```
* ```lists``` - list of the newsletters for which this contact is subscribed to.
*Read-only fields*
* ```url``` - the contact's resource URL.
* ```active``` - true if the contact is active and can receive mails, false otherwise.
* ```updated``` - the date of the last change.
* ```created``` - the date of creation.
#### Retreiving a contact
You have to create an instance of the ```ContactManager``` class and then use it's ```get()``` method to retrieve the contact you need.
```python
from ganapi import ContactManager
contact_manager = ContactManager(gan_api)
contact = contact_manager.get('john.doe@example.com')
```
The manager methods will throw an ```HTTPError``` in case of HTTP error from the API, so it's a good idea to catch it.
```python
try:
contact = contact_manager.get('john.doe@example.com')
except HTTPError as e:
if e.response.code == 404:
print 'Contact not found!'
else:
print 'API error: ' + e
```
### Querying for contacts
You have to create an instance of the ```ContactManager``` class and then use it's ```query()``` method to retrieve the contacts you need.
```query()``` takes a dict of [url parameters](https://api.getanewsletter.com/v3/docs/contacts/#get-contacts) and will return a ```PaginatedResultSet``` with the first page of contacts in a list in PaginatedResultSet.entities.
```python
# Get PaginatedResultSet containing contacts with emails starting with name@.
queried_contacts = contact_manager.query({'search_email': 'name@'})
# list of contacts in current page(1)
queried_contacts.entities
# list of contacts in next page(2) if available and update PaginatedResultSet
queried_contacts.next()
# list of contacts in previous page(1) if available and update PaginatedResultSet
queried_contacts.prev()
```
#### Creating a contact
```python
contact = contact_manager.create()
contact.email = 'jane.doe@example.com'
contact.first_name = 'Jane'
contact.save()
```
This will create a new contact and save it. Again, it'll be a good idea to catch exceptions when calling the ```save()``` method. The API will respond with an error if the contact already exists.
One way to avoid it is to force the creation of the contact, overwriting the existing one:
```python
contact.overwrite()
```
Both ```save()``` and ```overwrite()``` will return the same contact object with it's read-only fields updated (e.g. ```created```, ```updated```).
```python
contact = contact.save()
print contact.created
```
#### Updating an existing contact
```python
# Get the contact.
contact = contact_manager.get('john.doe@example.com')
# Change some fields.
contact.first_name = 'John'
# Save it.
contact.save()
```
You can avoid making two calls to the API by forcing a *partial update*.
```python
contact = contact_manager.create()
contact.set_persisted()
contact.email = 'john.doe@example.com'
contact.first_name = 'John'
contact.save()
```
Calling ```set_persisted()``` on the contact object marks it like it's already existing and coming from the API. The calls to the ```save()``` method when a contact is maked as existing will do only a *partial update*, i.e. update only the supplied fields and skipping all the ```None``` fields.
Do not forget that ```email``` is a ***_lookup field_*** and required when updating or deleting the contact.
#### Deleting a contact
```python
contact.delete()
```
#### The list object
The instances of the List class represent the [lists](http://help.getanewsletter.com/en/support/lists-overview/) in the API. They have the following structure:
*Required fields*
* ```email``` - sender's email.
* ```name``` - name of the list.
* ```sender``` - sender's name.
*
*Optional fields*
* ```description```
*Lookup field*
* ```hash``` - the list's unique hash.
*Read-only fields*
* ```responders_count```
* ```subcribers```
* ```created```
* ```url```
* ```subscribers_count```
* ```active_subscribers_count```
* ```responders```
#### Retreiving, creating, updating and deleting a list
The CRUD operations on lists are no different from the operations on contacts:
```python
list_manager = ListManager(gan_api)
# Retrieve a list.
list = list_manager.get('hash')
# Update the list.
list.name = 'my list'
list = list.save()
print list.updated
# Create new list.
new_list = list_manager.create()
new_list.email = 'john.doe@example.com' # required fields
new_list.name = 'my new list'
new_list.sender = 'John Doe'
new_list.save()
# Partial update.
list = list_manager.create()
list.hash = 'hash' # lookup field
list.name = 'updated list'
list.save()
# Delete the list.
list.delete()
```
#### Subscribing a contact to a list
```python
contact.subscribe_to(list)
contact.save()
```
You can also create a new contact automatically subscribed.
```python
contact = contact_manager.create()
contact.email = 'john.doe@example.com'
contact.subscribe_to(list)
contact.save()
```
#### Unsubscribing a contact from a list
```python
contact.unsubscribe_from(list)
contact.save()
```
#### Deleting a contacts subscription from a list
```python
contact.delete_subscription_from(list)
contact.save()
```
#### The attribute object
The instances of the Attribute class represent the attribute entities in the API.
They have the following fields:
*Required fields*
* ```name``` - attribute name.
*Lookup field*
* ```code``` - the slugified attribute code. required when updating or deleting the attribute. *The name "A new attribute" code will be "a-new-attribute"*
*Read-only fields*
* ```url``` - the attribute resource URL.
* ```usage_count``` - number of usages.
#### Retreiving an attribute
You have to create an instance of the ```AttributeManager``` class and then use it's ```get()``` method to retrieve the attribute you need.
```python
from ganapi import AttributeManager
attribute_manager = AttributeManager(gan_api)
attribute = attribute_manager.get('code')
```
The manager methods will raise a ```HTTPError``` in case of HTTP error from the API, so it's a good idea to catch it.
```python
try:
attribute = attribute_manager.get('code')
except HttpError as e:
if e.response.code == 404:
print 'Attribute not found!'
else:
print 'API error: ' + e
```
#### Creating an attribute
```python
attribute = attribute_manager.create()
attribute.name = 'City'
attribute.save()
```
This will create a new attribute and save it. Again, it'll be a good idea to catch exceptions when calling the ```save()``` method. The API will respond with an error if the attribute already exists.
One way to avoid it is to force the creation of the attribute, overwriting the existing one:
```python
attribute.overwrite()
```
Both ```save()``` and ```overwrite()``` will return the same attribute object with it's read-only fields updated (e.g. ```url```, ```usage_count```).
```python
attribute = attribute.save()
print attribute.usage_count
```
#### Updating an existing attribute
```python
# Get the attribute.
attribute = attribute_manager.get('code')
# Change name field.
attribute.name = 'Changed!'
# Save it.
attribute.save()
```
You can avoid making two calls to the API by forcing a *partial update*.
```python
attribute = attribute_manager.create()
attribute.set_persisted()
attribute.code = 'code'
attribute.name = 'Changed!'
attribute.save()
```
Calling ```set_persisted()``` on the attribute object marks it like it's already existing and coming from the API. The calls to the ```save()``` method when a attribute is made as existing will do only a *partial update*, i.e. update only the supplied fields and skipping all the ```None``` fields.
Do not forget that ```code``` is a ***_lookup field_*** and required when updating or deleting the attribute.
#### Deleting an attribute
```python
attribute.delete()
```
### Get all entities of type
You can get all contacts, lists or attributes in a generator using the ```all()``` method on their manager.
*Parameters*
* ```start``` - start index (default: 0)
* ```stop``` stop index (default: float('inf'))
```python
# Print all contacts emails
all_contacts = contact_manager.all()
for contact in all_contacts:
print contact.email
# Get a generator starting on contact 100 stopping on contact 200
all_contacts = contact_manager.all(start=100, stop=200)
```
#### The PaginatedResultSet class
The instance of the PaginatedResultSet class represent the result of get from the API.
*Parameters*
* ```data``` - json of result from the ```query()``` method in the managers.
* ```manager``` - the manager using ```query()```.
*Properties*
* ```next_link``` - URL to get the next page of the results.
* ```previous_link``` - URL to get the previous page of the results.
* ```manager``` - ```EntityManager``` currently used.
* ```entities``` - List of ```Entity``` for the current result page.
* ```count``` - Total amount of entity results in all pages.
*Methods*
* ```prev()``` - replaces the instance with results from the previous page and returns entities.
* ```next()``` - replaces the instance with results from the next page and returns entities.
```next()``` and ```prev()``` will raise ```StopIteration``` if the end of the direction has been reached.
They will raise ```HTTPError``` in case of HTTP error from the API,
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
ganapi-0.1.0.tar.gz
(15.8 kB
view hashes)