# Pypack - Python Project Packaging Tool

Pypack is an advanced Python project packaging tool that orchestrates multiple packaging tasks through a workflow engine, achieving optimal efficiency with mixed serial and parallel execution.

Built with modern design patterns and following Python best practices, pypack demonstrates:

- **Factory Pattern**: For configuration creation and validation
- **Strategy Pattern**: For flexible cleaning operations
- **Enum Types**: For improved type safety and code clarity
- **Data Classes**: For immutable configuration objects
- **Protocol Classes**: For defining clean interfaces

## Features

- **Workflow Orchestration**: Uses `workflowengine` for intelligent task scheduling
- **Project Parsing**: Integrates `pyprojectparse` to parse `pyproject.toml` files
- **Source Packing**: Uses `pysourcepack` to pack project source code
- **Embedded Python**: Installs Python runtime with `pyembedinstall`
- **Loader Generation**: Generates cross-platform loaders with `pyloadergen`
- **Parallel Execution**: Maximizes efficiency by running independent tasks concurrently
- **Dependency Management**: Automatically handles task dependencies and execution order
- **Design Patterns**: Implements factory, strategy, and other patterns for maintainability
- **Type Safety**: Uses enums and protocols for robust code
- **Extensible Architecture**: Easy to add new cleaning strategies and configuration options

## Installation

Pypack is part of the sfi project. Install from source:

```bash
cd sfi/pypack
pip install -e .
```

## GUI Interface

Pypack now includes a graphical user interface built with PySide2:

```bash
# Launch GUI
python pypack_gui.py

# Or from module
python -m sfi.pypack.pypack_gui
```

### GUI Features

- **Modern Interface**: Clean, professional design with gradient styling
- **Project Directory Selection**: Smart directory picker with automatic project name detection
- **Auto Project Name Detection**: Automatically analyzes project name from:
  - Directory name
  - `pyproject.toml` file (Poetry or PEP 621 format)
  - `setup.py` file
- **Real-time Logging**: Built-in log display showing build progress
- **Parameter Configuration**: Intuitive form-based parameter input
- **Persistent Settings**: Configuration automatically saved between sessions
- **Keyboard Shortcuts**: 
  - `Enter` - Start build
  - `Escape` - Reset parameters
  - `Ctrl+R` - Reset parameters
  - `Ctrl+Q` - Exit
- **Multi-language Support**: English and Chinese translations
- **Modular Styling**: Styles separated into independent QSS files for easy customization

### GUI Components

1. **Left Panel**: Build configuration parameters
   - **Project Directory**: Select the project folder to build (mandatory)
   - Project name and build settings
   - Python version selection
   - Loader type and archive options
   - **Final Archive**: Optional final project archive creation (zip, tar, gztar, bztar, xztar, 7z, nsis)
     - Note: Dependency library formats are automatically analyzed based on downloaded packages
   - Advanced options (offline mode, debug, etc.)

2. **Right Panel**: Real-time build log display
   - Color-coded output (dark theme)
   - Auto-scrolling to latest messages
   - Clear build progress tracking

3. **Bottom Controls**: 
   - Start Build button (green)
   - Clean Artifacts button (red)
   - Status indicator in status bar

### Style System

The GUI uses a modular style system:

- **Embedded Styles**: Main stylesheet embedded in `pypack_gui.py` for reliability
- **Separate QSS Files**: Styles organized in `styles/` directory for easy customization
- **CSS Class Names**: Semantic class names for consistent styling
- **Fallback Mechanism**: Automatic fallback to embedded styles if external files fail

To customize the appearance, you can either:
1. Modify the embedded styles in the `_get_embedded_styles()` method
2. Edit the individual `.qss` files in the `styles/` directory
3. Create new themes by copying and modifying the style files

## Usage

### Command Line Usage

```bash
# Build project in current directory
pypack build

# Build project in specific directory
pypack build -d /path/to/project

# Build specific project
pypack build -p myproject

# Use offline mode (skip Python download, use cache)
pypack build -o
```

### Advanced Options

```bash
# Specify Python version
pypack build --python-version 3.11.5

# Generate GUI loader
pypack build --loader-type gui

# Specify entry file for loader
pypack build --entry-file app.py

# Skip loader generation
pypack build --no-loader

# Recursive project parsing
pypack build -r

# Set maximum concurrent tasks
pypack build -j 8

# Debug mode
pypack build --debug
```

### Check Version

```bash
pypack version
```

## Workflow Stages

The packaging process consists of four stages:

### Stage 1: Project Parsing (Serial)

- Uses `pyprojectparse` to parse `pyproject.toml` files
- Extracts project metadata and dependencies
- Generates `projects.json` file

### Stage 2: Parallel Tasks

- **Source Packing**: Packs project source code using `pysourcepack`
- **Python Installation**: Installs embedded Python runtime using `pyembedinstall`
- These tasks run in parallel for maximum efficiency

### Stage 3: Loader Generation (Parallel)

- Generates cross-platform loaders using `pyloadergen`
- Supports both console and GUI modes
- Can be skipped with `--no-loader` flag

### Stage 4: Package Assembly (Serial)

- Assembles all components into final package
- Copies source code, Python runtime, and loaders
- Creates package metadata

## Workflow Diagram

```bash
┌─────────────────────────────────────────────────────────────┐
│                    Packaging Workflow                         │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
                   ┌─────────────────────┐
                   │  1. Parse Project   │ (Serial)
                   │  pyprojectparse       │
                   └──────────┬──────────┘
                              │
              ┌───────────────┴───────────────┐
              │                               │
              ▼                               ▼
  ┌──────────────────────┐        ┌──────────────────────┐
  │ 2a. Pack Source     │        │ 2b. Install Python   │ (Parallel)
  │    pysourcepack     │        │    pyembedinstall      │
  └──────────┬───────────┘        └──────────┬───────────┘
             │                               │
             └───────────────┬───────────────┘
                             │
                             ▼
                   ┌─────────────────────┐
                   │ 3. Generate Loader  │ (Parallel)
                   │    pyloadergen      │
                   └──────────┬──────────┘
                              │
                              ▼
                   ┌─────────────────────┐
                   │ 4. Assemble Package │ (Serial)
                   │    Copy & Bundle    │
                   └─────────────────────┘
```

## Configuration

### Command-Line Options

| Option             | Short | Description                | Default           |
| ------------------ | ----- | -------------------------- | ----------------- |
| `--directory`      | `-d`  | Project directory          | Current directory |
| `--project`        | `-p`  | Project name to pack       | All projects      |
| `--python-version` |       | Python version to install  | 3.8.10            |
| `--loader-type`    |       | Loader type (console/gui)  | console           |
| `--entry-file`     |       | Entry file for loader      | main.py           |
| `--no-loader`      |       | Skip loader generation     | false             |
| `--recursive`      | `-r`  | Parse projects recursively | false             |
| `--offline`        | `-o`  | Offline mode (use cache)   | false             |
| `--jobs`           | `-j`  | Maximum concurrent tasks   | 4                 |
| `--debug`          |       | Enable debug logging       | false             |

### Example Configurations

```bash
# Fast build for development (skip loader)
pypack build --no-loader -j 8

# Production build with GUI loader
pypack build --loader-type gui --python-version 3.11.5

# Offline build with specific project
pypack build -o -p myapp

# Debug build with verbose logging
pypack build --debug -j 2
```

## Output Structure

After successful packaging, the following directory structure is created:

```bash
dist/
├── src/              # Packed source code
│   └── project_name/
│       ├── __init__.py
│       ├── main.py
│       └── ...
├── loader/           # Generated loaders (if enabled)
│   └── main.exe
└── package/          # Final assembled package
    ├── src/          # Source code
    ├── runtime/      # Python runtime
    ├── main.exe      # Loader executable
    └── metadata.json # Package metadata
```

## Integration with Other Tools

Pypack integrates seamlessly with other sfi tools:

### pyprojectparse

- Parses `pyproject.toml` files
- Extracts project metadata
- Supports recursive parsing

### pysourcepack

- Packs source code with exclusion rules
- Supports custom include/exclude patterns
- Generates distributable source packages

### pyembedinstall

- Downloads and installs embedded Python
- Supports multiple versions and architectures
- Uses mirror sources for faster downloads
- Supports offline mode

### pyloadergen

- Generates cross-platform loaders
- Supports console and GUI modes
- Handles encoding and process management
- Works with Qt applications

## Performance Optimization

The workflow engine automatically optimizes execution:

1. **Parallel Execution**: Independent tasks run concurrently
2. **Dependency Management**: Tasks wait only when necessary
3. **Concurrent Control**: Configurable maximum concurrency
4. **I/O vs CPU**: I/O tasks use async, CPU tasks use thread pool

## Troubleshooting

### Build Fails at Stage 1

- Ensure `pyproject.toml` exists in project directory
- Check file permissions

### Build Fails at Stage 2

- Verify network connection (unless using offline mode)
- Check disk space for source code and runtime

### Build Fails at Stage 3

- Ensure C compiler is installed (GCC/Clang/MSVC)
- Check entry file exists and is valid Python

### Build Fails at Stage 4

- Verify previous stages completed successfully
- Check disk space in output directory

## Development

### Project Structure

```bash
pypack/
├── pypack.py    # New workflow-based implementation
├── pyproject.toml       # Project configuration
└── README.md            # This file
```

### Extending the Workflow

To add new tasks:

1. Create a new task class inheriting from appropriate base task
2. Implement the `execute()` method
3. Add task to workflow in `build_workflow()` method
4. Update dependencies as needed

Example:

```python
from sfi.workflowengine.workflowengine import IOTask

class CustomTask(IOTask):
    def __init__(self, some_param: str, timeout: float = 60.0):
        super().__init__("custom_task", 5.0, ["parse_project"], timeout)
        self.some_param = some_param

    async def execute(self, context: dict[str, Any]) -> Any:
        # Implement custom logic
        return {"result": "success"}
```

## License

Same as sfi project.

## Version

Current version: 1.0.0 (build 20260120)
