Skip to content

Commit

Permalink
[prakriya] Add drshya and anubandhas
Browse files Browse the repository at this point in the history
Available for certain pratyayas only.

- `drshya` returns the visible or "human-readable" form of some item.
  This method is not available on `Dhatu` because deriving this form
  for a dhatu requires much more work and can return multiple values
  for certain dhatus. Perhaps we will add this in the future if we
  can find a good trade-off here.

- `anubandhas` returns the anubandhas defined on the term. This method
  could be made available for `Dhatu` but is not available yet.

In addition, update some broken formatting in README.md.
  • Loading branch information
akprasad committed Jan 15, 2025
1 parent a2a68ad commit 861e810
Show file tree
Hide file tree
Showing 14 changed files with 527 additions and 43 deletions.
31 changes: 23 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ Installation
------------

Vidyut is implemented in [Rust][rust], which provides low-level control with
high-level ergonomics. We also provide first-class support for Python bindings
through the [vidyut][vidyut-py] Python package. This section describes how to
use Vidyut either through Rust or through Python.
high-level ergonomics. For your convenience, we also provide first-class support
for Python bindings through the [vidyut][vidyut-py] Python package. This section
describes how to use Vidyut either through Rust or through Python.

[pypi]: https://vidyut.readthedocs.io/en/latest/
[rust]: https://www.rust-lang.org/
[vidyut-py]: https://vidyut.readthedocs.io/en/latest/

### Through Rust

Expand Down Expand Up @@ -84,7 +84,7 @@ Python project.
Once your setup is ready, you can install the `vidyut` package:

```shell
# With Pip
# With pip
$ pip install vidyut

# With uv
Expand All @@ -108,6 +108,8 @@ We recommend using our pre-built linguistic data, which is available as a ZIP fi
For more information, see our [Python documentation][rtd].
[rtd]: https://vidyut.readthedocs.io/en/latest/
Building from source
--------------------
Expand Down Expand Up @@ -137,6 +139,7 @@ be much faster.
We recommend using our pre-built linguistic data, which is available as a ZIP file
[here][zip]. Or if you prefer, you can build this data for yourself:

[nextest]: https://nexte.st/
[zip]: https://github.com/ambuda-org/vidyut-py/releases/download/0.3.0/data-0.3.0.zip

```shell
Expand Down Expand Up @@ -245,9 +248,21 @@ For details, see the [vidyut-sandhi README][vidyut-sandhi].
Documentation
-------------

To view documentation for all crates (including private modules and structs),
run `make docs`. This command will generate Rust's standard documentation and
open it in your default web browser.
Our Rust documentation is available [on docs.rs][docs-rs], and our Python
documentation is available on [readthedocs.org][vidyut-rtd]. You can also build
our documentation from scratch:

- (Rust) To view documentation for all crates (including private modules and
structs), run `make docs` from the repository root. This command will
generate Rust's standard documentation and open it in your default web
browser.

- (Python) To view the latest build of our Python documentation, run `make docs`
from the `bindings-python` directory. This command will write our Python docs
to local HTML files, which you should then open manually.

[docs-rs]: https://docs.rs/releases/search?query=vidyut
[vidyut-rtd]: https://vidyut.readthedocs.io/en/latest/


Contributing
Expand Down
4 changes: 2 additions & 2 deletions bindings-python/CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ releases. That is, versions 0.x.a and 0.x.b will be able to use the same data.

Released 2025-01-12.

- Fix a `PanicException` when making many call to `transliterate`.
- Fix a `PanicException` when using the `YiWa` pratyaya.
- Fix a `PanicException` when making many calls to `transliterate`.
- Fix a `PanicException` when using the ``YiWa`` pratyaya.
- Add `Kosha.dhatus` and `Kosha.pratipadikas`.
- Update all `vidyut.prakriya` enums to use SLP1 strings for `as_str`.
- Update Python enums to use SLP1 strings for `__str__`.
Expand Down
8 changes: 4 additions & 4 deletions bindings-python/src/kosha/entries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ impl PyDhatuEntry {
self.dhatu.clone()
}

/// Convert this entry to a `Dhatu`.
/// Convert this entry to a :class:`~vidyut.prakriya.Dhatu`.
pub fn to_prakriya_args(&self) -> PyDhatu {
self.dhatu.clone()
}
Expand Down Expand Up @@ -140,7 +140,7 @@ impl PyPratipadikaEntry {
}
}

/// Convert this entry to a `Pratipadika`.
/// Convert this entry to a :class:`~vidyut.prakriya.Pratipadika`.
pub fn to_prakriya_args(&self) -> PyPratipadika {
use PyPratipadikaEntry as PE;
match self {
Expand Down Expand Up @@ -269,7 +269,7 @@ pub enum PyPadaEntry {
impl PyPadaEntry {
/// The lemma used by this *pada*.
///
/// The lemma is either aa *dhātu* or a simple *prātipadika*.
/// The lemma is either a *dhātu* or a simple *prātipadika*.
#[getter]
pub fn lemma(&self) -> Option<String> {
match self {
Expand Down Expand Up @@ -325,7 +325,7 @@ impl PyPadaEntry {
}
}

/// Convert this entry to a `Pada`.
/// Convert this entry to a :class:`~vidyut.prakriya.Pada`.
pub fn to_prakriya_args(&self) -> PyResult<PyPada> {
PyPada::try_from(self)
}
Expand Down
196 changes: 196 additions & 0 deletions bindings-python/src/macro_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,188 @@
///
/// For enum compat, see: https://github.com/PyO3/pyo3/issues/2887
macro_rules! py_enum {
($Py:ident, $Rust:ident, [$( $variant:ident ),*]) => {
impl From<$Rust> for $Py {
fn from(val: $Rust) -> Self {
match val {
$(
$Rust::$variant => $Py::$variant,
)*
}
}
}

impl From<$Py> for $Rust {
fn from(val: $Py) -> Self {
match val {
$(
$Py::$variant => $Rust::$variant,
)*
}
}
}

impl std::fmt::Display for $Py {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", $Rust::from(*self).as_str())
}
}

#[pymethods]
impl $Py {
#[new]
fn __new__(val: String) -> PyResult<$Py> {
// O(n), but this is a rare method not on a hot path, so it's fine for now.
for choice in Self::choices() {
if val == choice.__str__() {
return Ok(choice)
}
}
Err(pyo3::exceptions::PyValueError::new_err(
format!("{:?} is not a valid {}", val, stringify!($Rust))))
}

/*
fn __format__(&self, spec: String) -> String {
format!("{{{}:{}}}",
$Rust::from(*self).as_str(),
spec
)
}
*/

fn __getitem__(&self, val: String) -> PyResult<$Py> {
// O(n), but this is a rare method not on a hot path, so it's fine for now.
for choice in Self::choices() {
if val == choice.name() {
return Ok(choice)
}
}
Err(pyo3::exceptions::PyKeyError::new_err(String::new()))
}

fn __hash__(&self) -> u64 {
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
let mut hasher = DefaultHasher::new();
self.hash(&mut hasher);
hasher.finish()
}

pub(crate) fn __repr__(&self) -> String {
format!("{}.{}", stringify!{$Rust}, self.name())
}

/// The string representation of this enum.
///
/// `__str__` returns a valid SLP1 string. This string might include
/// accent marks (``\\``, ``^``) or nasality markers (``~``).
fn __str__(&self) -> String {
self.value()
}

// Enum built-ins
// -------------------

/// The name used to define the `Enum` member.
#[getter]
fn name(&self) -> String {
let ret = match self {
$(
$Py::$variant => stringify!($variant),
)*
};
ret.to_string()
}

/// The name used to define the `Enum` member. This is identical
/// to `name`.
///
/// (For compatibility with Python `Enum`).
#[getter]
fn _name_(&self) -> String {
self.name()
}

/// The name used to define the `Enum` member.
///
/// The returned value is guaranteed to be identical to the output of
/// `__str__`.
#[getter]
fn value(&self) -> String {
$Rust::from(*self).as_str().to_string()
}

/// The value associated with this variant. This is identical
/// to `value`.
///
/// (For compatibility with Python `Enum`).
#[getter]
fn _value_(&self) -> String {
self.value()
}

/// Return all possible values for this enum.
#[staticmethod]
fn choices() -> Vec<$Py> {
const CHOICES: &[$Py] = &[
$(
$Py::$variant,
)*
];
CHOICES.to_vec()
}

/// DEPRECATED -- prefer `__new__` instead.
///
/// Create an enum value from the given string.
///
/// This is the inverse of `__str__`. Performance is currently linear
/// in the number of enum options.
#[staticmethod]
fn from_string(val: &str) -> PyResult<Self> {
// O(n), but this is a rare method not on a hot path, so it's fine for now.
for choice in Self::choices() {
if val == choice.__str__() {
return Ok(choice)
}
}
Err(pyo3::exceptions::PyValueError::new_err(format!("Could not parse {val}")))
}

}
}
}

/// Helper macro for pratyayas (Krt, Taddhita, Sanadi)
///
/// Generates the following boilerplate methods:
///
/// - `From<RustEnum> for PyEnum`
/// - `From<PyEnum> for RustEnum`
/// - `__new__`
/// - `__format__`
/// - `__hash__`
/// - `__repr__`
/// - `__str__`
/// - `choices`
///
/// And the following boilerplate attributes:
/// - `drshya`
/// - `anubandhas`
/// - `name`
/// - `value`
/// - `_name_`
/// - `_value_`
///
/// `__iter__` is not possible since it requires accessing the metaclass.
/// See https://github.com/PyO3/pyo3/issues/906 and related issues.
///
/// Requirements:
/// - Enum must derive `Hash`
///
/// For enum compat, see: https://github.com/PyO3/pyo3/issues/2887
macro_rules! py_pratyaya {
($Py:ident, $Rust:ident, [$( $variant:ident ),*]) => {
impl From<$Rust> for $Py {
fn from(val: $Rust) -> Self {
Expand Down Expand Up @@ -167,6 +349,19 @@ macro_rules! py_enum {
}
Err(pyo3::exceptions::PyValueError::new_err(format!("Could not parse {val}")))
}

// Pratyaya methods
// ----------------

fn drshya(&self) -> String {
let rust = $Rust::from(*self);
rust.drshya().to_string()
}

fn anubandhas(&self) -> Vec<PyAnubandha> {
let rust = $Rust::from(*self);
rust.anubandhas().iter().map(|x| (*x).into()).collect()
}
}
}
}
Expand Down Expand Up @@ -274,3 +469,4 @@ macro_rules! py_only_enum {

pub(crate) use py_enum;
pub(crate) use py_only_enum;
pub(crate) use py_pratyaya;
Loading

0 comments on commit 861e810

Please sign in to comment.