diff --git a/.cursor/rules/README.md b/.cursor/rules/README.md new file mode 100644 index 0000000..0c75565 --- /dev/null +++ b/.cursor/rules/README.md @@ -0,0 +1,5 @@ +# Cursor (optional) + +**Cursor** users: start at the repo root **[`AGENTS.md`](../../AGENTS.md)**. All conventions live in **`skills/*/SKILL.md`** (universal for any editor or tool). + +This folder only points contributors here so nothing editor-specific duplicates the canonical docs. diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..929b198 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,67 @@ +# Contentstack Utils Python – Agent guide + +**Universal entry point** for anyone automating or assisting work in this repo—AI agents (Cursor, Copilot, CLI tools), reviewers, and contributors. Conventions and detailed guidance live in **`skills/*/SKILL.md`**, not in editor-specific config, so the same instructions apply whether or not you use Cursor. + +## What this repo is + +- **Name:** [contentstack-utils-python](https://github.com/contentstack/contentstack-utils-python) — **`contentstack_utils`** on PyPI (**Contentstack Python Utils SDK**). +- **Purpose:** Utilities for **Contentstack** headless CMS: **RTE / embedded** rendering (`Utils`, `Options`), **GQL** helpers, **editable tags** on entries, HTML/metadata helpers. Often used alongside the **Contentstack** Python delivery package. +- **Out of scope:** This package does **not** ship HTTP clients or stack credentials. Apps fetch content with the [Content Delivery API](https://www.contentstack.com/docs/developers/apis/content-delivery-api/) / Python SDK, then pass field data into **`Utils`**. + +## Tech stack (at a glance) + +| Area | Details | +|------|---------| +| **Language** | **Python** (`python_requires` in `setup.py`; classifiers list 3.6–3.9; dev tooling in `requirements.txt` may need a newer interpreter) | +| **Package** | **`setuptools`** — `find_packages()`, `contentstack_utils/` | +| **Runtime deps** | **`lxml`** (XML/HTML parsing in `utils.py` and helpers) | +| **Tests** | **pytest** + **pytest-cov**, **pytest-html** (optional HTML report) | +| **Lint / format** | **ruff**, **black**, **flake8**, **isort** (see `requirements.txt`) | + +## Source layout + +| Path | Role | +|------|------| +| `contentstack_utils/utils.py` | **`Utils`** — `render_content`, embedded/RTE flows; extends **`Automate`** | +| `contentstack_utils/render/options.py` | **`Options`** for rendering | +| `contentstack_utils/helper/` | **Metadata**, **NodeToHtml**, **converter** (e.g. `convert_style`) | +| `contentstack_utils/embedded/` | **ItemType**, **StyleType** | +| `contentstack_utils/gql.py` | **GQL** helpers | +| `contentstack_utils/automate.py` | **`Automate`** base for automation-style rendering | +| `contentstack_utils/entry_editable.py` | **`addEditableTags`**, **`addTags`**, **`getTag`**; re-exported via **`Utils`** static methods and package **`__init__`** | +| `contentstack_utils/__init__.py` | Public exports — keep **`__all__`** aligned with documented API | +| `tests/` | pytest modules (`test_*.py`), mocks under `tests/mocks/` | + +## Commands (quick reference) + +```bash +python -m venv .venv && source .venv/bin/activate # or equivalent on Windows +pip install -r requirements.txt +pip install -e . +pytest +pytest --html=tests/test-report/test-report.html --self-contained-html +coverage run -m pytest && coverage report -m +``` + +## Security + +- Do not commit **API keys**, **delivery tokens**, or other secrets. Examples in **`README.md`** use placeholders only. + +## Where the real documentation lives: skills + +Read these **`SKILL.md` files** for full conventions—**this is the source of truth** for implementation and review: + +| Skill | Path | What it covers | +|-------|------|----------------| +| **Development workflow** | [`skills/dev-workflow/SKILL.md`](skills/dev-workflow/SKILL.md) | Branches, CI, venv, **pytest**, ruff/black/flake8, PR expectations | +| **Contentstack Utils (SDK)** | [`skills/contentstack-utils/SKILL.md`](skills/contentstack-utils/SKILL.md) | **`Utils`**, **`Options`**, RTE/embedded, **GQL**, editable tags, JS parity, semver | +| **Python style & layout** | [`skills/python-style/SKILL.md`](skills/python-style/SKILL.md) | Package layout, typing, imports, **`lxml`**, **`setup.py`**, security | +| **Testing** | [`skills/testing/SKILL.md`](skills/testing/SKILL.md) | **pytest** layout, coverage, **`tests/mocks/`**, hygiene | +| **Code review** | [`skills/code-review/SKILL.md`](skills/code-review/SKILL.md) | PR checklist (API, **`__all__`**, deps, tests, secrets) | +| **Framework / integration** | [`skills/framework/SKILL.md`](skills/framework/SKILL.md) | **`lxml`**, companion **Contentstack** Python SDK, dependency boundaries | + +An index with short “when to use” hints is in [`skills/README.md`](skills/README.md). + +## Using Cursor + +If you use **Cursor**, [`.cursor/rules/README.md`](.cursor/rules/README.md) only points to **`AGENTS.md`**—same source of truth as everyone else; no separate `.mdc` rule files. diff --git a/skills/README.md b/skills/README.md new file mode 100644 index 0000000..b42ae39 --- /dev/null +++ b/skills/README.md @@ -0,0 +1,19 @@ +# Skills – Contentstack Utils Python + +**This directory is the source of truth** for conventions (workflow, SDK API, style, tests, review, framework). Read **`AGENTS.md`** at the repo root for the index and quick commands; each skill is a folder with **`SKILL.md`** (YAML frontmatter: `name`, `description`). + +## When to use which skill + +| Skill folder | Use when | +|--------------|----------| +| **dev-workflow** | Branches, CI, venv, **`pip install -e .`**, **pytest**, ruff/black/flake8, PRs | +| **contentstack-utils** | **`Utils`**, **`Options`**, RTE/embedded, **GQL**, editable tags, semver, README | +| **python-style** | `contentstack_utils/` layout, typing, **`lxml`** usage, **`setup.py`** | +| **testing** | **pytest**, coverage, **`tests/mocks/`**, HTML reports | +| **code-review** | PR checklist, public API / **`__all__`**, dependencies, security | +| **framework** | **`lxml`** integration, delivery SDK handoff, parsing impact | + +## How to use these docs + +- **Humans / any AI tool:** Start at **`AGENTS.md`**, then open the relevant **`skills//SKILL.md`**. +- **Cursor users:** **`.cursor/rules/README.md`** only points to **`AGENTS.md`** so guidance stays universal—no duplicate `.mdc` rule sets. diff --git a/skills/code-review/SKILL.md b/skills/code-review/SKILL.md new file mode 100644 index 0000000..014f57a --- /dev/null +++ b/skills/code-review/SKILL.md @@ -0,0 +1,48 @@ +--- +name: code-review +description: PR checklist—public API, __all__, semver, lxml/deps, pytest, secrets; aligns with JS utils where applicable. +--- + +# Code review – Contentstack Utils Python + +## When to use + +- Reviewing a PR, self-review before submit, or automated review prompts. + +## Instructions + +Work through the checklist below. Optionally tag findings: **Blocker**, **Major**, **Minor**. + +### Public API + +- [ ] **`contentstack_utils/__init__.py`** **`__all__`** and exports match **README** examples and intended surface (**`Utils`**, **`Options`**, **`GQL`**, **`Automate`**, embed types, **`addEditableTags`** / **`addTags`** / **`getTag`**). +- [ ] **JS parity** — where methods mirror the JS utils SDK, **parameter names** and behavior stay consistent unless a documented breaking change. + +### Compatibility + +- [ ] No breaking **`Utils`** / **`Options`** / tag helpers without a **semver** plan; **`setup.py` `version`** bumped for user-visible changes. + +### Dependencies + +- [ ] **`lxml`** usage stays bounded to parsing/rendering paths; new **`install_requires`** documented in **README** / changelog. + +### Tests + +- [ ] **`pytest`** passes; tests added or extended under **`tests/`** for new behavior and edge cases. + +### Security + +- [ ] No hardcoded tokens; no logging of secrets in new code. + +### Severity (optional) + +| Level | Examples | +|-------|----------| +| **Blocker** | Breaking public API without approval; security issue; no tests where practical | +| **Major** | Inconsistent behavior vs documented API; README examples wrong | +| **Minor** | Style; minor docs | + +## References + +- **`skills/testing/SKILL.md`** +- **`skills/contentstack-utils/SKILL.md`** diff --git a/skills/contentstack-utils/SKILL.md b/skills/contentstack-utils/SKILL.md new file mode 100644 index 0000000..5ef2f06 --- /dev/null +++ b/skills/contentstack-utils/SKILL.md @@ -0,0 +1,47 @@ +--- +name: contentstack-utils +description: Public API—Utils, Options, RTE/embedded, GQL, editable tags; JS parity; no bundled HTTP client. +--- + +# Contentstack Utils – SDK skill + +## When to use + +- Implementing or changing RTE/HTML rendering, embedded resolution, **GQL**, or editable-tag behavior. +- Updating **`README.md`** / **`changelog.rst`** / **`setup.py`** for user-visible behavior. +- Assessing semver impact of **`__init__.py`** exports and public classes. + +## Core entry points + +- **`Utils`** — **`contentstack_utils.utils`**: **`render_content`**, **`render`**, embedded/RTE resolution; subclasses **`Automate`**. +- **`Options`** — **`contentstack_utils.render.options`**: rendering configuration passed into **`Utils`** methods. +- **Editable tags** — **`entry_editable`**: **`addEditableTags`**, **`addTags`**, **`getTag`**; also exposed as **`Utils.addEditableTags`** / **`Utils.addTags`** / **`Utils.getTag`** for parity. + +## Features + +- **Embedded / RTE** — JSON and HTML paths through **`Utils`** and **`Automate`**; **metadata** via **`Metadata`**. +- **Styles** — **`convert_style`** and **embedded** **StyleType** / **ItemType** where applicable. +- **GQL** — **`GQL`** in **`gql.py`** for GraphQL-oriented HTML/helpers. + +## Public API and docs + +- **`contentstack_utils/__init__.py`** **`__all__`** and exports must match **README** examples and intended surface (**`Utils`**, **`Options`**, **`GQL`**, **`Automate`**, embed types, tag helpers). +- **JS parity** — where methods mirror the JS utils SDK, keep **parameter names** and behavior consistent unless a documented breaking change. + +## Compatibility + +- Avoid breaking **`Utils`** / **`Options`** / tag helpers without a **semver** plan; bump **`setup.py` `version`** for user-visible changes. + +## Dependencies + +- **`lxml`** usage stays bounded to parsing/rendering paths; note any new **`install_requires`** in **README** / changelog if added to **`setup.py`**. + +## No network layer + +- This package does **not** ship HTTP clients or tokens. +- Consumers often use **`contentstack.Stack`** (**Contentstack** package) to fetch entries, then **`Utils.render`** / **`Utils.render_content`** — keep **README** examples accurate. + +## References + +- [Content Delivery API](https://www.contentstack.com/docs/developers/apis/content-delivery-api/) +- **`skills/python-style/SKILL.md`**, **`skills/framework/SKILL.md`** diff --git a/skills/dev-workflow/SKILL.md b/skills/dev-workflow/SKILL.md new file mode 100644 index 0000000..355379e --- /dev/null +++ b/skills/dev-workflow/SKILL.md @@ -0,0 +1,27 @@ +--- +name: dev-workflow +description: Branches, CI, venv, pytest, lint—standard workflow for Contentstack Utils Python. +--- + +# Development workflow – Contentstack Utils Python + +## When to use + +- Setting up locally, opening a PR, or aligning with CI. +- Answering “how do we run tests?” or “which branch targets `master`?” + +## Before a PR + +1. **Install** — `pip install -r requirements.txt` and `pip install -e .` in a virtual environment. +2. **`pytest`** — full suite under **`tests/`** must pass. +3. **Lint / format** — run **ruff**, **black**, **flake8**, **isort** as configured for the repo (see **`requirements.txt`**). +4. **Version** — update **`setup.py` `version`** for releases per semver. + +## Branching + +- Follow org conventions: **`development`** / **`staging`** / **`master`**; PRs to **`master`** may be restricted (see **`.github/workflows/check-branch.yml`**). Confirm with your team before opening PRs to **`master`**. + +## Links + +- **`AGENTS.md`** — commands and layout overview. +- **`skills/code-review/SKILL.md`** — pre-merge checklist. diff --git a/skills/framework/SKILL.md b/skills/framework/SKILL.md new file mode 100644 index 0000000..5ebb98a --- /dev/null +++ b/skills/framework/SKILL.md @@ -0,0 +1,30 @@ +--- +name: framework +description: lxml parsing layers, setup.py install_requires, companion Contentstack Python SDK handoff. +--- + +# Framework / integration – Contentstack Utils Python + +## When to use + +- Changing HTML/XML parsing behavior or **`lxml`** touchpoints. +- Adding runtime dependencies or documenting **`install_requires`**. + +## Integration points + +- **`lxml.etree`** — parsing and tree operations in **`utils.py`** and related helpers; errors should remain predictable for malformed HTML/XML inputs. +- **Contentstack delivery SDK** — consumers fetch **`entry`** data with **`contentstack.Stack`**, then pass fields into **`Utils.render`** / **`Utils.render_content`** with **`Options`**. + +## When to change + +- **Parsing behavior** — verify impact on **RTE** output and existing **`tests/`** fixtures. +- **New dependencies** — add to **`setup.py` `install_requires`** and document; prefer stdlib or existing stack (**`lxml`** already required). + +## Testing + +- **Unit** — **`tests/test_*.py`** with mocks under **`tests/mocks/`** where applicable. + +## References + +- **`skills/python-style/SKILL.md`** +- **`skills/dev-workflow/SKILL.md`** diff --git a/skills/python-style/SKILL.md b/skills/python-style/SKILL.md new file mode 100644 index 0000000..5ef92e6 --- /dev/null +++ b/skills/python-style/SKILL.md @@ -0,0 +1,41 @@ +--- +name: python-style +description: Python layout for contentstack_utils, typing, lxml usage, setup.py, packaging. +--- + +# Python style and repo layout – Contentstack Utils Python + +## When to use + +- Editing any Python under **`contentstack_utils/`** or **`setup.py`**. +- Adding modules or changing how **`lxml`** is used. + +## Layout + +- **`contentstack_utils/utils.py`** — **`Utils`** class (rendering, embedded items); delegates **editable tag** static methods to **`entry_editable`**. +- **`contentstack_utils/render/`** — **`Options`** and render-related code. +- **`contentstack_utils/helper/`** — **Metadata**, **NodeToHtml**, **converter**. +- **`contentstack_utils/embedded/`** — **ItemType**, **StyleType**. +- **`contentstack_utils/gql.py`**, **`automate.py`**, **`entry_editable.py`** — feature modules. + +## Style + +- Match existing patterns: **typing** hints where already used; **pylint** pragmas only where established. +- Prefer **small, focused** changes; avoid drive-by refactors unrelated to the task. + +## Imports + +- **`lxml.etree`** — HTML/XML parsing in **`utils`** and helpers; keep usage consistent with existing error handling. + +## Packaging + +- **`setup.py`** — **`name`**, **`version`**, **`packages=find_packages()`**; keep **`install_requires`** accurate if dependencies change. + +## Security + +- Do not log **delivery tokens**, **API keys**, or stack secrets. + +## References + +- **`skills/contentstack-utils/SKILL.md`** — public API and features. +- **`skills/framework/SKILL.md`** — **`lxml`** and SDK integration. diff --git a/skills/testing/SKILL.md b/skills/testing/SKILL.md new file mode 100644 index 0000000..ae9fd06 --- /dev/null +++ b/skills/testing/SKILL.md @@ -0,0 +1,38 @@ +--- +name: testing +description: pytest—layout, coverage, tests/mocks, HTML reports; offline fixtures. +--- + +# Testing – Contentstack Utils Python + +## When to use + +- Adding or changing tests under **`tests/`**. +- Debugging flaky tests; improving mocks or fixtures. + +## Commands + +| Goal | Command | +|------|---------| +| Full suite | `pytest` | +| HTML report | `pytest --html=tests/test-report/test-report.html --self-contained-html` | +| Coverage (example) | `coverage run -m pytest && coverage report -m` | + +## Layout + +- **`tests/test_*.py`** — feature-focused modules (**utils**, **GQL**, **metadata**, **editable tags**, etc.). +- **`tests/mocks/`** — shared fixture-style data; extend for new scenarios instead of duplicating large JSON. + +## Setup + +- Install **`requirements.txt`** in a venv; **`pip install -e .`** for editable package tests. + +## Hygiene + +- No committed **`pytest.mark.skip`** or **`xfail`** without justification; no **`breakpoint()`** left in CI paths. +- No API keys or real tokens in tests. + +## References + +- **`skills/dev-workflow/SKILL.md`** +- **`skills/code-review/SKILL.md`**