# Documentation Conventions

This document defines documentation and writing standards for the Pinecone Python SDK.

## Writing Voice

### Persona and Tone

Write as a **peer helping another developer solve a problem**, not as a lecturer or salesperson. Focus on practical outcomes rather than theory.

- Use second person ("you") when addressing the reader in user-facing documentation
- Be collegial but factual - avoid both stuffiness and excessive casualness
- Explain difficult concepts without condescension
- Show, don't tell - demonstrate with code rather than abstract descriptions

### Core Principles

1. **Clarity over cleverness**: Write to be understood, not to impress
2. **Factual and objective**: Present information factually. Avoid self-praise and unsupported claims
3. **Active voice**: "The client sends a request" not "A request is sent by the client"
4. **Concise**: Remove unnecessary words without sacrificing clarity
5. **Specific**: Use concrete examples over abstract descriptions
6. **Plain language**: No flowery or nebulous adjectives. Choose precise words that convey meaning directly

### Sentence Structure

- Keep sentences short (15-20 words average)
- Use basic subject-verb-object construction
- One idea per sentence
- Use simple words: "use" not "utilize", "help" not "facilitate"
- Avoid chains of prepositional phrases and multiple dependent clauses
- Use simple punctuation - reserve em dashes for strong emphasis only
- Break up long paragraphs (3-5 sentences maximum)

## Timeless Content

Write documentation that remains accurate and relevant over time. Avoid language that will become stale.

### Avoid Time References

**Don't use:**
- Specific dates or years: "as of 2024", "in January 2025"
- Temporal phrases: "recently", "lately", "soon", "coming soon"
- Novelty language: "new", "newly released", "latest", "modern"
- Hype words: "cutting-edge", "state-of-the-art", "revolutionary"

**Do use:**
- Evergreen descriptions: "This method queries vectors"
- Factual statements: "The SDK supports batch operations"
- Current tense: "The client connects to the API"

### Examples

```python
# ❌ BAD: Time-sensitive language
"""
Query vectors using our new parallel processing feature.
This recently added capability provides cutting-edge performance
as of version 3.0, released in 2024.
"""

# ✅ GOOD: Timeless description
"""
Query vectors with parallel processing for improved performance.
"""

# ❌ BAD: References version in prose
"""
The latest upsert method now supports batching.
"""

# ✅ GOOD: Describes capability without timeline
"""
Upsert vectors in batches for efficient bulk operations.
"""
```

### When Time/Version Info Is Appropriate

There are specific contexts where dates and versions are necessary:

1. **Changelog and release notes**: Document what changed and when
   ```markdown
   ## [3.0.0] - 2024-01-15
   ### Added
   - Batch upsert support
   ```

2. **API reference annotations**: Help users understand compatibility
   ```python
   def batch_upsert(self, vectors: List[Vector]) -> UpsertResponse:
       """Upsert vectors in batches.
       
       .. versionadded:: 3.0.0
       """
   ```

3. **Migration guides**: Explain version transitions
   ```markdown
   # Migrating from 2.x to 3.x
   
   In version 3.0, the client initialization changed...
   ```

4. **Deprecation notices**: Specify timeline for removal
   ```python
   @deprecated(version="3.0.0", removal="4.0.0")
   def legacy_query(self, vector):
       """Query vectors (deprecated).
       
       .. deprecated:: 3.0.0
          Use :meth:`query` instead. Will be removed in 4.0.0.
       """
   ```

### Focus on Capabilities, Not Marketing

```python
# ❌ BAD: Marketing language with time references
"""
Experience the blazingly fast performance of our newly redesigned
state-of-the-art vector search, now available in the latest release.
"""

# ✅ GOOD: Factual capability description
"""
Search for similar vectors using approximate nearest neighbor algorithms.
Returns results sorted by similarity score.
"""
```

### Good vs Bad Examples

```python
# ❌ BAD: Passive voice, wordy
"""
A request is made to the API endpoint by the client, and the response
that is returned will be processed and the data will be extracted.
"""

# ✅ GOOD: Active voice, concise
"""
The client sends a request to the API and processes the response data.
"""

# ❌ BAD: Flowery language, self-praise
"""
Our powerful and intuitive SDK makes it incredibly easy to leverage
the amazing capabilities of vector search.
"""

# ✅ GOOD: Factual, objective
"""
The SDK provides methods to insert, query, and manage vectors.
"""

# ❌ BAD: Vague, abstract
"""
This method facilitates the retrieval of semantically similar entities.
"""

# ✅ GOOD: Concrete, clear
"""
This method finds vectors similar to your query vector.
"""
```

## Docstring Conventions

### Format: Google Style

Use Google-style docstrings for all public APIs:

```python
def query(self, vector: List[float], top_k: int = 10, namespace: str = "") -> QueryResponse:
    """Query vectors by similarity.

    Finds the top_k most similar vectors in the specified namespace.
    Returns results sorted by descending similarity score.

    Args:
        vector: Query vector as a list of floats
        top_k: Number of results to return (default: 10)
        namespace: Namespace to query (default: "" for default namespace)

    Returns:
        QueryResponse containing matches with ids, scores, and metadata

    Raises:
        PineconeException: If the request fails
        ValueError: If vector dimensions don't match index dimensions

    Examples:
        Basic query:
        >>> from pinecone import Pinecone
        >>> pc = Pinecone(api_key="your-api-key")
        >>> index = pc.Index("example-index")
        >>> results = index.query(vector=[0.1, 0.2, 0.3], top_k=5)
        >>> print(results.matches[0].id)
        'vec1'

        Query with filtering:
        >>> results = index.query(
        ...     vector=[0.1, 0.2, 0.3],
        ...     top_k=5,
        ...     filter={"category": "electronics"}
        ... )
    """
```

### Required Sections

- **Summary line**: One-line description of what the method does (imperative mood)
- **Args**: Document all parameters with types and descriptions
- **Returns**: Describe return value and its type
- **Raises**: Document exceptions that can be raised
- **Examples**: At least one concrete, runnable example

### Optional Sections

- **Note**: Important clarifications or caveats
- **Warning**: Critical information about potential issues
- **See Also**: Links to related methods or documentation

### Type Information

Include type information in docstrings even when type hints exist. This ensures documentation is clear when viewed outside the source code.

## Documentation Structure

### Standard Organization

1. **What**: Brief description of functionality (1-2 sentences)
2. **Why**: Motivation or context (when not obvious)
3. **How**: Usage examples (simple to complex)
4. **Reference**: Detailed parameter descriptions

### Progressive Disclosure

Start simple, add complexity gradually:

```python
def upsert(
    self,
    vectors: List[Tuple[str, List[float]]],
    namespace: str = "",
    batch_size: int = 100
) -> UpsertResponse:
    """Upsert vectors into the index.

    Inserts new vectors or updates existing ones by ID.

    Args:
        vectors: List of (id, values) tuples
        namespace: Target namespace (default: default namespace)
        batch_size: Vectors per batch request (default: 100)

    Returns:
        UpsertResponse with count of vectors upserted

    Examples:
        Simple upsert:
        >>> vectors = [("id1", [0.1, 0.2]), ("id2", [0.3, 0.4])]
        >>> response = index.upsert(vectors)
        >>> print(response.upserted_count)
        2

        Upsert with metadata:
        >>> from pinecone import Vector
        >>> vectors = [
        ...     Vector(id="id1", values=[0.1, 0.2], metadata={"category": "A"}),
        ...     Vector(id="id2", values=[0.3, 0.4], metadata={"category": "B"})
        ... ]
        >>> response = index.upsert(vectors)

        Upsert to specific namespace:
        >>> response = index.upsert(vectors, namespace="production")
    """
```

## Code Examples

### Requirements

1. **Runnable**: Examples must be valid Python code that actually works
2. **Complete**: Include necessary imports
3. **Realistic**: Use realistic variable names and scenarios
4. **Tested**: All examples should be validated (ideally as tests)

### Standard Patterns

```python
# ✅ GOOD: Complete example with imports
"""
Examples:
    >>> from pinecone import Pinecone
    >>> pc = Pinecone(api_key="your-api-key")
    >>> index = pc.Index("example-index")
    >>> results = index.query(vector=[0.1, 0.2, 0.3], top_k=5)
"""

# ❌ BAD: Incomplete, unclear where objects come from
"""
Examples:
    >>> results = query([0.1, 0.2, 0.3], 5)
"""
```

### Variable Naming in Examples

- Use `pc` for Pinecone client instances
- Use `index` for Index instances
- Use descriptive names for domain objects: `results`, `response`, `vectors`
- Avoid single letters unless in mathematical contexts

### Error Handling in Examples

Include error handling when:
- The operation can commonly fail
- The example demonstrates error handling patterns
- Recovery strategies exist

```python
"""
Examples:
    With error handling:
    >>> try:
    ...     results = index.query(vector=[0.1, 0.2])
    ... except PineconeException as e:
    ...     print(f"Query failed: {e}")
    ...     results = None
"""
```

## API Documentation

### Method Documentation

Document methods in this order:
1. What it does (first line)
2. Important behavior or constraints
3. Parameters
4. Return value
5. Exceptions
6. Examples (simple → advanced)

### Parameter Documentation

For each parameter, include:
- Type (even if type-hinted)
- Purpose/meaning
- Default value and its significance
- Valid ranges or constraints
- Common values or patterns

### Return Value Documentation

Specify:
- Type of return value
- Structure of complex objects
- Possible states or variations
- How to interpret the value

## Testing Documentation

All code examples in documentation should be:
1. Syntactically valid
2. Semantically correct (would work if API key was valid)
3. Tested via doctest or example tests
4. Updated when APIs change

## Anti-Patterns

### Avoid These

❌ **Redundant docstrings**:
```python
def get_name(self) -> str:
    """Get name."""  # Adds no value
```

❌ **Implementation details**:
```python
def query(self, vector):
    """Query vectors using numpy dot product and heap sort."""  # Too specific
```

❌ **Placeholder text**:
```python
def foo(self):
    """TODO: Write this."""  # Don't commit TODOs in public APIs
```

❌ **Overly technical jargon**:
```python
"""Leverages a distributed approximate nearest neighbor algorithm."""
# vs
"""Finds similar vectors using approximate search."""
```

❌ **Promotional language or unsupported claims**:
```python
"""Our blazingly fast, industry-leading vector database."""  # Marketing, not documentation
# vs
"""A vector database for similarity search."""
```

❌ **Vague or flowery descriptions**:
```python
"""Seamlessly orchestrates the harmonious flow of vector operations."""
# vs
"""Coordinates vector insert and query operations."""
```

❌ **Time-sensitive or novelty language**:
```python
"""Our recently released cutting-edge feature (new in 2024)."""
# vs
"""Batch upsert support for efficient bulk operations."""
```

### Do This Instead

✅ **Value-adding docstrings**:
```python
def get_name(self) -> str:
    """Return the index name.

    The name is immutable after index creation.
    """
```

✅ **User-focused descriptions**:
```python
def query(self, vector):
    """Find similar vectors.

    Returns the most similar vectors sorted by score.
    """
```

## Markdown Documentation

### File Organization

- Use ATX-style headers (`#` not underlines)
- One blank line before and after headers
- Two blank lines between major sections
- Code blocks must specify language

### Links

Use relative links for internal documentation:
```markdown
See [API Structure](./api-structure.md) for details.
```

### Code Blocks

Always specify the language:
````markdown
```python
from pinecone import Pinecone
```
````

### Lists

- Use `-` for unordered lists (not `*` or `+`)
- Use `1.` numbering for ordered lists
- Indent nested lists with 2 spaces
- Add blank line before and after lists

## Comments in Code

### When to Comment

**Do comment when:**
- The "why" is not obvious from the code
- There's a subtle bug or edge case to be aware of
- The code works around a limitation or quirk
- There's important historical context

**Don't comment when:**
- The code is self-explanatory
- The comment just repeats the code
- Type hints or docstrings already cover it

### Good vs Bad Comments

```python
# ❌ BAD: States the obvious
# Increment counter
counter += 1

# ❌ BAD: Outdated or wrong
# This will never be None (but it can be!)
if value is not None:
    ...

# ✅ GOOD: Explains why
# Batch size limited to 100 due to API gateway timeout constraints
batch_size = min(batch_size, 100)

# ✅ GOOD: Warns about edge case
# Empty namespace means "default namespace" in API v2+
namespace = namespace or ""
```

## Sphinx Documentation

This project uses Sphinx to generate API documentation from docstrings.

### Building Documentation Locally

Build the HTML documentation:

```bash
cd docs
make html
```

View the documentation by opening `docs/_build/html/index.html` in a browser.

Other useful commands:

```bash
make clean       # Remove build artifacts
make doctest     # Test code examples in docstrings
make linkcheck   # Verify all links work
make coverage    # Check documentation coverage
```

### Documentation Structure

```
docs/
├── conf.py              # Sphinx configuration
├── index.rst            # Landing page
├── api/                 # API reference (auto-generated from docstrings)
│   ├── client.rst       # Pinecone (sync client)
│   ├── async_client.rst # AsyncPinecone
│   ├── inference.rst    # Inference API
│   ├── models.rst       # Data models
│   └── exceptions.rst   # Exception hierarchy
├── guides/              # User guides (Markdown)
│   ├── quickstart.md
│   ├── configuration.md
│   └── error-handling.md
└── _static/             # Custom CSS and assets
    └── custom.css
```

### Adding New API Documentation

When adding new public APIs, update the appropriate RST file in `docs/api/`:

1. **New client methods**: Add to `docs/api/client.rst` or `docs/api/async_client.rst`
2. **New inference methods**: Add to `docs/api/inference.rst` or `docs/api/async_inference.rst`
3. **New models**: Add to `docs/api/models.rst`
4. **New exceptions**: Add to `docs/api/exceptions.rst`

Example of adding a new class to documentation:

```rst
.. autoclass:: pinecone.MyNewClass
   :members:
   :show-inheritance:
```

### Autodoc Behavior

Sphinx's autodoc extension automatically generates documentation from docstrings:

- **Included**: All public APIs in `pinecone/` package
- **Excluded**: Modules in `pinecone/_internal/` and `pinecone/__interface__/`
- **Private members**: Methods starting with `_` are excluded (except `__init__`)

The configuration in `docs/conf.py` handles this automatically.

### Testing Examples

All code examples in docstrings should work. Test them with:

```bash
cd docs
make doctest
```

This runs all `>>>` examples in docstrings and verifies they produce expected output.

### Continuous Integration

GitHub Actions automatically:

1. Builds documentation on every PR
2. Fails if there are warnings or errors
3. Runs doctest to verify examples
4. Checks documentation coverage

Documentation must build successfully before PRs can be merged.

## Review Checklist

Before committing documentation:

- [ ] Voice is clear, active, and concise
- [ ] Tone is collegial peer-to-peer (uses "you" in user-facing docs)
- [ ] Writing is factual and objective (no promotional language or unsupported claims)
- [ ] Language is plain and direct (no flowery or vague descriptions)
- [ ] Content is timeless (no dates, "recently", "new", "cutting-edge" in docstrings/examples)
- [ ] Docstrings use Google style with all required sections
- [ ] Examples are complete and runnable
- [ ] Examples use standard variable names (`pc`, `index`)
- [ ] Technical terms are explained or linked
- [ ] No TODOs or placeholders in public APIs
- [ ] Links are relative and valid
- [ ] Code blocks specify language
- [ ] Markdown follows formatting conventions
- [ ] Documentation builds without warnings (`make html`)
- [ ] Doctest passes (`make doctest`)
