class Rule(Native): __mapper_args__ = {"concrete": True} __tablename__ = "Rules" permissions = ("None", "Own", "Foreign", "All") id = Column(Integer, primary_key=True) role_id = Column(Integer, ForeignKey("Roles.id")) route = Column(String(255)) insert = Column(Enum(*permissions)) remove = Column(Enum(*permissions)) change = Column(Enum(*permissions)) view = Column(Enum(*permissions)) search = Column(Enum(*permissions)) role = relation(Role, "role_id") # ---------------------------------------------------------------------------- # def __init__(self, role_id=0, route=None, insert=None, remove=None, change=None, view=None, search=None): self.role_id = role_id self.route = route self.insert = insert self.remove = remove self.change = change self.view = view self.search = search
def __init__(self, enum: Any) -> None: self.enum = enum self.impl = Enum(*enum.values(), name="ck{0}".format( re.sub('([A-Z])', lambda m: "_" + m.group(1).lower(), enum.__name__)))
class ReportTableDefinition(JusticeCountsBase): """The definition for what a table within a report describes.""" __tablename__ = "report_table_definition" id = Column(Integer, autoincrement=True) system = Column(Enum(System)) metric_type = Column(Enum(MetricType)) measurement_type = Column(Enum(MeasurementType)) # Any dimensions where the data in the table only accounts for a subset of values for that dimension. For instance, # a table for the population metric may only cover data for the prison population, not those on parole or # probation. In that case filters would include a filter on population type. filtered_dimensions = Column(ARRAY(String(255))) # The value for each dimension from the above array. filtered_dimension_values = Column(ARRAY(String(255))) # The dimensions that the metric is broken down by in the report table. Each cell in a table instance has a unique # combination of values for the aggregated dimensions. Dimensions are sorted deterministically within the array. aggregated_dimensions = Column(ARRAY(String(255))) __table_args__ = tuple( [ PrimaryKeyConstraint(id), UniqueConstraint( metric_type, measurement_type, filtered_dimensions, filtered_dimension_values, aggregated_dimensions, ), ] )
class DeclEnumType(SchemaType, TypeDecorator): def __init__(self, enum): self.enum = enum self.impl = Enum( *enum.values(), name="ck%s" % re.sub( '([A-Z])', lambda m: "_" + m.group(1).lower(), enum.__name__) ) def _set_table(self, table, column): self.impl._set_table(table, column) def copy(self): return DeclEnumType(self.enum) def process_bind_param(self, value, dialect): if value is None: return None return value.value def process_result_value(self, value, dialect): if value is None: return None return self.enum.from_string(value.strip())
class DeclEnumType(SchemaType, TypeDecorator): """Declarative enumeration type.""" def __init__(self, enum: Any) -> None: self.enum = enum self.impl = Enum( *enum.values(), name="ck{0}".format(re.sub('([A-Z])', lambda m: "_" + m.group(1).lower(), enum.__name__)) ) def _set_table(self, table: Column, column: Table) -> None: self.impl._set_table(table, column) def copy(self) -> DeclEnumType: """Get enumeration type of self.""" return DeclEnumType(self.enum) def process_bind_param(self, value: EnumSymbol, dialect: SQLiteDialect_pysqlite) -> str: """Get process bind parameter.""" if value is None: return None return value.value def process_result_value(self, value: str, dialect: SQLiteDialect_pysqlite) -> EnumSymbol: """Get process result value.""" if value is None: return None return self.enum.from_string(value.strip())
class City(Base): __repr_args__ = 'name', 'size_code' # Column definition id = column(Integer, primary_key=True) name = column(Text, unique=True) size_code = column(Enum('S', 'M', 'L', 'XL', name='ck_city_size_type')) # Relationships citizens = relationship('Person', back_populates='city') companies = relationship('Company', back_populates='city') _links_higher = relationship('TransportLink', back_populates='lower_city', foreign_keys='TransportLink.lower_city_id') _links_lower = relationship('TransportLink', back_populates='higher_city', foreign_keys='TransportLink.higher_city_id') @property def transport_links(self): """Mapping of all transport links and associated costs.""" def link_getter(relative): for link in getattr(self, f'_links_{relative}'): yield getattr(link, f'{relative}_city'), link.distance return dict(chain(link_getter('higher'), link_getter('lower')))
class DataBlockLog(BaseModel): id = Column(Integer, primary_key=True, autoincrement=True) snap_log_id = Column(Integer, ForeignKey(SnapLog.id), nullable=False) data_block_id = Column( String(128), ForeignKey(f"{SNAPFLOW_METADATA_TABLE_PREFIX}data_block_metadata.id"), nullable=False, ) stream_name = Column(String(128), nullable=True) direction = Column(Enum(Direction, native_enum=False), nullable=False) processed_at = Column(DateTime, default=func.now(), nullable=False) invalidated = Column(Boolean, default=False) # Hints data_block: "DataBlockMetadata" snap_log: SnapLog def __repr__(self): return self._repr( id=self.id, snap_log=self.snap_log, data_block=self.data_block, direction=self.direction, processed_at=self.processed_at, ) @classmethod def summary(cls, env: Environment) -> str: s = "" for dbl in env.md_api.execute(select(DataBlockLog)).scalars().all(): s += f"{dbl.snap_log.node_key:50}" s += f"{str(dbl.data_block_id):23}" s += f"{str(dbl.data_block.record_count):6}" s += f"{dbl.direction.value:9}{str(dbl.data_block.updated_at):22}" s += f"{dbl.data_block.nominal_schema_key:20}{dbl.data_block.realized_schema_key:20}\n" return s
class Handout(BaseModel): __tablename__ = 'campaign_handout' id = Column(Integer, primary_key=True) title = Column(String(256)) content = Column(Text) campaign_id = Column(Integer, ForeignKey('campaign.id')) campaign = relationship("Campaign", back_populates='handouts') status = Column('status', Enum(HandoutStatus), default=HandoutStatus.draft) players = relationship('UserProfile', secondary=player_handouts, lazy='dynamic', backref=backref('campaign_handouts', lazy=True)) group_id = Column(Integer, ForeignKey('campaign_handout_group.id')) group = relationship('HandoutGroup') def __repr__(self): return '<Handout {}>'.format(self.title) _default_fields = ['id', 'title'] @property def url(self): return url_for('campaign.handout_view', campaign_id=self.campaign.id, handout_id=self.id)
class Report(JusticeCountsBase): """A document that is published by a source that contains data pertaining to the Justice Counts Framework. """ __tablename__ = 'report' id = Column(Integer, autoincrement=True) # The source that this report is published by. source_id = Column(Integer, nullable=False) # This distinguishes between the many types of reports that a single source may produce, e.g. a Daily Status # Report or Monthly Fact Sheet, that contain different information and are potentially fetched and parsed using # different logic. type = Column(String(255), nullable=False) # Identifies a specific instance of a given report type. It should be constructed such that it is unique within a # given report type and source. The combination of report type and instance is used when ingesting a report to # determine whether this is an update to an existing report or a new report. For PDF reports, this may simply be # the title of the document after some validation has been performed. For webpages it may need to be dynamically # generated. instance = Column(String(255), nullable=False) # The date the report was published. publish_date = Column(Date, nullable=False) # The method used to acquire the data (e.g. scraped). acquisition_method = Column(Enum(AcquisitionMethod), nullable=False) # TODO(#4485): Add a list of projects (e.g. Justice Counts, Spark) for which this data was ingested. __table_args__ = tuple([ PrimaryKeyConstraint(id), UniqueConstraint(source_id, type, instance), ForeignKeyConstraint([source_id], [Source.id])]) source = relationship(Source)
class DataBlockLog(BaseModel): id = Column(Integer, primary_key=True, autoincrement=True) pipe_log_id = Column(Integer, ForeignKey(PipeLog.id), nullable=False) data_block_id = Column( String(128), ForeignKey(f"{SNAPFLOW_METADATA_TABLE_PREFIX}data_block_metadata.id"), nullable=False, ) direction = Column(Enum(Direction, native_enum=False), nullable=False) processed_at = Column(DateTime, default=func.now(), nullable=False) # Hints data_block: "DataBlockMetadata" pipe_log: PipeLog def __repr__(self): return self._repr( id=self.id, pipe_log=self.pipe_log, data_block=self.data_block, direction=self.direction, processed_at=self.processed_at, ) @classmethod def summary(cls, sess: Session) -> str: s = "" for dbl in sess.query(DataBlockLog).all(): s += f"{dbl.pipe_log.node_key:50}" s += f"{str(dbl.data_block_id):23}" s += f"{str(dbl.data_block.record_count):6}" s += f"{dbl.direction.value:9}{str(dbl.data_block.updated_at):22}" s += f"{dbl.data_block.nominal_schema_key:20}{dbl.data_block.realized_schema_key:20}\n" return s
class URL(DBBase): __tablename__ = 'urls' id = Column(Integer, primary_key=True, autoincrement=True) url_str_id = Column(Integer, ForeignKey('url_strings.id'), nullable=False, unique=True, index=True) url_str_record = relationship('URLString', uselist=False, foreign_keys=[url_str_id]) url = association_proxy('url_str_record', 'url') status = Column( Enum( Status.done, Status.error, Status.in_progress, Status.skipped, Status.todo, ), index=True, default=Status.todo, nullable=False, ) try_count = Column(Integer, nullable=False, default=0) level = Column(Integer, nullable=False, default=0) top_url_str_id = Column(Integer, ForeignKey('url_strings.id')) top_url_record = relationship('URLString', uselist=False, foreign_keys=[top_url_str_id]) top_url = association_proxy('top_url_record', 'url') status_code = Column(Integer) referrer_id = Column(Integer, ForeignKey('url_strings.id')) referrer_record = relationship('URLString', uselist=False, foreign_keys=[referrer_id]) referrer = association_proxy('referrer_record', 'url') inline = Column(Boolean) link_type = Column(String) url_encoding = Column(String) post_data = Column(String) filename = Column(String) def to_plain(self): return URLRecord( self.url, self.status, self.try_count, self.level, self.top_url, self.status_code, self.referrer, self.inline, self.link_type, self.url_encoding, self.post_data, self.filename, )
def __init__(self, enum): self.enum = enum self.impl = Enum( *enum.values(), name="ck%s" % re.sub( '([A-Z])', lambda m: "_" + m.group(1).lower(), enum.__name__) )
def enums_factory(*, values: Strategy[str] = sql_identifiers, min_size: int = 1, max_size: Optional[int] = None) -> Strategy[TypeEngine]: enums_keys = values.filter(enumerable.is_valid_key) return ((strategies.tuples( enumerable.factory( keys=enums_keys, min_size=min_size, max_size=max_size)) | strategies.lists(values, min_size=min_size, max_size=max_size) ).map(lambda type_values: Enum(*type_values)))
class LeakTesterMeasurement(Schema): _repr_fields = [ 'stage', 'total_time', 'pressure', ] time_remaining = Column(Float, nullable=False) total_time = Column(Float, nullable=False) pressure = Column(Float, nullable=False) stage = Column(Enum(LeakTestStage), default=LeakTestStage.VENT)
class Score(BaseModel): id = db.Column(db.Integer, primary_key=True, nullable=False) judging: "Judging" criteria = db.Column(Enum(CriteriaEnum)) score = db.Column(db.Float) judging_id = db.Column(db.Integer, db.ForeignKey("judging.id"), nullable=False)
class Employment(Base): __repr_args__ = 'salary', # Column definition person_id = foreign_key('person.id', index=False, primary_key=True) company_id = foreign_key('company.id', primary_key=True) role = column(Enum('director', 'manager', 'worker', name='ck_role_type')) salary = column(Integer) # Relationships person = relationship('Person', back_populates='employment') company = relationship('Company', back_populates='contracts')
class DeclEnumType(SchemaType, TypeDecorator): def __init__(self, enum): self.enum = enum self.impl = Enum(*enum.values(), name="ck%s" % re.sub('([A-Z])', lambda m: "_" + m.group(1).lower(), enum.__name__)) def _set_table(self, table, column): self.impl._set_table(table, column) def copy(self): return DeclEnumType(self.enum) def process_bind_param(self, value, dialect): if value is None: return None return value.value def process_result_value(self, value, dialect): if value is None: return None return self.enum.from_string(value.strip())
class Ticker(Base): __tablename__ = 'tickers' id = Column(Integer, primary_key=True, autoincrement=True) symbol = Column(Enum(CurrencySymbol), index=True, nullable=False) bid = Column(Float, nullable=False, default=0) ask = Column(Float, nullable=False, default=0) last_price = Column(Float, nullable=False, default=0) created_at = Column(TZDateTime, nullable=False, server_default=func.now()) exchange_market_id = Column(ForeignKey('exchange_markets.id'), nullable=False) exchange_market = relationship('ExchangeMarket')
class Membership(db.Model): __tablename__ = "membership" uuid = Column(String(36), primary_key=True) account_id = Column(Integer, index=True, nullable=True) duration = Column(Enum(MembershipDuration), default=MembershipDuration.NONE, nullable=False) has_room = Column(Boolean, default=True, nullable=False) first_time = Column(Boolean, default=False, nullable=False) adherent_id = Column(Integer, index=True, nullable=False) payment_method_id = Column(Integer, index=True, nullable=True) products = Column(String(255), nullable=True) status = Column(Enum(MembershipStatus), default=MembershipStatus.INITIAL, nullable=False) create_at = Column(DateTime, nullable=False, default=func.now(), server_default=func.now()) update_at = Column(DateTime, nullable=False, default=func.now(), server_onupdate=func.now())
class QueuedFile(DBBase): __tablename__ = 'queued_files' id = Column(Integer, primary_key=True, autoincrement=True) queued_url_id = Column(Integer, ForeignKey(QueuedURL.id), nullable=False, unique=True) queued_url = relationship(QueuedURL, uselist=False, foreign_keys=[queued_url_id]) status = Column( Enum(*list(member.value for member in Status)), index=True, default=Status.todo.value, nullable=False, )
class BankingId(TimestampMixin, DeclarativeBase): __tablename__ = 'banking_id' id = Field(Integer(), primary_key=True) client_id = Field(Integer(), ForeignKey('client.id')) is_verified = Field(Boolean(), default=False) error = Field(Unicode(), nullable=True) client = relationship('Client', lazy='select', protected=True) type = Field(Enum('bank_account', 'bank_card', name='banking_id_type')) __mapper_args__ = { 'polymorphic_identity': __tablename__, 'polymorphic_on': type }
class Person(Base): __repr_args__ = 'first_name', 'last_name', 'gender' # Column definition id = column(Integer, primary_key=True) first_name = column(Text) last_name = column(Text) birthday = column(Date) gender = column(Enum('f', 'm', 'x', name='ck_gender_type')) city_id = foreign_key('city.id') self_employment_income = column(Integer, nullable=True) # Relationships city = relationship('City', back_populates='citizens') employment = relationship('Employment', back_populates='person') employer = relationship('Company', back_populates='employees', secondary='employment', uselist=False)
class Schedule(abstract.Schedule, Base): """Defines a database table for feeding schedules. Attributes: id (int): Primary key column schedule_type (abstract.ScheduleMode): Type of schedule time_ (time): Time of day for daily schedule """ __tablename__ = "schedule" id = Column(Integer, primary_key=True, index=True) schedule_type = Column(Enum(abstract.ScheduleMode), nullable=False) time_ = Column(Time, nullable=True) def __init__( self, schedule_type: abstract.ScheduleMode, time_: Optional[time] ) -> None: """Initialize the Schedule. Args: schedule_type (abstract.ScheduleMode): Type of schedule time_ (Optional[time]): Time of day for daily schedule Raises: Exception: An exception is raised if time_ is missing and schedule_type is DAILY """ if schedule_type is abstract.ScheduleMode.DAILY and time_ is None: raise Exception("Must specify time_ if schedule_type is DAILY") super().__init__(schedule_type=schedule_type, time_=time_) def get_id(self) -> str: """Return a unique id for the Schedule. Returns: str: A unique id """ return str(self.id)
class Board(Versioned, Base): """Model class for board. This model serve as a category to topic and also holds settings regarding how posts are created and displayed. It should always be accessed using :attr:`slug`. """ __tablename__ = 'board' id = Column(Integer, primary_key=True) created_at = Column(DateTime(timezone=True), default=func.now()) updated_at = Column(DateTime(timezone=True), onupdate=func.now()) slug = Column(String(64), unique=True, nullable=False) title = Column(Unicode(255), nullable=False) _settings = Column('settings', JsonType, nullable=False, default={}) agreements = Column(Text, nullable=True) description = Column(Text, nullable=True) status = Column(Enum('open', 'restricted', 'locked', 'archived', name='board_status'), default='open', nullable=False) def get_settings(self): settings = DEFAULT_BOARD_CONFIG.copy() settings.update(self._settings) return settings def set_settings(self, value): self._settings = value @declared_attr def settings(cls): return synonym('_settings', descriptor=property(cls.get_settings, cls.set_settings))
def __init__(self, enum): self.enum = enum self.impl = Enum(*enum.values(), name="ck%s" % re.sub('([A-Z])', lambda m: "_" + m.group(1).lower(), enum.__name__))
class ClientEvidence(ModifiedMixin, DeclarativeBase): __tablename__ = 'client_evidence' client_id = Field(Integer(), ForeignKey('member.id'), primary_key=True) first_name = Field(Unicode(50), nullable=True) last_name = Field(Unicode(50), nullable=True) mobile_phone = Field(Unicode(50), min_length=10, pattern=r'^\+[1-9]{1}[0-9]{3,14}$', watermark='Mobile Phone', example='+989876543210', nullable=True, unique=True) fixed_phone = Field(Unicode(50), min_length=10, pattern=r'^\+[1-9]{1}[0-9]{3,14}$', watermark='Fixed Phone', example='+982167653945', nullable=True, unique=True) gender = Field(Enum('male', 'female', name='gender'), nullable=True) birthday = Field(DateTime(), nullable=True) city_id = Field(Integer, ForeignKey('city.id'), nullable=True) city = relationship('City', uselist=False) national_code = Field(Unicode(50), nullable=True) address = Field(Unicode(), nullable=True) _id_card = Field(ClientIdCard.as_mutable(JSON), nullable=True, protected=True) # Attachment _id_card_secondary = Field(ClientIdCard.as_mutable(JSON), nullable=True, protected=True) # Attachment error = Field(Unicode(), nullable=True) @property def id_card(self): return self._id_card.locate() if self._id_card else None @id_card.setter def id_card(self, value): if value is not None: self._id_card = ClientIdCard.create_from(value) else: self._id_card = None @property def id_card_secondary(self): return self._id_card_secondary.locate( ) if self._id_card_secondary else None @id_card_secondary.setter def id_card_secondary(self, value): if value is not None: self._id_card_secondary = ClientIdCard.create_from(value) else: self._id_card_secondary = None def to_dict(self): result = super().to_dict() result['idCard'] = self.id_card result['idCardSecondary'] = self.id_card_secondary return result
Boolean, CheckConstraint, Column, DateTime, Integer, String, UniqueConstraint, ) from sqlalchemy.sql.sqltypes import Enum from recidiviz.common.constants.operations import enum_canonical_strings from recidiviz.persistence.database.base_schema import OperationsBase direct_ingest_instance = Enum( enum_canonical_strings.direct_ingest_instance_primary, enum_canonical_strings.direct_ingest_instance_secondary, name="direct_ingest_instance", ) class _DirectIngestFileMetadataRowSharedColumns: """A mixin which defines all columns common to each of the direct ingest file metadata columns.""" # Consider this class a mixin and only allow instantiating subclasses def __new__(cls, *_: Any, **__: Any) -> "_DirectIngestFileMetadataRowSharedColumns": if cls is _DirectIngestFileMetadataRowSharedColumns: raise Exception( "_DirectIngestFileMetadataRowSharedColumns cannot be instantiated" ) return super().__new__(cls)
class Currency(OrderingMixin, FilteringMixin, DeclarativeBase): """ For exp. for 'BTC' we'll use: * smallest_unit_scale = -8 * normalization_scale = 0 For exp. for 'ETH' we'll use: * smallest_unit_scale = -18 * normalization_scale = -1 For exp. for 'IRR' we'll use: * smallest_unit_scale = 0 * normalization_scale = -8 """ __tablename__ = 'currency' symbol = Field(Unicode(10), min_length=1, max_length=10, pattern=r'^[A-Z0-9]{1,10}$', primary_key=True) name = Field(Unicode(25), min_length=1, max_length=25) normalization_scale = Field(Integer(), default=0) smallest_unit_scale = Field(Integer(), default=0) type = Field(Enum('fiat', 'cryptocurrency', name='currency_type')) __mapper_args__ = { 'polymorphic_identity': __tablename__, 'polymorphic_on': type } def smallest_unit_to_normalized(self, number): """ :return: """ if number is None: return None return Decimal(number).scaleb(self.smallest_unit_scale + self.normalization_scale) def normalized_to_output(self, number: Decimal): """ :return: """ if number is None: return None if not isinstance(number, Decimal): number = Decimal(number) return ('{:.' + str(max(0, -self.smallest_unit_scale)) + 'f}') \ .format(number.scaleb(- self.normalization_scale)) def normalized_smallest_unit(self, number: Decimal): """ :return: """ if number is None: return None if not isinstance(number, Decimal): number = Decimal(number) return '{:.0f}'.format(number.scaleb(-self.smallest_unit_scale - self.normalization_scale)) def input_to_normalized(self, number: str, strict=True): """ :return: """ if number is None: return None if strict and \ ( (not (self.smallest_unit_scale >= 0 and len(number.split('.')) == 1)) and (len(number.split('.')) == 1 or len(number.split('.')[1]) != -self.smallest_unit_scale) ): raise HttpBadRequest(f'This number is in {self.symbol} unit and this currency should be presented with ' f'the exact ${-self.smallest_unit_scale} digits behind the floating-point', 'bad-number-format') number = Decimal(number) return number.scaleb(-self.normalization_scale) def smallest_unit_to_output(self, number): if number is None: return None return self.normalized_to_output(self.smallest_unit_to_normalized(number)) # def normalized_to_smallest_unit(self, number): # if number is None: # return None # if not isinstance(number, Decimal): # number = Decimal(number) # return self.normalized_to_output(self.smallest_unit_to_normalized(number)) def to_dict(self): result = super().to_dict() # TODO: Get the current user's wallet_tier_policy about this currency # result['tirePolicy'] = {} return result @classmethod def format_normalized_string(cls, number: Decimal): return '{:.8f}'.format(number)
class URL(DBBase): '''URL table containing each URL to be downloaded.''' __tablename__ = 'urls' id = Column(Integer, primary_key=True, autoincrement=True) url_str_id = Column( Integer, ForeignKey('url_strings.id'), nullable=False, unique=True, index=True ) url_str_record = relationship( 'URLString', uselist=False, foreign_keys=[url_str_id] ) url = association_proxy('url_str_record', 'url') status = Column( Enum( Status.done, Status.error, Status.in_progress, Status.skipped, Status.todo, ), index=True, default=Status.todo, nullable=False, doc='Status of the completion of the item.' ) try_count = Column( Integer, nullable=False, default=0, doc='Number of attempts made in order to process the item.' ) level = Column( Integer, nullable=False, default=0, doc='Recursive depth of the item. 0 is root, 1 is child of root, etc.' ) top_url_str_id = Column( Integer, ForeignKey('url_strings.id'), doc='Root URL.' ) top_url_record = relationship( 'URLString', uselist=False, foreign_keys=[top_url_str_id]) top_url = association_proxy('top_url_record', 'url') status_code = Column(Integer, doc='HTTP status code or FTP rely code.') referrer_id = Column( Integer, ForeignKey('url_strings.id'), doc='Parent item of this item.' ) referrer_record = relationship( 'URLString', uselist=False, foreign_keys=[referrer_id]) referrer = association_proxy('referrer_record', 'url') inline = Column( Integer, doc='Depth of the page requisite object. ' '0 is the object, 1 is the object\'s dependency, etc.' ) link_type = Column( Enum( LinkType.html, LinkType.css, LinkType.javascript, LinkType.media, LinkType.sitemap, LinkType.file, LinkType.directory, ), doc='Expected content type of extracted link.' ) post_data = Column(String, doc='Additional percent-encoded data for POST.') filename = Column(String, doc='Local filename of the item.') def to_plain(self): return URLRecord( self.url, self.status, self.try_count, self.level, self.top_url, self.status_code, self.referrer, self.inline, self.link_type, self.post_data, self.filename, )
class Star(Base): __tablename__ = 'stars' id = Column(BigInteger(), primary_key=True) group_id = Column(UUID(as_uuid=True), nullable=False) mass = Column(Float(), nullable=True) luminosity = Column(Float(), nullable=True) r_galactocentric = Column(Float(), nullable=True) th_galactocentric = Column(Float(), nullable=True) z_coordinate = Column(Float(), nullable=True) proper_motion = Column(Float(), nullable=True) proper_motion_component_b = Column(Float(), nullable=True) proper_motion_component_l = Column(Float(), nullable=True) proper_motion_component_vr = Column(Float(), nullable=True) right_ascension = Column(Float(), nullable=True) declination = Column(Float(), nullable=True) right_ascension_proper_motion = Column(Float(), nullable=True) declination_proper_motion = Column(Float(), nullable=True) distance = Column(Float(), nullable=True) galactic_latitude = Column(Float(), nullable=True) galactic_longitude = Column(Float(), nullable=True) j_abs_magnitude = Column(Float(), nullable=True) b_abs_magnitude = Column(Float(), nullable=True) r_abs_magnitude = Column(Float(), nullable=True) v_abs_magnitude = Column(Float(), nullable=True) i_abs_magnitude = Column(Float(), nullable=True) u_velocity = Column(Float(), nullable=True) v_velocity = Column(Float(), nullable=True) w_velocity = Column(Float(), nullable=True) birth_time = Column(Float(), nullable=True) # TODO: make it Enum, DA - 0, DB - 1, ONe - 2 spectral_type = Column(Integer(), nullable=True) galactic_disk_type = Column(Enum(GalacticDiskType), nullable=True) updated_timestamp = Column(DateTime(), server_default=func.now()) def __init__(self, group_id: uuid.UUID, mass: float = None, luminosity: float = None, proper_motion: float = None, r_galactocentric: float = None, th_galactocentric: float = None, z_coordinate: float = None, proper_motion_component_b: float = None, proper_motion_component_l: float = None, proper_motion_component_vr: float = None, right_ascension: float = None, declination: float = None, right_ascension_proper_motion: float = None, declination_proper_motion: float = None, distance: float = None, galactic_latitude: float = None, galactic_longitude: float = None, j_abs_magnitude: float = None, b_abs_magnitude: float = None, r_abs_magnitude: float = None, v_abs_magnitude: float = None, i_abs_magnitude: float = None, u_velocity: float = None, v_velocity: float = None, w_velocity: float = None, birth_time: float = None, spectral_type: int = None, galactic_disk_type: GalacticDiskType = None): self.id = None self.group_id = group_id self.mass = mass self.luminosity = luminosity self.proper_motion = proper_motion self.r_galactocentric = r_galactocentric self.th_galactocentric = th_galactocentric self.z_coordinate = z_coordinate self.proper_motion_component_b = proper_motion_component_b self.proper_motion_component_l = proper_motion_component_l self.proper_motion_component_vr = proper_motion_component_vr self.right_ascension = right_ascension self.declination = declination self.right_ascension_proper_motion = right_ascension_proper_motion self.declination_proper_motion = declination_proper_motion self.distance = distance self.galactic_latitude = galactic_latitude self.galactic_longitude = galactic_longitude self.j_abs_magnitude = j_abs_magnitude self.b_abs_magnitude = b_abs_magnitude self.r_abs_magnitude = r_abs_magnitude self.v_abs_magnitude = v_abs_magnitude self.i_abs_magnitude = i_abs_magnitude self.u_velocity = u_velocity self.v_velocity = v_velocity self.w_velocity = w_velocity self.birth_time = birth_time self.spectral_type = spectral_type self.galactic_disk_type = galactic_disk_type
class Topic(Versioned, Base): """Model class for topic. This model only holds topic metadata such as title or its associated board. The actual content of a topic belongs to :class:`Post`. """ __tablename__ = 'topic' id = Column(Integer, primary_key=True) created_at = Column(DateTime(timezone=True), default=func.now()) updated_at = Column(DateTime(timezone=True), onupdate=func.now()) board_id = Column(Integer, ForeignKey('board.id'), nullable=False) title = Column(Unicode(255), nullable=False) status = Column(Enum('open', 'locked', 'archived', name='topic_status'), default='open', nullable=False) board = relationship('Board', backref=backref('topics', lazy='dynamic', cascade='all,delete', order_by=desc(func.coalesce( select([TopicMeta.bumped_at]).\ where(TopicMeta.topic_id==id).\ as_scalar(), created_at)))) QUERY = ( ("single_post", re.compile("^(\d+)$")), ("ranged_posts", re.compile("^(\d+)?\-(\d+)?$")), ("recent_posts", re.compile("^l(\d+)$")), ("recent_posts", re.compile("^recent$")), ) def scoped_posts(self, query=None): """Return single post or multiple posts according to `query`. If `query` is not given, this method is an equivalent of calling :attr:`posts` directly. This method always returns an iterator. Single numeric (e.g. "253") Returns a single post that matches the number. For example if "253" is given, then an iterator containing post number "253" is returned. Ranged query (e.g. "100-150") Returns all posts within range. If start number is missing ("-150") or end number is missing ("100-") then the first post and last post are automatically assumed. Recent query (e.g. "l30", "recent") Returns the n last posts where n is the number after "l" letter. If named "recent" is given, then a default value of last 20 posts is used instead. """ if query is None: return self.posts.all() else: for handler, matcher in self.QUERY: match = matcher.match(str(query)) if match: fn = getattr(self, handler) return fn(*match.groups()) return [] def single_post(self, number=None): """Returns an iterator that contains a single post that matches `number`. If post with such number could not be found, an empty iterator is returned. """ if not number: number = -1 return self.posts.filter_by(number=int(number)).all() def ranged_posts(self, start=None, end=None): """Returns a range of post between `start` and `end`. When `start` or `end` is empty, the first and last posts are assumed respectively. """ if start is None: start = 1 if end is None: query = Post.number >= start else: query = Post.number.between(start, end) return self.posts.filter(query).all() def recent_posts(self, count=30): """Returns recent `count` number of posts associated with this topic. Defaults to 30 posts if `count` is not given. """ return self.posts.order_by(False).\ order_by(desc(Post.number)).\ limit(count).all()[::-1]
down_revision = '91b1beed9a1c' branch_labels = None depends_on = None # activity enum activities_old = [ 'skitouring', 'snow_ice_mixed', 'mountain_climbing', 'rock_climbing', 'ice_climbing', 'hiking', 'snowshoeing', 'paragliding', 'mountain_biking', 'via_ferrata' ] activities_new = activities_old + [ 'slacklining', ] activity_enum_old = Enum(*activities_old, name='activity_type', schema='guidebook') activity_enum_new = Enum(*activities_new, name='activity_type', schema='guidebook') activity_enum_tmp = Enum(*activities_new, name='_activity_type', schema='guidebook') tables_with_activity_column = [ ('guidebook', 'articles', 'activities', False), ('guidebook', 'books', 'activities', False), ('guidebook', 'images', 'activities', False), ('guidebook', 'outings', 'activities', False), ('guidebook', 'routes', 'activities', False), ('guidebook', 'user_profiles', 'activities', False),