Python binding of the afrim.
Project description
About
afrim-py provides Python bindings for the powerful afrim input method engine, enabling developers to build sophisticated input method applications in Python. This project brings the capabilities of the Rust-based afrim engine to the Python ecosystem through PyO3 bindings.
🔋 Features Included
- Preprocessor - Advanced key sequence processing and input transformation
- Translator - Dictionary-based text translation with multiple candidates
- TOML Support - Easy configuration through TOML files
- Unicode Support - Full support for international characters
- Rhai Scripting - Dynamic translation scripts (when
rhaifeature is enabled) - String Similarity - Fuzzy matching with
strsimfeature
Installation
afrim-py is available on pypi.
pip install afrim-py
Usage
Basic Example
from afrim_py import Preprocessor, Translator, Config
# Configure the preprocessor with key mappings
preprocessor_data = {
"a1": "à",
"e1": "é",
"u1": "ù",
"hello": "hi"
}
# Configure the translator with dictionary
translator_dict = {
"hello": ["hi", "hey", "greetings"],
"world": ["earth", "globe", "planet"],
"python": ["snake", "programming language"]
}
# Create instances
preprocessor = Preprocessor(preprocessor_data, buffer_size=64)
translator = Translator(translator_dict, auto_commit=True)
# Process keyboard events
changed = preprocessor.process("h", "keydown")
changed = preprocessor.process("e", "keydown")
changed = preprocessor.process("l", "keydown")
changed = preprocessor.process("l", "keydown")
changed = preprocessor.process("o", "keydown")
# Get the processed input
current_input = preprocessor.get_input() # "hello"
# Translate the input
translations = translator.translate(current_input)
print(translations)
# [{'texts': ['hi', 'hey', 'greetings'], 'code': 'hello', 'remaining_code': '', 'can_commit': True}]
# Process commands from the queue
while True:
command = preprocessor.pop_queue()
if command == "NOP":
break
print(f"Command: {command}")
Configuration
from afrim_py import Config
import json
# Configuration file `config.toml`
'''
[core]
buffer_size = 64
auto_capitalize = false
auto_commit = false
page_size = 10
[data]
a1 = "à"
e2 = "é"
[translators]
datetime = { path = "./scripts/datetime.toml" }
[translation]
hi = 'hello'
'''
config = Config('config.toml')
# Use the configuration
preprocessor_data = config.extract_data()
preprocessor = Preprocessor(preprocessor_data, 64)
translator_dict = config.extract_translation()
translator = Translator(translator_dict, True)
Advanced Usage with Command Processing
import asyncio
from afrim_py import Preprocessor, Translator, Config
class InputMethodEngine:
def __init__(self, config_file: str):
config = Config(config_file)
self.preprocessor = Preprocessor(config.extract_data(), 64)
self.translator = Translator(config.extract_translation(), True)
self.running = False
async def process_commands(self):
"""Process commands from the preprocessor queue"""
while self.running:
command = self.preprocessor.pop_queue()
if command == "NOP":
await asyncio.sleep(0.01) # Small delay
continue
# Handle different command types
if isinstance(command, dict):
if "Insert" in command:
text = command["Insert"]["text"]
print(f"Insert: {text}")
elif "Delete" in command:
count = command["Delete"]["count"]
print(f"Delete: {count} characters")
else:
print(f"Command: {command}")
def handle_key_event(self, key, state="keydown"):
"""Handle keyboard events"""
changed = self.preprocessor.process(key, state)
if changed:
current_input = self.preprocessor.get_input()
if current_input:
translations = self.translator.translate(current_input)
return translations
return []
def commit_text(self, text):
"""Commit selected text"""
self.preprocessor.commit(text)
async def start(self):
"""Start the input method engine"""
self.running = True
await self.process_commands()
def stop(self):
"""Stop the input method engine"""
self.running = False
# Usage
async def main():
ime = InputMethodEngine(
preprocessor_data={"A": "ዕ", "Aa": "ዓ", "C": "ጭ"},
translator_dict={"Atarah": ["ዓጣራ"], "Adiel": ["ዓዲዔል"]}
)
# Simulate key events
translations = ime.handle_key_event("A")
translations = ime.handle_key_event("a")
translations = ime.handle_key_event("C")
print("Translations:", translations)
# Commit text
if translations:
ime.commit_text(translations[0]["texts"][0])
# Run the example
# asyncio.run(main())
Development
Build requirements
Build from source
To simplify the development, we recommend to use uv.
Using maturin
# Clone the repository
git clone https://github.com/fodydev/afrim-py.git
cd afrim-py
# Create virtual environment
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
# Development build
maturin develop
# Release build
maturin build --release
# Build wheel
maturin build --interpreter python
Using uv
# Clone the repository
git clone https://github.com/fodydev/afrim-py.git
cd afrim-py
# Prerelease build
uv build --prerelease
# Release build
uv build
Testing
The project includes tests that represent a real user scenario:
# Run all tests
python -m pytest tests/ -v
Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
Acknowledgments
- afrim-js - Web bindings that inspired this project
License
Licensed under the MIT LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file afrim_py-0.1.0.tar.gz.
File metadata
- Download URL: afrim_py-0.1.0.tar.gz
- Upload date:
- Size: 32.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.30 {"installer":{"name":"uv","version":"0.9.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":null,"id":"forky","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e0adb85d661feb056a0fbf3fbd79a969c43bac8bd5fa2ca1bb1225173128e1cc
|
|
| MD5 |
20023731b9721ea46b1ebaeb3071beb7
|
|
| BLAKE2b-256 |
7dfa623368f23e08596e753b1c708096cff57c2aadc11de768b4d2a95dc11041
|