Skip to content

Commit

Permalink
Merge pull request #298 from pcattori/recommonmark
Browse files Browse the repository at this point in the history
Recommonmark: write docs in markdown
  • Loading branch information
pcattori committed Oct 7, 2019
2 parents aed16a5 + 008241f commit c983c49
Show file tree
Hide file tree
Showing 8 changed files with 246 additions and 210 deletions.
22 changes: 20 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import os
import sys

import recommonmark
from recommonmark.transform import AutoStructify
import toml

sys.path.insert(0, os.path.abspath(".."))
Expand Down Expand Up @@ -46,7 +48,12 @@
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = ["sphinx.ext.napoleon", "sphinx.ext.intersphinx", "sphinx.ext.viewcode"]
extensions = [
"recommonmark",
"sphinx.ext.napoleon",
"sphinx.ext.intersphinx",
"sphinx.ext.viewcode",
]
autodoc_default_flags = ["inherited-members", "members"]
autodoc_member_order = "bysource"
intersphinx_mapping = {
Expand All @@ -62,7 +69,6 @@
# You can specify multiple suffix as a list of string:
#
# source_suffix = ['.rst', '.md']
source_suffix = ".rst"

# The master toctree document.
master_doc = "index"
Expand Down Expand Up @@ -195,3 +201,15 @@

# A list of files that should not be packed into the epub file.
epub_exclude_files = ["search.html"]


def setup(app):
"""
https://recommonmark.readthedocs.io/en/latest/auto_structify.html#configuring-autostructify
"""
app.add_config_value(
"recommonmark_config",
{"enable_auto_toc_tree": True, "auto_toc_maxdepth": 2},
True,
)
app.add_transform(AutoStructify)
45 changes: 45 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Tamr - Python Client

[View on Github](https://github.com/Datatamer/tamr-client)

## Example

```python
from tamr_unify_client import Client
from tamr_unify_client.auth import UsernamePasswordAuth
import os

# grab credentials from environment variables
username = os.environ['TAMR_USERNAME']
password = os.environ['TAMR_PASSWORD']
auth = UsernamePasswordAuth(username, password)

host = 'localhost' # replace with your Tamr host
tamr = Client(auth, host=host)

# programmatically interact with Tamr!
# e.g. refresh your project's Unified Dataset
project = tamr.projects.by_resource_id('3')
ud = project.unified_dataset()
op = ud.refresh()
assert op.succeeded()
```

## User Guide

* [FAQ](user-guide/faq)
* [Install](user-guide/installation)
* [Quickstart](user-guide/quickstart)
* [Secure credentials](user-guide/secure-credentials)
* [Workflows](user-guide/workflows)
* [Create and update resources](user-guide/spec)
* [Geospatial data](user-guide/geo)
* [Advanced usage](user-guide/advanced-usage)

## Contributor Guide

* [Contributor guide](contributor-guide)

## Developer Interface

* [Developer interface](developer-interface)
59 changes: 0 additions & 59 deletions docs/index.rst

This file was deleted.

1 change: 1 addition & 0 deletions docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# TODO(pcattori) Delete this file once RTD fully supports poetry
recommonmark
Sphinx
sphinx_rtd_theme
toml
Expand Down
143 changes: 143 additions & 0 deletions docs/user-guide/advanced-usage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
# Advanced Usage

## Asynchronous Operations

You can opt-in to an asynchronous interface via the asynchronous keyword argument for methods that kick-off Tamr operations.

E.g.:

```python
op = project.unified_dataset().refresh(asynchronous=True)
# do asynchronous stuff here while operation is running
op = op.wait() # hangs until operation finishes
assert op.succeeded()
```

## Logging API calls

It can be useful (e.g. for debugging) to log the API calls made on your behalf by the Python Client.

You can set up HTTP-API-call logging on any client via
standard [Python logging mechanisms](https://docs.python.org/3/library/logging.html):

```python
from tamr_unify_client import Client
from tamr_unify_client import UsernamePasswordAuth
import logging

auth = UsernamePasswordAuth("username", "password")
tamr = Client(auth)

# Reload the `logging` library since other libraries (like `requests`) already
# configure logging differently. See: https://stackoverflow.com/a/53553516/1490091
import imp
imp.reload(logging)

logging.basicConfig(
level=logging.INFO, format="%(message)s", filename=log_path, filemode="w"
)
tamr.logger = logging.getLogger(name)
```

By default, when logging is set up, the client will log `{method} {url} : {response_status}` for each API call.

You can customize this by passing in a value for `log_entry`:

```python
def log_entry(method, url, response):
# custom logging function
# use the method, url, and response to construct the logged `str`
# e.g. for logging out machine-readable JSON:
import json
return json.dumps({
"request": f"{method} {url}",
"status": response.status_code,
"json": response.json(),
})

# after configuring `tamr.logger`
tamr.log_entry = log_entry
```


## Custom HTTP requests and Unversioned API Access

We encourage you to use the high-level, object-oriented interface offered by the Python Client. If you aren't sure whether you need to send low-level HTTP requests, you probably don't.

But sometimes it's useful to directly send HTTP requests to Tamr; for example, Tamr has many APIs that are not covered by the higher-level interface (most of which are neither versioned nor supported). You can still call these endpoints using the Python Client, but you'll need to work with raw `Response` objects.

### Custom endpoint

The client exposes a `request` method with the same interface as
`requests.request`:

```python
# import Python Client library and configure your client

tamr = Client(auth)
# do stuff with the `tamr` client

# now I NEED to send a request to a specific endpoint
response = tamr.request('GET', 'relative/path/to/resource')
```

This will send a request relative to the base_path registered with the client. If you provide an absolute path to the resource, the base_path will be ignored when composing the request:

```python
# import Python Client library and configure your client

tamr = Client(auth)

# request a resource outside the configured base_path
response = tamr.request('GET', '/absolute/path/to/resource')
```

You can also use the `get`, `post`, `put`, `delete` convenience
methods:

```python
# e.g. `get` convenience method
response = tamr.get('relative/path/to/resource')
```

### Custom Host / Port / Base API path

If you need to repeatedly send requests to another port or base API path (i.e. not `/api/versioned/v1/`), you can simply instantiate a different client.

Then just call `request` as described above:

```python
# import Python Client library and configure your client

tamr = api.Client(auth)
# do stuff with the `tamr` client

# now I NEED to send requests to a different host/port/base API path etc..
# NOTE: in this example, we reuse `auth` from the first client, but we could
# have made a new Authentication provider if this client needs it.
custom_client = api.Client(
auth,
host="10.10.0.1",
port=9090,
base_path="/api/some_service/",
)
response = custom_client.get('relative/path/to/resource')
```

### One-off authenticated request

All of the Python Client Authentication providers adhere to the `requests.auth.BaseAuth` interface.

This means that you can pass in an Authentication provider directly to the `requests` library:

```python
from tamr_unify_client.auth import UsernamePasswordAuth
import os
import requests

username = os.environ['TAMR_USERNAME']
password = os.environ['TAMR_PASSWORD']
auth = UsernamePasswordAuth(username, password)

response = requests.request('GET', 'some/specific/endpoint', auth=auth)
```

0 comments on commit c983c49

Please sign in to comment.