Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
12 changes: 12 additions & 0 deletions src/curies/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,10 @@ def without_name(self) -> Reference:
"""Return this reference, since it already has no name."""
return self

def with_name(self, name: str) -> NamableReference:
"""Return this reference, with a name."""
return NamedReference(prefix=self.prefix, identifier=self.identifier, name=name)

@classmethod
def from_curie(cls, curie: str, *, sep: str = ":", converter: Converter | None = None) -> Self:
"""Parse a CURIE string and populate a reference.
Expand Down Expand Up @@ -580,6 +584,10 @@ def without_name(self) -> Reference:
"""Return this reference without a name."""
return Reference(prefix=self.prefix, identifier=self.identifier)

def with_name(self, name: str) -> Self:
"""Return this reference, with a name."""
return self.model_copy(update={"name": name})


class NamedReference(NamableReference):
"""A reference with a name."""
Expand Down Expand Up @@ -638,6 +646,10 @@ def from_reference(
context=converter,
)

def with_name(self, name: str) -> Self:
"""Return this reference, with a name."""
return self.model_copy(update={"name": name})


RecordKey = tuple[str, str, str, str]

Expand Down
150 changes: 0 additions & 150 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

import pandas as pd
import rdflib
from pydantic import ValidationError

import curies
from curies.api import (
Expand All @@ -21,11 +20,8 @@
DuplicatePrefixes,
DuplicateURIPrefixes,
ExpansionError,
NamableReference,
NamedReference,
PrefixStandardizationError,
Record,
Records,
Reference,
ReferenceTuple,
URIStandardizationError,
Expand All @@ -39,159 +35,13 @@
get_monarch_converter,
get_obo_converter,
)
from curies.utils import NoCURIEDelimiterError
from curies.version import get_version
from tests.constants import SLOW

CHEBI_URI_PREFIX = "http://purl.obolibrary.org/obo/CHEBI_"
GO_URI_PREFIX = "http://purl.obolibrary.org/obo/GO_"


class TestStruct(unittest.TestCase):
"""Test the data structures."""

def test_not_curie(self) -> None:
"""Test a malformed CURIE."""
with self.assertRaises(NoCURIEDelimiterError) as e:
Reference.from_curie("not a curie")
self.assertIn("does not appear to be a CURIE", str(e.exception))

def test_default_prefix(self) -> None:
"""Test a default (empty) prefix."""
ref = Reference.from_curie(":something")
self.assertEqual("", ref.prefix)
self.assertEqual("something", ref.identifier)

def test_default_identifier(self) -> None:
"""Test a default (empty) identifier."""
ref = Reference.from_curie("p1:")
self.assertEqual("p1", ref.prefix)
self.assertEqual("", ref.identifier)

def test_multiple_delimiters(self) -> None:
"""Test a default (empty) identifier."""
ref = Reference.from_curie("a1:b2:c3")
self.assertEqual("a1", ref.prefix)
self.assertEqual("b2:c3", ref.identifier)

def test_records(self) -> None:
"""Test a list of records."""
records = Records.model_validate([{"prefix": "chebi", "uri_prefix": CHEBI_URI_PREFIX}])
converter = Converter(records=records)
self.assertEqual({"chebi"}, converter.get_prefixes())

def test_sort(self) -> None:
"""Test sorting."""
start = [
Reference.from_curie("def:1234"),
Reference.from_curie("abc:1234"),
Reference.from_curie("abc:1235"),
]
expected = [
Reference.from_curie("abc:1234"),
Reference.from_curie("abc:1235"),
Reference.from_curie("def:1234"),
]
self.assertEqual(expected, sorted(start))

def test_set_membership(self) -> None:
"""Test membership in sets."""
collection = {
Reference.from_curie("def:1234"),
Reference.from_curie("abc:1234"),
Reference.from_curie("abc:1235"),
}
self.assertIn(Reference.from_curie("def:1234"), collection)
self.assertNotIn(Reference.from_curie("xyz:1234"), collection)
self.assertNotIn(Reference.from_curie(":1234"), collection)
self.assertNotIn(Reference.from_curie("abc:"), collection)

def test_named_set_membership(self) -> None:
"""Test membership in sets of named references."""
references = {
NamedReference.from_curie("a:1", "name1"),
NamedReference.from_curie("a:2", "name2"),
}
self.assertIn(Reference.from_curie("a:1"), references)
self.assertIn(NamableReference.from_curie("a:1"), references)
self.assertIn(NamedReference.from_curie("a:1", "name1"), references)
self.assertIn(NamableReference.from_curie("a:1", "name1"), references)
# the following is a weird case, but shows how this works
self.assertIn(NamedReference.from_curie("a:1", "name2"), references)

references_2 = {
Reference.from_curie("a:1"),
Reference.from_curie("a:2"),
}
self.assertIn(Reference.from_curie("a:1"), references_2)
self.assertIn(NamableReference.from_curie("a:1", "name1"), references_2)
self.assertIn(NamedReference.from_curie("a:1", "name1"), references_2)

def test_tuple(self) -> None:
"""Test reference tuples."""
t = ReferenceTuple.from_curie("a:1")
self.assertEqual(Reference(prefix="a", identifier="1"), t.to_pydantic())
self.assertEqual(
NamedReference(prefix="a", identifier="1", name="name"), t.to_pydantic(name="name")
)
with self.assertRaises(ValueError):
t.to_pydantic(name="")

def test_reference_constructor(self) -> None:
"""Test constructing a reference."""
r1 = Reference(prefix="a", identifier="1")
r2 = NamableReference(prefix="a", identifier="2")
r3 = NamableReference(prefix="a", identifier="3", name="item 3")
r4 = NamedReference(prefix="a", identifier="4", name="item 4")

self.assertEqual(Reference(prefix="a", identifier="1"), Reference.from_reference(r1))
self.assertEqual(Reference(prefix="a", identifier="2"), Reference.from_reference(r2))
self.assertEqual(Reference(prefix="a", identifier="3"), Reference.from_reference(r3))
self.assertEqual(Reference(prefix="a", identifier="4"), Reference.from_reference(r4))

self.assertEqual(
NamableReference(prefix="a", identifier="1", name=None),
NamableReference.from_reference(r1),
)
self.assertEqual(
NamableReference(prefix="a", identifier="2", name=None),
NamableReference.from_reference(r2),
)
self.assertEqual(
NamableReference(prefix="a", identifier="3", name="item 3"),
NamableReference.from_reference(r3),
)
self.assertEqual(
NamableReference(prefix="a", identifier="4", name="item 4"),
NamableReference.from_reference(r4),
)

with self.assertRaises(TypeError):
NamedReference.from_reference(r1)
with self.assertRaises(ValidationError):
NamedReference.from_reference(r2)
self.assertEqual(
NamedReference(prefix="a", identifier="3", name="item 3"),
NamedReference.from_reference(r3),
)
self.assertEqual(
NamedReference(prefix="a", identifier="4", name="item 4"),
NamedReference.from_reference(r4),
)

def test_without_name(self) -> None:
"""Test removing names."""
c1 = Reference.from_curie("a:1")
c2 = NamableReference.from_curie("a:1")
c3 = NamableReference.from_curie("a:1", name="test")
c4 = NamedReference.from_curie("a:1", name="test")

for reference in [c1, c2, c3, c4]:
new = reference.without_name()
self.assertIsInstance(new, Reference)
self.assertNotIsInstance(new, NamableReference)


class TestAddRecord(unittest.TestCase):
"""Test adding records."""

Expand Down
174 changes: 174 additions & 0 deletions tests/test_struct.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
"""Tests for the structure."""

from __future__ import annotations

import unittest

from pydantic import ValidationError

import curies
from curies.api import (
Converter,
NamableReference,
NamedReference,
Records,
Reference,
ReferenceTuple,
)
from curies.utils import NoCURIEDelimiterError

CHEBI_URI_PREFIX = "http://purl.obolibrary.org/obo/CHEBI_"


class TestStruct(unittest.TestCase):
"""Test the data structures."""

def test_not_curie(self) -> None:
"""Test a malformed CURIE."""
with self.assertRaises(NoCURIEDelimiterError) as e:
Reference.from_curie("not a curie")
self.assertIn("does not appear to be a CURIE", str(e.exception))

def test_default_prefix(self) -> None:
"""Test a default (empty) prefix."""
ref = Reference.from_curie(":something")
self.assertEqual("", ref.prefix)
self.assertEqual("something", ref.identifier)

def test_default_identifier(self) -> None:
"""Test a default (empty) identifier."""
ref = Reference.from_curie("p1:")
self.assertEqual("p1", ref.prefix)
self.assertEqual("", ref.identifier)

def test_multiple_delimiters(self) -> None:
"""Test a default (empty) identifier."""
ref = Reference.from_curie("a1:b2:c3")
self.assertEqual("a1", ref.prefix)
self.assertEqual("b2:c3", ref.identifier)

def test_records(self) -> None:
"""Test a list of records."""
records = Records.model_validate([{"prefix": "chebi", "uri_prefix": CHEBI_URI_PREFIX}])
converter = Converter(records=records)
self.assertEqual({"chebi"}, converter.get_prefixes())

def test_sort(self) -> None:
"""Test sorting."""
start = [
Reference.from_curie("def:1234"),
Reference.from_curie("abc:1234"),
Reference.from_curie("abc:1235"),
]
expected = [
Reference.from_curie("abc:1234"),
Reference.from_curie("abc:1235"),
Reference.from_curie("def:1234"),
]
self.assertEqual(expected, sorted(start))

def test_set_membership(self) -> None:
"""Test membership in sets."""
collection = {
Reference.from_curie("def:1234"),
Reference.from_curie("abc:1234"),
Reference.from_curie("abc:1235"),
}
self.assertIn(Reference.from_curie("def:1234"), collection)
self.assertNotIn(Reference.from_curie("xyz:1234"), collection)
self.assertNotIn(Reference.from_curie(":1234"), collection)
self.assertNotIn(Reference.from_curie("abc:"), collection)

def test_named_set_membership(self) -> None:
"""Test membership in sets of named references."""
references = {
NamedReference.from_curie("a:1", "name1"),
NamedReference.from_curie("a:2", "name2"),
}
self.assertIn(Reference.from_curie("a:1"), references)
self.assertIn(NamableReference.from_curie("a:1"), references)
self.assertIn(NamedReference.from_curie("a:1", "name1"), references)
self.assertIn(NamableReference.from_curie("a:1", "name1"), references)
# the following is a weird case, but shows how this works
self.assertIn(NamedReference.from_curie("a:1", "name2"), references)

references_2 = {
Reference.from_curie("a:1"),
Reference.from_curie("a:2"),
}
self.assertIn(Reference.from_curie("a:1"), references_2)
self.assertIn(NamableReference.from_curie("a:1", "name1"), references_2)
self.assertIn(NamedReference.from_curie("a:1", "name1"), references_2)

def test_tuple(self) -> None:
"""Test reference tuples."""
t = ReferenceTuple.from_curie("a:1")
self.assertEqual(Reference(prefix="a", identifier="1"), t.to_pydantic())
self.assertEqual(
NamedReference(prefix="a", identifier="1", name="name"), t.to_pydantic(name="name")
)
with self.assertRaises(ValueError):
t.to_pydantic(name="")

def test_reference_constructor(self) -> None:
"""Test constructing a reference."""
r1 = Reference(prefix="a", identifier="1")
r2 = NamableReference(prefix="a", identifier="2")
r3 = NamableReference(prefix="a", identifier="3", name="item 3")
r4 = NamedReference(prefix="a", identifier="4", name="item 4")

self.assertEqual(Reference(prefix="a", identifier="1"), Reference.from_reference(r1))
self.assertEqual(Reference(prefix="a", identifier="2"), Reference.from_reference(r2))
self.assertEqual(Reference(prefix="a", identifier="3"), Reference.from_reference(r3))
self.assertEqual(Reference(prefix="a", identifier="4"), Reference.from_reference(r4))

self.assertEqual(
NamableReference(prefix="a", identifier="1", name=None),
NamableReference.from_reference(r1),
)
self.assertEqual(
NamableReference(prefix="a", identifier="2", name=None),
NamableReference.from_reference(r2),
)
self.assertEqual(
NamableReference(prefix="a", identifier="3", name="item 3"),
NamableReference.from_reference(r3),
)
self.assertEqual(
NamableReference(prefix="a", identifier="4", name="item 4"),
NamableReference.from_reference(r4),
)

with self.assertRaises(TypeError):
NamedReference.from_reference(r1)
with self.assertRaises(ValidationError):
NamedReference.from_reference(r2)
self.assertEqual(
NamedReference(prefix="a", identifier="3", name="item 3"),
NamedReference.from_reference(r3),
)
self.assertEqual(
NamedReference(prefix="a", identifier="4", name="item 4"),
NamedReference.from_reference(r4),
)

def test_without_name(self) -> None:
"""Test removing names."""
c1 = Reference.from_curie("a:1")
c2 = NamableReference.from_curie("a:1")
c3 = NamableReference.from_curie("a:1", name="test")
c4 = NamedReference.from_curie("a:1", name="test")

for reference in [c1, c2, c3, c4]:
new = reference.without_name()
self.assertIsInstance(new, Reference)
self.assertNotIsInstance(new, NamableReference)

def test_with_name(self) -> None:
"""Test with name."""
r1 = curies.Reference.from_curie("chebi:1234")
r2 = r1.with_name("test")
self.assertIsInstance(r2, NamedReference)
r3 = r2.without_name()
self.assertIsInstance(r3, Reference)
self.assertNotIsInstance(r3, NamableReference)
Loading