Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add VersionWithSource type to py-rattler #304

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 15 additions & 15 deletions py-rattler/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 8 additions & 2 deletions py-rattler/rattler/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
from rattler.version import Version
from rattler.version import Version, VersionWithSource
from rattler.match_spec import MatchSpec, NamelessMatchSpec
from rattler.repo_data import PackageRecord

__all__ = ["Version", "MatchSpec", "NamelessMatchSpec", "PackageRecord"]
__all__ = [
"Version",
"VersionWithSource",
"MatchSpec",
"NamelessMatchSpec",
"PackageRecord",
]
3 changes: 2 additions & 1 deletion py-rattler/rattler/version/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from rattler.version.version import Version
from rattler.version.with_source import VersionWithSource

__all__ = ["Version"]
__all__ = ["Version", "VersionWithSource"]
90 changes: 90 additions & 0 deletions py-rattler/rattler/version/with_source.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
from __future__ import annotations

from typing import Optional

from rattler.version import Version


class VersionWithSource:
Wackyator marked this conversation as resolved.
Show resolved Hide resolved
"""
Holds a version and the string it was created from. This is useful if
you want to retain the original string the version was created from.
This might be useful in cases where you have multiple strings that
are represented by the same [`Version`] but you still want to be able to
distinguish them.

The string `1.1` and `1.01` represent the same version. When you print
the parsed version though it will come out as `1.1`. You loose the
original representation. This class stores the original source string,
which can be accessed by `source` property.
"""

def __init__(self, source: str, version: Optional[Version] = None):
Wackyator marked this conversation as resolved.
Show resolved Hide resolved
if not isinstance(source, str):
raise TypeError(
"VersionWithSource constructor received unsupported type "
f" {type(source).__name__!r} for the `source` parameter"
)

if version is None:
version = Version(source)

if not isinstance(version, Version):
raise TypeError(
"VersionWithSource constructor received unsupported type "
f" {type(version).__name__!r} for the `version` parameter"
)

self._source = source
self._version = version

@property
def version(self) -> Version:
"""
Returns the `Version` from current object.

Examples
--------
>>> v = VersionWithSource("1.01")
>>> v.version
Version("1.1")
>>> v2 = VersionWithSource("1.01", v.version)
>>> v2.version
Version("1.1")
"""
return self._version

@property
def source(self) -> str:
"""
Returns the `source` current object was used to create.

Examples
--------
>>> v = VersionWithSource("1.01.01")
>>> v.source
'1.01.01'
"""
return self._source

def __str__(self) -> str:
"""
Returns the string representation of the version

Examples
--------
>>> str(VersionWithSource("1.02.3"))
'1.02.3'
"""
return self._source

def __repr__(self) -> str:
"""
Returns a representation of the version

Examples
--------
>>> VersionWithSource("1.02.3")
VersionWithSource("1.02.3")
"""
return f'{type(self).__name__}("{self.__str__()}")'
3 changes: 2 additions & 1 deletion py-rattler/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ use error::{
use match_spec::PyMatchSpec;
use nameless_match_spec::PyNamelessMatchSpec;
use repo_data::package_record::PyPackageRecord;
use version::PyVersion;
use version::{PyVersion, PyVersionWithSource};

use pyo3::prelude::*;

#[pymodule]
fn rattler(py: Python, m: &PyModule) -> PyResult<()> {
m.add_class::<PyVersion>().unwrap();
m.add_class::<PyVersionWithSource>().unwrap();

m.add_class::<PyMatchSpec>().unwrap();
m.add_class::<PyNamelessMatchSpec>().unwrap();
Expand Down
13 changes: 11 additions & 2 deletions py-rattler/src/version/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod component;
mod with_source;

use crate::PyRattlerError;
use component::PyComponent;
Expand All @@ -10,11 +11,13 @@ use std::{
str::FromStr,
};

#[pyclass]
pub use with_source::PyVersionWithSource;

#[pyclass(subclass)]
#[repr(transparent)]
#[derive(Clone)]
pub struct PyVersion {
inner: Version,
pub(crate) inner: Version,
}

impl From<Version> for PyVersion {
Expand All @@ -23,6 +26,12 @@ impl From<Version> for PyVersion {
}
}

impl From<PyVersion> for Version {
fn from(value: PyVersion) -> Self {
value.inner
}
}

#[pymethods]
impl PyVersion {
#[new]
Expand Down
59 changes: 59 additions & 0 deletions py-rattler/src/version/with_source.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
use std::{
collections::hash_map::DefaultHasher,
hash::{Hash, Hasher},
};

use pyo3::{basic::CompareOp, pyclass, pymethods, PyClassInitializer};
use rattler_conda_types::VersionWithSource;

use crate::version::PyVersion;

#[pyclass(extends=PyVersion, subclass)]
#[repr(transparent)]
#[derive(Clone)]
pub struct PyVersionWithSource {
pub(crate) inner: VersionWithSource,
}

impl From<VersionWithSource> for PyVersionWithSource {
fn from(value: VersionWithSource) -> Self {
Self { inner: value }
}
}

impl From<PyVersionWithSource> for VersionWithSource {
fn from(value: PyVersionWithSource) -> Self {
value.inner
}
}

#[pymethods]
impl PyVersionWithSource {
#[new]
pub fn new(version: &PyVersion, source: String) -> pyo3::PyClassInitializer<Self> {
PyClassInitializer::from(version.clone())
.add_subclass(VersionWithSource::new(version.inner.clone(), source).into())
}

/// Returns the `PyVersion` from current object.
pub fn version(&self) -> PyVersion {
self.inner.version().clone().into()
}

/// Returns a string representation of `PyVersionWithSource`.
pub fn as_str(&self) -> String {
self.inner.as_str().into_owned()
}

/// Compute the hash of the version.
fn __hash__(&self) -> u64 {
let mut hasher = DefaultHasher::new();
self.inner.hash(&mut hasher);
hasher.finish()
}

/// Performs comparison between this version and another.
pub fn __richcmp__(&self, other: &Self, op: CompareOp) -> bool {
op.matches(self.inner.cmp(&other.inner))
}
Wackyator marked this conversation as resolved.
Show resolved Hide resolved
}