earthsnake/earthsnake/share.py

62 lines
1.8 KiB
Python

"""Share handling"""
from random import choice
import re
from typing import Optional
from .exc import ValidationError
from .types import ALPHA_LOWER, ALPHA_LOWER_OR_DIGIT
class Share:
"""Class to handle a share (space or workspace in older terminology)"""
_NAME_PATTERN = f'[{ALPHA_LOWER}][{ALPHA_LOWER_OR_DIGIT}]{{0,14}}'
_SUFFIX_PATTERN = f'[{ALPHA_LOWER}][{ALPHA_LOWER_OR_DIGIT}]{{0,52}}'
PATTERN = f'^[+]{_NAME_PATTERN}[.]{_SUFFIX_PATTERN}$'
def __init__(self, name: str, suffix: Optional[str] = None) -> None:
suffix = suffix or self.generate_random_suffix()
if not re.match(f'^{self._NAME_PATTERN}$', name):
raise ValidationError(f'Invalid name "{name}"')
if not re.match(f'^{self._SUFFIX_PATTERN}$', suffix):
raise ValidationError(f'Invalid suffix "{suffix}"')
self.name = name
self.suffix = suffix
@classmethod
def validate_address(cls, share_address: str) -> None:
"""Check if share_address is a valid share address"""
if not re.match(cls.PATTERN, share_address):
raise ValidationError(f'Invalid share address {share_address}')
@classmethod
def from_address(cls, share_address: str) -> 'Share':
"""Create a Share object from a share address"""
cls.validate_address(share_address)
name, suffix = share_address[1:].split('.')
return cls(name, suffix)
@staticmethod
def generate_random_suffix(length: int = 53) -> str:
"""Generate a random share suffix of the desired length"""
assert 54 > length > 0
return choice(ALPHA_LOWER) + ''.join(
choice(ALPHA_LOWER_OR_DIGIT) for _ in range(length - 1)
)
def __str__(self) -> str:
return f'+{self.name}.{self.suffix}'
def __repr__(self) -> str:
return f'<Share {self}>'