Skip to content

Commit

Permalink
fix: tests & docs
Browse files Browse the repository at this point in the history
  • Loading branch information
rwxd committed Mar 8, 2023
1 parent 4a1f16d commit 37b98d3
Show file tree
Hide file tree
Showing 7 changed files with 299 additions and 47 deletions.
33 changes: 30 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ on:
- "v*.*.*"

jobs:
test:
pre-commit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.10'
python-version: '3.11'

- name: Debug
run: pwd && ls -la
Expand All @@ -26,6 +26,23 @@ jobs:
env:
SKIP: "no-commit-to-branch"

test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.11'

- name: Debug
run: pwd && ls -la

- name: Setup
run: make setup

- name: Run pytest
run: make unit

pypi:
runs-on: ubuntu-latest
needs:
Expand All @@ -35,7 +52,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.10'
python-version: '3.11'

- name: Install dependencies
run: pip install wheel
Expand Down Expand Up @@ -68,3 +85,13 @@ jobs:
branch: pages
folder: ./site
token: ${{ secrets.GH_TOKEN }}

semantic-release:
uses: rwxd/gh-templates/.github/workflows/common-semantic-release.yml@main
if: github.event_name == 'push' && github.ref == 'main'
needs:
- docs
- test
- pre-commit
secrets:
token: ${{ secrets.GH_TOKEN }}
11 changes: 0 additions & 11 deletions .github/workflows/semantic-release.yml

This file was deleted.

4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ setup: ## Setup required things
python3 -m pip install -U -r requirements-dev.txt
python3 -m pip install -U -r requirements-docs.txt
pre-commit install
pre-commit install-hooks

serve-docs: ## Serve the documentation locally
mkdocs serve

build-docs: ## Build the documentation
mkdocs build

unit: ## Run unit tests
python3 -m pytest -vvl tests/unit
39 changes: 39 additions & 0 deletions docs/advanced-usage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Advanced Usage

## Custom request

You can use the `get`, `post`, `delete` or `request` methods to make a custom request.

```python
from readwise import Readwise

client = Readwise('token')
response = client.get('/books/', params={'category': 'articles'})
response.raise_for_status()
print(response.json())
```

Custom http method

```python
from readwise import Readwise

client = Readwise('token')
response = client.request('get', '/books/', params={'category': 'articles'})
response.raise_for_status()
print(response.json())
```

## Pagination

A helper method for pagination is available.

```python
from readwise import Readwise

client = Readwise('token')
for response in client.get_pagination('/books/', params={'category': 'articles'}):
response.raise_for_status()
for book in response.json()['results']:
print(book)
```
104 changes: 72 additions & 32 deletions readwise/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,67 @@ def delete(self, endpoint: str) -> requests.Response:
logging.debug(f'Deleting "{endpoint}"')
return self._request('DELETE', endpoint)

def get_pagination(
self, endpoint: str, params: dict = {}
) -> Generator[dict, None, None]:
'''
Get a response from the Readwise API with pagination.
Args:
endpoint: API endpoint
params: Query parameters
Yields:
dict: Response data
'''
yield from self._get_pagination('get', endpoint, params)

def get_pagination_limit_20(
self, endpoint: str, params: dict = {}, page_size: int = 1000
) -> Generator[dict, None, None]:
'''
Get a response from the Readwise API with pagination and a rate limit
of 20 requests per minute.
Args:
endpoint: API endpoint
params: Query parameters
page_size: Number of items per page
Yields:
dict: Response data
'''
yield from self._get_pagination(
'get_with_limit_20', endpoint, params, page_size
)

def _get_pagination(
self,
get_method: Literal['get', 'get_with_limit_20'],
endpoint: str,
params: dict = {},
page_size: int = 1000,
) -> Generator[dict, None, None]:
'''
Get a response from the Readwise API with pagination.
Args:
get_method: Method to use for making requests
endpoint: API endpoint
params: Query parameters
page_size: Number of items per page
Yields:
dict: Response data
'''
page = 1
while True:
response = getattr(self, get_method)(
endpoint, params={'page': page, 'page_size': page_size, **params}
)
data = response.json()
yield data
if not data['next']:
break
page += 1

def get_books(
self, category: Literal['articles', 'books', 'tweets', 'podcasts']
) -> Generator[ReadwiseBook, None, None]:
Expand All @@ -167,14 +228,9 @@ def get_books(
Returns:
A generator of ReadwiseBook objects
'''
page = 1
page_size = 1000
while True:
data = self.get_with_limit_20(
'/books',
{'page': page, 'page_size': page_size, 'category': category},
).json()

for data in self.get_pagination_limit_20(
'/books/', params={'category': category}
):
for book in data['results']:
yield ReadwiseBook(
id=book['id'],
Expand All @@ -196,10 +252,6 @@ def get_books(
document_note=book['document_note'],
)

if not data['next']:
break
page += 1

def get_book_highlights(
self, book_id: str
) -> Generator[ReadwiseHighlight, None, None]:
Expand All @@ -212,13 +264,9 @@ def get_book_highlights(
Returns:
A generator of ReadwiseHighlight objects
'''
page = 1
page_size = 1000
while True:
data = self.get_with_limit_20(
'/highlights',
{'page': page, 'page_size': page_size, 'book_id': book_id},
).json()
for data in self.get_pagination_limit_20(
f'/books/{book_id}/highlights/', params={'book_id': book_id}
):
for highlight in data['results']:
yield ReadwiseHighlight(
id=highlight['id'],
Expand All @@ -236,10 +284,6 @@ def get_book_highlights(
],
)

if not data['next']:
break
page += 1

def create_highlight(
self,
text: str,
Expand Down Expand Up @@ -284,15 +328,11 @@ def get_book_tags(self, book_id: str) -> Generator[ReadwiseTag, None, None]:
Returns:
A generator of ReadwiseTag objects
'''
page = 1
page_size = 1000
data = self.get(
f'/books/{book_id}/tags',
{'page': page, 'page_size': page_size, 'book_id': book_id},
).json()

for tag in data:
yield ReadwiseTag(tag['id'], tag['name'])
for data in self.get_pagination_limit_20(
f'/books/{book_id}/tags/', params={'book_id': book_id}
):
for tag in data['results']:
yield ReadwiseTag(id=tag['id'], name=tag['name'])

def add_tag(self, book_id: str, tag: str):
'''
Expand Down
1 change: 1 addition & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pre-commit==3.1.1
pytest==7.2.2
Loading

0 comments on commit 37b98d3

Please sign in to comment.