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.3.tar.gz (16.1 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.3-py3-none-any.whl (16.6 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: mogu_sdk-0.1.3.tar.gz
  • Upload date:
  • Size: 16.1 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.3.tar.gz
Algorithm Hash digest
SHA256 47999ecce0573649d9d9a74dc49a8f848301e10ec08fd69f85dd0b3964b05a81
MD5 43ab250f58cf40d35b49d2f714bbaf80
BLAKE2b-256 3f35bda87b38455097fb8df574d4f5e16189b8523e5d30bcd9264b3d07d708e8

See more details on using hashes here.

File details

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

File metadata

  • Download URL: mogu_sdk-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 16.6 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.3-py3-none-any.whl
Algorithm Hash digest
SHA256 6616cca1cb2ecc5fb92a903a7c3d1df49358920c82b4214431ba883d9072916a
MD5 8532121be10929c16fdb4b72c4b3bb5a
BLAKE2b-256 9a03f90926a46d04cf72f47a4f3e0997c532d6a6971a78aea9239409f50f2b50

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