Skip to main content

libmorpheus for Python

libmorpheus modernizes the Morpheus morphological analyzer for Ancient Greek and Latin. It turns the historical C programs into an installable C17 shared library with a stable, opaque ABI and a typed Python binding.

This package loads the libmorpheus shared library with the standard-library ctypes module. It exposes normalized Greek and Latin analysis plus experimental Greek lemma generation. Native results are copied into immutable Python objects before their C allocations are released.

Summary

  1. Quick start (using the PyPI package)
  2. In-depth overview
    1. Analyze a form
    2. Generate forms from a lemma
    3. Use parallel contexts
    4. Raw access and cleanup
  3. Other installation options
    1. Install from a source checkout
    2. Build the native runtime
  4. Native library and runtime data
    1. Acquire stem data
    2. Acquire the native library
    3. Language and data coverage
  5. Python and platform support
  6. Documentation
  7. Local checks
  8. License

Quick start (using the PyPI package)

The Python package requires Python 3.11 or later and has no third-party runtime dependencies. Install the typed, universal wheel:

python -m pip install libmorpheus

The wheel contains neither the native library nor linguistic stem data. Install a compatible native libmorpheus release and stemlib as described below, then create app.py:

from libmorpheus import Language, Library, Option

with Library("/path/to/libmorpheus.so") as library:
    with library.context("/path/to/stemlib", Language.GREEK) as context:
        analyses = context.analyze(
            "a)/nqrwpos",
            Option.STRICT_CASE,
        )

        for analysis in analyses:
            print(analysis.lemma, analysis.part_of_speech)

Run it normally:

python app.py

The binding itself performs no network access and reads no environment variables. Applications may pass paths from their own configuration:

import os

library_path = os.environ["MORPHEUS_LIBRARY"]
stemlib_path = os.environ["MORPHEUS_STEMLIB"]

Version 0.1.0 deliberately leaves runtime and data acquisition outside the Python package. The native releases and runtime-data guide provide the required components; a complete source-checkout recipe appears below.

In-depth overview

Analyze a form

from libmorpheus import Language, Library, MorpheusError, Option

try:
    with Library("/usr/local/lib/libmorpheus.so") as library:
        with library.context(
            "/path/to/stemlib", Language.GREEK
        ) as context:
            analyses = context.analyze(
                "a)/nqrwpos", Option.STRICT_CASE
            )
            print(analyses[0].part_of_speech)  # "noun"
            print(analyses[0].grammatical_number)  # "singular"
            print(analyses[0].grammatical_cases)  # ("nominative",)
except MorpheusError as error:
    print(f"Morpheus status {error.status}: {error}")

analyze() returns stable English identifiers, tuples for combinable masks, and None for inapplicable scalar values. It preserves all analyses. A generic stemlib indecl class remains "unknown" because it does not identify a lexical category. An empty dialect tuple means no recorded restriction.

Options are IntFlag values and may be combined with |. For example, strict case plus accent-insensitive fallback is:

options = Option.STRICT_CASE | Option.IGNORE_ACCENTS
analyses = context.analyze("a)/nqrwpos", options)

Passing no option uses the binding's default analysis behavior. See the native option table before enabling specialized modes.

Option.HQ_DICTIONARY requires both HQ index files. If they are absent, analyze() raises MorpheusError with Status.STEMLIB_ERROR before native analysis.

Generate forms from a lemma

[!WARNING] generate() and generate_raw() are experimental. Their automated differential, isolation, failure, portability, and sanitizer coverage is extensive, but sufficient real-world use is still required before this qualification can be removed.

from libmorpheus import (
    Dialect,
    GenerationOptions,
    Language,
    Library,
    MorpheusError,
    Number,
    Status,
)

try:
    with Library("/usr/local/lib/libmorpheus.so") as library:
        with library.context(
            "/path/to/stemlib", Language.GREEK
        ) as context:
            duals = context.generate(
                "lo/gos",
                GenerationOptions(
                    number=Number.DUAL,
                    dialect=Dialect.ATTIC,
                    result_limit=256,
                ),
            )
            for form in duals:
                print(form.surface, form.grammatical_cases)
except MorpheusError as error:
    if error.status == Status.RESULT_LIMIT_EXCEEDED:
        print("Increase the explicit result limit for this paradigm")
    else:
        raise

generate() accepts typed filters for part of speech, dialect, region, person, number, gender, case, tense, mood, voice, and degree. It preserves dialect masks, duals, duplicate surfaces, and multiple indexed interpretations unless filters remove them. Set exclude_duals=True when dual forms are unwanted. result_limit=0 uses the native default of 4,096; a nonzero value is a hard safety ceiling, not a truncation request. The explicit maximum is 65,536.

Use parallel contexts

Calls are synchronous at the Python surface. One context deliberately serializes its native operations because the underlying state is mutable. Create separate contexts and submit them to separate threads for independent work:

from concurrent.futures import ThreadPoolExecutor

with Library("/usr/local/lib/libmorpheus.so") as library:
    with (
        library.context(stemlib, Language.GREEK) as first,
        library.context(stemlib, Language.GREEK) as second,
        ThreadPoolExecutor(max_workers=2) as executor,
    ):
        analysis_future = executor.submit(first.analyze, "a)/nqrwpos")
        generation_future = executor.submit(second.generate, "lo/gos")
        analyses = analysis_future.result()
        forms = generation_future.result()

ctypes.CDLL releases the GIL during native calls, so distinct contexts can execute concurrently. The actual speedup depends on the workload and machine. Reuse warm contexts; the generation index is loaded lazily once per context.

Raw access and cleanup

Use analyze_raw() and generate_raw() for ABI inspection and low-level tools. They return numeric normalized traits, struct_size, the complete 11-byte public morphology vector, and a numeric truncation mask. The semantic methods return named morphology flags and truncated fields.

Close contexts before their parent library. Both objects support context managers and idempotent close() methods. Library.close() raises while any child context remains open. Context managers provide deterministic cleanup, including when an operation raises.

Other installation options

Install from a source checkout

For binding development, install the Python package from a checkout in editable mode:

python -m pip install -e bindings/python

This installs only the pure-Python facade. It does not compile or install the native runtime and does not copy stem data.

Build the native runtime

A recursive checkout can supply all three development components: the Python facade, native library, and Perseids stemlib.

git clone --recurse-submodules \
  https://github.com/defense-humanites/libmorpheus.git
cd libmorpheus
cmake --preset dev
cmake --build --preset dev --target morpheus
python -m pip install ./bindings/python

Use build/dev/libmorpheus.so on Linux or build/dev/libmorpheus.dylib on macOS, and use the checkout's stemlib/ directory for Greek and Latin analysis.

Native library and runtime data

The binding needs both a native libmorpheus library and a compatible stemlib. Neither is part of the Python wheel or source distribution.

Distribution Native library Stem data What to do
PyPI wheel or source distribution Not included Not included Install a compatible native release and acquire a stemlib.
Recursive project checkout Build with CMake Perseids submodule Pass the build output and stemlib/ paths explicitly.

Binding and runtime versions are independent. Python binding 0.1.0 targets native runtime 0.3.2 and requires C ABI 2. The package exports MORPHEUS_PYTHON_VERSION, MORPHEUS_NATIVE_VERSION, and MORPHEUS_NATIVE_ABI_VERSION; __version__ is the conventional alias for the Python package version.

Acquire stem data

For analysis from a source checkout, use its recursively initialized stemlib/ directory. It contains the Perseids dataset for Ancient Greek and Latin. The Alpheios dataset is a Greek-only alternative under vendor/alpheios-morpheus/dist/stemlib.

Experimental generation requires a prepared Alpheios directory containing a validated gener.index:

sh tools/prepare-runtime-data.sh "$PWD/morpheus-greek-data"

The output directory must not already exist. Pass its absolute path to Library.context(). See the complete runtime-data guide for pinned sources, validation, and redistribution boundaries.

Acquire the native library

Version 0.1.0 does not download native code during pip install and provides no Python acquisition command. Install the compatible v0.3.2 native archive from the GitHub releases page, or build the runtime from a matching source checkout as shown above. Pass the actual .so or .dylib path to Library; the binding does not search system paths or environment variables implicitly.

Language and data coverage

The operation and selected dataset together determine language coverage:

Operation or dataset Ancient Greek Latin Additional requirement
analyze() Yes Yes A stemlib for the selected language.
generate() Yes No Alpheios data prepared with gener.index.
Perseids Yes Yes No
Alpheios Yes No Prepare gener.index for generation.

See the stem-library inventory for dataset origins and repository locations.

Python and platform support

The package requires Python 3.11 or later, ships a py.typed marker, and has no third-party runtime dependencies. Its wheel is py3-none-any because the FFI layer is pure Python; execution still requires a compatible separately installed native library.

The release qualification matrix covers Python 3.11 and 3.14 on Linux with the real runtime and an ABI fixture. The native release currently provides Linux x86-64 glibc, Linux aarch64 glibc, and macOS arm64 archives. Windows is not supported by native runtime 0.3.2.

Documentation

Public classes, enums, immutable result dataclasses, and version constants are exported directly from libmorpheus. The package includes a py.typed marker for static type checkers.

Topic Document
Native ABI, ownership, and options Public API
Runtime and dataset acquisition Runtime data
AGPL/MPL file boundary Licensing guide
Source and dataset lineage Provenance
Available stem libraries Stem libraries
Supported platforms Portability
Release archives and qualification Releasing

Local checks

Build the library and small differential generation index before running the binding tests:

cmake --preset dev
cmake --build --preset dev --target \
  morpheus morpheus_gener_index_builder
build/dev/morpheus_gener_index_builder \
  stemlib/gener.index test/generation-service-source.txt
PYTHONDONTWRITEBYTECODE=1 \
PYTHONPATH=bindings/python/src \
python -B -m unittest discover -s bindings/python/test -v
PYTHONDONTWRITEBYTECODE=1 \
PYTHONPATH=bindings/python/src \
python -B bindings/python/test/runtime_smoke.py \
  build/dev/libmorpheus.so stemlib

Build and inspect the universal distributions with:

python -m build bindings/python
python -m pip install --no-deps bindings/python/dist/*.whl

License

The Python binding itself is licensed under AGPL-3.0-or-later. Its pure-Python ctypes facade does not inherit the mixed licensing of the separately installed native runtime and contains no linguistic stem data.

See the package notice and the project's licensing guide for the precise file-level boundary and redistribution considerations.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

libmorpheus-0.1.0.tar.gz (33.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

libmorpheus-0.1.0-py3-none-any.whl (28.4 kB view details)

Uploaded Python 3

File details

Details for the file libmorpheus-0.1.0.tar.gz.

File metadata

  • Download URL: libmorpheus-0.1.0.tar.gz
  • Upload date:
  • Size: 33.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for libmorpheus-0.1.0.tar.gz
Algorithm Hash digest
SHA256 96c07594bab49ebb6debbb4aa512b4e5590512a4dd5b47558c3632de35c8aa8a
MD5 796bab98b71ae79883f8995b0ef18566
BLAKE2b-256 07e9e83752faec10e61280541c56a2043bbbd4c0b6f6692c42df7e28bee076e5

See more details on using hashes here.

Provenance

The following attestation bundles were made for libmorpheus-0.1.0.tar.gz:

Publisher: python-release.yml on defense-humanites/libmorpheus

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file libmorpheus-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: libmorpheus-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 28.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for libmorpheus-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9775660a609b2810565c8f7d94b747b2846d3c64afdcc7fcb753a13fb199545e
MD5 a5a514a9d7306cf50d7ff7346f5cfcf5
BLAKE2b-256 17438cdf7330309ae4acf0f7de3808323ef2f887caabdf693c02593308f301d4

See more details on using hashes here.

Provenance

The following attestation bundles were made for libmorpheus-0.1.0-py3-none-any.whl:

Publisher: python-release.yml on defense-humanites/libmorpheus

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page