Skip to main content

python-alfresco-api v1.0

A Complete Python client package for developing python code and apps for Alfresco. Great for doing AI development with Python based LangChain, LlamaIndex, neo4j-graphrag, etc. Also great for creating MCP servers (see python-alfreso-mcp-server in this repository).

Note this uses the remote Alfresco REST APIs. Not for in-process development in Alfresco.

A modern, type-safe Python client library for Alfresco Content Services REST APIs with comprehensive Pydantic v2 model integration and async support.

PyPI version PyPI downloads Python Version Pydantic License Test Coverage

🚀 Features

  • Complete API Coverage: All 7 Alfresco REST APIs (Auth, Core, Discovery, Search, Workflow, Model, Search SQL)
  • 1,400+ Pydantic v2 Models: Type-safe data validation and serialization
  • Async/Sync Support: Both synchronous and asynchronous API calls
  • Modular Architecture: Individual client design for scalability
  • LLM/AI Ready: Type-safe Pydantic v2 models perfect for AI integration and tool interfaces
  • Event System: ActiveMQ and Event Gateway support for Python apps to handle change events
  • Docker Compatible: Works with Alfresco running in separate Docker Compose setups
  • Comprehensive Testing: 100% unit and live Alfresco integration tests

📚 Documentation & Examples

📦 Installation

Quick Install from PyPI

PyPI

pip install python-alfresco-api

All features included - No optional dependencies needed! Includes event system, async support, and all 7 Alfresco APIs.

Virtual Environment Setup (Recommended)

Best Practice: Always use a virtual environment to avoid dependency conflicts

Windows

# Clone the repository
git clone https://github.com/stevereiner/python-alfresco-api.git
cd python-alfresco-api

# Create virtual environment
python -m venv venv

# Activate virtual environment
venv\Scripts\activate

# Verify activation (should show venv path)
where python

# Install dependencies
pip install -r requirements.txt

# For development (RECOMMENDED - includes mypy, black, pytest, etc.)
pip install -e .[dev]

# Deactivate when done
deactivate

Linux / MacOS

# Clone the repository
git clone https://github.com/stevereiner/python-alfresco-api.git
cd python-alfresco-api

# Create virtual environment
python3 -m venv venv

# Activate virtual environment
source venv/bin/activate

# Verify activation (should show venv path)
which python

# Install dependencies
pip install -r requirements.txt

# For development (RECOMMENDED - includes mypy, black, pytest, etc.)
pip install -e .[dev]

# Deactivate when done
deactivate

Alternative: Using conda

# Create conda environment
conda create -n alfresco-api python=3.11
conda activate alfresco-api

# Install dependencies
pip install -r requirements.txt

# Deactivate when done
conda deactivate

Runtime Installation

Install the package for production use:

pip install python-alfresco-api

This installs all features including event system support.

Development Installation

For development, testing, or package regeneration:

# After setting up virtual environment above
git clone https://github.com/your-org/python-alfresco-api.git
cd python-alfresco-api

# Activate your virtual environment first
# Windows: venv\Scripts\activate
# Linux/macOS: source venv/bin/activate

# Install development dependencies (RECOMMENDED)
pip install -e .[dev]

# Or install in development mode
pip install -e .

🎯 Quick Start

Basic Usage

from python_alfresco_api import ClientFactory

# Create client factory
factory = ClientFactory(
    base_url="http://localhost:8080",
    username="admin",
    password="admin"
)

# Get all clients
clients = factory.create_all_clients()

# Use individual clients
auth_client = factory.create_auth_client()
core_client = factory.create_core_client()
search_client = factory.create_search_client()

Async Usage

import asyncio
from python_alfresco_api import ClientFactory

async def main():
    factory = ClientFactory(
        base_url="http://localhost:8080",
        username="admin",
        password="admin"
    )
    
    # Authenticate
    await factory.auth.authenticate()
    
    # Use authenticated API calls
    # Your async API operations here

asyncio.run(main())

Architecture Options

Option 1: Individual Clients + Factory Pattern (Recommended)

from python_alfresco_api import ClientFactory

# Factory pattern for easy configuration
factory = ClientFactory(
    base_url="http://localhost:8080",
    username="admin",
    password="admin"
)

# Individual clients for modular architecture
auth_client = factory.create_auth_client()
core_client = factory.create_core_client()
search_client = factory.create_search_client()
workflow_client = factory.create_workflow_client()

Option 2: Master Client Pattern (Unified Interface)

from python_alfresco_api import ClientFactory

# Create factory
factory = ClientFactory(
    base_url="http://localhost:8080",
    username="admin",
    password="admin"
)

# Master client with dot syntax access
master_client = factory.create_master_client()

# Use dot syntax for API access
nodes = master_client.core.get_node("some-node-id")
results = master_client.search.search("my query")
ticket = master_client.auth.create_ticket()
processes = master_client.workflow.list_processes()

Option 3: Direct Individual Clients (No Factory)

# Direct client creation without factory
from python_alfresco_api.clients import (
    AlfrescoAuthClient,
    AlfrescoCoreClient,
    AlfrescoSearchClient,
    AlfrescoWorkflowClient
)
from python_alfresco_api import AuthUtil

# Create auth utility
auth_util = AuthUtil(
    base_url="http://localhost:8080",
    username="admin",
    password="admin"
)

# Create individual clients directly
auth_client = AlfrescoAuthClient("http://localhost:8080")
core_client = AlfrescoCoreClient("http://localhost:8080", auth_util)
search_client = AlfrescoSearchClient("http://localhost:8080", auth_util)

All approaches provide:

  • Type Safety: Full Pydantic v2 model integration
  • Async Support: Modern async/await patterns
  • Authentication: Automatic ticket-based auth with renewal
  • Error Handling: Comprehensive error management

Pydantic Models

from python_alfresco_api.models.alfresco_core_models import NodeBodyCreate
from python_alfresco_api.models.alfresco_auth_models import TicketBody

# Type-safe model creation
node_data = NodeBodyCreate(
    name="my-document.txt",
    nodeType="cm:content",
    properties={"cm:title": "My Document"}
)

# Serialize to dict/JSON
node_dict = node_data.model_dump()
node_json = node_data.model_dump_json()

# Validation
ticket = TicketBody(userId="admin", password="admin")

🔧 Code Regeneration

The library uses OpenAPI 3.0 specifications for generating both Pydantic models and HTTP clients. These were derived from alfresco swagger / openapi 2.0 yaml files, processed to clean (still openapi 2.0) and then given to swagger2openapi to convert to openapi 3.0 .

Prerequisites

Install development dependencies:

# RECOMMENDED - includes mypy, black, pytest, etc.
pip install -e .[dev]

# Alternative (may have missing dependencies)
pip install -r requirements-dev.txt

Regeneration Steps

  1. Update OpenAPI Specifications

    Download the latest specifications from Alfresco API Explorer and place them in:

    openapi/openapi2/alfresco-auth.yaml
    openapi/openapi2/alfresco-core.yaml
    openapi/openapi2/alfresco-discovery.yaml
    openapi/openapi2/alfresco-search.yaml
    openapi/openapi2/alfresco-workflow.yaml
    openapi/openapi2/alfresco-model.yaml
    openapi/openapi2/alfresco-search-sql.yaml
    
  2. Run the Generation Pipeline

    python scripts/generate_hybrid_pipeline.py
    

    This script:

    • Processes and cleans the OpenAPI 2.0 specifications
    • Converts them to OpenAPI 3.0 format
    • Generates Pydantic v2 models from OpenAPI 3.0
    • Generates HTTP clients from OpenAPI 3.0
    • Creates the unified package structure
  3. Manual Steps (if needed)

    Generate individual components:

    # Generate Pydantic models from OpenAPI 3.0
    datamodel-codegen \
      --input openapi/openapi3/alfresco-core.yaml \
      --output python_alfresco_api/models/alfresco_core_models.py \
      --target-python-version 3.8
    
    # Generate HTTP client from OpenAPI 3.0
    openapi-python-client generate \
      --path openapi/openapi3/alfresco-core.yaml \
      --config client_config.yaml
    
  4. Package Integration

    The pipeline automatically:

    • Creates individual client wrappers
    • Sets up the ClientFactory
    • Configures AuthUtil integration
    • Establishes the unified package structure

Generation Configuration

Configuration files for all Alfresco API clients are organized in the config/ folder:

config/
├── auth.yaml          # Authentication API → auth_client
├── core.yaml          # Core Repository API → core_client  
├── discovery.yaml     # Discovery API → discovery_client
├── search.yaml        # Search API → search_client
├── workflow.yaml      # Workflow API → workflow_client
├── model.yaml         # Model API → model_client
├── search_sql.yaml    # Search SQL API → search_sql_client
├── general.yaml       # Unified package → alfresco_client
└── README.md          # Configuration documentation

Example configuration (config/auth.yaml):

# Alfresco Auth API Client Configuration
class_overrides:
  "Error": "AuthError"
  "HTTPValidationError": "AuthValidationError"

project_name_override: "auth_client"
package_name_override: "auth_client"

field_constraints: true
use_annotated: true

Usage:

# Generate specific API client
openapi-python-client generate \
  --path openapi/openapi3/alfresco-auth.yaml \
  --config config/auth.yaml \
  --output-path clients/auth_client

Note: All generated package names use short, practical names instead of the default long names. See config/README.md for complete documentation and customization options.

🧪 Testing

Run Tests

# Run all tests
pytest

# Run with coverage
pytest --cov=python_alfresco_api --cov-report=html

# Run specific test suites
pytest tests/test_current_architecture.py
pytest tests/test_enhanced_coverage.py

Live Integration Tests

To run tests against a live Alfresco server (tested with Community Edition 23.2.0 and Community Edition 25.1):

  1. Start Alfresco with Docker Compose

    # docker-compose.yml - Community Edition (tested with 23.2.0 and 25.1)
    version: '3.8'
    services:
      alfresco:
        image: alfresco/alfresco-content-repository-community:23.2.0
        # or: alfresco/alfresco-content-repository-community:25.1.0
        ports:
          - "8080:8080"
        environment:
          JAVA_OPTS: "-Xms1500m -Xmx1500m"
    
    docker-compose up -d
    
  2. Run Integration Tests

    pytest tests/ -m integration
    

Test Coverage

Current test coverage: 80% of code lines tested with 106/106 tests passing (100% success rate)

  • Core Components: 80%+ test coverage
  • Pydantic Models: 100% test coverage (1,400+ classes)
  • Live Integration: 100% functional validation (tested with Community Edition 23.2.0 and 25.1)
  • Individual Clients: 81% test coverage each
  • Authentication: 81% test coverage
  • Client Factory: 94% test coverage
  • Master Client: 70% test coverage

Test Runner Script

Use the convenient test runner for professional output:

# From project root
python run_tests.py

# From tests directory  
cd tests && python ../run_tests.py

The test runner automatically detects your location and provides:

  • Colored output and progress indicators
  • Coverage reporting with visual display
  • Live integration test status
  • Performance metrics and timing
  • Auto-adjusts working directory as needed

🔌 Event System

ActiveMQ Integration (Community Edition)

from python_alfresco_api.activemq_events import AlfrescoActiveMQEventClient

# Create event client
event_client = AlfrescoActiveMQEventClient(
    activemq_host="localhost",
    activemq_port=61616,
    username="admin",
    password="admin"
)

# Register event handler
async def node_created_handler(notification):
    print(f"Node created: {notification.nodeId}")

event_client.register_event_handler("alfresco.node.created", node_created_handler)

# Start listening
await event_client.connect()
await event_client.start_listening()

Event Gateway (Enterprise Edition)

from python_alfresco_api.event_client import AlfrescoEventClient

# Unified event client (auto-detects available systems)
event_client = AlfrescoEventClient()

# Works with both Community (ActiveMQ) and Enterprise (Event Gateway)
await event_client.create_subscription("node-events")
await event_client.start_listening()

🤖 MCP Server / LLM Integration (see python-alfresco-mcp-server)

Perfect for Model Context Protocol (MCP) servers with FastMCP 2.0 and type-safe Pydantic v2 models:

FastMCP 2.0 Server Example

from fastmcp import FastMCP
from python_alfresco_api import ClientFactory

# Create MCP server with FastMCP 2.0
mcp = FastMCP("Alfresco Content Management")

# Initialize Alfresco client
factory = ClientFactory(
    base_url="http://localhost:8080",
    username="admin", 
    password="admin"
)

@mcp.tool()
def search_documents(query: str) -> str:
    """Search for documents in Alfresco"""
    search_client = factory.create_search_client()
    results = search_client.search({
        "query": {"query": query, "language": "afts"},
        "paging": {"maxItems": 10}
    })
    return f"Found {results.list.pagination.totalItems} documents"

@mcp.tool()
def get_repository_info() -> str:
    """Get Alfresco repository information"""
    discovery_client = factory.create_discovery_client()
    info = discovery_client.get_repository_info()
    return f"Connected to {info.entry.repository.name} v{info.entry.repository.version.major}.{info.entry.repository.version.minor}"

if __name__ == "__main__":
    mcp.run()

Master Client with FastMCP 2.0

from fastmcp import FastMCP
from python_alfresco_api import ClientFactory

mcp = FastMCP("Alfresco Master Client")

# Use master client for dot syntax access
master = ClientFactory(
    base_url="http://localhost:8080",
    username="admin",
    password="admin"
).create_master_client()

@mcp.tool()
def list_root_nodes() -> str:
    """List root nodes in Alfresco"""
    nodes = master.core.get_nodes()
    return f"Found {len(nodes.list.entries)} root nodes"

@mcp.tool()  
def search_content(query: str) -> str:
    """Search content with master client"""
    results = master.search.search({
        "query": {"query": query, "language": "afts"}
    })
    return f"Search returned {results.list.pagination.totalItems} results"

📁 Project Structure

python-alfresco-api/
├── python_alfresco_api/
│   ├── __init__.py                 # Main exports
│   ├── auth_util.py               # Authentication utility
│   ├── client_factory.py          # Client factory pattern
│   ├── master_client.py           # Unified master client
│   ├── clients/                   # Individual API clients
│   │   ├── auth_client.py
│   │   ├── core_client.py
│   │   ├── discovery_client.py
│   │   ├── search_client.py
│   │   ├── workflow_client.py
│   │   ├── model_client.py
│   │   └── search_sql_client.py
│   ├── models/                    # Pydantic v2 models
│   │   ├── alfresco_auth_models.py
│   │   ├── alfresco_core_models.py
│   │   ├── alfresco_discovery_models.py
│   │   ├── alfresco_search_models.py
│   │   ├── alfresco_workflow_models.py
│   │   ├── alfresco_model_models.py
│   │   └── alfresco_search_sql_models.py
│   ├── raw_clients/               # Generated HTTP clients
│   └── events/                    # Event system (Community + Enterprise)
│       ├── __init__.py            # Event exports
│       ├── event_client.py        # Unified event client (AlfrescoEventClient)
│       └── models.py              # Event models (EventSubscription, EventNotification)
├── config/                        # OpenAPI client configurations
│   ├── auth.yaml                  # Auth API config → auth_client
│   ├── core.yaml                  # Core API config → core_client
│   ├── discovery.yaml             # Discovery API config → discovery_client
│   ├── search.yaml                # Search API config → search_client
│   ├── workflow.yaml              # Workflow API config → workflow_client
│   ├── model.yaml                 # Model API config → model_client
│   ├── search_sql.yaml            # Search SQL API config → search_sql_client
│   ├── general.yaml               # Unified config → alfresco_client
│   └── README.md                  # Configuration documentation
├── openapi/                       # OpenAPI specifications (checked in)
│   ├── openapi2/                  # Original OpenAPI 2.0 specs
│   ├── openapi2-processed/        # Cleaned OpenAPI 2.0 specs
│   └── openapi3/                  # Converted OpenAPI 3.0 specs
├── tests/                         # Comprehensive test suite
├── scripts/                       # Generation scripts
├── docs/                          # Documentation
├── examples/                      # Usage examples
├── requirements.txt               # Runtime dependencies
├── requirements-dev.txt           # Development dependencies
├── run_tests.py                   # Test runner with nice display
└── README.md                      # This file

🔄 Development Workflow

Standard Development (No Regeneration Needed)

For most development work, you can develop directly without regenerating code:

git clone https://github.com/your-org/python-alfresco-api.git
cd python-alfresco-api

# Install with all development dependencies (RECOMMENDED)
pip install -e .[dev]

All OpenAPI specifications are checked in - you can develop immediately:

  • openapi/openapi2/ - Original specifications
  • openapi/openapi2-processed/ - Processed specifications
  • openapi/openapi3/ - OpenAPI 3.0 specifications

Development Tasks

# Run tests with nice display
python run_tests.py

# Run specific test suites
pytest tests/test_current_architecture.py
pytest tests/test_enhanced_coverage.py

# Format code
black python_alfresco_api/
isort python_alfresco_api/

# Type checking
mypy python_alfresco_api/

Making Changes

  1. Modify existing code - No regeneration needed
  2. Add new features - Work with existing generated clients
  3. Update documentation - Edit docs/ and examples/
  4. Add tests - Extend the test suite

Code Regeneration (Only When Needed)

Only regenerate when updating OpenAPI specifications:

# Update OpenAPI specs in openapi/openapi2/
# Then regenerate
python scripts/generate_hybrid_pipeline.py

📋 Requirements

Runtime Requirements

  • Python: 3.8+
  • pydantic: >=2.0.0,<3.0.0
  • requests: >=2.31.0
  • httpx: >=0.24.0 (for async support)
  • aiohttp: >=3.8.0 (for async HTTP)

Optional Dependencies

  • stomp.py: >=8.1.0 (for ActiveMQ events)
  • ujson: >=5.7.0 (faster JSON parsing)
  • requests-oauthlib: >=1.3.0 (OAuth support)

Development Requirements

Code Rebuild/Regeneration Requirements

  • datamodel-code-generator: >=0.21.0
  • openapi-python-client: >=0.15.0
  • pytest: >=7.4.0
  • black: >=23.0.0
  • mypy: >=1.5.0

🤝 Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Run tests: pytest
  5. Submit a pull request

📄 License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.

🆘 Support

🔗 Related Projects

⭐ Star History

If this project helps you, please consider giving it a star! ⭐

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

python_alfresco_api-1.0.0.tar.gz (543.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

python_alfresco_api-1.0.0-py3-none-any.whl (735.0 kB view details)

Uploaded Python 3

File details

Details for the file python_alfresco_api-1.0.0.tar.gz.

File metadata

  • Download URL: python_alfresco_api-1.0.0.tar.gz
  • Upload date:
  • Size: 543.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.10

File hashes

Hashes for python_alfresco_api-1.0.0.tar.gz
Algorithm Hash digest
SHA256 6fc16f34395e600e5da04a48fb616d60cdee3448ca8aeb2dafe80dae54d2c8ef
MD5 9464d0b568b4fa1d1718e5f7c796c25c
BLAKE2b-256 22ee4f05b0c4c8714d5ba82b2d76418493f585fbbb53fb1b0ac85064d1e7f7dc

See more details on using hashes here.

File details

Details for the file python_alfresco_api-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for python_alfresco_api-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 48b8406409d83d813482892b17a40ca09710e906a4b92e49b98b7cf74913f242
MD5 770b8ce5182b3d4e0d29898d275bb8a2
BLAKE2b-256 39e4ae307486c1199aee98b9391ad377e1edd614536c374572f927414a2d483e

See more details on using hashes here.

Release history Release notifications | RSS feed

1.2.1

2 files

1.2.0

2 files

1.1.5

2 files

1.1.4

2 files

1.1.2

2 files

1.1.1

2 files

1.1.0

2 files

1.0.2

2 files

1.0.1

2 files

This release

1.0.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page