Skip to content

Commit

Permalink
identifiers
Browse files Browse the repository at this point in the history
  • Loading branch information
daviddoret committed Dec 8, 2024
1 parent 9a2cedc commit 33bd4ec
Show file tree
Hide file tree
Showing 52 changed files with 191 additions and 50 deletions.
6 changes: 3 additions & 3 deletions .idea/2023_05_02_PyCharmProject_Maths.iml

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

2 changes: 1 addition & 1 deletion .idea/encodings.xml

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

74 changes: 52 additions & 22 deletions .idea/workspace.xml

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

Binary file modified src/punctilious/__pycache__/_foundations.cpython-312.pyc
Binary file not shown.
Binary file not shown.
Binary file modified src/punctilious/__pycache__/_presentation.cpython-312.pyc
Binary file not shown.
Binary file modified src/punctilious/__pycache__/_util.cpython-312.pyc
Binary file not shown.
26 changes: 2 additions & 24 deletions src/punctilious/_foundations.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
import yaml
import importlib.resources
import collections.abc
import re

# punctilious modules
import _util
from _util import get_logger
import _identifiers
import _presentation


Expand Down Expand Up @@ -144,30 +146,6 @@ def get_preferences():
return Preferences()


def ensure_slug(o: str | Slug) -> Slug:
if isinstance(o, Slug):
return o
elif isinstance(o, str):
return Slug(o)
else:
raise ValueError(f'Invalid slug {o}')


class Slug(str):
pass


class Slugs(dict):
def __init__(self):
super().__init__()

def __setitem__(self, slug, value):
slug = ensure_slug(o=slug)
if slug in self:
raise KeyError(f"Key '{slug}' already exists.")
super().__setitem__(slug, value)


class Import:
__slots__ = ('_slug', '_scheme', '_path', '_resource', '_method', '_package')

Expand Down
128 changes: 128 additions & 0 deletions src/punctilious/_identifiers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import re
import uuid
import typing


class Slug(str):
"""A slug is an identifier that uses lowercase alphanumeric ASCII characters with words
delimited with underscores."""

def __eq__(self, other):
return hash(self) == hash(other)

def __hash__(self):
return hash((self.__class__, str(self),))

def __init__(self, slug: str):
super().__init__()

def __new__(cls, slug: str):
pattern = r"^[a-zA-Z][a-zA-Z0-9]+(?:_[a-zA-Z0-9]+)*[a-zA-Z0-9]$"
if not bool(re.fullmatch(pattern, slug)):
raise ValueError(f'Invalid slug: "{slug}".')
return super().__new__(cls, slug)

def __repr__(self):
return f'"{str(super())}" slug'

def __str__(self):
return str(super())


class SlugsDictionary(dict):
"""A typed dictionary of slugs.
"""

def __init__(self):
super().__init__()

def __setitem__(self, slug, value):
slug = ensure_slug(o=slug)
if slug in self:
raise KeyError(f"Key '{slug}' already exists.")
super().__setitem__(slug, value)


FlexibleSlug = typing.Union[Slug, str]


def ensure_slug(o: FlexibleSlug) -> Slug:
"""Assure `o` is of type Slug, or implicitly convert `o` to Slug, or raise an error if this fails.
"""
if isinstance(o, Slug):
return o
elif isinstance(o, str):
i: str
return Slug(o)
else:
raise ValueError(f'Invalid slug {o}')


FlexibleUUID = typing.Union[uuid.UUID, str]


def ensure_uuid(o: str | uuid.UUID) -> uuid.UUID:
"""Assure `o` is of type uuid.UUID, or implicitly convert `o` to uuid.UUID, or raise an error if this fails.
"""
if isinstance(o, uuid.UUID):
return o
elif isinstance(o, str):
return uuid.UUID(o)
else:
raise ValueError(f'Invalid uuid {o}')


class Identifier(tuple):

def __eq__(self, other):
return hash(self) == hash(other)

def __hash__(self):
return hash((self.__class__, self[0], self[1], self[2],))

def __init__(self, i: FlexibleUUID, p: FlexibleSlug, s: FlexibleSlug):
"""A globally unique identifier composed of a UUID and a slug.
:param i: A uuid.
:param p: A package slug.
:param s: An object slug.
"""
i = ensure_uuid(i)
p = ensure_slug(p)
s = ensure_slug(s)
phi = (i, p, s,)
super().__init__(phi)

def __new__(cls, i: FlexibleUUID, p: FlexibleSlug, s: FlexibleSlug):
i = ensure_uuid(i)
p = ensure_slug(p)
s = ensure_slug(s)
phi = (i, p, s,)
return super().__new__(cls, phi)

def __repr__(self):
"""An unambiguous technical representation of the identifier.
:return:
"""
return f'{self[0]}.{self[2]} ({self[1]}) identifier'

def __str__(self):
"""A friendly representation of the identifier.
:return:
"""
return f'{self[0]}.{self[2]}'

@property
def package_slug(self) -> Slug:
return self[1]

@property
def package_uuid(self) -> uuid.UUID:
return self[0]

@property
def slug(self) -> Slug:
return self[2]
1 change: 1 addition & 0 deletions src/punctilious/_presentation.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import jinja2
# punctilious packages
import _util
import _identifiers


def ensure_tag(o) -> Tag:
Expand Down
4 changes: 4 additions & 0 deletions src/punctilious/_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,7 @@ def info(self, msg: str):

def get_logger():
return Logger()


class Id:
pass
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 comments on commit 33bd4ec

Please sign in to comment.