You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

57 lines
2.1 KiB
Python

import re
from typing import List
from sqlalchemy import ForeignKey
from sqlalchemy import String
from sqlalchemy.orm import DeclarativeBase
from sqlalchemy.orm import Mapped
from sqlalchemy.orm import mapped_column
from sqlalchemy.orm import relationship
# See https://en.wikipedia.org/wiki/North_American_Numbering_Plan
PHONE_REGEX = "^(?:(?:\+?1\s*(?:[.-]\s*)?)?(?:\(\s*([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9])\s*\)|([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9]))\s*(?:[.-]\s*)?)?([2-9]1[02-9]|[2-9][02-9]1|[2-9][02-9]{2})\s*(?:[.-]\s*)?([0-9]{4})(?:\s*(?:#|x\.?|ext\.?|extension)\s*(\d+))?$" # noqa: E501
def _is_valid_phone_number(phone_number):
return bool(re.match(PHONE_REGEX, phone_number))
class Base(DeclarativeBase):
pass
class User(Base):
__tablename__ = "user"
id: Mapped[int] = mapped_column(primary_key=True)
username: Mapped[str] = mapped_column(String(30), unique=True)
primary_email: Mapped[str] = mapped_column(String(120), unique=True)
contacts: Mapped[List["Contact"]] = relationship(back_populates="user", cascade="all, delete-orphan")
def __repr__(self) -> str:
return f"User(id={self.id!r}, username={self.username!r})" # see format specifiers for !r
class Contact(Base):
__tablename__ = "contact"
id: Mapped[int] = mapped_column(primary_key=True)
user_id: Mapped[int] = mapped_column(ForeignKey("user.id"))
first_name: Mapped[str] = mapped_column(String(30))
last_name: Mapped[str] = mapped_column(String(30))
phone_contents: Mapped[str] = mapped_column(String(30))
email: Mapped[str] = mapped_column(String(120), unique=True)
user: Mapped["User"] = relationship(back_populates="contacts")
@property
def phone(self):
return self.phone_contents
@phone.setter
def phone(self, value):
if not _is_valid_phone_number(value):
raise ValueError(f"Invalid phone number {value}")
self.phone_contents = value
def __repr__(self) -> str:
return f"Contact(id={self.id!r}, first_name={self.first_name!r}, last_name={self.last_name!r}, phone={self.phone!r}, email={self.email!r})" # noqa: E501