Advertisement
Guest User

Untitled

a guest
Apr 26th, 2019
115
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.52 KB | None | 0 0
  1. #!/usr/bin/env python
  2.  
  3. from __future__ import annotations
  4.  
  5. import logging
  6. import os
  7. import re
  8. import uuid
  9. from typing import Any, Dict, Optional, Type
  10. from uuid import uuid4
  11.  
  12. from sqlalchemy import (BigInteger, Boolean, Column, Date, DateTime, ForeignKey,
  13. ForeignKeyConstraint, Integer, SmallInteger, String,
  14. create_engine)
  15. from sqlalchemy.dialects.postgresql import UUID
  16. from sqlalchemy.ext.declarative import declarative_base
  17. from sqlalchemy.orm import relationship, scoped_session, sessionmaker
  18.  
  19. logger = logging.getLogger(__name__)
  20.  
  21. user = os.environ.get('DB_USER', 'postgres')
  22. password = os.environ.get('DB_PASSWORD', 'password')
  23. host = os.environ.get('DB_HOST', 'db2')
  24. port = os.environ.get('DB_PORT', '5432')
  25.  
  26. DeclarativeBase = declarative_base()
  27.  
  28.  
  29. class BaseModel(DeclarativeBase):
  30. __abstract__ = True
  31.  
  32. def __repr__(self) -> str:
  33. """Represent the model with all its fields, like a dataclass would."""
  34.  
  35. name = self.__class__.__name__
  36.  
  37. attrs_dict = {}
  38. for column in self.__table__.c:
  39. key = column.name
  40. value = getattr(self, key)
  41.  
  42. if isinstance(value, str) or isinstance(value, uuid.UUID):
  43. value = f"'{value}'"
  44.  
  45. attrs_dict[key] = value
  46.  
  47. attrs_repr = ', '.join(f'{k}={v}' for k, v in attrs_dict.items())
  48.  
  49. return f'{name}({attrs_repr})'
  50.  
  51.  
  52. class Order(BaseModel):
  53. __tablename__ = 'orders'
  54.  
  55. id = Column(UUID(as_uuid=True), primary_key=True, default=uuid4)
  56.  
  57. actions = relationship('OrderAction', back_populates='order')
  58.  
  59. rerun_links = relationship('RerunLink',
  60. back_populates='rerun_of_order',
  61. foreign_keys='RerunLink.rerun_of')
  62. rerun_of_link = relationship('RerunLink',
  63. back_populates='order',
  64. foreign_keys='RerunLink.order_id',
  65. uselist=False)
  66. reruns = relationship('Order',
  67. secondary='rerun_links',
  68. primaryjoin=('rerun_links.c.rerun_of == Order.id'),
  69. secondaryjoin=('rerun_links.c.order_id == Order.id'),
  70. back_populates='rerun_of')
  71. rerun_of = relationship('Order',
  72. secondary='rerun_links',
  73. primaryjoin=('rerun_links.c.order_id == Order.id'),
  74. secondaryjoin=('rerun_links.c.rerun_of == Order.id'),
  75. back_populates='reruns',
  76. uselist=False)
  77.  
  78.  
  79. class OrderAction(BaseModel):
  80. """All order actions (Cancellations, reruns, etc.)"""
  81. __tablename__ = 'order_actions'
  82.  
  83. id = Column(Integer, primary_key=True)
  84. order_id = Column(UUID(as_uuid=True), ForeignKey('orders.id'), nullable=False)
  85.  
  86. rerun = relationship('RerunLink', back_populates='action', uselist=False)
  87. order = relationship('Order', back_populates='actions')
  88.  
  89.  
  90. class RerunLink(BaseModel):
  91. """All new orders created based on old orders."""
  92. __tablename__ = 'rerun_links'
  93.  
  94. order_id = Column(UUID(as_uuid=True), ForeignKey('orders.id'), primary_key=True)
  95. rerun_of = Column(UUID(as_uuid=True), ForeignKey('orders.id'))
  96. action_id = Column(Integer, ForeignKey('order_actions.id'), unique=True, nullable=False)
  97.  
  98. order = relationship('Order', back_populates='rerun_of_link', foreign_keys=[order_id])
  99. rerun_of_order = relationship('Order', back_populates='rerun_links', foreign_keys=[rerun_of])
  100. action = relationship('OrderAction', back_populates='rerun')
  101.  
  102.  
  103. class DB:
  104. class __DB:
  105. engine: Engine
  106. session: scoped_session
  107.  
  108. def __init__(self) -> None:
  109. self.engine = create_engine(f'postgresql://{user}:{password}@{host}:{port}', convert_unicode=True)
  110. self.session = scoped_session(sessionmaker(autocommit=False,
  111. autoflush=False,
  112. bind=self.engine))
  113.  
  114. def query(self, model_class: Type[BaseModel]) -> Any:
  115. return self.session.query(model_class) # type: ignore
  116.  
  117. def commit(self) -> Any:
  118. return self.session.commit() # type: ignore
  119.  
  120. def drop_all(self) -> Any:
  121. DeclarativeBase.metadata.drop_all(bind=self.engine)
  122.  
  123. def create_all(self) -> Any:
  124. DeclarativeBase.metadata.create_all(bind=self.engine)
  125.  
  126. instance = None
  127.  
  128. def __init__(self) -> None:
  129. if not DB.instance:
  130. DB.instance = DB.__DB()
  131.  
  132. def __getattr__(self, name: str) -> Any:
  133. return getattr(self.instance, name)
  134.  
  135.  
  136. def recreate_db() -> None:
  137. DB().drop_all()
  138. DB().create_all()
  139.  
  140.  
  141. def test():
  142. # columns: id
  143. # relationships: actions, rerun_links, rerun_of_link, reruns, rerun_of
  144. old_order = Order()
  145. DB().session.add(old_order)
  146. DB().session.commit()
  147.  
  148. # columns: id, order_id
  149. # relationships: order
  150. action = OrderAction(order_id=old_order.id)
  151. DB().session.add(action)
  152. DB().session.commit()
  153.  
  154. # columns: id
  155. # relationships: actions, rerun_links, rerun_of_link, reruns, rerun_of
  156. new_order = Order(rerun_of=old_order)
  157. DB().session.add(new_order)
  158. DB().session.commit()
  159.  
  160. # columns: order_id, rerun_of, action_id
  161. # relationships: order, rerun_of_order, action
  162. rerun_link = RerunLink(rerun_of=old_order.id,
  163. action_id=action.id)
  164. DB().session.add(rerun_link)
  165. DB().session.commit()
  166.  
  167.  
  168. if __name__ == '__main__':
  169. recreate_db()
  170. test()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement