Skip to content

Best Practices

This guide outlines recommended practices for using the Teable Client Library effectively and safely.

Authentication

API Key Management

# DON'T: Hardcode API keys
client = TeableClient(TeableConfig(
    api_key="1234567890abcdef"  # Bad practice
))

# DO: Use environment variables
from dotenv import load_dotenv
load_dotenv()

client = TeableClient.from_env()  # Reads from environment variables

Authentication Flow

# DO: Implement proper authentication flow
try:
    # Initialize with API key
    client = TeableClient(TeableConfig(
        api_key=os.getenv('TEABLE_API_KEY')
    ))

    # Sign in for operations requiring full access
    client.auth.signin(
        email=os.getenv('TEABLE_EMAIL'),
        password=os.getenv('TEABLE_PASSWORD')
    )

    # Perform operations

finally:
    # Always sign out when done
    client.auth.signout()

Resource Management

Cleanup

# DO: Always clean up resources
def manage_temporary_space():
    space = None
    try:
        space = client.spaces.create_space(name="Temporary")
        # ... perform operations ...
    finally:
        if space:
            client.spaces.permanently_delete_space(space.space_id)

Resource Hierarchy

# DO: Follow the resource hierarchy
space = client.spaces.create_space(name="Project")
base = space.create_base(name="Database")
table = client.tables.create_table(
    base_id=base.base_id,
    name="Employees"
)

Data Operations

Batch Operations

# DON'T: Create records one by one in a loop
for data in records_data:
    table.create_record(data)  # Inefficient

# DO: Use batch operations
batch_result = table.batch_create_records(records_data)
print(f"Created {batch_result.success_count} records")

Query Optimization

# DON'T: Fetch all records and filter in memory
all_records = table.get_records()
filtered = [r for r in all_records if r.fields["Age"] > 30]

# DO: Use API-level filtering
filter_data = {
    "filterSet": [
        {
            "fieldId": "Age",
            "operator": "isGreaterThan",
            "value": 30
        }
    ]
}
filtered_records = table.get_records(filter=filter_data)

Pagination

# DO: Use pagination for large datasets
def fetch_all_records(table):
    records = []
    skip = 0
    take = 100

    while True:
        batch = table.get_records(skip=skip, take=take)
        if not batch:
            break
        records.extend(batch)
        skip += take

    return records

Error Handling

Specific Exceptions

# DO: Handle specific exceptions
from teable.exceptions import ValidationError, APIError

try:
    record = table.create_record(data)
except ValidationError as e:
    # Handle validation errors
    logger.error(f"Validation error: {str(e)}")
except APIError as e:
    # Handle API errors
    logger.error(f"API error: {str(e)}")
except Exception as e:
    # Handle unexpected errors
    logger.error(f"Unexpected error: {str(e)}")

Retry Logic

# DO: Implement retry logic for transient failures
def retry_operation(operation, max_retries=3):
    for attempt in range(max_retries):
        try:
            return operation()
        except APIError as e:
            if e.status_code == 429:  # Rate limit
                time.sleep(2 ** attempt)  # Exponential backoff
                continue
            raise
    raise Exception("Max retries exceeded")

Performance

Connection Management

# DON'T: Create multiple clients
client1 = TeableClient(config)
client2 = TeableClient(config)  # Unnecessary

# DO: Reuse client instance
client = TeableClient(config)
# Use the same client throughout your application

Caching

# DO: Cache frequently accessed data
from functools import lru_cache

@lru_cache(maxsize=100)
def get_table_schema(table_id):
    return client.tables.get_table(table_id)

Testing

Test Environment

# DO: Use a separate test environment
def setup_test_client():
    return TeableClient(TeableConfig(
        api_key=os.getenv('TEABLE_TEST_API_KEY'),
        api_url=os.getenv('TEABLE_TEST_API_URL')
    ))

Test Data Management

# DO: Clean up test data
@pytest.fixture
def test_space(client):
    space = client.spaces.create_space(name="Test Space")
    yield space
    client.spaces.permanently_delete_space(space.space_id)

Security

Credential Management

# DON'T: Store credentials in code
credentials = {
    "api_key": "secret_key",
    "password": "secret_pass"
}

# DO: Use secure credential management
from keyring import get_password

api_key = get_password("teable", "api_key")
client = TeableClient(TeableConfig(api_key=api_key))

Permission Checks

# DO: Check permissions before operations
def create_record_if_allowed(table, data):
    permissions = client.tables.get_table_permission(
        table.base_id,
        table.table_id
    )

    if permissions["record"]["create"]:
        return table.create_record(data)
    else:
        raise PermissionError("No create permission")

Code Organization

Module Structure

# DO: Organize code logically
from teable import TeableClient
from teable.exceptions import APIError
from teable.models import Table, Record

class TeableManager:
    def __init__(self):
        self.client = TeableClient.from_env()

    def setup_workspace(self):
        """Create and configure workspace"""
        pass

    def manage_records(self):
        """Handle record operations"""
        pass

Configuration Management

# DO: Centralize configuration
class TeableConfig:
    def __init__(self):
        load_dotenv()

        self.api_key = os.getenv('TEABLE_API_KEY')
        self.api_url = os.getenv('TEABLE_API_URL')
        self.email = os.getenv('TEABLE_EMAIL')
        self.password = os.getenv('TEABLE_PASSWORD')

config = TeableConfig()
client = TeableClient(TeableConfig(
    api_key=config.api_key,
    api_url=config.api_url
))

Logging

Structured Logging

# DO: Implement proper logging
import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

def perform_operation():
    try:
        result = client.spaces.create_space(name="New Space")
        logger.info("Space created", extra={
            "space_id": result.space_id,
            "name": result.name
        })
        return result
    except Exception as e:
        logger.error("Failed to create space", exc_info=True)
        raise

Documentation

Code Comments

# DO: Document code properly
def process_records(table, filter_criteria=None):
    """
    Process records from a table with optional filtering.

    Args:
        table: Table instance to process
        filter_criteria: Optional dict of filter parameters

    Returns:
        List of processed records

    Raises:
        APIError: If API request fails
        ValidationError: If filter criteria is invalid
    """
    pass

Version Control

Dependencies

# DO: Specify version requirements
# requirements.txt
teable-client>=1.0.0,<2.0.0
python-dotenv>=0.19.0

Git Integration

```python

DO: Add proper .gitignore

.gitignore

.env pycache/ *.pyc .pytest_cache/