Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 113 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# AGENTS.md

This file is for agents contributing to this repository. If you are *using* the
installed `cloudinary` package in another project, read the bundled docs in the
installed package's `cloudinary/docs/` directory instead.

## Commands

```bash
pip install -e . # install for development
pip install tox pytest # test tooling
python -m pytest test # core test suite
python -m pytest test/test_uploader.py # a single module
tox # full matrix (Python 3.10-3.14, Django 4.2-6.0)
tox -e py312-core # one environment, as CI runs it
DJANGO_SETTINGS_MODULE=django_tests.settings \
django-admin test -v2 django_tests # Django integration suite
python -m build # build sdist + wheel
```

Every suite needs a working `CLOUDINARY_URL` in the environment — there is no
offline or mocked tier. CI allocates a throwaway cloud per job via
`tools/get_test_cloud.sh`; locally, export your own or provision one with
`python -c "from cloudinary.provisioning import create_cloud; print(create_cloud())"`.

## Testing

- `test/` is the core suite and hits the live API. Tests namespace their assets with
`UNIQUE_TEST_ID` from `test/helper_test.py` and clean up after themselves — follow
that pattern rather than leaving fixtures behind.
- `django_tests/` runs as a real Django app (`django_tests.settings`, in-memory
sqlite). It covers `CloudinaryField`, the form fields, and migrations; the
templatetags have no coverage yet.
- Provisioning tests (`test/test_provisioning_api.py`) additionally need
`CLOUDINARY_ACCOUNT_URL`; they are skipped without it.
- Add-on tests (`test/addon_types.py`) require paid add-ons. Guard anything new with
the existing skip decorators rather than making the default suite fail.
- Nondeterministic AI output (auto-tagging, captioning, moderation verdicts) must be
asserted by request shape, state transition, and response schema — never exact
values.
- There is no lint tooling in this repo. Do not add a linter or reformat files
wholesale as part of an unrelated change.

## Project structure

- `cloudinary/` — the package. `uploader.py` (Upload API), `api.py` (Admin API),
`utils.py` (URL building, signing, transformation strings), `search.py`.
- `cloudinary/docs/` — version-matched Markdown task docs, shipped inside the
published package. Keep in sync with the code they document.
- `cloudinary/models.py`, `forms.py`, `templatetags/`, `templates/`, `static/` — the
Django integration. `static/` is generated by `prepare.sh` and gitignored.
- `cloudinary/provisioning/` — Account/Provisioning API, including `create_cloud`
(Claimable Clouds) and `create_agent_account`.
- `cloudinary/api_client/` — shared HTTP plumbing; `cloudinary/poster/` is vendored
MIT code for multipart streaming.
- `examples/` — complete runnable task examples, one per task doc. Repo-only, not
shipped in the package.
- `samples/` — legacy full sample applications; not part of the tested example set.
- `test/`, `django_tests/` — the two suites. `tools/` — release and CI scripts.
- The version lives in **three** places that must stay in sync:
`cloudinary/__init__.py`, `pyproject.toml`, and the legacy Python 2 branch of
`setup.py`. `tools/update_version.sh` bumps all three. `tools/get_test_cloud.sh`
greps the version out of `setup.py`, so do not reformat that line.

## Code style

- Python 2/3 compatible source: the package still imports `six` and
`cloudinary/compat.py`. Do not introduce f-strings, walrus operators, or
type-annotation syntax into `cloudinary/`.
- 4-space indent, `snake_case`, module-level functions for API surface (not classes).
- Public API convention: positional arguments first, then `**options` passed through
to the API call.

```python
def upload(file, **options):
params = utils.build_upload_params(**options)
return call_cacheable_api("upload", params, file=file, **options)
```
- New upload or transformation parameters must be added to the whitelists in
`cloudinary/utils.py` (`__SIMPLE_UPLOAD_PARAMS`, `__SERIALIZED_UPLOAD_PARAMS`,
`_SIMPLE_TRANSFORMATION_PARAMS`) or they are silently dropped.

## Git workflow

- Branch from `master`; one topic per pull request.
- Run `python -m pytest test` before opening a PR, and the Django suite when touching
`models.py`, `forms.py`, or `templatetags/`.
- Never rewrite published `CHANGELOG.md` entries; new entries go at the top and are
added by the release process, not by feature PRs.
- Never commit credentials, `.env`, real cloud names, build output (`dist/`,
`build/`, `*.egg-info/`), or `cloudinary/static/`.

## Boundaries

**Always**

- Keep `cloudinary/docs/` and `examples/` consistent with the code they document.
- Update tests when public behavior changes.
- Keep API secrets out of examples, docs, tests, and fixtures.

**Ask first**

- Changing supported Python or Django versions, dependencies, classifiers, or
packaging configuration (`pyproject.toml`, `MANIFEST.in`, `setup.py`).
- Renaming or removing any public function, class, or module.
- Changing release, CI, or version-bump tooling in `tools/`.

**Never**

- Commit credentials or real account identifiers.
- Add a linter, formatter, or reformat unrelated files.
- Document a Cloudinary platform capability as an SDK method unless this package
implements it (see `cloudinary/docs/platform-capabilities.md`).
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@AGENTS.md
37 changes: 25 additions & 12 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ Please be aware that the package is used in a wide variety of environments and t
- Ensure the PR description clearly describes the bug / feature. Include the relevant issue number if applicable.
- Provide test code that covers the new code
- Make sure that your code works both with and without Django
- The code should support:
- Python >= 2.7
- Django >= 1.8
- The code should support the versions tested in CI:
- Python 3.10 - 3.14
- Django 4.2, 5.0, 5.1, 5.2, 6.0

## Code contribution

Expand Down Expand Up @@ -71,29 +71,42 @@ We definitely appreciate pull requests that highlight or reproduce a problem, ev

Implement your feature or bug fix.
Try to follow [PEP8](https://pep8.org/).
Make sure that your code works both with and without Django
The code should support:
Make sure that your code works both with and without Django.
The code should support the versions tested in CI:

- Python >= 2.7
- Django >= 1.8
- Python 3.10 - 3.14
- Django 4.2, 5.0, 5.1, 5.2, 6.0

Make sure that tests completes without errors.

#### Write Documentation

Document any external behavior in the [README](README.md).
Document any external behavior in the bundled task docs under
[cloudinary/docs](cloudinary/docs) — these ship inside the published package and are the
source of truth for the installed version. Add a matching runnable file to
[examples](examples) when the change introduces a new task, and keep the two consistent.
The [README](README.md) links the task docs; update it only when the set of tasks
changes.

#### Running the tests

Run the basic test suite with your `CLOUDINARY_URL`:

CLOUDINARY_URL=cloudinary://apikey:apisecret@cloudname python setup.py test
CLOUDINARY_URL=cloudinary://apikey:apisecret@cloudname python -m pytest test

The suite runs against the live API, so a working `CLOUDINARY_URL` is required. If you do
not have credentials, provision a throwaway cloud with
`python -c "from cloudinary.provisioning import create_cloud; print(create_cloud())"`.

Run the Django suite separately:

DJANGO_SETTINGS_MODULE=django_tests.settings django-admin test -v2 django_tests

This only runs the tests for the current environment.
Travis-CI will run the full suite when you submit your pull request.
GitHub Actions will run the full suite when you submit your pull request.

The full test suite takes a long time to run because it tests multiple combinations of Python and Django.
You need to have Python 2.7, 3.4, 3.5, 3.6, 3.7 installed to run all environments. Then run:
You need the Python versions listed above installed to run all environments. Then run:

CLOUDINARY_URL=cloudinary://apikey:apisecret@cloudname tox

Expand Down Expand Up @@ -139,7 +152,7 @@ git push origin my-feature-branch -f

#### Check on Your Pull Request

Go back to your pull request after a few minutes and see whether it passed muster with Travis-CI. Everything should look green, otherwise fix issues and amend your commit as described above.
Go back to your pull request after a few minutes and see whether it passed muster with GitHub Actions. Everything should look green, otherwise fix issues and amend your commit as described above.

#### Be Patient

Expand Down
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) Cloudinary Ltd.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
5 changes: 0 additions & 5 deletions LICENSE.txt

This file was deleted.

2 changes: 2 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
include *.txt
include LICENSE
recursive-include cloudinary/docs *.md
recursive-include cloudinary/templates *.html
recursive-include cloudinary/static *.html *.js
prune django_tests
Loading
Loading