Skip to content

Commit 844ba01

Browse files
Improve documentation clarity, fix typos, and align project descriptions (#14)
Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 94b0ae1 commit 844ba01

8 files changed

Lines changed: 264 additions & 150 deletions

File tree

README.md

Lines changed: 64 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,87 +1,95 @@
1-
# "Create, Read, Update, Delete"s
1+
# CRUDs
22

33
[![PyPI - Version](https://img.shields.io/pypi/v/cruds)](https://pypi.org/project/cruds/)
44
[![Supported Python Version](https://img.shields.io/pypi/pyversions/cruds?logo=python&logoColor=FFE873)](https://pypi.org/project/cruds/)
55
[![Development](https://github.com/johnbrandborg/cruds/actions/workflows/development.yml/badge.svg)](https://github.com/johnbrandborg/cruds/actions/workflows/development.yml)
66
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=johnbrandborg_cruds&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=johnbrandborg_cruds)
77
[![Documentation Status](https://readthedocs.org/projects/cruds/badge/?version=latest)](https://cruds.readthedocs.io/en/latest/?badge=latest)
88

9-
**CRUDs** is a high level client library for APIs written in Python, and is ideal for back-end
10-
communication, automated data processing and interactive environments like Notebooks.
9+
**CRUDs** is a lightweight Python client for REST APIs — create, read, update,
10+
and delete with zero boilerplate.
1111

1212
```python
13-
>>> import cruds
14-
>>>
15-
>>> catfact_ninja = cruds.Client("catfact.ninja")
16-
>>>
17-
>>> data = catfact_ninja.read("fact")
18-
>>> type(date) # Python built-in data types you can use instantly!
19-
<class 'dict'>
20-
```
13+
import cruds
2114

22-
## Why CRUDs?
15+
api = cruds.Client("https://api.example.com", auth="your-token")
2316

24-
When working with APIs, you have several options. Here's why CRUDs might be the right choice:
17+
# Create a resource
18+
user = api.create("users", data={"name": "Ada", "role": "engineer"})
2519

26-
**vs. requests/httpx/urllib3:**
27-
- **Semantic API Design**: Think about what you're doing (create, read, update, delete) instead of HTTP methods
28-
- **Production-Ready**: Built-in retry logic, error handling, and logging without configuration
29-
- **Simplified Auth**: OAuth2, bearer tokens, and basic auth handled automatically
30-
- **Data-First**: Returns Python data structures directly instead of response objects
20+
# Read it back
21+
user = api.read(f"users/{user['id']}")
3122

32-
**vs. SDKs for specific APIs:**
33-
- **Consistent Interface**: Same patterns across all APIs
34-
- **No Vendor Lock-in**: Switch between APIs without learning new patterns
35-
- **Lightweight**: No need for multiple heavy SDKs
36-
- **Customizable**: Full control while maintaining simplicity
23+
# Update it
24+
api.update(f"users/{user['id']}", data={"role": "lead"})
3725

38-
**Perfect for:**
39-
- Data engineers working with multiple APIs
40-
- Backend developers building integrations
41-
- Data scientists in notebooks
42-
- DevOps teams automating API interactions
26+
# Delete it
27+
api.delete(f"users/{user['id']}")
28+
```
4329

44-
Make Create, Read, Update and Delete operations quickly, easily, and safely. CRUDs
45-
aims to implement URLLib3's best practises while remaining as light as possible.
30+
No response objects to unpack. No manual JSON parsing. No boilerplate retry
31+
logic. Just your data.
4632

47-
Features:
48-
* Authentication: Username & Password, Bearer Token and OAuth2
49-
* JSON Serialization/Deserialization
50-
* Request parameters and automatically URL encoded
51-
* Configurable timeouts (default 5 minutes)
52-
* Exceptions handling for bad status codes
53-
* Built-in retry logic with exponential backoff
54-
* SSL Certificate Verification
55-
* Logging for monitoring
56-
* Interfaces (SDK Creation)
33+
## Quickstart
5734

58-
### Interfaces
35+
```bash
36+
pip install cruds
37+
```
5938

60-
CRUDs provides pre-configured interfaces for popular APIs, making integration even easier:
39+
```python
40+
import cruds
6141

62-
* **PlanHat** - Complete customer success platform interface with 20+ data models, bulk operations, and advanced analytics. [View Documentation](https://cruds.readthedocs.io/en/latest/interfaces.html#planhat)
42+
catfacts = cruds.Client("catfact.ninja")
43+
fact = catfacts.read("fact")
44+
print(fact["fact"])
45+
```
6346

64-
### Installation
47+
## Why CRUDs over requests/httpx?
6548

66-
To install a stable version use [PyPI](https://pypi.org/project/cruds/).
49+
| You get | Without writing |
50+
|----------------------------|--------------------------|
51+
| Semantic CRUD methods | HTTP method boilerplate |
52+
| Automatic JSON SerDes | `.json()` / `.raise_for_status()` calls |
53+
| Retry with backoff | `HTTPAdapter` / `Retry` setup |
54+
| Bearer, Basic & OAuth2 auth| Manual header management |
55+
| SSL verification | `certifi` wiring |
6756

68-
```bash
69-
$ pip install cruds
57+
```python
58+
# requests — 6 lines of ceremony
59+
import requests
60+
response = requests.get("https://api.example.com/users",
61+
headers={"Authorization": "Bearer token"})
62+
response.raise_for_status()
63+
users = response.json()
64+
65+
# CRUDs — 2 lines of intent
66+
import cruds
67+
users = cruds.Client("api.example.com", auth="token").read("users")
7068
```
7169

72-
### Documentation
70+
## Features
71+
72+
- **Authentication** — Bearer tokens, username/password, and OAuth2 (Client
73+
Credentials, Resource Owner Password, Authorization Code with CSRF protection)
74+
- **JSON Serialization** — Send and receive Python dicts and lists directly
75+
- **Retries with backoff** — Configurable retry count, backoff factor, and
76+
status codes (429, 500–504, etc.)
77+
- **Error handling** — Automatic exceptions for 4xx/5xx responses
78+
- **SSL verification** — Enabled by default via certifi
79+
- **Logging** — Built-in INFO/DEBUG logging for monitoring
80+
- **Interfaces** — Build SDKs with YAML configuration (ships with a full
81+
[Planhat](https://cruds.readthedocs.io/en/latest/interfaces.html#planhat)
82+
interface)
83+
84+
## Documentation
7385

74-
Whether you are an data engineer wanting to retrieve or load data, a developer
75-
writing software for the back-of-the-front-end, or someone wanting to contribute
76-
to the project, for more information about CRUDs please visit
77-
[Read the Docs](https://cruds.readthedocs.io).
86+
Full user guide, API reference, and examples at
87+
**[cruds.readthedocs.io](https://cruds.readthedocs.io)**.
7888

7989
## License
8090

81-
CRUDs is released under the MIT License. See the bundled
82-
[LICENSE file](https://github.com/johnbrandborg/cruds/blob/main/LICENSE)
83-
for details.
91+
MIT — see [LICENSE](https://github.com/johnbrandborg/cruds/blob/main/LICENSE).
8492

8593
## Credits
8694

87-
* [URLLib3 Team](https://github.com/urllib3)
95+
* [urllib3 Team](https://github.com/urllib3)

docs/changelog.rst

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,29 @@
11
Changelog
22
=========
33

4+
Release 1.5.0 (February 20, 2026)
5+
----------------------------------
6+
7+
Updates:
8+
- Modernized project tooling: migrated from setup.cfg/setup.py to pyproject.toml
9+
and adopted uv for dependency management.
10+
- Aligned urllib3 usage with current best practices.
11+
- Updated SonarQube scan action from v4 to v6.
12+
- Minimum supported Python version is now 3.10.
13+
14+
Release 1.4.2 (September 9, 2025)
15+
----------------------------------
16+
17+
Fixes:
18+
- Enhanced response handling in Planhat bulk upsert logic to skip non-dictionary
19+
types.
20+
21+
Release 1.4.1 (July 1, 2025)
22+
-----------------------------
23+
24+
Fixes:
25+
- Version bump to resolve PyPI version conflict with 1.4.0.
26+
427
Release 1.4.0 (June 30, 2025)
528
------------------------------
629

docs/development.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ Development
44
===========
55

66
At this time because the CRUDs code base is located on a repository not located
7-
under an Orgination, to contribute it is recommended that you create a fork of
7+
under an Organization, to contribute it is recommended that you create a fork of
88
CRUDs and then `Create a PR <https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork>`_
99
from there.
1010

1111
Setup
1212
-----
1313

14-
It is highlight recommended to create a virtual environment of Python. There are
14+
It is highly recommended to create a virtual environment of Python. There are
1515
multiple ways to do this. The standard way is using Pythons very own
1616
`venv <https://docs.python.org/3/library/venv.html>`_.
1717

docs/examples.rst

Lines changed: 106 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,117 @@
11
Examples
22
========
33

4-
Here you can find code snippets that show how easy it is to work with some platforms.
4+
Here you can find code snippets that show how easy it is to work with various
5+
platforms and public APIs.
6+
7+
JSONPlaceholder (Try It Now)
8+
----------------------------
9+
10+
`JSONPlaceholder <https://jsonplaceholder.typicode.com/>`_ is a free fake REST
11+
API — perfect for testing CRUDs without any API keys.
12+
13+
.. code-block:: python
14+
15+
import cruds
16+
17+
api = cruds.Client("jsonplaceholder.typicode.com")
18+
19+
# Read all posts
20+
posts = api.read("posts", params={"_limit": 5})
21+
print(f"Got {len(posts)} posts")
22+
23+
# Create a new post
24+
new_post = api.create("posts", data={
25+
"title": "Hello from CRUDs",
26+
"body": "This was easy.",
27+
"userId": 1,
28+
})
29+
print(f"Created post #{new_post['id']}")
30+
31+
# Update the post
32+
api.update(f"posts/{new_post['id']}", data={"title": "Updated title"})
33+
34+
# Delete the post
35+
api.delete(f"posts/{new_post['id']}")
36+
37+
GitHub API
38+
----------
39+
40+
Read public repository data from the GitHub REST API.
41+
42+
.. code-block:: python
43+
44+
import cruds
45+
46+
github = cruds.Client("api.github.com")
47+
48+
# Get repository info (no auth needed for public repos)
49+
repo = github.read("repos/johnbrandborg/cruds")
50+
print(f"{repo['full_name']}{repo['stargazers_count']} stars")
51+
52+
# List recent commits
53+
commits = github.read("repos/johnbrandborg/cruds/commits", params={"per_page": 5})
54+
for commit in commits:
55+
print(f" {commit['sha'][:7]} {commit['commit']['message'].splitlines()[0]}")
56+
57+
With a personal access token you can access private resources:
58+
59+
.. code-block:: python
60+
61+
github = cruds.Client("api.github.com", auth="ghp_your_token_here")
62+
user = github.read("user")
63+
print(f"Authenticated as {user['login']}")
64+
65+
Weather API
66+
-----------
67+
68+
Fetch weather data from the free `Open-Meteo <https://open-meteo.com/>`_ API
69+
(no API key required).
70+
71+
.. code-block:: python
72+
73+
import cruds
74+
75+
weather = cruds.Client("api.open-meteo.com")
76+
77+
forecast = weather.read("v1/forecast", params={
78+
"latitude": -33.87,
79+
"longitude": 151.21,
80+
"current_weather": True,
81+
})
82+
83+
current = forecast["current_weather"]
84+
print(f"Sydney: {current['temperature']}°C, wind {current['windspeed']} km/h")
85+
86+
Authenticated API with OAuth2
87+
-----------------------------
88+
89+
For APIs that require OAuth2 Client Credentials (common in B2B integrations):
90+
91+
.. code-block:: python
92+
93+
from cruds import Client
94+
from cruds.auth import OAuth2
95+
96+
api = Client(
97+
host="https://api.example.com",
98+
auth=OAuth2(
99+
url="https://api.example.com/oauth/token",
100+
client_id="your-client-id",
101+
client_secret="your-client-secret",
102+
scope="read write",
103+
),
104+
)
105+
106+
data = api.read("protected/resource")
107+
108+
CRUDs handles token acquisition, caching, and refresh automatically.
5109

6110
Databricks
7111
----------
8112

9113
Serverless OLTP Database - PostgREST
10-
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
114+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
11115

12116
Currently in Private Preview from Databricks, however it offers a Service URL which
13117
is an API that with Service Principal OAuth2 credentials can read data from the database.

0 commit comments

Comments
 (0)