mbuali's picture
Upload folder using huggingface_hub
d1ceb73 verified
"""Process URI templates per http://tools.ietf.org/html/rfc6570."""
from __future__ import annotations
import re
from typing import TYPE_CHECKING
from .expansions import (CommaExpansion, Expansion,
FormStyleQueryContinuation, FormStyleQueryExpansion,
FragmentExpansion, LabelExpansion, Literal,
PathExpansion, PathStyleExpansion,
ReservedCommaExpansion, ReservedExpansion, SimpleExpansion)
if (TYPE_CHECKING):
from collections.abc import Iterable
from .variable import Variable
class ExpansionReservedError(Exception):
"""Exception thrown for reserved but unsupported expansions."""
expansion: str
def __init__(self, expansion: str) -> None:
self.expansion = expansion
def __str__(self) -> str:
"""Convert to string."""
return 'Unsupported expansion: ' + self.expansion
class ExpansionInvalidError(Exception):
"""Exception thrown for unknown expansions."""
expansion: str
def __init__(self, expansion: str) -> None:
self.expansion = expansion
def __str__(self) -> str:
"""Convert to string."""
return 'Bad expansion: ' + self.expansion
class URITemplate:
"""
URI Template object.
Constructor may raise ExpansionReservedError, ExpansionInvalidError, or VariableInvalidError.
"""
expansions: list[Expansion]
def __init__(self, template: str) -> None:
self.expansions = []
parts = re.split(r'(\{[^\}]*\})', template)
for part in parts:
if (part):
if (('{' == part[0]) and ('}' == part[-1])):
expansion = part[1:-1]
if (re.match('^([a-zA-Z0-9_]|%[0-9a-fA-F][0-9a-fA-F]).*$', expansion)):
self.expansions.append(SimpleExpansion(expansion))
elif ('+' == part[1]):
self.expansions.append(ReservedExpansion(expansion))
elif ('#' == part[1]):
self.expansions.append(FragmentExpansion(expansion))
elif ('.' == part[1]):
self.expansions.append(LabelExpansion(expansion))
elif ('/' == part[1]):
self.expansions.append(PathExpansion(expansion))
elif (';' == part[1]):
self.expansions.append(PathStyleExpansion(expansion))
elif ('?' == part[1]):
self.expansions.append(FormStyleQueryExpansion(expansion))
elif ('&' == part[1]):
self.expansions.append(FormStyleQueryContinuation(expansion))
elif (',' == part[1]):
if ((1 < len(part)) and ('+' == part[2])):
self.expansions.append(ReservedCommaExpansion(expansion))
else:
self.expansions.append(CommaExpansion(expansion))
elif (part[1] in '=!@|'):
raise ExpansionReservedError(part)
else:
raise ExpansionInvalidError(part)
else:
if (('{' not in part) and ('}' not in part)):
self.expansions.append(Literal(part))
else:
raise ExpansionInvalidError(part)
@property
def variables(self) -> Iterable[Variable]:
"""Get all variables in template."""
vars: dict[str, Variable] = {}
for expansion in self.expansions:
for var in expansion.variables:
vars[var.name] = var
return vars.values()
@property
def variable_names(self) -> Iterable[str]:
"""Get names of all variables in template."""
vars: dict[str, Variable] = {}
for expansion in self.expansions:
for var in expansion.variables:
vars[var.name] = var
return [var.name for var in vars.values()]
def expand(self, **kwargs) -> str:
"""
Expand the template.
May raise ExpansionFailed if a composite value is passed to a variable with a prefix modifier.
"""
expanded = [expansion.expand(kwargs) for expansion in self.expansions]
return ''.join([expansion for expansion in expanded if (expansion is not None)])
def partial(self, **kwargs) -> URITemplate:
"""
Expand the template, preserving expansions for missing variables.
May raise ExpansionFailed if a composite value is passed to a variable with a prefix modifier.
"""
expanded = [expansion.partial(kwargs) for expansion in self.expansions]
return URITemplate(''.join(expanded))
@property
def expanded(self) -> bool:
"""Determine if template is fully expanded."""
return (str(self) == self.expand())
def __str__(self) -> str:
"""Convert to string, returns original template."""
return ''.join([str(expansion) for expansion in self.expansions])
def __repr__(self) -> str:
"""Convert to string, returns original template."""
return str(self)