hangeul 1.0.0
A modern, optimized Korean Hangul syllable and jamo manipulation library for Python 3.13+
Requires Python: >=3.13
Keywords: hangul, jamo, korean, korean-language, nlp

# Hangeul 한글

A modern, high-performance Korean Hangul syllable and jamo manipulation library for Python 3.13+.

[![Python Version](https://img.shields.io/badge/python-3.13+-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

## Features

✨ **Modern Python 3.13+ optimized** - Leverages the latest Python features for maximum performance

🚀 **Fast and efficient** - Optimized algorithms with O(1) lookups using frozen sets and dictionaries

📦 **Zero dependencies** - Pure Python implementation with no external dependencies

🔤 **Complete Hangul support** - Full support for all modern Korean syllables and jamo

🎯 **Type-safe** - Fully typed with type hints for excellent IDE support

🧪 **Well-tested** - Comprehensive test suite with 100% coverage

## Installation

```bash
# Using uv (recommended)
uv add hangeul

# Using pip
pip install hangeul
```

## Quick Start

```python
import hangeul

# Decompose Hangul syllables into jamo
hangeul.decompose('안녕하세요')
# 'ㅇㅏㄴㄴㅕㅇㅎㅏㅅㅔㅇㅛ'

# Compose jamo into Hangul syllables
hangeul.compose('ㅎㅏㄴㄱㅡㄹ')
# '한글'

# Decompose a single syllable
hangeul.decompose_syllable('한')
# Syllable(lead='ㅎ', vowel='ㅏ', tail='ㄴ')

# Compose from individual jamo
hangeul.compose_jamo('ㅎ', 'ㅏ', 'ㄴ')
# '한'
```

## Usage Examples

### Text Processing

```python
import hangeul

# Decompose Korean text while preserving other characters
text = "Hello, 안녕하세요!"
decomposed = hangeul.decompose(text)
print(decomposed)  # "Hello, ㅇㅏㄴㄴㅕㅇㅎㅏㅅㅔㅇㅛ!"

# Compose jamo back into syllables
recomposed = hangeul.compose(decomposed)
print(recomposed)  # "Hello, 안녕하세요!"
```

### Working with Individual Syllables

```python
# Decompose a syllable into its components
syllable = hangeul.decompose_syllable('한')
print(f"Lead: {syllable.lead}")      # ㅎ
print(f"Vowel: {syllable.vowel}")    # ㅏ
print(f"Tail: {syllable.tail}")      # ㄴ

# Compose jamo into a syllable
syllable = hangeul.compose_jamo('ㄱ', 'ㅏ', 'ㄴ')
print(syllable)  # 간
```

### Compound Jamo

```python
# Decompose compound jamo (double consonants, clusters, diphthongs)
hangeul.decompose_compound('ㄲ')  # ('ㄱ', 'ㄱ')
hangeul.decompose_compound('ㅘ')  # ('ㅗ', 'ㅏ')
hangeul.decompose_compound('ㄺ')  # ('ㄹ', 'ㄱ')

# Compose compound jamo from components
hangeul.compose_compound(('ㄱ', 'ㄱ'))  # 'ㄲ'
hangeul.compose_compound(['ㅗ', 'ㅏ'])  # 'ㅘ'
```

### Validation

```python
# Check if a character is a Hangul syllable
hangeul.is_hangul_syllable('한')  # True
hangeul.is_hangul_syllable('ㄱ')  # False

# Check if a character is jamo
hangeul.is_jamo('ᄀ')  # True (U+11xx jamo)
hangeul.is_hcj('ㄱ')   # True (Hangul Compatibility Jamo)

# Check jamo types
hangeul.is_jamo_lead('ㄱ')   # True
hangeul.is_jamo_vowel('ㅏ')  # True
hangeul.is_jamo_tail('ㄴ')   # True

# Check if jamo is compound
hangeul.is_jamo_compound('ㄲ')  # True
hangeul.is_jamo_compound('ㄱ')  # False
```

### Jamo Conversion

```python
# Convert between jamo forms
hangeul.jamo_to_hcj('ᄀ')  # 'ㄱ' (U+11xx to U+31xx)
hangeul.hcj_to_jamo('ㄱ', 'lead')  # 'ᄀ' (U+31xx to U+11xx)
```

### Memory-Efficient Processing

```python
# Use iterators for large texts to save memory
for jamo in hangeul.iter_decompose('한글프로그래밍'):
    print(jamo)  # Yields one jamo at a time
```

## API Reference

### Main Functions

- **`decompose(text: str, *, use_jamo: bool = False) -> str`**
  - Decompose Hangul syllables in text into jamo characters
  - Returns HCJ (U+31xx) by default, or U+11xx jamo if `use_jamo=True`

- **`compose(text: str) -> str`**
  - Compose jamo characters in text into Hangul syllables
  - Automatically detects valid syllable patterns

- **`decompose_syllable(syllable: str) -> Syllable`**
  - Decompose a single Hangul syllable into a `Syllable` namedtuple
  - Returns components in HCJ form

- **`compose_jamo(lead: str, vowel: str, tail: str | None = None) -> str`**
  - Compose individual jamo into a Hangul syllable
  - Accepts HCJ characters

### Validation Functions

- **`is_hangul_syllable(char: str) -> bool`** - Check if character is a Hangul syllable
- **`is_jamo(char: str) -> bool`** - Check if character is U+11xx jamo
- **`is_hcj(char: str) -> bool`** - Check if character is Hangul Compatibility Jamo
- **`is_jamo_lead(char: str) -> bool`** - Check if character is a leading consonant
- **`is_jamo_vowel(char: str) -> bool`** - Check if character is a vowel
- **`is_jamo_tail(char: str) -> bool`** - Check if character is a trailing consonant
- **`is_jamo_compound(char: str) -> bool`** - Check if jamo is compound

### Compound Jamo Functions

- **`decompose_compound(jamo: str) -> tuple[str, ...]`** - Decompose compound jamo into components
- **`compose_compound(components: tuple[str, ...] | list[str]) -> str`** - Compose compound jamo

### Conversion Functions

- **`jamo_to_hcj(char: str) -> str`** - Convert U+11xx jamo to HCJ
- **`hcj_to_jamo(char: str, position: str) -> str`** - Convert HCJ to U+11xx jamo

### Iterator Functions

- **`iter_decompose(text: str, *, use_jamo: bool = False) -> Iterator[str]`** - Lazily decompose text

### Types

- **`Syllable`** - A namedtuple with fields: `lead`, `vowel`, `tail`
- **`HangeulError`** - Base exception class
- **`InvalidJamoError`** - Raised for invalid jamo operations
- **`InvalidSyllableError`** - Raised for invalid syllable operations

## Performance

This library is optimized for Python 3.13+ with several performance enhancements:

- **O(1) lookups** using frozen sets and dictionaries
- **Pre-computed mappings** for jamo-to-syllable conversions
- **Type-stable operations** leveraging Python 3.13's JIT improvements
- **Memory-efficient iterators** for processing large texts

### Benchmark Results

Run `python benchmark.py` to see detailed performance metrics. Here are some highlights:

| Operation | Performance | Details |
|-----------|-------------|---------|
| Single syllable decomposition | ~0.001 ms | 100K ops/sec |
| Single syllable composition | ~0.0004 ms | 250K ops/sec |
| Text decomposition (1000 chars) | ~1.7 ms | 590K+ chars/sec |
| Text composition (1000 chars) | ~1.4 ms | 2.2M+ chars/sec |
| Validation operations | ~0.0001 ms | 2M+ ops/sec |
| Memory efficiency (iterators) | 97.9% reduction | vs string decomposition |

#### Scalability

The library maintains **linear time complexity O(n)** with consistent performance:

```
Text Size    Decompose Time    Per Character
   10 chars     0.017 ms         1.70 µs/char
  100 chars     0.173 ms         1.73 µs/char
1,000 chars     1.667 ms         1.67 µs/char
10,000 chars   16.647 ms         1.66 µs/char
```

Performance ratio: **~1.0x** (perfect linear scaling)

#### Real-world Performance

- **NLP Preprocessing** (5 sentences): ~0.26 ms per batch, 3,870 batches/sec
- **Search Indexing** (10 documents): ~2.7 ms per batch, 373 batches/sec
- **Throughput**: 600K chars/sec decomposition, 2.2M chars/sec composition

Run the benchmarks yourself:

```bash
# Standalone benchmark script
uv run python benchmark.py

# Pytest benchmark suite
uv run pytest tests/test_benchmark.py -v
```

## Comparison with Other Libraries

### Why choose Hangeul?

| Feature | Hangeul | python-jamo | hangul-jamo |
|---------|---------|-------------|-------------|
| Python 3.13+ optimized | ✅ | ❌ | ❌ |
| Type hints | ✅ | ⚠️ Partial | ✅ |
| Zero dependencies | ✅ | ❌ (JSON files) | ✅ |
| Performance | ⚡ Optimized | Standard | Good |
| Compound jamo support | ✅ | ✅ | ❌ |
| Iterator support | ✅ | ✅ | ❌ |
| Modern syntax | ✅ (3.13+) | ❌ (3.6+) | ✅ (3.6+) |

### Advantages from python-jamo

- ✅ Comprehensive HCJ support
- ✅ Compound jamo decomposition/composition
- ✅ Multiple jamo forms (U+11xx and U+31xx)
- ✅ Extensive validation functions

### Advantages from hangul-jamo

- ✅ Clean, simple API
- ✅ Named tuples for syllable representation
- ✅ Smart composition algorithm
- ✅ Efficient constant lookups

### Our improvements

- ✅ Python 3.13+ optimizations (type parameters, pattern matching)
- ✅ Frozen sets for O(1) membership testing
- ✅ Complete type annotations with generics
- ✅ No external file dependencies
- ✅ Modern error handling
- ✅ Comprehensive test coverage

## Development

### Setting up development environment

```bash
# Clone the repository
git clone https://github.com/yourusername/hangeul.git
cd hangeul

# Install dependencies with uv
uv sync

# Run tests
uv run pytest

# Run tests with coverage
uv run pytest --cov=hangeul --cov-report=html

# Type checking
uv run mypy src/hangeul

# Linting
uv run ruff check src/hangeul
```

### Running tests

```bash
# Run all tests
uv run pytest

# Run with verbose output
uv run pytest -v

# Run specific test file
uv run pytest tests/test_hangeul.py

# Run specific test class
uv run pytest tests/test_hangeul.py::TestDecomposition
```

## Unicode Reference

### Hangul Syllables
- Range: U+AC00 to U+D7A3 (가 to 힣)
- Total: 11,172 syllables

### Hangul Jamo (U+11xx)
- Leading consonants (초성): U+1100 to U+1112 (19 characters)
- Vowels (중성): U+1161 to U+1175 (21 characters)
- Trailing consonants (종성): U+11A8 to U+11C2 (27 characters)

### Hangul Compatibility Jamo (U+31xx)
- Range: U+3131 to U+318E
- Used for standalone jamo representation

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request

## License

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

## Acknowledgments

This library combines the best features from:
- [python-jamo](https://github.com/jdongian/python-jamo) - Comprehensive jamo manipulation
- [hangul-jamo](https://github.com/kaniblu/hangul-jamo) - Clean API design

Special thanks to the maintainers of these excellent libraries!

## Citation

If you use this library in your research, please cite:

```bibtex
@software{hangeul2025,
  title={Hangeul: A Modern Korean Hangul Library for Python},
  author={gembleman},
  year={2025},
  url={https://github.com/gembleman/hangeul}
}
```

## Support

- 📫 Issues: [GitHub Issues](https://github.com/gembleman/hangeul/issues)
- 💬 Discussions: [GitHub Discussions](https://github.com/gembleman/hangeul/discussions)
- 📧 Email: 81058727+gembleman@users.noreply.github.com