lss-parser


Namelss-parser JSON
Version 0.1.0 PyPI version JSON
download
home_pageNone
SummaryA Python module for parsing and manipulating LiveSplit .lss files
upload_time2025-07-12 22:10:57
maintainerNone
docs_urlNone
authormushroomsuprise
requires_python>=3.8
licenseMIT
keywords livesplit lss parser speedrunning xml
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # LiveSplit LSS File Parser

A comprehensive Python module for parsing and manipulating LiveSplit `.lss` files. This module converts XML-based LSS files into easy-to-use Python objects, allowing for programmatic analysis and manipulation of speedrun data.

## Features

- **Complete LSS File Support**: Parse all elements of LSS files including metadata, attempts, segments, and timing data
- **Pydantic-Based Models**: Robust data validation and serialization using Pydantic BaseModel
- **Bidirectional Conversion**: Load LSS files into Python objects and save them back to LSS format
- **Type Safety**: Full type annotations with automatic validation for better IDE support and code reliability
- **JSON Serialization**: Built-in support for JSON export/import via Pydantic
- **Data Validation**: Automatic type conversion and validation (e.g., integers to strings where needed)
- **Comprehensive API**: Simple interface with just two main functions: `load_lss_file()` and `save_lss_file()`

## Installation

This module requires Pydantic. Install dependencies:

```bash
pip install pydantic
```

Then copy the `lss_parser.py` file to your project directory or install it as a module.

```python
import lss_parser
```

## Quick Start

### Loading an LSS File

```python
import lss_parser

# Load a LiveSplit file
run = lss_parser.load_lss_file("my_speedrun.lss")

# Access basic information
print(f"Game: {run.game_name}")
print(f"Category: {run.category_name}")
print(f"Total Attempts: {run.attempt_count}")
print(f"Number of Segments: {len(run.segments)}")
```

### Saving an LSS File

```python
# Modify the run data
run.game_name = "Modified Game Name"
run.category_name = "Any% Modified"

# Save the modified run
lss_parser.save_lss_file(run, "modified_speedrun.lss")
```

## Data Structure

The module provides several Pydantic models to represent LSS file structure:

### `Run` - Main Container
- `game_name`: Name of the game
- `category_name`: Speedrun category
- `version`: LSS file version
- `attempt_count`: Total number of attempts
- `segments`: List of segments (splits)
- `attempt_history`: List of all attempts
- `metadata`: Platform, region, and other metadata
- `auto_splitter_settings`: Auto-splitter configuration

### `Segment` - Individual Splits
- `name`: Segment name
- `icon`: Icon path/data
- `split_times`: List of split times with different timing methods
- `best_segment_time`: Best time for this segment
- `segment_history`: Historical times for this segment

### `Attempt` - Run Attempts
- `id`: Unique attempt identifier
- `started`: Start time/date
- `ended`: End time/date
- `time`: Timing data (real time, game time, pause time)

### `Time` - Timing Information
- `real_time`: Real world time
- `game_time`: In-game time
- `pause_time`: Paused time

## Pydantic Features

The module leverages Pydantic's powerful features:

### Data Validation
```python
import lss_parser

# Automatic type conversion
time = lss_parser.Time(real_time=123)  # Converts to "123"
print(time.real_time)  # "123"

# Validation on assignment
run = lss_parser.Run(game_name="Test Game")
run.attempt_count = "42"  # Automatically converted to int
```

### JSON Serialization
```python
# Export to JSON
run = lss_parser.load_lss_file("speedrun.lss")
run_dict = run.model_dump()  # or run.dict() for older Pydantic versions

# Import from JSON
run_data = {...}  # JSON data
run = lss_parser.Run(**run_data)
```

### Type Safety
```python
# IDE support with type hints
def analyze_run(run: lss_parser.Run) -> None:
    for segment in run.segments:  # Full IDE autocomplete
        print(f"Segment: {segment.name}")
        print(f"Best time: {segment.best_segment_time.real_time}")
```

## Usage Examples

### Analyzing Speedrun Data

```python
import lss_parser

# Load the file
run = lss_parser.load_lss_file("my_speedrun.lss")

# Find completed attempts
completed_attempts = [a for a in run.attempt_history if a.time.real_time]
print(f"Completed {len(completed_attempts)} out of {len(run.attempt_history)} attempts")

# Analyze segment times
for segment in run.segments:
    print(f"{segment.name}: Best {segment.best_segment_time.real_time or 'N/A'}")
    
# Get personal best
pb_attempts = [a for a in completed_attempts if a.time.real_time]
if pb_attempts:
    best_time = min(pb_attempts, key=lambda x: x.time.real_time)
    print(f"Personal Best: {best_time.time.real_time}")
```

### Creating a New Run

```python
import lss_parser

# Create a new run
new_run = lss_parser.Run(
    game_name="My Game",
    category_name="Any%"
)

# Add segments
segments = [
    lss_parser.Segment(
        name="Level 1",
        best_segment_time=lss_parser.Time(real_time="00:01:30.0000000")
    ),
    lss_parser.Segment(
        name="Level 2", 
        best_segment_time=lss_parser.Time(real_time="00:02:15.0000000")
    ),
    lss_parser.Segment(
        name="Boss",
        best_segment_time=lss_parser.Time(real_time="00:03:45.0000000")
    )
]

new_run.segments = segments

# Add metadata
new_run.metadata.platform = "PC"
new_run.metadata.region = "USA"

# Save the new run
lss_parser.save_lss_file(new_run, "new_speedrun.lss")
```

### Modifying Existing Data

```python
import lss_parser

# Load existing file
run = lss_parser.load_lss_file("existing_run.lss")

# Modify segment names
for segment in run.segments:
    segment.name = f"Modified {segment.name}"

# Add a new segment
new_segment = lss_parser.Segment(
    name="New Final Boss",
    best_segment_time=lss_parser.Time(real_time="00:05:00.0000000")
)
run.segments.append(new_segment)

# Update attempt count
run.attempt_count = len(run.attempt_history)

# Save changes
lss_parser.save_lss_file(run, "modified_run.lss")
```

## API Reference

### Main Functions

#### `load_lss_file(file_path: Union[str, Path]) -> Run`
Loads and parses an LSS file into a Run object.

**Parameters:**
- `file_path`: Path to the .lss file

**Returns:**
- `Run` object containing all parsed data

**Raises:**
- `FileNotFoundError`: If the file doesn't exist
- `ValueError`: If the file is not a valid LSS file
- `xml.etree.ElementTree.ParseError`: If the XML is malformed

#### `save_lss_file(run: Run, file_path: Union[str, Path]) -> None`
Saves a Run object to an LSS file.

**Parameters:**
- `run`: Run object to save
- `file_path`: Path where to save the .lss file

**Raises:**
- `ValueError`: If the file path is invalid

### Data Models

All data models are implemented using Pydantic's `BaseModel` and include:
- Type annotations with automatic validation
- Default values where appropriate
- Automatic data conversion and validation
- JSON serialization/deserialization support
- IDE support with full type hints

## Error Handling

The module includes comprehensive error handling:

```python
import lss_parser

try:
    run = lss_parser.load_lss_file("nonexistent.lss")
except FileNotFoundError:
    print("File not found!")
except ValueError as e:
    print(f"Invalid file: {e}")
except Exception as e:
    print(f"Parse error: {e}")
```

## Testing

The module includes comprehensive tests. Run them with:

```bash
python test_parser.py
```

## Demo

See `demo.py` for a comprehensive demonstration of all features:

```bash
python demo.py
```

## File Format Support

This parser supports LiveSplit LSS files version 1.7.0 and should be compatible with other versions. The parser handles:

- Game metadata (name, category, platform, region)
- Attempt history with timestamps and timing data
- Segment information with split times and history
- Auto-splitter settings
- Custom variables and platform-specific data

## License

This module is provided as-is for educational and personal use. It is not affiliated with LiveSplit or the LiveSplit development team.

## Contributing

This is a complete, self-contained module designed for parsing LSS files. Feel free to extend it for your specific needs.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "lss-parser",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": "livesplit, lss, parser, speedrunning, xml",
    "author": "mushroomsuprise",
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/95/c5/6204b158364ecb31d324d769cad25983ff4ac451f0d4bddcb55913c560e3/lss_parser-0.1.0.tar.gz",
    "platform": null,
    "description": "# LiveSplit LSS File Parser\n\nA comprehensive Python module for parsing and manipulating LiveSplit `.lss` files. This module converts XML-based LSS files into easy-to-use Python objects, allowing for programmatic analysis and manipulation of speedrun data.\n\n## Features\n\n- **Complete LSS File Support**: Parse all elements of LSS files including metadata, attempts, segments, and timing data\n- **Pydantic-Based Models**: Robust data validation and serialization using Pydantic BaseModel\n- **Bidirectional Conversion**: Load LSS files into Python objects and save them back to LSS format\n- **Type Safety**: Full type annotations with automatic validation for better IDE support and code reliability\n- **JSON Serialization**: Built-in support for JSON export/import via Pydantic\n- **Data Validation**: Automatic type conversion and validation (e.g., integers to strings where needed)\n- **Comprehensive API**: Simple interface with just two main functions: `load_lss_file()` and `save_lss_file()`\n\n## Installation\n\nThis module requires Pydantic. Install dependencies:\n\n```bash\npip install pydantic\n```\n\nThen copy the `lss_parser.py` file to your project directory or install it as a module.\n\n```python\nimport lss_parser\n```\n\n## Quick Start\n\n### Loading an LSS File\n\n```python\nimport lss_parser\n\n# Load a LiveSplit file\nrun = lss_parser.load_lss_file(\"my_speedrun.lss\")\n\n# Access basic information\nprint(f\"Game: {run.game_name}\")\nprint(f\"Category: {run.category_name}\")\nprint(f\"Total Attempts: {run.attempt_count}\")\nprint(f\"Number of Segments: {len(run.segments)}\")\n```\n\n### Saving an LSS File\n\n```python\n# Modify the run data\nrun.game_name = \"Modified Game Name\"\nrun.category_name = \"Any% Modified\"\n\n# Save the modified run\nlss_parser.save_lss_file(run, \"modified_speedrun.lss\")\n```\n\n## Data Structure\n\nThe module provides several Pydantic models to represent LSS file structure:\n\n### `Run` - Main Container\n- `game_name`: Name of the game\n- `category_name`: Speedrun category\n- `version`: LSS file version\n- `attempt_count`: Total number of attempts\n- `segments`: List of segments (splits)\n- `attempt_history`: List of all attempts\n- `metadata`: Platform, region, and other metadata\n- `auto_splitter_settings`: Auto-splitter configuration\n\n### `Segment` - Individual Splits\n- `name`: Segment name\n- `icon`: Icon path/data\n- `split_times`: List of split times with different timing methods\n- `best_segment_time`: Best time for this segment\n- `segment_history`: Historical times for this segment\n\n### `Attempt` - Run Attempts\n- `id`: Unique attempt identifier\n- `started`: Start time/date\n- `ended`: End time/date\n- `time`: Timing data (real time, game time, pause time)\n\n### `Time` - Timing Information\n- `real_time`: Real world time\n- `game_time`: In-game time\n- `pause_time`: Paused time\n\n## Pydantic Features\n\nThe module leverages Pydantic's powerful features:\n\n### Data Validation\n```python\nimport lss_parser\n\n# Automatic type conversion\ntime = lss_parser.Time(real_time=123)  # Converts to \"123\"\nprint(time.real_time)  # \"123\"\n\n# Validation on assignment\nrun = lss_parser.Run(game_name=\"Test Game\")\nrun.attempt_count = \"42\"  # Automatically converted to int\n```\n\n### JSON Serialization\n```python\n# Export to JSON\nrun = lss_parser.load_lss_file(\"speedrun.lss\")\nrun_dict = run.model_dump()  # or run.dict() for older Pydantic versions\n\n# Import from JSON\nrun_data = {...}  # JSON data\nrun = lss_parser.Run(**run_data)\n```\n\n### Type Safety\n```python\n# IDE support with type hints\ndef analyze_run(run: lss_parser.Run) -> None:\n    for segment in run.segments:  # Full IDE autocomplete\n        print(f\"Segment: {segment.name}\")\n        print(f\"Best time: {segment.best_segment_time.real_time}\")\n```\n\n## Usage Examples\n\n### Analyzing Speedrun Data\n\n```python\nimport lss_parser\n\n# Load the file\nrun = lss_parser.load_lss_file(\"my_speedrun.lss\")\n\n# Find completed attempts\ncompleted_attempts = [a for a in run.attempt_history if a.time.real_time]\nprint(f\"Completed {len(completed_attempts)} out of {len(run.attempt_history)} attempts\")\n\n# Analyze segment times\nfor segment in run.segments:\n    print(f\"{segment.name}: Best {segment.best_segment_time.real_time or 'N/A'}\")\n    \n# Get personal best\npb_attempts = [a for a in completed_attempts if a.time.real_time]\nif pb_attempts:\n    best_time = min(pb_attempts, key=lambda x: x.time.real_time)\n    print(f\"Personal Best: {best_time.time.real_time}\")\n```\n\n### Creating a New Run\n\n```python\nimport lss_parser\n\n# Create a new run\nnew_run = lss_parser.Run(\n    game_name=\"My Game\",\n    category_name=\"Any%\"\n)\n\n# Add segments\nsegments = [\n    lss_parser.Segment(\n        name=\"Level 1\",\n        best_segment_time=lss_parser.Time(real_time=\"00:01:30.0000000\")\n    ),\n    lss_parser.Segment(\n        name=\"Level 2\", \n        best_segment_time=lss_parser.Time(real_time=\"00:02:15.0000000\")\n    ),\n    lss_parser.Segment(\n        name=\"Boss\",\n        best_segment_time=lss_parser.Time(real_time=\"00:03:45.0000000\")\n    )\n]\n\nnew_run.segments = segments\n\n# Add metadata\nnew_run.metadata.platform = \"PC\"\nnew_run.metadata.region = \"USA\"\n\n# Save the new run\nlss_parser.save_lss_file(new_run, \"new_speedrun.lss\")\n```\n\n### Modifying Existing Data\n\n```python\nimport lss_parser\n\n# Load existing file\nrun = lss_parser.load_lss_file(\"existing_run.lss\")\n\n# Modify segment names\nfor segment in run.segments:\n    segment.name = f\"Modified {segment.name}\"\n\n# Add a new segment\nnew_segment = lss_parser.Segment(\n    name=\"New Final Boss\",\n    best_segment_time=lss_parser.Time(real_time=\"00:05:00.0000000\")\n)\nrun.segments.append(new_segment)\n\n# Update attempt count\nrun.attempt_count = len(run.attempt_history)\n\n# Save changes\nlss_parser.save_lss_file(run, \"modified_run.lss\")\n```\n\n## API Reference\n\n### Main Functions\n\n#### `load_lss_file(file_path: Union[str, Path]) -> Run`\nLoads and parses an LSS file into a Run object.\n\n**Parameters:**\n- `file_path`: Path to the .lss file\n\n**Returns:**\n- `Run` object containing all parsed data\n\n**Raises:**\n- `FileNotFoundError`: If the file doesn't exist\n- `ValueError`: If the file is not a valid LSS file\n- `xml.etree.ElementTree.ParseError`: If the XML is malformed\n\n#### `save_lss_file(run: Run, file_path: Union[str, Path]) -> None`\nSaves a Run object to an LSS file.\n\n**Parameters:**\n- `run`: Run object to save\n- `file_path`: Path where to save the .lss file\n\n**Raises:**\n- `ValueError`: If the file path is invalid\n\n### Data Models\n\nAll data models are implemented using Pydantic's `BaseModel` and include:\n- Type annotations with automatic validation\n- Default values where appropriate\n- Automatic data conversion and validation\n- JSON serialization/deserialization support\n- IDE support with full type hints\n\n## Error Handling\n\nThe module includes comprehensive error handling:\n\n```python\nimport lss_parser\n\ntry:\n    run = lss_parser.load_lss_file(\"nonexistent.lss\")\nexcept FileNotFoundError:\n    print(\"File not found!\")\nexcept ValueError as e:\n    print(f\"Invalid file: {e}\")\nexcept Exception as e:\n    print(f\"Parse error: {e}\")\n```\n\n## Testing\n\nThe module includes comprehensive tests. Run them with:\n\n```bash\npython test_parser.py\n```\n\n## Demo\n\nSee `demo.py` for a comprehensive demonstration of all features:\n\n```bash\npython demo.py\n```\n\n## File Format Support\n\nThis parser supports LiveSplit LSS files version 1.7.0 and should be compatible with other versions. The parser handles:\n\n- Game metadata (name, category, platform, region)\n- Attempt history with timestamps and timing data\n- Segment information with split times and history\n- Auto-splitter settings\n- Custom variables and platform-specific data\n\n## License\n\nThis module is provided as-is for educational and personal use. It is not affiliated with LiveSplit or the LiveSplit development team.\n\n## Contributing\n\nThis is a complete, self-contained module designed for parsing LSS files. Feel free to extend it for your specific needs.\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A Python module for parsing and manipulating LiveSplit .lss files",
    "version": "0.1.0",
    "project_urls": {
        "Bug Reports": "https://github.com/mushroomsuprise/lss-parser/issues",
        "Homepage": "https://github.com/mushroomsuprise/lss-parser",
        "Source": "https://github.com/mushroomsuprise/lss-parser"
    },
    "split_keywords": [
        "livesplit",
        " lss",
        " parser",
        " speedrunning",
        " xml"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "63bd01694fb41b065103663b2f5d78fdc4304db82e65e6ffa7bcce9835d98b50",
                "md5": "bb3050f455dee8f7e0d989dc3b5ebece",
                "sha256": "0b9581410111356ef63347bfb9dc6c157eff5a22a4274224be86e2aef87d6e9c"
            },
            "downloads": -1,
            "filename": "lss_parser-0.1.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "bb3050f455dee8f7e0d989dc3b5ebece",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 10084,
            "upload_time": "2025-07-12T22:10:56",
            "upload_time_iso_8601": "2025-07-12T22:10:56.291155Z",
            "url": "https://files.pythonhosted.org/packages/63/bd/01694fb41b065103663b2f5d78fdc4304db82e65e6ffa7bcce9835d98b50/lss_parser-0.1.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "95c56204b158364ecb31d324d769cad25983ff4ac451f0d4bddcb55913c560e3",
                "md5": "c6c080ec127d23f2e0b7ed51f5c546f2",
                "sha256": "6e8f46f1aa320a753db62f3d83cef399acde8de16ccda5f73b562ecf92f7b250"
            },
            "downloads": -1,
            "filename": "lss_parser-0.1.0.tar.gz",
            "has_sig": false,
            "md5_digest": "c6c080ec127d23f2e0b7ed51f5c546f2",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 57655,
            "upload_time": "2025-07-12T22:10:57",
            "upload_time_iso_8601": "2025-07-12T22:10:57.522863Z",
            "url": "https://files.pythonhosted.org/packages/95/c5/6204b158364ecb31d324d769cad25983ff4ac451f0d4bddcb55913c560e3/lss_parser-0.1.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-07-12 22:10:57",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "mushroomsuprise",
    "github_project": "lss-parser",
    "github_not_found": true,
    "lcname": "lss-parser"
}
        
Elapsed time: 0.77303s