Last active
December 19, 2020 09:39
-
-
Save ricky-lim/9da923663417cfebf6a9c745b6a0d09c to your computer and use it in GitHub Desktop.
club-member
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import pytest | |
from sqlalchemy import ( | |
create_engine, | |
Column, | |
Integer, | |
String, | |
Table, | |
ForeignKey, | |
PrimaryKeyConstraint, | |
) | |
from sqlalchemy.ext.associationproxy import association_proxy | |
from sqlalchemy.orm import sessionmaker, relationship | |
from sqlalchemy.exc import IntegrityError | |
from sqlalchemy.ext.declarative import declarative_base | |
engine = create_engine("sqlite:///:memory:") | |
# engine = create_engine("sqlite:///clubs.sqlite") | |
Session = sessionmaker(bind=engine) | |
session = Session() | |
Base = declarative_base() | |
member_club = Table( | |
"member_club", | |
Base.metadata, | |
Column("member_id", Integer, ForeignKey("members.id"), nullable=False), | |
Column("club_id", Integer, ForeignKey("clubs.id")), | |
PrimaryKeyConstraint("member_id", "club_id"), | |
) | |
class Member(Base): | |
__tablename__ = "members" | |
id = Column(Integer, primary_key=True) | |
name = Column(String, unique=True, index=True) | |
clubs = relationship("Club", secondary=member_club, back_populates="members") | |
def __repr__(self): | |
return f"Member({self.name})" | |
class Club(Base): | |
__tablename__ = "clubs" | |
id = Column(Integer, primary_key=True) | |
name = Column(String, unique=True, index=True) | |
members = relationship("Member", secondary=member_club, back_populates="clubs") | |
member_names = association_proxy("members", "name") | |
def __init__(self, *args, **kwargs): | |
super().__init__(*args, **kwargs) | |
if not self.members: | |
raise ValueError("Club needs at least one member") | |
def remove_member(self, member_name): | |
if member_name not in self.member_names: | |
raise ValueError(f"{member_name} is not a member") | |
if member_name in self.member_names and len(self.member_names) == 1: | |
raise ValueError(f"{member_name} is the only member in the club!") | |
if member_name in self.member_names and len(self.member_names) >= 2: | |
self.members = [member for member in self.members if member.name != member] | |
print(f"{member_name} has been removed") | |
def __repr__(self): | |
return f"Club({self.name})" | |
Base.metadata.create_all(bind=engine) | |
m1 = Member(name="m1") | |
m2 = Member(name="m2") | |
m3 = Member(name="m3") | |
session.add_all([m1, m2, m3]) | |
session.commit() | |
with pytest.raises(ValueError) as e: | |
c1 = Club(name="c1") | |
assert "Club needs at least one member" in str(e) | |
c1 = Club(name="c1", members=[m1]) | |
session.add(c1) | |
session.commit() | |
with pytest.raises(ValueError) as e: | |
c1.remove_member("m1") | |
assert "m1 is the only member in the club" in str(e) | |
c2 = Club(name="c2", members=[m1, m2]) | |
session.add(c2) | |
session.commit() | |
c2.remove_member("m1") | |
c3 = Club(name="c3", members=[m2, m3]) | |
session.add(c3) | |
session.commit() | |
with pytest.raises(ValueError) as e: | |
c3.remove_member("m1") | |
assert "m1 is not a member" in str(e) | |
# Adding duplicated members | |
c4 = Club(name="c4", members=[m1, m2, m3, m3]) | |
try: | |
session.add(c4) | |
session.commit() | |
except IntegrityError as e: | |
session.rollback() | |
if "UNIQUE constraint failed" in str(e): | |
print("Adding duplicated members are not allowed") | |
print(f"{c4} not addedd") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment