<commit_before># Tapioca-Wrapper

![Tapioca!!](tapioca.jpg "Tapioca")

Tapioca provides an easy way to make explorable python API wrappers.
APIs wrapped by Tapioca follow a simple interaction pattern that works uniformelly so developers don't need to learn how to use a new library for each service they want to interact with.

## Concepts

Tapioca is thought to reduce the effort needed to use a service API, this is done by making the API wrapper explorable, so developers don't need to read full API and wrapper docs before starting to play with it.

We will use ```tapioca-facebook``` as example to gide us through Tapioca.   
We start by installing ```tapioca-facebook```:
```
pip install tapioca-facebook
```

To better experience Tapioca, we will also use iPython:
```
pip install ipython
```

Now, lets explore!!  
Go to [https://developers.facebook.com/tools/explorer/](https://developers.facebook.com/tools/explorer/), click "Get Access Token", select all "User Data Permissions" and "Extended Permissions" and click "Get Access Token". This will give you an teporary access token to play with Facebook API. In case it expires, just generate a new one. 

``` python
from tapioca_facebook import Facebook

api = Facebook(api_params={
    'access_token': '{{your_genereated_access_token}}'})

```

If you are using iPython, you can now list available endpoints by typing ```api.``` and pressing ```tab```.

``` python
In [2]: api.
api.user_likes                  api.page_blocked                 api.page_locations               
api.page_statuses                api.user_applications_developer  api.user_friends                 
api.user_invitable_friends       api.user_photos                  api.user_videos
api.object                       api.page_conversations           api.page_milestones  
...            
```

### Resources

Those are the available endpoints for the facebook API. As we can see there is one called: ```user_likes```, lets take a closer look.

Type ```api.user_likes``` and press ```enter```

``` python
In [3]: api.user_likes
Out [3]: {
    'resource': '{id}/likes',
    'docs': 'https://developers.facebook.com/docs/graph-api/reference/v2.2/user/likes'
}
```

As we can see, ```user_likes``` resource requires an ```id``` to be passed to the url. Lets do it:

``` python 
api.user_likes(url_params={'id': 'me'})

```

### Fetching data

To request current user likes, its easy:

``` python 
likes = api.user_likes(url_params={'id': 'me'}).get()
```

To print the returned data do:

``` python
In [9]: likes().data()
OUT [9]: {
    'data': [...],
    'paging': {...}
}
```

### Exploring data

We can also expore the returned data using the iPython ```tab``` auto-complete

``` python
In [9]: likes.
likes.data    likes.paging
```

### Executor object

Whenever you use brackets, Tapioca will return to you an ```Executor``` object. You will use the executor every time you want to perform an action over data you possess. An example was when we filled url params for the ```user_likes``` resource, and then used the ```get``` method to fetch data.

Tapioca provides many methods, here are they:

#### get()/post()

Tapioca uses ```requests``` library to make requests, so http methods will work just the same.
``` python 
likes = api.user_likes(url_params={'id': 'me'}).get()
```

#### data()
Use data to return data contained in the Tapioca object
``` python 
likes = api.user_likes(url_params={'id': 'me'}).get()

# this will print only the array contained in data field of the response
print(likes.data().data())
[...]
```

#### iterator

Many APIs use paging concept to provide large amounts of data. This way data is returned in multiple requests avoing a single long request. 
Tapioca is buit to provide easy way to access paged data using iterators:

``` python
likes = api.user_likes(url_params={'id': 'me'}).get()

for like in likes:
    print(like.id().data())
```
This will keep fetching user likes until there are none left.

#### open_docs()

If you are accessing a resource, you can call ```open_docs``` to open resource documentation in browser:

``` python 
api.user_likes().open_docs()
```

#### open_in_browser()

Whenever the data contained in Tapioca object is a URL, you can open it in browser by using the ```open_in_browser``` method.


## Tapioca comes in many flavours

Facebook - [https://github.com/vintasoftware/tapioca-facebook](https://github.com/vintasoftware/tapioca-facebook)   
Twitter - [https://github.com/vintasoftware/tapioca-twitter](https://github.com/vintasoftware/tapioca-twitter)   

Send a pull request to add new ones to the list.

## Wrapping an API with Tapioca

This is all the code you need to build the Facebook Graph API you just played:   
``` python
# surce here: https://github.com/vintasoftware/tapioca-facebook/blob/master/tapioca_facebook/tapioca_facebook.py

from tapioca import (TapiocaClient, TapiocaAdapter)
from requests_oauthlib import OAuth2

from resource_mapping import RESOURCE_MAPPING


class FacebookClientAdapter(TapiocaAdapter):
    api_root = 'https://graph.facebook.com'
    resource_mapping = RESOURCE_MAPPING

    def get_request_kwargs(self, api_params):
        client_id = api_params.get('client_id')
        return {
            'auth': OAuth2(client_id,
                token={
                    'access_token': api_params.get('access_token'),
                    'token_type': 'Bearer'})
        }

    def get_iterator_list(self, response_data):
        return response_data['data']

    def get_iterator_next_request_kwargs(self,
            iterator_request_kwargs, response_data):
        paging = response_data.get('paging')
        if not paging:
            return
        url = paging.get('next')

        if url:
            return {'url': url}


Facebook = TapiocaClient(FacebookClientAdapter())
```
Everything else is what we call ```resource_mapping``` and its merely documentation. You can take a look  [here](https://github.com/vintasoftware/tapioca-facebook/blob/master/tapioca_facebook/resource_mapping.py)<commit_msg>improving README<commit_after># Tapioca-Wrapper

![Tapioca!!](tapioca.jpg "Tapioca")

Tapioca provides an easy way to make explorable python API wrappers.
APIs wrapped by Tapioca follow a simple interaction pattern that works uniformelly so developers don't need to learn how to use a new library for each service they want to interact with.

## Concepts

Tapioca is thought to reduce the effort needed to use a service API, this is done by making the API wrapper explorable, so developers don't need to read full API and wrapper docs before starting to play with it.

We will use ```tapioca-facebook``` as example to gide us through Tapioca.   
We start by installing ```tapioca-facebook```:
```
pip install tapioca-facebook
```

To better experience Tapioca, we will also use iPython:
```
pip install ipython
```

Now, lets explore!!  
Go to [https://developers.facebook.com/tools/explorer/](https://developers.facebook.com/tools/explorer/), click "Get Access Token", select all "User Data Permissions" and "Extended Permissions" and click "Get Access Token". This will give you an teporary access token to play with Facebook API. In case it expires, just generate a new one. 

``` python
from tapioca_facebook import Facebook

api = Facebook(api_params={
    'access_token': '{{your_genereated_access_token}}'})

```

If you are using iPython, you can now list available endpoints by typing ```api.``` and pressing ```tab```.

``` python
In [2]: api.
api.user_likes                  api.page_blocked                 api.page_locations               
api.page_statuses                api.user_applications_developer  api.user_friends                 
api.user_invitable_friends       api.user_photos                  api.user_videos
api.object                       api.page_conversations           api.page_milestones  
...            
```

### Resources

Those are the available endpoints for the facebook API. As we can see there is one called: ```user_likes```, lets take a closer look.

Type ```api.user_likes``` and press ```enter```

``` python
In [3]: api.user_likes
Out [3]: {
    'resource': '{id}/likes',
    'docs': 'https://developers.facebook.com/docs/graph-api/reference/v2.2/user/likes'
}
```

As we can see, ```user_likes``` resource requires an ```id``` to be passed to the url. Lets do it:

``` python 
api.user_likes(url_params={'id': 'me'})

```

### Fetching data

To request current user likes, its easy:

``` python 
likes = api.user_likes(url_params={'id': 'me'}).get()
```

To print the returned data do:

``` python
In [9]: likes().data()
OUT [9]: {
    'data': [...],
    'paging': {...}
}
```

### Exploring data

We can also expore the returned data using the iPython ```tab``` auto-complete

``` python
In [9]: likes.
likes.data    likes.paging
```

### Executor object

Whenever you use brackets, Tapioca will return to you an ```Executor``` object. You will use the executor every time you want to perform an action over data you possess. An example was when we filled url params for the ```user_likes``` resource, and then used the ```get``` method to fetch data.

Tapioca provides many methods, here are they:

#### get()/post()

Tapioca uses ```requests``` library to make requests, so http methods will work just the same.
``` python 
likes = api.user_likes(url_params={'id': 'me'}).get()
```

#### data()
Use data to return data contained in the Tapioca object
``` python 
likes = api.user_likes(url_params={'id': 'me'}).get()

# this will print only the array contained in data field of the response
print(likes.data().data())
[...]
```

#### iterator

Many APIs use paging concept to provide large amounts of data. This way data is returned in multiple requests avoing a single long request. 
Tapioca is buit to provide easy way to access paged data using iterators:

``` python
likes = api.user_likes(url_params={'id': 'me'}).get()

for like in likes:
    print(like.id().data())
```
This will keep fetching user likes until there are none left.

#### open_docs()

If you are accessing a resource, you can call ```open_docs``` to open resource documentation in browser:

``` python 
api.user_likes().open_docs()
```

#### open_in_browser()

Whenever the data contained in Tapioca object is a URL, you can open it in browser by using the ```open_in_browser``` method.


## Tapioca comes in many flavours

Facebook - [https://github.com/vintasoftware/tapioca-facebook](https://github.com/vintasoftware/tapioca-facebook)   
Twitter - [https://github.com/vintasoftware/tapioca-twitter](https://github.com/vintasoftware/tapioca-twitter)   

Send a pull request to add new ones to the list.

## Wrapping an API with Tapioca

This is all the code you need to build the Facebook Graph API wrapper you just played with:   
``` python
# surce here: https://github.com/vintasoftware/tapioca-facebook/blob/master/tapioca_facebook/tapioca_facebook.py

from tapioca import (TapiocaClient, TapiocaAdapter)
from requests_oauthlib import OAuth2

from resource_mapping import RESOURCE_MAPPING


class FacebookClientAdapter(TapiocaAdapter):
    api_root = 'https://graph.facebook.com'
    resource_mapping = RESOURCE_MAPPING

    def get_request_kwargs(self, api_params):
        client_id = api_params.get('client_id')
        return {
            'auth': OAuth2(client_id,
                token={
                    'access_token': api_params.get('access_token'),
                    'token_type': 'Bearer'})
        }

    def get_iterator_list(self, response_data):
        return response_data['data']

    def get_iterator_next_request_kwargs(self,
            iterator_request_kwargs, response_data):
        paging = response_data.get('paging')
        if not paging:
            return
        url = paging.get('next')

        if url:
            return {'url': url}


Facebook = TapiocaClient(FacebookClientAdapter())
```
Everything else is what we call ```resource_mapping``` and its merely documentation. You can take a look  [here](https://github.com/vintasoftware/tapioca-facebook/blob/master/tapioca_facebook/resource_mapping.py).
{'fraction_non_alphanumeric': 0.11505154639175258, 'fraction_numerical': 0.0016494845360824743, 'mean_word_length': 3.637093690248566, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 20, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 16, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2783147', 'n_tokens_mistral': 3741, 'n_tokens_neox': 3584, 'n_words': 1276}