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.
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 + wheelEvery 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())".
test/is the core suite and hits the live API. Tests namespace their assets withUNIQUE_TEST_IDfromtest/helper_test.pyand 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 coversCloudinaryField, the form fields, and migrations; the templatetags have no coverage yet.- Provisioning tests (
test/test_provisioning_api.py) additionally needCLOUDINARY_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.
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 byprepare.shand gitignored.cloudinary/provisioning/— Account/Provisioning API, includingcreate_cloud(Claimable Clouds) andcreate_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 ofsetup.py.tools/update_version.shbumps all three.tools/get_test_cloud.shgreps the version out ofsetup.py, so do not reformat that line.
-
Python 2/3 compatible source: the package still imports
sixandcloudinary/compat.py. Do not introduce f-strings, walrus operators, or type-annotation syntax intocloudinary/. -
4-space indent,
snake_case, module-level functions for API surface (not classes). -
Public API convention: positional arguments first, then
**optionspassed through to the API call.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.
- Branch from
master; one topic per pull request. - Run
python -m pytest testbefore opening a PR, and the Django suite when touchingmodels.py,forms.py, ortemplatetags/. - Never rewrite published
CHANGELOG.mdentries; 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/), orcloudinary/static/.
Always
- Keep
cloudinary/docs/andexamples/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).