From a932555fc2d0971728f070a623d160de7ded5ace Mon Sep 17 00:00:00 2001 From: sunil-lakshman <104969541+sunil-lakshman@users.noreply.github.com> Date: Thu, 2 Apr 2026 11:27:46 +0530 Subject: [PATCH 1/5] fix: request version bump --- requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 5ac3538..52b184c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ twython==3.9.1 setuptools==80.3.1 contentstack-utils==1.3.0 python-dateutil==2.8.2 -requests==2.32.4 +requests==2.33.0 coverage==7.6.0 tox==4.5.1 virtualenv~=20.36.1 @@ -47,7 +47,7 @@ mccabe==0.7.0 platformdirs==3.9.1 imagesize==1.4.1 snowballstemmer~=2.2.0 -Pygments~=2.18.0 +Pygments~=2.20.0 wrapt==1.16.0 certifi==2024.8.30 oauthlib==3.2.2 From 59137f558c7ce31b2cea3ddf5adbaecc2ce6f742 Mon Sep 17 00:00:00 2001 From: sunil-lakshman <104969541+sunil-lakshman@users.noreply.github.com> Date: Mon, 6 Apr 2026 09:35:57 +0530 Subject: [PATCH 2/5] Enh: Added cursor rules and skills --- .cursor/rules/README.md | 37 ++++++++++++++ .cursor/rules/code-review.mdc | 27 ++++++++++ .../rules/contentstack-delivery-python.mdc | 31 ++++++++++++ .cursor/rules/dev-workflow.md | 21 ++++++++ .cursor/rules/python.mdc | 30 ++++++++++++ .cursor/rules/testing.mdc | 33 +++++++++++++ AGENTS.md | 49 +++++++++++++++++++ skills/README.md | 10 ++++ skills/code-review/SKILL.md | 19 +++++++ skills/contentstack-delivery-python/SKILL.md | 34 +++++++++++++ skills/framework/SKILL.md | 24 +++++++++ skills/testing/SKILL.md | 26 ++++++++++ 12 files changed, 341 insertions(+) create mode 100644 .cursor/rules/README.md create mode 100644 .cursor/rules/code-review.mdc create mode 100644 .cursor/rules/contentstack-delivery-python.mdc create mode 100644 .cursor/rules/dev-workflow.md create mode 100644 .cursor/rules/python.mdc create mode 100644 .cursor/rules/testing.mdc create mode 100644 AGENTS.md create mode 100644 skills/README.md create mode 100644 skills/code-review/SKILL.md create mode 100644 skills/contentstack-delivery-python/SKILL.md create mode 100644 skills/framework/SKILL.md create mode 100644 skills/testing/SKILL.md diff --git a/.cursor/rules/README.md b/.cursor/rules/README.md new file mode 100644 index 0000000..5aa0c08 --- /dev/null +++ b/.cursor/rules/README.md @@ -0,0 +1,37 @@ +# Cursor Rules — Contentstack Python CDA SDK + +Rules for **contentstack-python**: Python **Content Delivery API (CDA)** SDK (`pip` package **Contentstack**). + +## Rules overview + +| Rule | Role | +|------|------| +| [`dev-workflow.md`](dev-workflow.md) | Branch/PR, install, tests | +| [`python.mdc`](python.mdc) | Python layout, `contentstack/`, `setup.py` | +| [`contentstack-delivery-python.mdc`](contentstack-delivery-python.mdc) | **Stack**, queries, live preview, **HTTPSConnection** / **requests** | +| [`testing.mdc`](testing.mdc) | **pytest** + **unittest** under `tests/` | +| [`code-review.mdc`](code-review.mdc) | PR checklist (**always applied**) | + +## Rule application + +| Context | Typical rules | +|---------|----------------| +| **Every session** | `code-review.mdc` | +| **Most files** | `dev-workflow.md` | +| **`contentstack/`** | `python.mdc` + `contentstack-delivery-python.mdc` | +| **`tests/**`** | `testing.mdc` | +| **Packaging** | `python.mdc` | + +## Quick reference + +| File | `alwaysApply` | Globs (summary) | +|------|---------------|-----------------| +| `dev-workflow.md` | no | `**/*.py`, `requirements.txt`, `setup.py`, `tests/pytest.ini` | +| `python.mdc` | no | `contentstack/**/*.py`, `setup.py` | +| `contentstack-delivery-python.mdc` | no | `contentstack/**/*.py` | +| `testing.mdc` | no | `tests/**/*.py`, `tests/pytest.ini` | +| `code-review.mdc` | **yes** | — | + +## Skills + +- [`skills/README.md`](../../skills/README.md) · [`AGENTS.md`](../../AGENTS.md) diff --git a/.cursor/rules/code-review.mdc b/.cursor/rules/code-review.mdc new file mode 100644 index 0000000..2cd6baa --- /dev/null +++ b/.cursor/rules/code-review.mdc @@ -0,0 +1,27 @@ +--- +description: "PR checklist for Contentstack Python CDA SDK — API, Stack, HTTP layer, tests" +alwaysApply: true +--- + +# Code review — Contentstack Python CDA SDK + +## Public API + +- **Exported** **`Stack`**, **ContentType**, **Query**, asset/entry helpers match **README** and consumer expectations; **`contentstack/__init__.py`** **`__all__`** stays accurate when exports change. +- **Docstrings** on **`Stack`** and key public methods when behavior or options change. + +## Compatibility + +- Avoid breaking **`Stack.__init__`** signatures or method chains without a semver strategy; document migration for breaking changes (**`setup.py`** / **`__version__`**). + +## HTTP / dependencies + +- Changes to **`requests`**, **retry** behavior, or **`HTTPSConnection`** should stay consistent with **`contentstack/controller.py`** and **`urllib3`** **`Retry`** usage in **`stack.py`**. + +## Tests + +- **Tests** hit the live CDA when using **`config`** credentials; extend **`tests/`** when request/response behavior changes. Do not commit new secrets. + +## Security + +- No hardcoded tokens in source or docs; no logging of **api keys**, **delivery tokens**, **preview**, or **management** tokens. diff --git a/.cursor/rules/contentstack-delivery-python.mdc b/.cursor/rules/contentstack-delivery-python.mdc new file mode 100644 index 0000000..0eb54b8 --- /dev/null +++ b/.cursor/rules/contentstack-delivery-python.mdc @@ -0,0 +1,31 @@ +--- +description: "CDA Delivery SDK — Stack, queries, live preview, requests session" +globs: ["contentstack/**/*.py"] +alwaysApply: false +--- + +# Contentstack Python Delivery SDK (`contentstack/`) + +## Stack entry + +- **`Stack`** in **`contentstack/stack.py`**: validates **api_key**, **delivery_token**, **environment**; resolves **region → host** via **`ContentstackRegion`**; builds **`endpoint`**; wires **`HTTPSConnection`** with **headers**, **timeout**, **`urllib3.Retry`**, and optional **`live_preview`** / **`branch`** / **`early_access`**. + +## Features + +- **Content types & entries** — **`contenttype.py`**, **`entry.py`**, **`entryqueryable.py`**. +- **Queries** — **`basequery.py`**, **`query.py`**; chain methods align with CDA query parameters. +- **Assets** — **`asset.py`**, **`assetquery.py`**. +- **Taxonomy, global fields, variants, image transform** — **`taxonomy.py`**, **`globalfields.py`**, **`variants.py`**, **`image_transform.py`**. +- **Sync** — **`Stack.sync_init`**, **`pagination`**, **`sync_token`** → **`/stacks/sync`** via **`__sync_request`**. + +## Live preview + +- **`live_preview`** dict (**enable**, **host**, **authorization**, etc.) merged in **`deep_merge_lp.py`** / stack setup; keep behavior aligned with **`tests/test_live_preview.py`**. + +## HTTP layer + +- **`https_connection.py`** — **`requests.Session`**, **`HTTPAdapter`**, **`get_request`** from **`controller.py`**; user-agent uses **`contentstack.__title__`** / **`__version__`**. + +## Docs + +- [Content Delivery API](https://www.contentstack.com/docs/developers/apis/content-delivery-api/) diff --git a/.cursor/rules/dev-workflow.md b/.cursor/rules/dev-workflow.md new file mode 100644 index 0000000..4785bb2 --- /dev/null +++ b/.cursor/rules/dev-workflow.md @@ -0,0 +1,21 @@ +--- +description: "Branches, install, and tests for contentstack-python" +globs: ["**/*.py", "requirements.txt", "setup.py", "tests/pytest.ini"] +alwaysApply: false +--- + +# Development workflow — Contentstack Python CDA SDK + +## Before a PR + +1. **Install** — `pip install -r requirements.txt` and editable package as needed: `pip install -e .` +2. **Tests** — `pytest tests/` (or `python -m pytest tests/`) from the repo root; **`tests/pytest.ini`** applies. +3. **Integration tests** use **`config.py`** at repo root for **HOST**, **APIKEY**, **DELIVERYTOKEN**, **ENVIRONMENT**, etc. Use local credentials only; **never commit** real tokens—prefer a gitignored local **`config.py`** or environment-based loading if you refactor tests. + +## Versioning + +- Bump **`contentstack/__init__.py`** **`__version__`** and **`setup.py`**-driven releases per semver for user-visible SDK changes. + +## Links + +- [`AGENTS.md`](../../AGENTS.md) · [`skills/contentstack-delivery-python/SKILL.md`](../../skills/contentstack-delivery-python/SKILL.md) diff --git a/.cursor/rules/python.mdc b/.cursor/rules/python.mdc new file mode 100644 index 0000000..93dcecc --- /dev/null +++ b/.cursor/rules/python.mdc @@ -0,0 +1,30 @@ +--- +description: "Python conventions for the CDA SDK package and packaging" +globs: + - "contentstack/**/*.py" + - "setup.py" +alwaysApply: false +--- + +# Python — Contentstack CDA SDK + +## Layout + +- **`contentstack/stack.py`** — **`Stack`**, **`ContentstackRegion`**. +- **`contentstack/query.py`**, **`basequery.py`** — query building. +- **`contentstack/entry.py`**, **`asset.py`**, **`contenttype.py`**, **`taxonomy.py`**, **`globalfields.py`** — domain objects. +- **`contentstack/https_connection.py`**, **`controller.py`** — HTTP. +- **`contentstack/error_messages.py`**, **`utility.py`** — shared helpers. + +## Style + +- Match existing patterns (typing on **`Stack`**, **unittest**-style tests in **`tests/`**). +- Prefer clear public APIs over internal churn; keep module boundaries similar to neighboring files. + +## Dependencies + +- **`requests`**, **`python-dateutil`**, **`urllib3`** (Retry) — see **`setup.py`** **`install_requires`**. + +## Security + +- Do not log **delivery tokens**, **preview tokens**, **api keys**, or **management** tokens; follow existing logging on **`Stack`**. diff --git a/.cursor/rules/testing.mdc b/.cursor/rules/testing.mdc new file mode 100644 index 0000000..aba84ac --- /dev/null +++ b/.cursor/rules/testing.mdc @@ -0,0 +1,33 @@ +--- +description: "pytest and unittest integration tests for contentstack-python" +globs: + - "tests/**/*.py" + - "tests/pytest.ini" +alwaysApply: false +--- + +# Testing — Contentstack Python CDA SDK + +## Runner + +- **`pytest tests/`** from repo root ( **`tests/pytest.ini`** — warning filters). +- Tests are **`unittest.TestCase`** subclasses; pytest discovers them normally. + +## Credentials + +- Most integration tests **`import config`** from the repo root **`config.py`** ( **HOST**, **APIKEY**, **DELIVERYTOKEN**, **ENVIRONMENT**, optional **PREVIEW_TOKEN**, entry UIDs, etc.). +- Treat **`config.py`** as **local-only** when it contains secrets; do not commit credentials. + +## Scope by module + +| Area | Example tests | +|------|----------------| +| Stack / region | **`tests/test_stack.py`** | +| Queries | **`tests/test_query.py`**, **`tests/test_basequery.py`** | +| Entries / assets | **`tests/test_entry.py`**, **`tests/test_assets.py`** | +| Taxonomy / global fields / live preview | **`tests/test_taxonomies.py`**, **`tests/test_global_fields.py`**, **`tests/test_live_preview.py`** | +| Early access | **`tests/test_early_find.py`**, **`tests/test_early_fetch.py`** | + +## Hygiene + +- No committed **`pytest.mark.skip`** without reason; avoid **`@unittest.skip`** unless environment is genuinely unavailable in CI. diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..bebaba2 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,49 @@ +# AGENTS.md — AI / automation context + +## Project + +| | | +|---|---| +| **Name** | **Contentstack** (PyPI) — **Python Content Delivery SDK** | +| **Purpose** | Python client for the **Content Delivery API (CDA)**: **Stack**, content types, entries, assets, queries, live preview, taxonomy, variants. Uses **`requests`** + **`urllib3.Retry`** via **`HTTPSConnection`**. | +| **Repository** | [contentstack/contentstack-python](https://github.com/contentstack/contentstack-python.git) | + +## Tech stack + +| Area | Details | +|------|---------| +| **Language** | **Python** (see **`setup.py`** `python_requires`, classifiers) | +| **HTTP** | **`requests`**, **`urllib3`** | +| **Tests** | **pytest** + **`unittest.TestCase`** under **`tests/`** | +| **Packaging** | **`setuptools`** / **`setup.py`**, package **`contentstack`** | + +## Source layout + +| Path | Role | +|------|------| +| `contentstack/stack.py` | **`Stack`**, **`ContentstackRegion`**, endpoint and **HTTPSConnection** wiring | +| `contentstack/https_connection.py`, `contentstack/controller.py` | Session, retries, **`get_request`** | +| `contentstack/query.py`, `contentstack/basequery.py` | Queries | +| `contentstack/entry.py`, `asset.py`, `contenttype.py`, … | Domain modules | +| `contentstack/__init__.py` | Public exports (**`Stack`**, **`Entry`**, **`Asset`**, …), **`__version__`** | +| `config.py` (repo root) | Test credentials and UIDs — **must not commit secrets** | +| `tests/*.py` | Integration-style tests importing **`config`** | + +## Common commands + +```bash +pip install -r requirements.txt +pip install -e . +pytest tests/ +``` + +## Environment / test configuration + +Tests load stack settings from root **`config.py`** (e.g. **HOST**, **APIKEY**, **DELIVERYTOKEN**, **ENVIRONMENT**). Use a local, gitignored file or sanitized values for CI. Do not commit secrets. + +## Further guidance + +- **Cursor rules:** [`.cursor/rules/README.md`](.cursor/rules/README.md) +- **Skills:** [`skills/README.md`](skills/README.md) + +Product docs: [Content Delivery API](https://www.contentstack.com/docs/developers/apis/content-delivery-api/). diff --git a/skills/README.md b/skills/README.md new file mode 100644 index 0000000..518edcd --- /dev/null +++ b/skills/README.md @@ -0,0 +1,10 @@ +# Project skills — Contentstack Python CDA SDK + +| Skill | When to use | +|-------|-------------| +| [`code-review/`](code-review/SKILL.md) | PR review, semver, public API on **Stack** | +| [`testing/`](testing/SKILL.md) | **pytest** + **`tests/`** + **`config.py`** | +| [`contentstack-delivery-python/`](contentstack-delivery-python/SKILL.md) | **Stack**, queries, entries, assets, live preview | +| [`framework/`](framework/SKILL.md) | **requests**, **HTTPSConnection**, retries | + +**Overview:** [`AGENTS.md`](../AGENTS.md) · **Rules:** [`.cursor/rules/README.md`](../.cursor/rules/README.md) diff --git a/skills/code-review/SKILL.md b/skills/code-review/SKILL.md new file mode 100644 index 0000000..4787a45 --- /dev/null +++ b/skills/code-review/SKILL.md @@ -0,0 +1,19 @@ +--- +name: code-review +description: PR review for Contentstack Python CDA SDK — public API, Stack, HTTP layer, tests. +--- + +# Code review — Contentstack Python CDA SDK + +## Checklist + +- [ ] **API:** New or changed **`Stack`** / content-type / query / entry methods documented; **`contentstack/__init__.py`** exports updated if needed. +- [ ] **Version:** **`__version__`** in **`contentstack/__init__.py`** aligned with release strategy for breaking changes. +- [ ] **HTTP:** **`https_connection.py`** / **`controller.py`** changes keep retry and timeout behavior predictable. +- [ ] **Tests:** **`pytest tests/`** passes; extend **`tests/`** when CDA behavior changes. +- [ ] **Secrets:** No tokens in repo; **`config.py`** remains local-only when it holds real credentials. + +## References + +- `.cursor/rules/code-review.mdc` +- `.cursor/rules/dev-workflow.md` diff --git a/skills/contentstack-delivery-python/SKILL.md b/skills/contentstack-delivery-python/SKILL.md new file mode 100644 index 0000000..6291e70 --- /dev/null +++ b/skills/contentstack-delivery-python/SKILL.md @@ -0,0 +1,34 @@ +--- +name: contentstack-delivery-python +description: Contentstack Python CDA SDK — Stack, queries, entries, assets, live preview, taxonomy. +--- + +# Contentstack Python Delivery SDK skill + +## Entry + +- **`contentstack.Stack(api_key, delivery_token, environment, ...)`** — **`contentstack/stack.py`**: validates credentials, sets **region** / **host**, builds **`endpoint`**, instantiates **`HTTPSConnection`** with **retry_strategy** and **live_preview**. + +## Structure + +- **`Stack`** — content types, entries, assets, sync helpers as implemented on the class. +- **Queries** — **`BaseQuery`**, **`Query`**, **`AssetQuery`**, **`EntryQueryable`**, etc. +- **Live preview** — **`live_preview`** dict and **`deep_merge_lp`** behavior. +- **Sync** — **`sync_init`**, **`pagination`**, **`sync_token`** on **`Stack`**. + +## Extending + +- Add query or stack methods consistent with [CDA query parameters](https://www.contentstack.com/docs/developers/apis/content-delivery-api/). +- Keep transport logic in **`HTTPSConnection`** / **`controller`** rather than duplicating **`requests`** setup. + +## Dependencies + +- **`requests`**, **`urllib3`** (**Retry**), **`python-dateutil`** + +## Docs + +- [Content Delivery API](https://www.contentstack.com/docs/developers/apis/content-delivery-api/) + +## Rule shortcut + +- `.cursor/rules/contentstack-delivery-python.mdc` diff --git a/skills/framework/SKILL.md b/skills/framework/SKILL.md new file mode 100644 index 0000000..e5e4f1f --- /dev/null +++ b/skills/framework/SKILL.md @@ -0,0 +1,24 @@ +--- +name: framework +description: HTTP layer for the Python CDA SDK — requests Session, urllib3 retries, HTTPSConnection. +--- + +# Framework skill — requests + Contentstack Python SDK + +## Integration point + +- **`contentstack/stack.py`** constructs **`HTTPSConnection`** with **endpoint**, **headers**, **timeout**, **`retry_strategy`** (**`urllib3.Retry`**), and **live_preview**. +- **`contentstack/https_connection.py`** mounts **`HTTPAdapter(max_retries=...)`** and calls **`get_request`** from **`contentstack/controller.py`**. + +## When to change + +- **Retry / timeout** behavior: align **`Stack`** defaults with **`HTTPSConnection`** and **`HTTPAdapter`** usage; avoid breaking existing **`Retry`** constructor expectations. +- **Headers / user-agent** — **`user_agents()`** in **`https_connection.py`** uses **`contentstack.__title__`** and **`__version__`**. + +## Testing + +- **Integration** — full stack via **`tests/`** and **`config`**; **unit-style** assertions on URL building and headers where tests exist. + +## Rule shortcut + +- `.cursor/rules/contentstack-delivery-python.mdc` diff --git a/skills/testing/SKILL.md b/skills/testing/SKILL.md new file mode 100644 index 0000000..cff6621 --- /dev/null +++ b/skills/testing/SKILL.md @@ -0,0 +1,26 @@ +--- +name: testing +description: pytest and unittest tests for contentstack-python — tests/ and config.py. +--- + +# Testing — Contentstack Python CDA SDK + +## Commands + +| Goal | Command | +|------|---------| +| Full test tree | `pytest tests/` | +| Single file | `pytest tests/test_stack.py` | + +## Environment + +- Root **`config.py`**: **HOST**, **APIKEY**, **DELIVERYTOKEN**, **ENVIRONMENT**, optional **PREVIEW_TOKEN**, content UIDs for specific suites. +- Use a **local** **`config.py`** or sanitized values; never commit live secrets. + +## Conventions + +- Tests subclass **`unittest.TestCase`**; **`tests/pytest.ini`** applies warning filters. + +## References + +- `.cursor/rules/testing.mdc` From 1564374230ab9352df51b902513c7d4c33850233 Mon Sep 17 00:00:00 2001 From: sunil-lakshman <104969541+sunil-lakshman@users.noreply.github.com> Date: Tue, 7 Apr 2026 13:05:37 +0530 Subject: [PATCH 3/5] Updated rules as per new structure --- .cursor/rules/README.md | 43 +++++-------------- .cursor/rules/code-review.mdc | 27 ------------ .cursor/rules/testing.mdc | 33 -------------- skills/README.md | 8 ++-- skills/code-review/SKILL.md | 25 ++++++++++- skills/contentstack-delivery-python/SKILL.md | 34 --------------- .../contentstack-utils/SKILL.md | 18 ++++++-- .../dev-workflow/SKILL.md | 9 ++-- skills/framework/SKILL.md | 4 +- .../python-style/SKILL.md | 9 ++-- skills/testing/SKILL.md | 16 ++++++- 11 files changed, 78 insertions(+), 148 deletions(-) delete mode 100644 .cursor/rules/code-review.mdc delete mode 100644 .cursor/rules/testing.mdc delete mode 100644 skills/contentstack-delivery-python/SKILL.md rename .cursor/rules/contentstack-delivery-python.mdc => skills/contentstack-utils/SKILL.md (70%) rename .cursor/rules/dev-workflow.md => skills/dev-workflow/SKILL.md (70%) rename .cursor/rules/python.mdc => skills/python-style/SKILL.md (84%) diff --git a/.cursor/rules/README.md b/.cursor/rules/README.md index 5aa0c08..d5db24e 100644 --- a/.cursor/rules/README.md +++ b/.cursor/rules/README.md @@ -1,37 +1,16 @@ # Cursor Rules — Contentstack Python CDA SDK -Rules for **contentstack-python**: Python **Content Delivery API (CDA)** SDK (`pip` package **Contentstack**). +This repository keeps **project guidance in [skills](../../skills/)** (one folder per topic, each with **`SKILL.md`**), not as separate rule files under `.cursor/rules/`. -## Rules overview +## Where to look -| Rule | Role | -|------|------| -| [`dev-workflow.md`](dev-workflow.md) | Branch/PR, install, tests | -| [`python.mdc`](python.mdc) | Python layout, `contentstack/`, `setup.py` | -| [`contentstack-delivery-python.mdc`](contentstack-delivery-python.mdc) | **Stack**, queries, live preview, **HTTPSConnection** / **requests** | -| [`testing.mdc`](testing.mdc) | **pytest** + **unittest** under `tests/` | -| [`code-review.mdc`](code-review.mdc) | PR checklist (**always applied**) | +| Topic | Skill | +|-------|--------| +| PR checklist, public API, semver | [`skills/code-review/SKILL.md`](../../skills/code-review/SKILL.md) | +| Branch, install, tests, versioning | [`skills/dev-workflow/SKILL.md`](../../skills/dev-workflow/SKILL.md) | +| **Stack**, queries, CDA features | [`skills/contentstack-utils/SKILL.md`](../../skills/contentstack-utils/SKILL.md) | +| **requests**, retries, **HTTPSConnection** | [`skills/framework/SKILL.md`](../../skills/framework/SKILL.md) | +| Python layout and package conventions | [`skills/python-style/SKILL.md`](../../skills/python-style/SKILL.md) | +| **pytest**, **`tests/`**, **`config.py`** | [`skills/testing/SKILL.md`](../../skills/testing/SKILL.md) | -## Rule application - -| Context | Typical rules | -|---------|----------------| -| **Every session** | `code-review.mdc` | -| **Most files** | `dev-workflow.md` | -| **`contentstack/`** | `python.mdc` + `contentstack-delivery-python.mdc` | -| **`tests/**`** | `testing.mdc` | -| **Packaging** | `python.mdc` | - -## Quick reference - -| File | `alwaysApply` | Globs (summary) | -|------|---------------|-----------------| -| `dev-workflow.md` | no | `**/*.py`, `requirements.txt`, `setup.py`, `tests/pytest.ini` | -| `python.mdc` | no | `contentstack/**/*.py`, `setup.py` | -| `contentstack-delivery-python.mdc` | no | `contentstack/**/*.py` | -| `testing.mdc` | no | `tests/**/*.py`, `tests/pytest.ini` | -| `code-review.mdc` | **yes** | — | - -## Skills - -- [`skills/README.md`](../../skills/README.md) · [`AGENTS.md`](../../AGENTS.md) +**Index:** [`skills/README.md`](../../skills/README.md) · [`AGENTS.md`](../../AGENTS.md) diff --git a/.cursor/rules/code-review.mdc b/.cursor/rules/code-review.mdc deleted file mode 100644 index 2cd6baa..0000000 --- a/.cursor/rules/code-review.mdc +++ /dev/null @@ -1,27 +0,0 @@ ---- -description: "PR checklist for Contentstack Python CDA SDK — API, Stack, HTTP layer, tests" -alwaysApply: true ---- - -# Code review — Contentstack Python CDA SDK - -## Public API - -- **Exported** **`Stack`**, **ContentType**, **Query**, asset/entry helpers match **README** and consumer expectations; **`contentstack/__init__.py`** **`__all__`** stays accurate when exports change. -- **Docstrings** on **`Stack`** and key public methods when behavior or options change. - -## Compatibility - -- Avoid breaking **`Stack.__init__`** signatures or method chains without a semver strategy; document migration for breaking changes (**`setup.py`** / **`__version__`**). - -## HTTP / dependencies - -- Changes to **`requests`**, **retry** behavior, or **`HTTPSConnection`** should stay consistent with **`contentstack/controller.py`** and **`urllib3`** **`Retry`** usage in **`stack.py`**. - -## Tests - -- **Tests** hit the live CDA when using **`config`** credentials; extend **`tests/`** when request/response behavior changes. Do not commit new secrets. - -## Security - -- No hardcoded tokens in source or docs; no logging of **api keys**, **delivery tokens**, **preview**, or **management** tokens. diff --git a/.cursor/rules/testing.mdc b/.cursor/rules/testing.mdc deleted file mode 100644 index aba84ac..0000000 --- a/.cursor/rules/testing.mdc +++ /dev/null @@ -1,33 +0,0 @@ ---- -description: "pytest and unittest integration tests for contentstack-python" -globs: - - "tests/**/*.py" - - "tests/pytest.ini" -alwaysApply: false ---- - -# Testing — Contentstack Python CDA SDK - -## Runner - -- **`pytest tests/`** from repo root ( **`tests/pytest.ini`** — warning filters). -- Tests are **`unittest.TestCase`** subclasses; pytest discovers them normally. - -## Credentials - -- Most integration tests **`import config`** from the repo root **`config.py`** ( **HOST**, **APIKEY**, **DELIVERYTOKEN**, **ENVIRONMENT**, optional **PREVIEW_TOKEN**, entry UIDs, etc.). -- Treat **`config.py`** as **local-only** when it contains secrets; do not commit credentials. - -## Scope by module - -| Area | Example tests | -|------|----------------| -| Stack / region | **`tests/test_stack.py`** | -| Queries | **`tests/test_query.py`**, **`tests/test_basequery.py`** | -| Entries / assets | **`tests/test_entry.py`**, **`tests/test_assets.py`** | -| Taxonomy / global fields / live preview | **`tests/test_taxonomies.py`**, **`tests/test_global_fields.py`**, **`tests/test_live_preview.py`** | -| Early access | **`tests/test_early_find.py`**, **`tests/test_early_fetch.py`** | - -## Hygiene - -- No committed **`pytest.mark.skip`** without reason; avoid **`@unittest.skip`** unless environment is genuinely unavailable in CI. diff --git a/skills/README.md b/skills/README.md index 518edcd..5843982 100644 --- a/skills/README.md +++ b/skills/README.md @@ -3,8 +3,10 @@ | Skill | When to use | |-------|-------------| | [`code-review/`](code-review/SKILL.md) | PR review, semver, public API on **Stack** | -| [`testing/`](testing/SKILL.md) | **pytest** + **`tests/`** + **`config.py`** | -| [`contentstack-delivery-python/`](contentstack-delivery-python/SKILL.md) | **Stack**, queries, entries, assets, live preview | +| [`contentstack-utils/`](contentstack-utils/SKILL.md) | **Stack**, queries, entries, assets, live preview, CDA behavior | +| [`dev-workflow/`](dev-workflow/SKILL.md) | Branch/PR, install, tests, **config.py**, versioning | | [`framework/`](framework/SKILL.md) | **requests**, **HTTPSConnection**, retries | +| [`python-style/`](python-style/SKILL.md) | **`contentstack/`** layout, **setup.py**, Python conventions | +| [`testing/`](testing/SKILL.md) | **pytest** + **`tests/`** + **`config.py`** | -**Overview:** [`AGENTS.md`](../AGENTS.md) · **Rules:** [`.cursor/rules/README.md`](../.cursor/rules/README.md) +**Overview:** [`AGENTS.md`](../AGENTS.md) · **Cursor rules index:** [`.cursor/rules/README.md`](../.cursor/rules/README.md) diff --git a/skills/code-review/SKILL.md b/skills/code-review/SKILL.md index 4787a45..2fad477 100644 --- a/skills/code-review/SKILL.md +++ b/skills/code-review/SKILL.md @@ -13,7 +13,28 @@ description: PR review for Contentstack Python CDA SDK — public API, Stack, HT - [ ] **Tests:** **`pytest tests/`** passes; extend **`tests/`** when CDA behavior changes. - [ ] **Secrets:** No tokens in repo; **`config.py`** remains local-only when it holds real credentials. +## Public API + +- **Exported** **`Stack`**, **ContentType**, **Query**, asset/entry helpers match **README** and consumer expectations; **`contentstack/__init__.py`** **`__all__`** stays accurate when exports change. +- **Docstrings** on **`Stack`** and key public methods when behavior or options change. + +## Compatibility + +- Avoid breaking **`Stack.__init__`** signatures or method chains without a semver strategy; document migration for breaking changes (**`setup.py`** / **`__version__`**). + +## HTTP / dependencies + +- Changes to **`requests`**, **retry** behavior, or **`HTTPSConnection`** should stay consistent with **`contentstack/controller.py`** and **`urllib3`** **`Retry`** usage in **`stack.py`**. + +## Tests + +- **Tests** hit the live CDA when using **`config`** credentials; extend **`tests/`** when request/response behavior changes. Do not commit new secrets. + +## Security + +- No hardcoded tokens in source or docs; no logging of **api keys**, **delivery tokens**, **preview**, or **management** tokens. + ## References -- `.cursor/rules/code-review.mdc` -- `.cursor/rules/dev-workflow.md` +- [`dev-workflow/SKILL.md`](../dev-workflow/SKILL.md) +- [`python-style/SKILL.md`](../python-style/SKILL.md) diff --git a/skills/contentstack-delivery-python/SKILL.md b/skills/contentstack-delivery-python/SKILL.md deleted file mode 100644 index 6291e70..0000000 --- a/skills/contentstack-delivery-python/SKILL.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -name: contentstack-delivery-python -description: Contentstack Python CDA SDK — Stack, queries, entries, assets, live preview, taxonomy. ---- - -# Contentstack Python Delivery SDK skill - -## Entry - -- **`contentstack.Stack(api_key, delivery_token, environment, ...)`** — **`contentstack/stack.py`**: validates credentials, sets **region** / **host**, builds **`endpoint`**, instantiates **`HTTPSConnection`** with **retry_strategy** and **live_preview**. - -## Structure - -- **`Stack`** — content types, entries, assets, sync helpers as implemented on the class. -- **Queries** — **`BaseQuery`**, **`Query`**, **`AssetQuery`**, **`EntryQueryable`**, etc. -- **Live preview** — **`live_preview`** dict and **`deep_merge_lp`** behavior. -- **Sync** — **`sync_init`**, **`pagination`**, **`sync_token`** on **`Stack`**. - -## Extending - -- Add query or stack methods consistent with [CDA query parameters](https://www.contentstack.com/docs/developers/apis/content-delivery-api/). -- Keep transport logic in **`HTTPSConnection`** / **`controller`** rather than duplicating **`requests`** setup. - -## Dependencies - -- **`requests`**, **`urllib3`** (**Retry**), **`python-dateutil`** - -## Docs - -- [Content Delivery API](https://www.contentstack.com/docs/developers/apis/content-delivery-api/) - -## Rule shortcut - -- `.cursor/rules/contentstack-delivery-python.mdc` diff --git a/.cursor/rules/contentstack-delivery-python.mdc b/skills/contentstack-utils/SKILL.md similarity index 70% rename from .cursor/rules/contentstack-delivery-python.mdc rename to skills/contentstack-utils/SKILL.md index 0eb54b8..417cff6 100644 --- a/.cursor/rules/contentstack-delivery-python.mdc +++ b/skills/contentstack-utils/SKILL.md @@ -1,7 +1,6 @@ --- -description: "CDA Delivery SDK — Stack, queries, live preview, requests session" -globs: ["contentstack/**/*.py"] -alwaysApply: false +name: contentstack-utils +description: Contentstack Python CDA SDK — Stack, queries, entries, assets, live preview, taxonomy, HTTP session. --- # Contentstack Python Delivery SDK (`contentstack/`) @@ -26,6 +25,19 @@ alwaysApply: false - **`https_connection.py`** — **`requests.Session`**, **`HTTPAdapter`**, **`get_request`** from **`controller.py`**; user-agent uses **`contentstack.__title__`** / **`__version__`**. +## Extending + +- Add query or stack methods consistent with [CDA query parameters](https://www.contentstack.com/docs/developers/apis/content-delivery-api/). +- Keep transport logic in **`HTTPSConnection`** / **`controller`** rather than duplicating **`requests`** setup. + +## Dependencies + +- **`requests`**, **`urllib3`** (**Retry**), **`python-dateutil`** + +## Related skills + +- [`framework/SKILL.md`](../framework/SKILL.md) — retries, **`HTTPAdapter`**, timeouts + ## Docs - [Content Delivery API](https://www.contentstack.com/docs/developers/apis/content-delivery-api/) diff --git a/.cursor/rules/dev-workflow.md b/skills/dev-workflow/SKILL.md similarity index 70% rename from .cursor/rules/dev-workflow.md rename to skills/dev-workflow/SKILL.md index 4785bb2..33a7495 100644 --- a/.cursor/rules/dev-workflow.md +++ b/skills/dev-workflow/SKILL.md @@ -1,7 +1,6 @@ --- -description: "Branches, install, and tests for contentstack-python" -globs: ["**/*.py", "requirements.txt", "setup.py", "tests/pytest.ini"] -alwaysApply: false +name: dev-workflow +description: Branches, install, tests, and versioning for contentstack-python. --- # Development workflow — Contentstack Python CDA SDK @@ -16,6 +15,6 @@ alwaysApply: false - Bump **`contentstack/__init__.py`** **`__version__`** and **`setup.py`**-driven releases per semver for user-visible SDK changes. -## Links +## References -- [`AGENTS.md`](../../AGENTS.md) · [`skills/contentstack-delivery-python/SKILL.md`](../../skills/contentstack-delivery-python/SKILL.md) +- [`AGENTS.md`](../../AGENTS.md) · [`contentstack-utils/SKILL.md`](../contentstack-utils/SKILL.md) diff --git a/skills/framework/SKILL.md b/skills/framework/SKILL.md index e5e4f1f..78e966c 100644 --- a/skills/framework/SKILL.md +++ b/skills/framework/SKILL.md @@ -19,6 +19,6 @@ description: HTTP layer for the Python CDA SDK — requests Session, urllib3 ret - **Integration** — full stack via **`tests/`** and **`config`**; **unit-style** assertions on URL building and headers where tests exist. -## Rule shortcut +## Related skills -- `.cursor/rules/contentstack-delivery-python.mdc` +- [`contentstack-utils/SKILL.md`](../contentstack-utils/SKILL.md) diff --git a/.cursor/rules/python.mdc b/skills/python-style/SKILL.md similarity index 84% rename from .cursor/rules/python.mdc rename to skills/python-style/SKILL.md index 93dcecc..1896780 100644 --- a/.cursor/rules/python.mdc +++ b/skills/python-style/SKILL.md @@ -1,12 +1,9 @@ --- -description: "Python conventions for the CDA SDK package and packaging" -globs: - - "contentstack/**/*.py" - - "setup.py" -alwaysApply: false +name: python-style +description: Python layout, packaging, and conventions for the Contentstack CDA SDK package. --- -# Python — Contentstack CDA SDK +# Python style — Contentstack CDA SDK ## Layout diff --git a/skills/testing/SKILL.md b/skills/testing/SKILL.md index cff6621..2ee568f 100644 --- a/skills/testing/SKILL.md +++ b/skills/testing/SKILL.md @@ -21,6 +21,20 @@ description: pytest and unittest tests for contentstack-python — tests/ and co - Tests subclass **`unittest.TestCase`**; **`tests/pytest.ini`** applies warning filters. +## Scope by module + +| Area | Example tests | +|------|----------------| +| Stack / region | **`tests/test_stack.py`** | +| Queries | **`tests/test_query.py`**, **`tests/test_basequery.py`** | +| Entries / assets | **`tests/test_entry.py`**, **`tests/test_assets.py`** | +| Taxonomy / global fields / live preview | **`tests/test_taxonomies.py`**, **`tests/test_global_fields.py`**, **`tests/test_live_preview.py`** | +| Early access | **`tests/test_early_find.py`**, **`tests/test_early_fetch.py`** | + +## Hygiene + +- No committed **`pytest.mark.skip`** without reason; avoid **`@unittest.skip`** unless environment is genuinely unavailable in CI. + ## References -- `.cursor/rules/testing.mdc` +- [`dev-workflow/SKILL.md`](../dev-workflow/SKILL.md) From cc1eba32eab2e03ddf6e98771fea9316abb33e79 Mon Sep 17 00:00:00 2001 From: sunil-lakshman <104969541+sunil-lakshman@users.noreply.github.com> Date: Wed, 15 Apr 2026 14:52:41 +0530 Subject: [PATCH 4/5] Added version bump --- CHANGELOG.md | 6 + contentstack/__init__.py | 2 +- tests/report/assets/style.css | 319 ++++++++++++++ tests/report/test-report.html | 773 ++++++++++++++++++++++++++++++++++ 4 files changed, 1099 insertions(+), 1 deletion(-) create mode 100644 tests/report/assets/style.css create mode 100644 tests/report/test-report.html diff --git a/CHANGELOG.md b/CHANGELOG.md index bc7cedd..ada53b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # CHANGELOG +## _v2.5.1_ + +### **Date: 15-April-2026** + +- Fixed security issues. + ## _v2.5.0_ ### **Date: 02-March-2026** diff --git a/contentstack/__init__.py b/contentstack/__init__.py index fc6f5e0..dea0db0 100644 --- a/contentstack/__init__.py +++ b/contentstack/__init__.py @@ -22,7 +22,7 @@ __title__ = 'contentstack-delivery-python' __author__ = 'contentstack' __status__ = 'debug' -__version__ = 'v2.5.0' +__version__ = 'v2.5.1' __endpoint__ = 'cdn.contentstack.io' __email__ = 'support@contentstack.com' __developer_email__ = 'mobile@contentstack.com' diff --git a/tests/report/assets/style.css b/tests/report/assets/style.css new file mode 100644 index 0000000..561524c --- /dev/null +++ b/tests/report/assets/style.css @@ -0,0 +1,319 @@ +body { + font-family: Helvetica, Arial, sans-serif; + font-size: 12px; + /* do not increase min-width as some may use split screens */ + min-width: 800px; + color: #999; +} + +h1 { + font-size: 24px; + color: black; +} + +h2 { + font-size: 16px; + color: black; +} + +p { + color: black; +} + +a { + color: #999; +} + +table { + border-collapse: collapse; +} + +/****************************** + * SUMMARY INFORMATION + ******************************/ +#environment td { + padding: 5px; + border: 1px solid #e6e6e6; + vertical-align: top; +} +#environment tr:nth-child(odd) { + background-color: #f6f6f6; +} +#environment ul { + margin: 0; + padding: 0 20px; +} + +/****************************** + * TEST RESULT COLORS + ******************************/ +span.passed, +.passed .col-result { + color: green; +} + +span.skipped, +span.xfailed, +span.rerun, +.skipped .col-result, +.xfailed .col-result, +.rerun .col-result { + color: orange; +} + +span.error, +span.failed, +span.xpassed, +.error .col-result, +.failed .col-result, +.xpassed .col-result { + color: red; +} + +.col-links__extra { + margin-right: 3px; +} + +/****************************** + * RESULTS TABLE + * + * 1. Table Layout + * 2. Extra + * 3. Sorting items + * + ******************************/ +/*------------------ + * 1. Table Layout + *------------------*/ +#results-table { + border: 1px solid #e6e6e6; + color: #999; + font-size: 12px; + width: 100%; +} +#results-table th, +#results-table td { + padding: 5px; + border: 1px solid #e6e6e6; + text-align: left; +} +#results-table th { + font-weight: bold; +} + +/*------------------ + * 2. Extra + *------------------*/ +.logwrapper { + max-height: 230px; + overflow-y: scroll; + background-color: #e6e6e6; +} +.logwrapper.expanded { + max-height: none; +} +.logwrapper.expanded .logexpander:after { + content: "collapse [-]"; +} +.logwrapper .logexpander { + z-index: 1; + position: sticky; + top: 10px; + width: max-content; + border: 1px solid; + border-radius: 3px; + padding: 5px 7px; + margin: 10px 0 10px calc(100% - 80px); + cursor: pointer; + background-color: #e6e6e6; +} +.logwrapper .logexpander:after { + content: "expand [+]"; +} +.logwrapper .logexpander:hover { + color: #000; + border-color: #000; +} +.logwrapper .log { + min-height: 40px; + position: relative; + top: -50px; + height: calc(100% + 50px); + border: 1px solid #e6e6e6; + color: black; + display: block; + font-family: "Courier New", Courier, monospace; + padding: 5px; + padding-right: 80px; + white-space: pre-wrap; +} + +div.media { + border: 1px solid #e6e6e6; + float: right; + height: 240px; + margin: 0 5px; + overflow: hidden; + width: 320px; +} + +.media-container { + display: grid; + grid-template-columns: 25px auto 25px; + align-items: center; + flex: 1 1; + overflow: hidden; + height: 200px; +} + +.media-container--fullscreen { + grid-template-columns: 0px auto 0px; +} + +.media-container__nav--right, +.media-container__nav--left { + text-align: center; + cursor: pointer; +} + +.media-container__viewport { + cursor: pointer; + text-align: center; + height: inherit; +} +.media-container__viewport img, +.media-container__viewport video { + object-fit: cover; + width: 100%; + max-height: 100%; +} + +.media__name, +.media__counter { + display: flex; + flex-direction: row; + justify-content: space-around; + flex: 0 0 25px; + align-items: center; +} + +.collapsible td:not(.col-links) { + cursor: pointer; +} +.collapsible td:not(.col-links):hover::after { + color: #bbb; + font-style: italic; + cursor: pointer; +} + +.col-result { + width: 130px; +} +.col-result:hover::after { + content: " (hide details)"; +} + +.col-result.collapsed:hover::after { + content: " (show details)"; +} + +#environment-header h2:hover::after { + content: " (hide details)"; + color: #bbb; + font-style: italic; + cursor: pointer; + font-size: 12px; +} + +#environment-header.collapsed h2:hover::after { + content: " (show details)"; + color: #bbb; + font-style: italic; + cursor: pointer; + font-size: 12px; +} + +/*------------------ + * 3. Sorting items + *------------------*/ +.sortable { + cursor: pointer; +} +.sortable.desc:after { + content: " "; + position: relative; + left: 5px; + bottom: -12.5px; + border: 10px solid #4caf50; + border-bottom: 0; + border-left-color: transparent; + border-right-color: transparent; +} +.sortable.asc:after { + content: " "; + position: relative; + left: 5px; + bottom: 12.5px; + border: 10px solid #4caf50; + border-top: 0; + border-left-color: transparent; + border-right-color: transparent; +} + +.hidden, .summary__reload__button.hidden { + display: none; +} + +.summary__data { + flex: 0 0 550px; +} +.summary__reload { + flex: 1 1; + display: flex; + justify-content: center; +} +.summary__reload__button { + flex: 0 0 300px; + display: flex; + color: white; + font-weight: bold; + background-color: #4caf50; + text-align: center; + justify-content: center; + align-items: center; + border-radius: 3px; + cursor: pointer; +} +.summary__reload__button:hover { + background-color: #46a049; +} +.summary__spacer { + flex: 0 0 550px; +} + +.controls { + display: flex; + justify-content: space-between; +} + +.filters, +.collapse { + display: flex; + align-items: center; +} +.filters button, +.collapse button { + color: #999; + border: none; + background: none; + cursor: pointer; + text-decoration: underline; +} +.filters button:hover, +.collapse button:hover { + color: #ccc; +} + +.filter__label { + margin-right: 10px; +} diff --git a/tests/report/test-report.html b/tests/report/test-report.html new file mode 100644 index 0000000..b035eea --- /dev/null +++ b/tests/report/test-report.html @@ -0,0 +1,773 @@ + + +
+ +Report generated on 15-Apr-2026 at 14:44:51 by pytest-html + v4.2.0
+315 tests took 00:00:39.
+(Un)check the boxes to filter the results.
+| Result | +Test | +Duration | +Links | +
|---|
Report generated on 15-Apr-2026 at 14:44:51 by pytest-html - v4.2.0
-315 tests took 00:00:39.
-(Un)check the boxes to filter the results.
-| Result | -Test | -Duration | -Links | -
|---|