Skip to content

Commit 147df2b

Browse files
Merge pull request #1248 from gooddata/snapshot-master-8c301641-to-rel/dev
[bot] Merge master/8c301641 into rel/dev
2 parents 5efe260 + 8c30164 commit 147df2b

File tree

9 files changed

+357
-1
lines changed

9 files changed

+357
-1
lines changed

.cursor/rules/cursor/rules.mdc

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
---
2+
description: How to create or update Cursor rule files - minimal templates and standards
3+
alwaysApply: false
4+
---
5+
6+
# Creating and Updating Cursor Rules
7+
8+
## Folder Structure
9+
10+
- `.cursor/rules/general/` - General rules (always applied)
11+
- `.cursor/rules/packages/` - Package-specific rules
12+
- `.cursor/rules/technologies/` - Technology rules (Python, testing)
13+
- `.cursor/rules/cursor/` - Cursor workflow and meta-rules
14+
15+
## Rule Creation Process
16+
17+
1. **Ask for clarification** if codebase location unclear
18+
2. **Investigate the codebase** relevant to the rule
19+
3. **Look at similar existing rules** as examples (better than templates)
20+
4. **Keep it minimal** - target 25-40 lines max
21+
5. **Focus on proprietary knowledge** - not generic patterns
22+
23+
## Updating Existing Rules
24+
25+
**CRITICAL**: Be MINIMAL. Add only what prevents actual errors.
26+
27+
**DO (Minimal):**
28+
```python
29+
# Just the pattern that fixes the error
30+
from typing import TYPE_CHECKING, Any
31+
if TYPE_CHECKING:
32+
Context = MCPContext[Any, Any, Any]
33+
```
34+
35+
**DON'T (Verbose):**
36+
- ❌ Pattern explanations (why it works, alternatives, trade-offs)
37+
- ❌ Multiple examples (good vs bad, before vs after)
38+
- ❌ Best practices unrelated to errors
39+
- ❌ Prose explanations ("Why:", "Note:", paragraphs)
40+
- ❌ Decision matrices or tables (unless critical for error prevention)
41+
- ❌ Checklists (unless they prevent actual errors)
42+
- ❌ Step-by-step tutorials
43+
- ❌ Verbose "correct vs wrong" comparisons
44+
45+
**Rule of thumb**: If it didn't cause a validation error, don't add it.
46+
47+
**Target length**: 25-40 lines. If over 50 lines, too verbose.
48+
49+
## Rule Structure
50+
51+
**Essential sections:**
52+
- Description header (1 line)
53+
- Owns / Does NOT Own (clear boundaries)
54+
- Critical constraints (if any)
55+
- Dependencies
56+
57+
## Rule Header Format
58+
59+
```markdown
60+
---
61+
description: {Brief - used by Cursor for rule selection}
62+
alwaysApply: false # (true only for general rules)
63+
---
64+
```
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
---
2+
description: Cursor IDE workflow validation and rule management
3+
alwaysApply: true
4+
---
5+
6+
# Cursor IDE Workflow Validation
7+
8+
## Workflow Constraints
9+
10+
- Include all rules related to the user question; if rules mention dependencies, include those too.
11+
- After fully answering, report the list of used rules.
12+
- Example: **Used rules**: general/general, technologies/python, packages/gooddata-sdk
13+
- Do not print rule previews or long plans.
14+
- Keep status updates to one short sentence.
15+
- Never inline full rule contents; reference by rule path only when needed.
16+
17+
## Rule Search
18+
19+
Always look for relevant cursor rules based on the character of changes.

.cursor/rules/general/general.mdc

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
---
2+
alwaysApply: true
3+
---
4+
5+
# GoodData Python SDK Coding Guidelines
6+
7+
Applies to all packages and code in this Python SDK workspace.
8+
Think in steps before changes. Search for relevant cursor rules based on the character of changes.
9+
10+
## Core Principles
11+
12+
**Search first, don't invent**: Always search this repository for everything related to the developer question. **Do not invent a new design for something that already exists!**
13+
14+
**Code Principles**: **1** Simplicity, **2** Readability, **3** Performance (don't over-optimize), **4** Maintainability, **5** Testability, **6** Reusability, **7** Encapsulation & single responsibility
15+
16+
## ⚠️ CRITICAL: AI Behavior Rules - ALWAYS ENFORCE
17+
18+
**NO AUTO-IMPLEMENTATION**:
19+
- Do not generate code changes unless user explicitly asks for it
20+
- NEVER create summary/documentation markdown files unless explicitly requested
21+
- Break complex tasks into smaller deliverable units
22+
23+
**For complex tasks**:
24+
1. Implement ONLY the first task, then STOP
25+
2. Ask permission to continue, offering: (a) next task only, or (b) all remaining tasks
26+
3. Create todos but DO NOT auto-implement them
27+
4. When in doubt, ask before implementing
28+
29+
## Code Validation
30+
31+
**If gdc-ruler MCP server is available**: Use `validate_python` tool with this workspace path.
32+
```
33+
validate_python(path=".") # From workspace root
34+
```
35+
36+
**Otherwise**: Run manually:
37+
```bash
38+
make format-fix && make mypy && make test
39+
```
40+
41+
**Scoped testing**: `TEST_ENVS=py312 ADD_ARGS="-k test_name" make test`
42+
43+
See `technologies/testing` rule for VCR cassette workflow.
44+
45+
## Package Structure
46+
47+
**Workspace packages** (in `packages/`):
48+
- `gooddata-sdk` - Core SDK for GoodData Cloud
49+
- `gooddata-pandas` - Pandas integration layer
50+
- `gooddata-dbt`, `gooddata-flight-server`, `gooddata-flexconnect`, `gooddata-pipelines`
51+
- `tests-support` - Shared test utilities
52+
53+
**Generated clients** (do NOT edit manually):
54+
- `gooddata-api-client` - Generated from OpenAPI specs
55+
56+
## Dependencies
57+
58+
**Internal**: Use `~={current_version}` for package dependencies.
59+
60+
**Adding**: Add to `pyproject.toml`, run `uv lock`.
61+
62+
## OpenAPI Client Generation
63+
64+
**DO NOT manually edit** generated client code in `gooddata-*-client/` directories.
65+
66+
See `.openapi-generator/README.md` for regeneration instructions.
67+
68+
## Fast-Changing Dependencies
69+
70+
**When suggesting third-party libraries**: Verify current APIs, prefer established libraries, check Python 3.10+ compatibility.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
---
2+
description: GoodData Pandas package - pandas integration layer for GoodData SDK
3+
alwaysApply: false
4+
---
5+
6+
# GoodData Pandas Package
7+
8+
**Location**: `packages/gooddata-pandas/`
9+
10+
## Owns
11+
12+
- Pandas Series and DataFrame creation from GoodData data
13+
- Integration layer between GoodData SDK and pandas
14+
15+
## Does NOT Own
16+
17+
- Core SDK functionality → gooddata-sdk package
18+
19+
## Architecture
20+
21+
**Dependency**: Depends on `gooddata-sdk` core package.
22+
23+
**Main class**: `GoodPandas` - extends SDK with pandas-specific operations
24+
25+
## Usage
26+
27+
```python
28+
from gooddata_pandas import GoodPandas
29+
30+
gp = GoodPandas(host="https://example.gooddata.com", token="...")
31+
df = gp.data_frames(workspace_id="demo", insight_id="...")
32+
```
33+
34+
## Dependencies
35+
36+
Required: technologies/python, packages/gooddata-sdk
37+
Related: technologies/testing
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
---
2+
description: GoodData SDK core package - primary interface for GoodData Cloud
3+
alwaysApply: false
4+
---
5+
6+
# GoodData SDK Package
7+
8+
**Location**: `packages/gooddata-sdk/`
9+
10+
## Owns
11+
12+
- Core SDK client (`GoodDataSdk`) - main entry point
13+
- Catalog services (workspaces, data sources, users, permissions)
14+
- Compute services (execution, caching, export)
15+
- Visualization services (insights, dashboards)
16+
- Declarative API support (layout export/import)
17+
- Model management (LDM, PDM operations)
18+
19+
## Does NOT Own
20+
21+
- Pandas integration → gooddata-pandas package
22+
- dbt integration → gooddata-dbt package
23+
- Flight server → gooddata-flight-server package
24+
- API client generation → gooddata-api-client (generated)
25+
26+
## Architecture
27+
28+
**Service-based**: `catalog_*`, `compute_*`, `insights_*`, `tables_*`
29+
30+
**Depends on**: `gooddata-api-client` (generated OpenAPI client)
31+
32+
## SDK Usage
33+
34+
```python
35+
from gooddata_sdk import GoodDataSdk
36+
37+
sdk = GoodDataSdk.create(host="https://example.gooddata.com", token="...")
38+
workspaces = sdk.catalog_workspace.list_workspaces()
39+
```
40+
41+
## Testing
42+
43+
Uses vcrpy cassettes. See `technologies/testing` rule for workflow.
44+
45+
## Dependencies
46+
47+
Required: technologies/python, technologies/testing
48+
Related: packages/gooddata-pandas
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
---
2+
description: Python development - mypy-clean code patterns
3+
alwaysApply: false
4+
---
5+
6+
# Python Development
7+
8+
**Goal:** Ship mypy-clean code on first pass. No "write → validate → fix" loops.
9+
10+
**Supported versions**: Python 3.10 and higher
11+
12+
## Imports
13+
14+
**Absolute imports only.** Relative imports break monorepo navigation.
15+
```python
16+
from gooddata_sdk.client import GoodDataSdk # ✅
17+
from .client import GoodDataSdk # ❌
18+
```
19+
20+
**All imports at top of file.** After docstring and `from __future__ import annotations`.
21+
22+
## Type-first Habits
23+
24+
- Every def + local (esp empty list/dict/set) annotated; dataclasses fully typed.
25+
- Use `from __future__ import annotations` for forward references.
26+
- Guard external data (YAML/JSON) as `Any` then narrow types.
27+
28+
## External Data (YAML/JSON)
29+
30+
```python
31+
raw = yaml.safe_load(handle)
32+
if not isinstance(raw, dict):
33+
raise ValueError("expected mapping")
34+
cfg: dict[str, object] = {str(k): v for k, v in raw.items()}
35+
```
36+
37+
## Casts / Guards
38+
39+
- Single authoritative `cast(...)` + reuse variable
40+
- Guard pattern: `if isinstance(mode_raw, str): mode = mode_raw else: raise ValueError("...")`
41+
- `typing.assert_never` for exhaustive branches
42+
43+
## Validation flow (If MCP server installed)
44+
- Python-only chores: `validate_python(path)` (format, lint, types, test).
45+
- Mixed stacks: run Python + Kotlin validators separately; skip umbrella `validate` until new classifier routing lands.
46+
47+
## Documentation
48+
49+
**Google-style docstrings** for all public APIs.
50+
51+
## Dependencies
52+
53+
Required: general/general
54+
Related: technologies/testing, packages/*
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
---
2+
description: Validation and testing - VCR cassettes for HTTP snapshots
3+
alwaysApply: false
4+
---
5+
6+
# Validation & Testing
7+
8+
## Validation Flow
9+
10+
**If gdc-ruler MCP server is available**:
11+
```
12+
validate_python(path=".") # Full validation
13+
validate_python(path=".", steps=["format", "lint"]) # Quick check
14+
```
15+
16+
**Manual commands** (from workspace root):
17+
```bash
18+
make format-fix # ruff format + fix
19+
make mypy # Type check (aliased as `make types`)
20+
make test # pytest via tox (all Python versions)
21+
```
22+
23+
**Scoped**:
24+
```bash
25+
TEST_ENVS=py312,py313 make test # Specific Python versions
26+
ADD_ARGS="-k test_catalog" make test # Filter tests
27+
RECREATE_ENVS=1 make test # Force tox rebuild
28+
```
29+
30+
**CI-like**: `make test-ci` (Docker-based)
31+
32+
## VCR Cassettes (HTTP Snapshots)
33+
34+
**Purpose**: Record GoodData Cloud HTTP calls for reproducible tests.
35+
36+
**Update workflow** (when API changes):
37+
```bash
38+
docker-compose up # Start local GoodData Cloud
39+
make remove-cassettes # Delete old fixtures
40+
make test # Generates new cassettes
41+
git add tests/**/fixtures/*.yaml
42+
```
43+
44+
**Location**: `tests/**/fixtures/*.yaml`
45+
46+
## Test Pattern
47+
48+
```python
49+
@vcr.use_cassette("tests/catalog/fixtures/test_workspace.yaml")
50+
def test_get_workspace(sdk):
51+
workspace = sdk.catalog_workspace.get_workspace("demo")
52+
assert workspace.id == "demo"
53+
```
54+
55+
## Dependencies
56+
57+
Required: technologies/python
58+
Related: general/general

Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,12 @@ download:
7070
.PHONY: mypy
7171
mypy:
7272
RESULT=0; \
73-
for project in $(NO_CLIENT_GD_PROJECTS_DIRS); do $(MAKE) -C packages/$${project} $@ || RESULT=$$?; done; \
73+
for project in $(NO_CLIENT_GD_PROJECTS_DIRS); do $(MAKE) -C packages/$${project} mypy || RESULT=$$?; done; \
7474
exit $$RESULT
7575

76+
.PHONY: types
77+
types: mypy
78+
7679
.PHONY: test
7780
test:
7881
RESULT=0; \

project_common.mk

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ format-fix:
4040
mypy:
4141
uv run tox $(TOX_FLAGS) -e mypy
4242

43+
.PHONY: types
44+
types: mypy
45+
4346
.PHONY: test
4447
test:
4548
uv run tox -v $(TOX_FLAGS) $(LOCAL_TEST_ENVS) $(LOCAL_ADD_ARGS)

0 commit comments

Comments
 (0)