Skip to content
Merged
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
4 changes: 4 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@
- __all__ lists must contain only strings, no unpacking or concatenation (PLE0604, PLE0605)
- Catch specific exceptions instead of broad Exception classes (BLE001, S110)
- For functions with many parameters (>5), use `# noqa: PLR0913` comment when needed for convenience functions
- For F401 unused imports in type stubs (under if False), add to __all__
- For N818 exception names, add Error suffix
- For PLR0911 too many return statements, use dict mapping or match to reduce returns
- For SLF001 private member access in tests (e.g., _client), add noqa if necessary for mocking

## Testing

Expand Down
12 changes: 12 additions & 0 deletions .github/openapi-config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
project_name_override: templafy
package_name_override: templafy
literal_enums: true
generate_all_tags: true
post_hooks:
- "ruff check src/templafy --fix"
- "ruff format src/templafy"
field_prefix: attr_
content_type_overrides:
application/vnd.openxmlformats-officedocument.wordprocessingml.document: application/octet-stream
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet: application/octet-stream
application/vnd.openxmlformats-officedocument.presentationml.presentation: application/octet-stream
21 changes: 21 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
# Agent Guidelines

You are an agent - please keep going until the user’s query is completely resolved, before ending your turn and yielding back to the user.

Your thinking should be thorough and so it's fine if it's very long. However, avoid unnecessary repetition and verbosity. You should be concise, but thorough.

You MUST iterate and keep going until the problem is solved.

You have everything you need to resolve this problem. I want you to fully solve this autonomously before coming back to me.

Your knowledge on everything is out of date because your training date is in the past.

Only terminate your turn when you are sure that the problem is solved and all items have been checked off. Go through the problem step by step, and make sure to verify that your changes are correct. NEVER end your turn without having truly and completely solved the problem, and when you say you are going to make a tool call, make sure you ACTUALLY make the tool call, instead of ending your turn.

THE PROBLEM CAN NOT BE SOLVED WITHOUT EXTENSIVE INTERNET RESEARCH.

You must use the context7 mcp tool and fetch_webpage tool to recursively gather all information from URL's provided to you by the user, as well as any links you find in the content of those pages.

You MUST plan extensively before each function call, and reflect extensively on the outcomes of the previous function calls. DO NOT do this entire process by making function calls only, as this can impair your ability to solve the problem and think insightfully.


# CI: pass pre-commit gate before committing

## One-time setup
Expand Down
153 changes: 120 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,58 +1,145 @@
# Python PyPI Package Template
# Templafy API Client

https://api.templafy.com/
A Python client for the Templafy API using openapi-python-client for type-safe, modern Python API access.

A minimal template for creating Python packages with a simple "Hello World" example.
## Overview

This package provides a Python client for the Templafy API, allowing you to programmatically access templates, documents, images, and other assets in your Templafy workspace.

## Installation

```bash
pip install -e .
```

## Quick Start

### 1. Use this template
### Basic Usage

```python
from templafy import AuthenticatedClient
from templafy.api import spaces, documents

# Initialize client
client = AuthenticatedClient(
base_url="https://your-tenant.api.templafy.com/v3",
token="your-api-token"
)

# Use with context manager (recommended)
with client as client:
# List all spaces
all_spaces = spaces.get_spaces(client=client)
print(f"Found {len(all_spaces)} spaces")

# List documents
all_documents = documents.get_documents(client=client)
print(f"Found {len(all_documents)} documents")
```

Click the "Use this template" button on GitHub to create your own repository:
### Available API Endpoints

### 2. Install dependencies
The client provides access to the following Templafy API resources:

```bash
# Run the development setup script
.\tasks\dev_sync.ps1
- **Spaces** - Workspace/tenant management
- **Libraries** - Library management across spaces
- **Documents** - Document template operations and generation
- **Folders** - Folder structure management
- **Images** - Image asset management
- **Slides** - PowerPoint slide management
- **Spreadsheets** - Excel template operations
- **Links** - Link asset management

### Models

The client includes type-safe models for all API resources:

```python
from templafy import Space, Document, Library, Image

# Models are automatically used when calling API methods
spaces = spaces.get_spaces(client=client)
for space in spaces:
print(f"Space: {space.name} (ID: {space.id})")
```

### 3. Customize the package
## API Structure

#### Rename the package
```
templafy/
├── client.py # Base Client and AuthenticatedClient classes
├── models/ # Type-safe models for all schemas
│ ├── space.py # Space-related models
│ ├── document.py # Document-related models
│ ├── library.py # Library-related models
│ └── ...
├── api/ # API endpoint modules by resource
│ ├── spaces.py # Spaces API endpoints
│ ├── documents.py # Documents API endpoints
│ ├── libraries.py # Libraries API endpoints
│ └── ...
├── types.py # Common type definitions
└── errors.py # Error classes and exceptions
```

1. Rename directories:
```bash
mv src/whitelabel src/YOUR_PACKAGE_NAME
mv tests/whitelabel tests/YOUR_PACKAGE_NAME
```
## Error Handling

The client provides specific error classes for different types of API errors:

```python
from templafy.errors import (
AuthenticationError,
AuthorizationError,
NotFoundError,
ValidationError,
RateLimitError,
ServerError
)

try:
documents = documents.get_documents(client=client)
except AuthenticationError:
print("API token is invalid")
except AuthorizationError:
print("Insufficient permissions")
except NotFoundError:
print("Resource not found")
except RateLimitError:
print("Rate limit exceeded")
```

2. Update `pyproject.toml`:
- Change `name = "whitelabel"` to `name = "YOUR_PACKAGE_NAME"`
- Update author information
- Update repository URLs
## Development

3. Update import statements in your code from `whitelabel` to `YOUR_PACKAGE_NAME`
### Dependencies

This project requires Python 3.12+ and the following dependencies:

## Next Steps
- `httpx` - HTTP client
- `pydantic` - Data validation and settings management
- `typing-extensions` - Additional typing features

1. Replace the hello_world function with your own code
2. Add your functions to `src/YOUR_PACKAGE_NAME/functions/`
3. Write tests in `tests/YOUR_PACKAGE_NAME/`
4. Update `pyproject.toml` with your package details
### Testing

## CI/CD Configuration
```bash
python -m pytest tests/ -v
```

### Code Quality

### SonarQube Setup
The project uses `ruff` for linting and formatting:

To enable SonarQube analysis in your CI/CD pipeline, set the following variables:
```bash
ruff check src/templafy --fix
ruff format src/templafy
```

- `SONAR_TOKEN`: Set as a **secret** in your CI/CD platform (authentication token for SonarQube)
- `SONAR_PROJECT_KEY`: Set as an **environment variable** in your CI/CD pipeline (unique key for your project, e.g., `your-org_your-repo`)
## Contributing

`SONAR_HOST_URL` is typically configured at the organization level.
1. Install development dependencies
2. Make your changes
3. Run tests and linting
4. Submit a pull request

## License

MIT License
MIT License - see LICENSE file for details.
18 changes: 9 additions & 9 deletions assets/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@
},
"Name": {
"type": "string",
"description": "The name is inferred from the file name by default. It can be overriden by providing a different value with this field"
"description": "The name is inferred from the file name by default. It can be overridden by providing a different value with this field"
},
"Description": {
"type": "string",
Expand Down Expand Up @@ -810,7 +810,7 @@
},
"Name": {
"type": "string",
"description": "The name is inferred from the file name by default. It can be overriden by providing a different value with this field"
"description": "The name is inferred from the file name by default. It can be overridden by providing a different value with this field"
},
"Description": {
"type": "string",
Expand Down Expand Up @@ -1776,7 +1776,7 @@
},
"Name": {
"type": "string",
"description": "The name is inferred from the file name by default. It can be overriden by providing a different value with this field"
"description": "The name is inferred from the file name by default. It can be overridden by providing a different value with this field"
},
"Description": {
"type": "string",
Expand Down Expand Up @@ -2838,7 +2838,7 @@
},
"Name": {
"type": "string",
"description": "The name is inferred from the file name by default. It can be overriden by providing a different value with this field"
"description": "The name is inferred from the file name by default. It can be overridden by providing a different value with this field"
},
"Description": {
"type": "string",
Expand Down Expand Up @@ -3439,7 +3439,7 @@
},
"Name": {
"type": "string",
"description": "The name is inferred from the file name by default. It can be overriden by providing a different value with this field"
"description": "The name is inferred from the file name by default. It can be overridden by providing a different value with this field"
},
"Description": {
"type": "string",
Expand Down Expand Up @@ -3973,7 +3973,7 @@
},
"Name": {
"type": "string",
"description": "The name is inferred from the file name by default. It can be overriden by providing a different value with this field"
"description": "The name is inferred from the file name by default. It can be overridden by providing a different value with this field"
},
"Description": {
"type": "string",
Expand Down Expand Up @@ -4507,7 +4507,7 @@
},
"Name": {
"type": "string",
"description": "The name is inferred from the file name by default. It can be overriden by providing a different value with this field"
"description": "The name is inferred from the file name by default. It can be overridden by providing a different value with this field"
},
"Description": {
"type": "string",
Expand Down Expand Up @@ -5119,7 +5119,7 @@
},
"Name": {
"type": "string",
"description": "The name is inferred from the file name by default. It can be overriden by providing a different value with this field"
"description": "The name is inferred from the file name by default. It can be overridden by providing a different value with this field"
},
"Description": {
"type": "string",
Expand Down Expand Up @@ -5713,7 +5713,7 @@
},
"Name": {
"type": "string",
"description": "The name is inferred from the file name by default. It can be overriden by providing a different value with this field"
"description": "The name is inferred from the file name by default. It can be overridden by providing a different value with this field"
},
"Description": {
"type": "string",
Expand Down
12 changes: 8 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ requires = [
]

[project]
name = "whitelabel"
description = "A minimal Python package template with a simple Hello World example."
name = "templafy"
description = "A Python client for the Templafy API using openapi-python-client."
readme = "README.md"
license = "MIT"
license-files = [ "LICENSE" ]
Expand All @@ -33,7 +33,10 @@ classifiers = [
"Programming Language :: Python :: 3.13",
]
dynamic = [ "urls", "version" ]
dependencies = [ ]
dependencies = [
"httpx>=0.24.0",
"pydantic>=2.0.0",
]

[dependency-groups]
dev = [
Expand All @@ -44,6 +47,7 @@ dev = [
"ipywidgets>=8.1.7",
"matplotlib>=3.10.3",
"nbstripout>=0.8.1",
"openapi-python-client>=0.15.0",
"perfplot>=0.10.2",
"pip>=25.1.1",
"pre-commit>=4.2.0",
Expand Down Expand Up @@ -74,7 +78,7 @@ source = "vcs"
"Source Archive" = "https://github.com/tonkintaylor/YOUR_REPOSITORY/archive/{commit_hash}.zip"

[tool.hatch.build.hooks.vcs]
version-file = "src/whitelabel/_version.py"
version-file = "src/templafy/_version.py"

[tool.ruff]
line-length = 88
Expand Down
Loading
Loading