This is a pre-production deployment of Warehouse, however changes made here WILL affect the production instance of PyPI.
Latest Version Dependencies status unknown Test status unknown Test coverage unknown
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,
Release History

Release History

0.1.0

This version

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

Download Files

Download Files

TODO: Brief introduction on what you do with files - including link to relevant help section.

File Name & Checksum SHA256 Checksum Help Version File Type Upload Date
ganapi-0.1.0.tar.gz (15.8 kB) Copy SHA256 Checksum SHA256 Source Feb 15, 2016

Supported By

WebFaction WebFaction Technical Writing Elastic Elastic Search Pingdom Pingdom Monitoring Dyn Dyn DNS HPE HPE Development Sentry Sentry Error Logging CloudAMQP CloudAMQP RabbitMQ Heroku Heroku PaaS Kabu Creative Kabu Creative UX & Design Fastly Fastly CDN DigiCert DigiCert EV Certificate Rackspace Rackspace Cloud Servers DreamHost DreamHost Log Hosting