Skip to main content

Official Python SDK for Mogu Workflow Management Platform

Project description

Mogu SDK

Official Python SDK for the Mogu Workflow Management Platform.

PyPI version Python 3.12+ License: MIT Code style: black

Features

  • 🔐 OAuth2 Authentication - Secure token-based authentication
  • 📝 Wiki Management - Create, update, search wiki pages in Git repositories
  • Async-First - Built on httpx for high-performance async operations
  • 🎯 Type-Safe - Full type hints with Pydantic models
  • 🧪 Well-Tested - Comprehensive test coverage
  • 📚 Great Documentation - Detailed API docs and examples

Installation

pip install mogu-sdk

Or with Poetry:

poetry add mogu-sdk

Quick Start

Environment Configuration

The SDK automatically reads configuration from environment variables or a .env file:

# Create a .env file
MOGU_BASE_URL=http://localhost:8000
MOGU_TOKEN=your-oauth-token
MOGU_WORKSPACE_ID=your-workspace-id

Basic Usage

import asyncio
from mogu_sdk import MoguClient

async def main():
    # Initialize client - automatically reads from environment variables
    client = MoguClient()
    
    # Or override specific values
    client = MoguClient(
        base_url="https://api.mogu.example.com",
        token="your-oauth-token"
    )
    
    # Access wiki client
    wiki = client.wiki
    
    # Create or update a wiki page
    result = await wiki.create_or_update_page(
        workspace_id="ws-123",
        path="docs/getting-started.md",
        content="# Getting Started\n\nWelcome to our wiki!",
        commit_message="Add getting started guide"
    )
    print(f"Committed: {result.commit_id}")
    
    # Search wiki with context
    results = await wiki.search(
        workspace_id="ws-123",
        query="authentication",
        max_results=10,
        context_lines=3
    )
    
    for result in results:
        print(f"\nFound in: {result.path}")
        for match in result.matches:
            print(f"  Line {match.line_number}: {match.line_content}")

if __name__ == "__main__":
    asyncio.run(main())

Wiki Client

Create or Update Wiki Page

Smart method that automatically detects if a file exists and creates or updates accordingly:

result = await wiki.create_or_update_page(
    workspace_id="ws-123",
    path="docs/api-reference.md",
    content="# API Reference\n\n## Authentication\n...",
    commit_message="Update API reference"
)

print(f"Success: {result.success}")
print(f"Commit ID: {result.commit_id}")
print(f"Message: {result.message}")

Search Wiki with Context

Search across all wiki files with configurable context extraction:

results = await wiki.search(
    workspace_id="ws-123",
    query="deployment kubernetes",
    max_results=20,
    context_lines=5  # Get 5 lines before/after each match
)

for result in results:
    print(f"\n📄 {result.path} (score: {result.score})")
    
    for match in result.matches:
        print(f"\n  Line {match.line_number}:")
        
        # Context before match
        if match.context_before:
            for line in match.context_before:
                print(f"    {line}")
        
        # The matched line (highlighted)
        print(f"  ➤ {match.line_content}")
        
        # Context after match
        if match.context_after:
            for line in match.context_after:
                print(f"    {line}")

Search with Character-Based Snippets (NEW!)

Extract text snippets of specific character length around matches - perfect for displaying search results in UIs:

results = await wiki.search(
    workspace_id="ws-123",
    query="authentication",
    max_results=10,
    snippet_chars=1000  # Extract ~1000 character snippet around each match
)

for result in results:
    for match in result.matches:
        if match.text_snippet:
            # Get the snippet with match position
            snippet = match.text_snippet
            start = match.snippet_match_start
            end = match.snippet_match_end
            
            # Highlight the match within snippet
            before = snippet[:start]
            matched = snippet[start:end]
            after = snippet[end:]
            
            print(f"{before}**{matched}**{after}")

Features:

  • Character-based extraction (e.g., 1000 chars) for consistent UI display
  • Smart word boundaries - avoids cutting words mid-character
  • Automatic ellipsis (...) for truncated text
  • Exact match position within snippet for highlighting
  • Works alongside line-based context (use both together!)

Combined context example:

# Get both line-based and character-based context
results = await wiki.search(
    workspace_id="ws-123",
    query="configuration",
    context_lines=2,      # 2 lines before/after (for code structure)
    snippet_chars=800     # 800 char snippet (for prose context)
)

# Now you have:
# - match.context_before / context_after (lines)
# - match.text_snippet (character-based snippet)

Search with Character-Based Snippets (NEW!)

Extract text snippets of specific character length around matches - perfect for displaying search results in UIs:

results = await wiki.search(
    workspace_id="ws-123",
    query="authentication",
    max_results=10,
    snippet_chars=1000  # Extract ~1000 character snippet around each match
)

for result in results:
    for match in result.matches:
        if match.text_snippet:
            # Get the snippet with match position
            snippet = match.text_snippet
            start = match.snippet_match_start
            end = match.snippet_match_end
            
            # Highlight the match within snippet
            before = snippet[:start]
            matched = snippet[start:end]
            after = snippet[end:]
            
            print(f"{before}**{matched}**{after}")

Features:

  • Character-based extraction (e.g., 1000 chars) for consistent UI display
  • Smart word boundaries - avoids cutting words mid-character
  • Automatic ellipsis (...) for truncated text
  • Exact match position within snippet for highlighting
  • Works alongside line-based context (use both together!)

Combined context example:

# Get both line-based and character-based context
results = await wiki.search(
    workspace_id="ws-123",
    query="configuration",
    context_lines=2,      # 2 lines before/after (for code structure)
    snippet_chars=800     # 800 char snippet (for prose context)
)

# Now you have:
# - match.context_before / context_after (lines)
# - match.text_snippet (character-based snippet)

List Wiki Files

files = await wiki.list_files(
    workspace_id="ws-123",
    folder_path="docs",  # Optional: filter by folder
    recursive=True
)

for file in files:
    icon = "📁" if file.is_folder else "📄"
    print(f"{icon} {file.path}")

Get File Content

content = await wiki.get_content(
    workspace_id="ws-123",
    path="docs/README.md"
)

print(f"Path: {content.path}")
print(f"Content:\n{content.content}")

Delete File

result = await wiki.delete_file(
    workspace_id="ws-123",
    path="docs/old-guide.md",
    commit_message="Remove outdated guide"
)

print(f"Deleted: {result.success}")

Configuration

The SDK supports multiple configuration methods with automatic environment variable loading.

Method 1: .env File (Recommended)

Create a .env file in your project root:

# .env
MOGU_BASE_URL=http://localhost:8000
MOGU_TOKEN=your-oauth-token
MOGU_WORKSPACE_ID=your-workspace-id
MOGU_TIMEOUT=30.0
MOGU_MAX_RETRIES=3
MOGU_VERIFY_SSL=true

Then simply initialize the client:

from mogu_sdk import MoguClient

# Automatically reads from .env file
client = MoguClient()

# Access default workspace_id
print(client.workspace_id)  # your-workspace-id

Method 2: Environment Variables

Set environment variables directly:

export MOGU_BASE_URL="https://api.mogu.example.com"
export MOGU_TOKEN="your-oauth-token"
export MOGU_WORKSPACE_ID="your-workspace-id"
from mogu_sdk import MoguClient

client = MoguClient()  # Reads from environment

Method 3: Direct Parameters

Override environment variables by passing parameters:

from mogu_sdk import MoguClient

client = MoguClient(
    base_url="https://api.mogu.example.com",
    token="your-oauth-token",
    workspace_id="your-workspace-id",
    timeout=30.0,  # Request timeout in seconds
    max_retries=3,  # Number of retry attempts
    verify_ssl=True  # SSL certificate verification
)

Error Handling

The SDK provides specific exceptions for different error scenarios:

from mogu_sdk.exceptions import (
    MoguAPIError,
    AuthenticationError,
    NotFoundError,
    PermissionDeniedError,
    ValidationError
)

try:
    result = await wiki.create_or_update_page(
        workspace_id="ws-123",
        path="docs/guide.md",
        content="# Guide",
        commit_message="Update guide"
    )
except AuthenticationError:
    print("Invalid or expired token")
except PermissionDeniedError:
    print("No permission to edit wiki")
except NotFoundError:
    print("Workspace not found")
except ValidationError as e:
    print(f"Invalid input: {e}")
except MoguAPIError as e:
    print(f"API error: {e.status_code} - {e.message}")

Advanced Usage

Context Manager

async with MoguClient(base_url="...", token="...") as client:
    result = await client.wiki.search(
        workspace_id="ws-123",
        query="deployment"
    )
    # Client automatically closed after context

Async Iteration

# Process search results as they arrive
async for result in wiki.search_stream(
    workspace_id="ws-123",
    query="api"
):
    print(f"Found: {result.path}")

Custom Headers

client = MoguClient(
    base_url="...",
    token="...",
    headers={
        "X-Custom-Header": "value",
        "User-Agent": "MyApp/1.0"
    }
)

Development

Setup Development Environment

# Clone the repository
git clone https://github.com/yourusername/mogu-sdk.git
cd mogu-sdk

# Install dependencies
poetry install

# Run tests
poetry run pytest

# Run linters
poetry run black mogu_sdk tests
poetry run ruff mogu_sdk tests
poetry run mypy mogu_sdk

Run Examples

# Set environment variables
export MOGU_BASE_URL="http://localhost:8000"
export MOGU_TOKEN="your-token"

# Run examples
poetry run python examples/wiki_basic.py
poetry run python examples/wiki_search.py

Contributing

Contributions are welcome! Please read our Contributing Guide for details.

License

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

Links

Support

Project details


Download files

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

Source Distribution

mogu_sdk-0.1.6.tar.gz (21.0 kB view details)

Uploaded Source

Built Distribution

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

mogu_sdk-0.1.6-py3-none-any.whl (21.9 kB view details)

Uploaded Python 3

File details

Details for the file mogu_sdk-0.1.6.tar.gz.

File metadata

  • Download URL: mogu_sdk-0.1.6.tar.gz
  • Upload date:
  • Size: 21.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.2.1 CPython/3.13.7 Darwin/25.1.0

File hashes

Hashes for mogu_sdk-0.1.6.tar.gz
Algorithm Hash digest
SHA256 e9a23a93e39583d731cf105b344cf25cd0f06c3fe17f004ecde1f9b42026560f
MD5 10c9ec6a69aa31bf09d5c67aaeccca93
BLAKE2b-256 17309f30ed7ef131ae6d9fa5839abd05f999376952c521a6a6dc77e67d30bdfc

See more details on using hashes here.

File details

Details for the file mogu_sdk-0.1.6-py3-none-any.whl.

File metadata

  • Download URL: mogu_sdk-0.1.6-py3-none-any.whl
  • Upload date:
  • Size: 21.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.2.1 CPython/3.13.7 Darwin/25.1.0

File hashes

Hashes for mogu_sdk-0.1.6-py3-none-any.whl
Algorithm Hash digest
SHA256 1180584141c2c5e57fe99313f2dc3b4575e8b6f46af3dbdd6390f5356b09c520
MD5 17755f03e349be336fca6c93438ca0f7
BLAKE2b-256 b9d6a39966fc6ca5997f0bed754e3649a2913a14380a4a241ab80931ef0cf25a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page