<commit_before>#   Copyright 2013 David Malcolm <dmalcolm@redhat.com>
#   Copyright 2013 Red Hat, Inc.
#   Copyright 2013 Matthieu Caneill <matthieu.caneill@gmail.com>
#
#   This library is free software; you can redistribute it and/or
#   modify it under the terms of the GNU Lesser General Public
#   License as published by the Free Software Foundation; either
#   version 2.1 of the License, or (at your option) any later version.
#
#   This library is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
#   Lesser General Public License for more details.
#
#   You should have received a copy of the GNU Lesser General Public
#   License along with this library; if not, write to the Free Software
#   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
#   USA

from sqlalchemy import Table, MetaData, Column, \
    ForeignKey, Integer, String, Float, ForeignKeyConstraint, \
    event, DDL, Index
from sqlalchemy.orm import mapper, relationship, polymorphic_union, \
    sessionmaker
from sqlalchemy.schema import Sequence

metadata = MetaData()

from firehose_noslots import *

# imported from firehose-orm/orm.py:

############################################################################
# Tables
############################################################################

t_analysis = \
    Table('analysis', metadata,
          Column('id', String, primary_key=True, autoincrement=False),
          Column('metadata_id', String,
                 ForeignKey('metadata.id'), nullable=False),
          Column('customfields_id', String,
                 ForeignKey('customfields.id')),
          )
Index('ix_analysis_metadata_id', t_analysis.c.metadata_id)

t_generator = \
    Table('generator', metadata,
          Column('id', String, primary_key=True, autoincrement=False),
          Column('name', String),
          Column('version', String), # optional in RNG
          )
Index('ix_generator_name_version', t_generator.c.name, t_generator.c.version)

t_metadata = \
    Table('metadata', metadata,
          Column('id', String, primary_key=True, autoincrement=False),
          Column('generator_id', String,
                 ForeignKey('generator.id'), nullable=False),
          Column('sut_id', String, ForeignKey('sut.id')),
          Column('file_id', String, ForeignKey('file.id')),
          Column('stats_id', String, ForeignKey('stats.id')),
          )
Index('ix_metadata_generator_id', t_metadata.c.generator_id)
Index('ix_metadata_sut_id', t_metadata.c.sut_id)

t_stats = \
    Table('stats', metadata,
          Column('id', String, primary_key=True, autoincrement=False),
          Column('wallclocktime', Float, nullable=False),
          )
Index('ix_metadata_wallclocktime', t_stats.c.wallclocktime)

# For the Sut hierarchy we use joined-table inheritance
t_sut = \
    Table('sut', metadata,
          Column('id', String, primary_key=True, autoincrement=False),
          Column('type', String(20), nullable=False),
          Column('name', String, nullable=False),
          Column('version', String, nullable=False),
          Column('release', String),
          Column('buildarch', String),
          )
Index('ix_sut_name_version_release_buildarch',
      t_sut.c.name,
      t_sut.c.version,
      t_sut.c.release,
      t_sut.c.buildarch)

# For the Result hierarchy we use joined-table inheritance
t_result = \
    Table('result', metadata,
          Column('id', String, primary_key=True, autoincrement=False), # renamed from result_id
          Column('analysis_id', String,
                 ForeignKey('analysis.id'), nullable=False),
          Column('type', String(10), nullable=False),
          )
Index('ix_result_analysis_id', t_result.c.analysis_id)
Index('ix_result_type', t_result.c.type)

t_issue = \
    Table('issue', metadata,
          Column('result_id', String,
                 ForeignKey('result.id'), primary_key=True),
          Column('cwe', Integer),
          Column('testid', String),
          Column('severity', String),
          Column('message_id', String,
                 ForeignKey('message.id'), nullable=False),
          Column('notes_id', String, ForeignKey('notes.id')),
          Column('location_id', String,
                 ForeignKey('location.id'), nullable=False),
          Column('trace_id', String, ForeignKey('trace.id')),
          Column('customfields_id', String,
                 ForeignKey('customfields.id')),
          )
Index('ix_issue_result_id', t_issue.c.result_id)
Index('ix_issue_testid', t_issue.c.testid)
Index('ix_issue_message_id', t_issue.c.message_id)
Index('ix_issue_location_id', t_issue.c.location_id)

t_failure = \
    Table('failure', metadata,
          Column('result_id', String,
                 ForeignKey('result.id'), primary_key=True),
          Column('failureid', String),
          Column('location_id', String, ForeignKey('location.id')),
          Column('message_id', String, ForeignKey('message.id')),
          Column('customfields_id', String, ForeignKey('customfields.id')),
          )
Index('ix_failure_result_id', t_failure.c.result_id)
Index('ix_failure_failureid', t_failure.c.failureid)
Index('ix_failure_location_id', t_failure.c.location_id)
Index('ix_failure_message_id', t_failure.c.message_id)

t_info = \
    Table('info', metadata,
          Column('result_id', String,
                 ForeignKey('result.id'), primary_key=True),
          Column('infoid', String),
          Column('location_id', String, ForeignKey('location.id')),
          Column('message_id', String, ForeignKey('message.id')),
          Column('customfields_id', String, ForeignKey('customfields.id')),
          )
Index('ix_info_result_id', t_info.c.result_id)
Index('ix_info_infoid', t_info.c.infoid)
Index('ix_info_location_id', t_info.c.location_id)
Index('ix_info_message_id', t_info.c.message_id)

t_message = \
    Table('message', metadata,
          Column('id', String, primary_key=True, autoincrement=False),
          Column('text', String),
          )
Index('ix_message_text', t_message.c.text)

t_notes = \
    Table('notes', metadata,
          Column('id', String, primary_key=True, autoincrement=False),
          Column('text', String),
          )
Index('ix_notes_text', t_notes.c.text)

t_trace = \
    Table('trace', metadata,
          Column('id', String, primary_key=True, autoincrement=False)
          )

t_state = \
    Table('state', metadata,
          Column('id', String, primary_key=True, autoincrement=False),
          Column('trace_id', String, ForeignKey('trace.id')),
          Column('location_id', String,
                 ForeignKey('location.id'), nullable=False),
          Column('notes_id', String, ForeignKey('notes.id')),
          # annotation (key/value) pairs -> why not CustomFields here?
          )
Index('ix_state_trace_id', t_state.c.trace_id)

t_location = \
    Table('location', metadata,
          Column('id', String, primary_key=True, autoincrement=False),
          Column('file_id', String, ForeignKey('file.id'), nullable=False),
          Column('function_id', String, ForeignKey('function.id')),
          # either a point or a range:
          Column('point_id', String, ForeignKey('point.id')),
          Column('range_id', String, ForeignKey('range.id')),
          )
Index('ix_location_file_id_function_id',
      t_location.c.file_id,
      t_location.c.function_id)

t_file = \
    Table('file', metadata,
          Column('id', String, primary_key=True, autoincrement=False),
          Column('givenpath', String, nullable=False),
          Column('abspath', String),
          Column('hash_id', String, ForeignKey('hash.id')),
          )
Index('ix_file_givenpath', t_file.c.givenpath)

t_hash = \
    Table('hash', metadata,
          Column('id', String, primary_key=True, autoincrement=False),
          Column('alg', String, nullable=False),
          Column('hexdigest', String, nullable=False),
          )
Index('ix_hash_hexdigest', t_hash.c.hexdigest)

t_function = \
    Table('function', metadata,
          Column('id', String, primary_key=True, autoincrement=False),
          Column('name', String, nullable=False),
          )
Index('ix_function_name', t_function.c.name)

t_point = \
    Table('point', metadata,
          Column('id', String, primary_key=True, autoincrement=False),
          Column('line', Integer, nullable=False),
          Column('column', Integer, nullable=False),
          )
Index('ix_point_line_column', t_point.c.line, t_point.c.column)

t_range = \
    Table('range', metadata,
          Column('id', String, primary_key=True, autoincrement=False),
          Column('start_id', String,
                 ForeignKey('point.id'), nullable=False),
          Column('end_id', String,
                 ForeignKey('point.id'), nullable=False),
          )
Index('ix_range_start_id_end_id', t_range.c.start_id, t_range.c.end_id)

t_customfields = \
    Table('customfields', metadata,
          Column('id', String, primary_key=True, autoincrement=False))

t_intfield = \
    Table('intfield', metadata,
          Column('id', String, primary_key=True, autoincrement=False),
          Column('customfields_id', String,
                 ForeignKey('customfields.id'), nullable=False),
          Column('name', String, nullable=False),
          Column('value', Integer, nullable=False),
          )
Index('ix_intfield_name', t_intfield.c.name)

t_strfield = \
    Table('strfield', metadata,
          Column('id', String, primary_key=True, autoincrement=False),
          Column('customfields_id', String,
                 ForeignKey('customfields.id'), nullable=False),
          Column('name', String, nullable=False),
          Column('value', String, nullable=False),
          )
Index('ix_strfield_name', t_strfield.c.name)

############################################################################
# Mappers
############################################################################

mapper(Analysis, t_analysis,
       properties={
        'metadata': relationship(Metadata, lazy='joined'),
        'results': relationship(
            Result, order_by=t_result.c.id, lazy='noload'),
        'customfields': relationship(CustomFields),
        }
       )

mapper(Metadata, t_metadata,
       properties={
        'generator': relationship(Generator, lazy='joined'),
        'sut': relationship(Sut, lazy='joined'),
        'file_': relationship(File, lazy='joined'),
        'stats': relationship(Stats, lazy='joined'),
        }
       )

mapper(Generator, t_generator)

# Map the Sut hierarchy using single table inheritance
sut_mapper = mapper(Sut, t_sut,
                    polymorphic_on=t_sut.c.type,
                    polymorphic_identity='sut')

mapper(SourceRpm,
       inherits=sut_mapper,
       polymorphic_identity='source-rpm')

mapper(DebianBinary,
       inherits=sut_mapper,
       polymorphic_identity='debian-binary')

mapper(DebianSource,
       inherits=sut_mapper,
       polymorphic_identity='debian-source')

mapper(Stats, t_stats)
mapper(Message, t_message)
mapper(Notes, t_notes)

mapper(Trace, t_trace,
       properties={
        'states': relationship(
            State, order_by=t_state.c.id, lazy='joined')
        }
       )

mapper(State, t_state,
       properties={
        'location': relationship(Location, lazy='joined'),
        'notes': relationship(Notes, lazy='joined'),
        }
       )

# Map the Result hierarchy using Joined Table Inheritance:
mapper(Result, t_result,
       polymorphic_on=t_result.c.type,
       polymorphic_identity='result',
       properties={
        'analysis': relationship(Analysis),
        }
       )

mapper(Issue, t_issue,
       inherits=Result,
       polymorphic_identity='issue',
       properties={
        'location': relationship(Location, lazy='joined'),
        'message':  relationship(Message, lazy='joined'),
        'notes':  relationship(Notes, lazy='joined'),
        'trace': relationship(Trace, lazy='joined'),
        'customfields': relationship(CustomFields),
        }
       )

mapper(Failure, t_failure,
       inherits=Result,
       polymorphic_identity='failure',
       properties={
        'location': relationship(Location, lazy='joined'),
        'message': relationship(Message, lazy='joined'),
        'customfields': relationship(CustomFields),
        }
       )

mapper(Info, t_info,
       inherits=Result,
       polymorphic_identity='info',
       properties={
        'location': relationship(Location, lazy='joined'),
        'message': relationship(Message, lazy='joined'),
        'customfields': relationship(CustomFields),
        }
       )

mapper(Location, t_location,
       properties={
        'file': relationship(File, lazy='joined'),
        #, backref='locations', order_by=t_file.c.abspath)
        'function': relationship(Function, lazy='joined'),
        'point': relationship(Point, lazy='joined'),
        'range_': relationship(Range, lazy='joined'),
        }
       )

mapper(File, t_file,
       properties={
        'hash_': relationship(Hash, lazy='joined'),
        }
       )

mapper(Hash, t_hash)

mapper(Function, t_function)

mapper(Point, t_point)

mapper(Range, t_range,
       properties={
        'start': relationship(Point, foreign_keys=t_range.c.start_id,
                              lazy='joined'),
        'end': relationship(Point, foreign_keys=t_range.c.end_id,
                            lazy='joined')
        # foreign_keys specified to avoid ambiguity
        }
       )

mapper(CustomFields, t_customfields)
<commit_msg>add: debian tables for mapping packages/people<commit_after>#   Copyright 2013 David Malcolm <dmalcolm@redhat.com>
#   Copyright 2013 Red Hat, Inc.
#   Copyright 2013 Matthieu Caneill <matthieu.caneill@gmail.com>
#
#   This library is free software; you can redistribute it and/or
#   modify it under the terms of the GNU Lesser General Public
#   License as published by the Free Software Foundation; either
#   version 2.1 of the License, or (at your option) any later version.
#
#   This library is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
#   Lesser General Public License for more details.
#
#   You should have received a copy of the GNU Lesser General Public
#   License along with this library; if not, write to the Free Software
#   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
#   USA

from sqlalchemy import Table, MetaData, Column, \
    ForeignKey, Integer, String, Float, ForeignKeyConstraint, \
    event, DDL, Index
from sqlalchemy.orm import mapper, relationship, polymorphic_union, \
    sessionmaker
from sqlalchemy.schema import Sequence

metadata = MetaData()

from firehose_noslots import *

# imported from firehose-orm/orm.py:

############################################################################
# Tables
############################################################################

t_analysis = \
    Table('analysis', metadata,
          Column('id', String, primary_key=True, autoincrement=False),
          Column('metadata_id', String,
                 ForeignKey('metadata.id'), nullable=False),
          Column('customfields_id', String,
                 ForeignKey('customfields.id')),
          )
Index('ix_analysis_metadata_id', t_analysis.c.metadata_id)

t_generator = \
    Table('generator', metadata,
          Column('id', String, primary_key=True, autoincrement=False),
          Column('name', String),
          Column('version', String), # optional in RNG
          )
Index('ix_generator_name_version', t_generator.c.name, t_generator.c.version)

t_metadata = \
    Table('metadata', metadata,
          Column('id', String, primary_key=True, autoincrement=False),
          Column('generator_id', String,
                 ForeignKey('generator.id'), nullable=False),
          Column('sut_id', String, ForeignKey('sut.id')),
          Column('file_id', String, ForeignKey('file.id')),
          Column('stats_id', String, ForeignKey('stats.id')),
          )
Index('ix_metadata_generator_id', t_metadata.c.generator_id)
Index('ix_metadata_sut_id', t_metadata.c.sut_id)

t_stats = \
    Table('stats', metadata,
          Column('id', String, primary_key=True, autoincrement=False),
          Column('wallclocktime', Float, nullable=False),
          )
Index('ix_metadata_wallclocktime', t_stats.c.wallclocktime)

# For the Sut hierarchy we use joined-table inheritance
t_sut = \
    Table('sut', metadata,
          Column('id', String, primary_key=True, autoincrement=False),
          Column('type', String(20), nullable=False),
          Column('name', String, nullable=False),
          Column('version', String, nullable=False),
          Column('release', String),
          Column('buildarch', String),
          )
Index('ix_sut_name_version_release_buildarch',
      t_sut.c.name,
      t_sut.c.version,
      t_sut.c.release,
      t_sut.c.buildarch)

# For the Result hierarchy we use joined-table inheritance
t_result = \
    Table('result', metadata,
          Column('id', String, primary_key=True, autoincrement=False), # renamed from result_id
          Column('analysis_id', String,
                 ForeignKey('analysis.id'), nullable=False),
          Column('type', String(10), nullable=False),
          )
Index('ix_result_analysis_id', t_result.c.analysis_id)
Index('ix_result_type', t_result.c.type)

t_issue = \
    Table('issue', metadata,
          Column('result_id', String,
                 ForeignKey('result.id'), primary_key=True),
          Column('cwe', Integer),
          Column('testid', String),
          Column('severity', String),
          Column('message_id', String,
                 ForeignKey('message.id'), nullable=False),
          Column('notes_id', String, ForeignKey('notes.id')),
          Column('location_id', String,
                 ForeignKey('location.id'), nullable=False),
          Column('trace_id', String, ForeignKey('trace.id')),
          Column('customfields_id', String,
                 ForeignKey('customfields.id')),
          )
Index('ix_issue_result_id', t_issue.c.result_id)
Index('ix_issue_testid', t_issue.c.testid)
Index('ix_issue_message_id', t_issue.c.message_id)
Index('ix_issue_location_id', t_issue.c.location_id)

t_failure = \
    Table('failure', metadata,
          Column('result_id', String,
                 ForeignKey('result.id'), primary_key=True),
          Column('failureid', String),
          Column('location_id', String, ForeignKey('location.id')),
          Column('message_id', String, ForeignKey('message.id')),
          Column('customfields_id', String, ForeignKey('customfields.id')),
          )
Index('ix_failure_result_id', t_failure.c.result_id)
Index('ix_failure_failureid', t_failure.c.failureid)
Index('ix_failure_location_id', t_failure.c.location_id)
Index('ix_failure_message_id', t_failure.c.message_id)

t_info = \
    Table('info', metadata,
          Column('result_id', String,
                 ForeignKey('result.id'), primary_key=True),
          Column('infoid', String),
          Column('location_id', String, ForeignKey('location.id')),
          Column('message_id', String, ForeignKey('message.id')),
          Column('customfields_id', String, ForeignKey('customfields.id')),
          )
Index('ix_info_result_id', t_info.c.result_id)
Index('ix_info_infoid', t_info.c.infoid)
Index('ix_info_location_id', t_info.c.location_id)
Index('ix_info_message_id', t_info.c.message_id)

t_message = \
    Table('message', metadata,
          Column('id', String, primary_key=True, autoincrement=False),
          Column('text', String),
          )
Index('ix_message_text', t_message.c.text)

t_notes = \
    Table('notes', metadata,
          Column('id', String, primary_key=True, autoincrement=False),
          Column('text', String),
          )
Index('ix_notes_text', t_notes.c.text)

t_trace = \
    Table('trace', metadata,
          Column('id', String, primary_key=True, autoincrement=False)
          )

t_state = \
    Table('state', metadata,
          Column('id', String, primary_key=True, autoincrement=False),
          Column('trace_id', String, ForeignKey('trace.id')),
          Column('location_id', String,
                 ForeignKey('location.id'), nullable=False),
          Column('notes_id', String, ForeignKey('notes.id')),
          # annotation (key/value) pairs -> why not CustomFields here?
          )
Index('ix_state_trace_id', t_state.c.trace_id)

t_location = \
    Table('location', metadata,
          Column('id', String, primary_key=True, autoincrement=False),
          Column('file_id', String, ForeignKey('file.id'), nullable=False),
          Column('function_id', String, ForeignKey('function.id')),
          # either a point or a range:
          Column('point_id', String, ForeignKey('point.id')),
          Column('range_id', String, ForeignKey('range.id')),
          )
Index('ix_location_file_id_function_id',
      t_location.c.file_id,
      t_location.c.function_id)

t_file = \
    Table('file', metadata,
          Column('id', String, primary_key=True, autoincrement=False),
          Column('givenpath', String, nullable=False),
          Column('abspath', String),
          Column('hash_id', String, ForeignKey('hash.id')),
          )
Index('ix_file_givenpath', t_file.c.givenpath)

t_hash = \
    Table('hash', metadata,
          Column('id', String, primary_key=True, autoincrement=False),
          Column('alg', String, nullable=False),
          Column('hexdigest', String, nullable=False),
          )
Index('ix_hash_hexdigest', t_hash.c.hexdigest)

t_function = \
    Table('function', metadata,
          Column('id', String, primary_key=True, autoincrement=False),
          Column('name', String, nullable=False),
          )
Index('ix_function_name', t_function.c.name)

t_point = \
    Table('point', metadata,
          Column('id', String, primary_key=True, autoincrement=False),
          Column('line', Integer, nullable=False),
          Column('column', Integer, nullable=False),
          )
Index('ix_point_line_column', t_point.c.line, t_point.c.column)

t_range = \
    Table('range', metadata,
          Column('id', String, primary_key=True, autoincrement=False),
          Column('start_id', String,
                 ForeignKey('point.id'), nullable=False),
          Column('end_id', String,
                 ForeignKey('point.id'), nullable=False),
          )
Index('ix_range_start_id_end_id', t_range.c.start_id, t_range.c.end_id)

t_customfields = \
    Table('customfields', metadata,
          Column('id', String, primary_key=True, autoincrement=False))

t_intfield = \
    Table('intfield', metadata,
          Column('id', String, primary_key=True, autoincrement=False),
          Column('customfields_id', String,
                 ForeignKey('customfields.id'), nullable=False),
          Column('name', String, nullable=False),
          Column('value', Integer, nullable=False),
          )
Index('ix_intfield_name', t_intfield.c.name)

t_strfield = \
    Table('strfield', metadata,
          Column('id', String, primary_key=True, autoincrement=False),
          Column('customfields_id', String,
                 ForeignKey('customfields.id'), nullable=False),
          Column('name', String, nullable=False),
          Column('value', String, nullable=False),
          )
Index('ix_strfield_name', t_strfield.c.name)

############################################################################
# Mappers
############################################################################

mapper(Analysis, t_analysis,
       properties={
        'metadata': relationship(Metadata, lazy='joined'),
        'results': relationship(
            Result, order_by=t_result.c.id, lazy='noload'),
        'customfields': relationship(CustomFields),
        }
       )

mapper(Metadata, t_metadata,
       properties={
        'generator': relationship(Generator, lazy='joined'),
        'sut': relationship(Sut, lazy='joined'),
        'file_': relationship(File, lazy='joined'),
        'stats': relationship(Stats, lazy='joined'),
        }
       )

mapper(Generator, t_generator)

# Map the Sut hierarchy using single table inheritance
sut_mapper = mapper(Sut, t_sut,
                    polymorphic_on=t_sut.c.type,
                    polymorphic_identity='sut')

mapper(SourceRpm,
       inherits=sut_mapper,
       polymorphic_identity='source-rpm')

mapper(DebianBinary,
       inherits=sut_mapper,
       polymorphic_identity='debian-binary')

mapper(DebianSource,
       inherits=sut_mapper,
       polymorphic_identity='debian-source')

mapper(Stats, t_stats)
mapper(Message, t_message)
mapper(Notes, t_notes)

mapper(Trace, t_trace,
       properties={
        'states': relationship(
            State, order_by=t_state.c.id, lazy='joined')
        }
       )

mapper(State, t_state,
       properties={
        'location': relationship(Location, lazy='joined'),
        'notes': relationship(Notes, lazy='joined'),
        }
       )

# Map the Result hierarchy using Joined Table Inheritance:
mapper(Result, t_result,
       polymorphic_on=t_result.c.type,
       polymorphic_identity='result',
       properties={
        'analysis': relationship(Analysis),
        }
       )

mapper(Issue, t_issue,
       inherits=Result,
       polymorphic_identity='issue',
       properties={
        'location': relationship(Location, lazy='joined'),
        'message':  relationship(Message, lazy='joined'),
        'notes':  relationship(Notes, lazy='joined'),
        'trace': relationship(Trace, lazy='joined'),
        'customfields': relationship(CustomFields),
        }
       )

mapper(Failure, t_failure,
       inherits=Result,
       polymorphic_identity='failure',
       properties={
        'location': relationship(Location, lazy='joined'),
        'message': relationship(Message, lazy='joined'),
        'customfields': relationship(CustomFields),
        }
       )

mapper(Info, t_info,
       inherits=Result,
       polymorphic_identity='info',
       properties={
        'location': relationship(Location, lazy='joined'),
        'message': relationship(Message, lazy='joined'),
        'customfields': relationship(CustomFields),
        }
       )

mapper(Location, t_location,
       properties={
        'file': relationship(File, lazy='joined'),
        #, backref='locations', order_by=t_file.c.abspath)
        'function': relationship(Function, lazy='joined'),
        'point': relationship(Point, lazy='joined'),
        'range_': relationship(Range, lazy='joined'),
        }
       )

mapper(File, t_file,
       properties={
        'hash_': relationship(Hash, lazy='joined'),
        }
       )

mapper(Hash, t_hash)

mapper(Function, t_function)

mapper(Point, t_point)

mapper(Range, t_range,
       properties={
        'start': relationship(Point, foreign_keys=t_range.c.start_id,
                              lazy='joined'),
        'end': relationship(Point, foreign_keys=t_range.c.end_id,
                            lazy='joined')
        # foreign_keys specified to avoid ambiguity
        }
       )

mapper(CustomFields, t_customfields)

###################################################
### Debian specific tables, objects and mappers ###
###################################################

t_debian_packages = \
    Table('debian_packages', metadata,
          #Column('id', Integer, primary_key=True),
          Column('name', String, primary_key=True),
          )
#Index('ix_debian_packages_name', t_debian_packages.c.name)

t_debian_maintainers = \
    Table('debian_maintainers', metadata,
          #Column('id', Integer, primary_key=True),
          Column('email', String, primary_key=True),
          Column('name', String),
          )
#Index('ix_debian_maintainers_name', t_debian_maintainers.c.name)

t_debian_package_people_mapping = \
    Table('debian_package_people_mapping', metadata,
          #Column('id', Integer, primary_key=True),
          Column('debian_package_name', String,
                 ForeignKey('debian_packages.name'), primary_key=True),
          Column('debian_maintainer_email', String,
                 ForeignKey('debian_maintainers.email'), primary_key=True),
          )
#Index('ix_debian_package_people_mapping_maintainer_id',
#      t_debian_package_people_mapping.c.debian_maintainer_id)

class DebianPackage(object):
    def __init__(self, name):
        self.name = name

class DebianMaintainer(object):
    def __init__(self, email, name):
        self.email = email
        self.name = name

class DebianPackagePeopleMapping(object):
    def __init__(self, debian_package, debian_maintainer):
        self.debian_package = debian_package
        self.debian_maintainer = debian_maintainer

mapper(DebianPackage, t_debian_packages)
mapper(DebianMaintainer, t_debian_maintainers)
mapper(DebianPackagePeopleMapping, t_debian_package_people_mapping,
       properties={
        'debian_package': relationship(DebianPackage, lazy='joined'),
        'debian_maintainer': relationship(DebianMaintainer, lazy='joined')
        }
       )
<|endoftext|>


<commit_before>#!/usr/bin/python3
# -*- coding: utf-8 -*-

# Copyright (C) 2010 BloatIt.
#
# This file is part of BloatIt.
#
# BloatIt is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BloatIt is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with BloatIt. If not, see <http://www.gnu.org/licenses/>.

from bloatit.server.dispatchserver import DispatchServer
from urllib.parse import parse_qs
from scgi.scgi_server import SCGIHandler
from scgi.scgi_server import SCGIServer
import logging
import traceback
import sys

LOG_FILENAME = '/tmp/bloatit_scgi.log'
logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")

class HtmlHandler(SCGIHandler):

    def produce(self, env, bodysize, input, output):
        logging.info("HtmlHandler : produce page begin")
        try:
            query = parse_qs(env["QUERY_STRING"])
            post = parse_qs(input.read(bodysize))

            preferred_langs = env["HTTP_ACCEPT_LANGUAGE"].split(",")
            cookie_string = env["HTTP_COOKIE"].split(";")
            cookies = {}
            for cookie in cookie_string:
                parts = cookie.split("=")
                if len(parts) == 2 :
                    cookies[parts[0].strip()] = parts[1].strip()
            page = DispatchServer(query, post, cookies, preferred_langs)

            result = page.process()
            output.write(result)

        except Exception as e:
            exc_type, exc_value, exc_traceback = sys.exc_info()

            output.write("Content-Type: text/html\r\n\r\n")
            #TODO:disable in prod
            logging.error("Fail to generate page : "+str(e))
            logging.error('Error Type: ' + str(exc_type))
            logging.error(repr(traceback.format_tb(exc_traceback)).replace("\\n", "\n"))
            logging.error('Error Value: ' + str(exc_value))

            output.write("Fail to generate page : "+str(e)+"\n")
            output.write('Error Type: ' + str(exc_type)+"\n")
            output.write(repr(traceback.format_tb(exc_traceback)).replace("\\n", "\n")+"\n")
            output.write('Error Value: ' + str(exc_value)+"\n")

            print('Error Type: ' + str(exc_type))
            traceback.print_tb(exc_traceback)
            print('Error Value: ' + str(exc_value))

        logging.info("HtmlHandler : produce page end")

try:
    logging.info("Start scgi server")
    SCGIServer(handler_class=HtmlHandler).serve()
except Exception as e:

    logging.critical("Crash : "+str(e))

logging.info("Stop scgi server")
<commit_msg>fix a crash when no cookieis send by client<commit_after>#!/usr/bin/python3
# -*- coding: utf-8 -*-

# Copyright (C) 2010 BloatIt.
#
# This file is part of BloatIt.
#
# BloatIt is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BloatIt is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with BloatIt. If not, see <http://www.gnu.org/licenses/>.

from bloatit.server.dispatchserver import DispatchServer
from urllib.parse import parse_qs
from scgi.scgi_server import SCGIHandler
from scgi.scgi_server import SCGIServer
import logging
import traceback
import sys

LOG_FILENAME = '/tmp/bloatit_scgi.log'
logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")

class HtmlHandler(SCGIHandler):

    def produce(self, env, bodysize, input, output):
        logging.info("HtmlHandler : produce page begin")
        try:
            query = parse_qs(env["QUERY_STRING"])
            post = parse_qs(input.read(bodysize))

            preferred_langs = env["HTTP_ACCEPT_LANGUAGE"].split(",")

            cookies = {}
            if "HTTP_COOKIE" in env:
                cookie_string = env["HTTP_COOKIE"].split(";")
                for cookie in cookie_string:
                    parts = cookie.split("=")
                    if len(parts) == 2 :
                        cookies[parts[0].strip()] = parts[1].strip()

            page = DispatchServer(query, post, cookies, preferred_langs)

            result = page.process()
            output.write(result)

        except Exception as e:
            exc_type, exc_value, exc_traceback = sys.exc_info()

            output.write("Content-Type: text/html\r\n\r\n")
            #TODO:disable in prod
            logging.error("Fail to generate page : "+str(e))
            logging.error('Error Type: ' + str(exc_type))
            logging.error(repr(traceback.format_tb(exc_traceback)).replace("\\n", "\n"))
            logging.error('Error Value: ' + str(exc_value))

            output.write("Fail to generate page : "+str(e)+"\n")
            output.write('Error Type: ' + str(exc_type)+"\n")
            output.write(repr(traceback.format_tb(exc_traceback)).replace("\\n", "\n")+"\n")
            output.write('Error Value: ' + str(exc_value)+"\n")

            print('Error Type: ' + str(exc_type))
            traceback.print_tb(exc_traceback)
            print('Error Value: ' + str(exc_value))

        logging.info("HtmlHandler : produce page end")

try:
    logging.info("Start scgi server")
    SCGIServer(handler_class=HtmlHandler).serve()
except Exception as e:

    logging.critical("Crash : "+str(e))

logging.info("Stop scgi server")
<|endoftext|>


<commit_before>#
# Tool-Related Pages
#

import pscheduler

from pschedulerapiserver import application

from flask import request

from .dbcursor import dbcursor_query
from .json import *
from .log import log
from .response import *

#
# Tools
#

@application.route("/tools", methods=['GET'])
def tools():
    # Get only the tools that can run this test.
    test_filter = request.args.get('test', None)

    # HACK: BWCTLBC
    lead_bind = request.args.get('lead-bind', None)

    if test_filter is None:
        return json_query("SELECT json FROM tool WHERE available ORDER BY NAME")
    else:
        log.debug("Looking for tools against filter %s", test_filter)
        try:
            cursor = dbcursor_query("SELECT api_tools_for_test(%s, %s)",
                                    [test_filter,
                                     lead_bind],  # HACK: BWTCLBC
                                    onerow=True)
        except Exception as ex:
            return error(str(ex))
        return ok_json( cursor.fetchone()[0] )

@application.route("/tools/<name>", methods=['GET'])
def tools_name(name):
    return json_query("SELECT json FROM tool WHERE name = %s", [name], single=True)

<commit_msg>Don't figure lead bind if it isn't going to be used.<commit_after>#
# Tool-Related Pages
#

import pscheduler

from pschedulerapiserver import application

from flask import request

from .dbcursor import dbcursor_query
from .json import *
from .log import log
from .response import *

#
# Tools
#

@application.route("/tools", methods=['GET'])
def tools():
    # Get only the tools that can run this test.
    test_filter = request.args.get('test', None)

    if test_filter is None:
        return json_query("SELECT json FROM tool WHERE available ORDER BY NAME")
    else:
        log.debug("Looking for tools against filter %s", test_filter)
        lead_bind = request.args.get('lead-bind', None)  # HACK: BWCTLBC
        try:
            cursor = dbcursor_query("SELECT api_tools_for_test(%s, %s)",
                                    [test_filter,
                                     lead_bind],  # HACK: BWTCLBC
                                    onerow=True)
        except Exception as ex:
            return error(str(ex))
        return ok_json( cursor.fetchone()[0] )

@application.route("/tools/<name>", methods=['GET'])
def tools_name(name):
    return json_query("SELECT json FROM tool WHERE name = %s", [name], single=True)

<|endoftext|>


<commit_before>from flashget.page import Page, log
from flashget.extension import Extension
from flashget.url import UrlMgr
from flashget.helper import textextract
from lxml import html
from lxml import etree
import re

class AnimeLoads(Page, Extension):
    eregex = '.*anime-loads.org/media/.*'
    ename = 'anime-loads'

    name = 'anime-loads'
    url = 'http://anime-loads.org'

    def __init__(self, *args, **kwargs):
        self.cookies = {'hentai':'aktiviert'}
        super(AnimeLoads, self).__init__(*args, **kwargs)

    def get(self):
        link = self.link
        url = UrlMgr(url=link, cookies=self.cookies)
        name = textextract(textextract(url.data, '
','
'), ' :: ', '')
        media = self.getMedia(name, link)

        if not media:
            return None

        root = html.fromstring(url.data)
        try:
            listTable = root.get_element_by_id('partlist')
        except Exception: # TODO take a more specific exception
            log.error("no partlist table inside data")
            log.error(link)
            log.error(url.data)
            return None
        for row in listTable.iterfind(".//tr[@class='link']"):
            part = media.createSub()
            curCol = 0
            for column in row.iterfind("td"):
                curCol += 1
                if curCol == 1:
                    part.num = column.text
                elif curCol == 2:
                    part.name = column.text
                elif curCol == 5: # download links
                    pass
                elif curCol == 6: # stream links
                    dlTable = column.find(".//table[@class='dltable']")
                    if dlTable is None:
                        dlTable = column.find(".//table[@class='list']")
                        if dlTable is None:
                            log.error("no downloadtable in %s", link)
                            continue
                    for streamRow in dlTable.iterfind(".//tr[@class='medialink']"):
                        alternative = part.createSub()
                        streamCurCol = 0
                        for streamColumn in streamRow.iterfind("td"):
                            streamCurCol += 1
                            if streamCurCol == 1:
                                streamColumnString = etree.tostring(streamColumn)
                                tmp = re.search("hoster/(.*?)\.png", streamColumnString)
                                if tmp:
                                    alternative.hoster = tmp.group(1)
                                alternativePart = alternative.createSub()
                                redirectUrl = re.search("a href=\"(.*?)\"", streamColumnString)
                                if redirectUrl:
                                    alternativePart.url = redirectUrl.group(1)
                                else:
                                    continue
                            if streamCurCol == 2:
                                # there can exist multiple langs but i take just one
                                lang = re.search("lang/(..)\.png", etree.tostring(streamColumn))
                                if lang:
                                    lang = lang.group(1)
                                alternative.language = getLanguage(lang, 'de')
                            if streamCurCol == 3:
                                # there can exist multiple langs but i take just one
                                lang = re.search("lang/(..)\.png", etree.tostring(streamColumn))
                                if lang:
                                    lang = lang.group(1)
                                alternative.subtitle = getLanguage(lang)
                            if streamCurCol == 4:
                                alternativePart.size = streamColumn.text

        tags = []
        for i in ('Zielgruppe', 'Genres'):
            newTags = textextract(url.data, '
'+i+'
', '
')
            if newTags:
                newTags = textextract(newTags, '
', '')
                newTags = newTags.split(', ')
                tags.extend(newTags)
        year = textextract(url.data, '
Jahr
', '
')
        year = textextract(year, '
', '')
        try:
            media.year = int(year[:4])
        except ValueError:
            log.warning("Problem with year in %s", link)
        media.addTags(tags)
        return self.afterExtract(media)

def getLanguage(name, default=None):
    if name is None:
        name = default
    return name
def getLanguages(names):
    ret = []
    for i in names:
        ret.append(getLanguage(i))
    return ret<commit_msg>set the season number for animeloads<commit_after>from flashget.page import Page, log
from flashget.extension import Extension
from flashget.url import UrlMgr
from flashget.helper import textextract
from lxml import html
from lxml import etree
import re

class AnimeLoads(Page, Extension):
    eregex = '.*anime-loads.org/media/.*'
    ename = 'anime-loads'

    name = 'anime-loads'
    url = 'http://anime-loads.org'

    def __init__(self, *args, **kwargs):
        self.cookies = {'hentai':'aktiviert'}
        super(AnimeLoads, self).__init__(*args, **kwargs)

    def get(self):
        link = self.link
        url = UrlMgr(url=link, cookies=self.cookies)
        name = textextract(textextract(url.data, '
','
'), ' :: ', '')
        media = self.getMedia(name, link)

        if not media:
            return None

        season = 0

        # there is no season information on that page :/
        # look if it is a tvshow by that string and just assume a season
        if "Anime-Serie ::" in url.data:
            season = 1

        root = html.fromstring(url.data)
        try:
            listTable = root.get_element_by_id('partlist')
        except Exception: # TODO take a more specific exception
            log.error("no partlist table inside data")
            log.error(link)
            log.error(url.data)
            return None
        for row in listTable.iterfind(".//tr[@class='link']"):
            part = media.createSub()
            part.season = season
            curCol = 0
            for column in row.iterfind("td"):
                curCol += 1
                if curCol == 1:
                    part.num = column.text
                elif curCol == 2:
                    part.name = column.text
                elif curCol == 5: # download links
                    pass
                elif curCol == 6: # stream links
                    dlTable = column.find(".//table[@class='dltable']")
                    if dlTable is None:
                        dlTable = column.find(".//table[@class='list']")
                        if dlTable is None:
                            log.error("no downloadtable in %s", link)
                            continue
                    for streamRow in dlTable.iterfind(".//tr[@class='medialink']"):
                        alternative = part.createSub()
                        streamCurCol = 0
                        for streamColumn in streamRow.iterfind("td"):
                            streamCurCol += 1
                            if streamCurCol == 1:
                                streamColumnString = etree.tostring(streamColumn)
                                tmp = re.search("hoster/(.*?)\.png", streamColumnString)
                                if tmp:
                                    alternative.hoster = tmp.group(1)
                                alternativePart = alternative.createSub()
                                redirectUrl = re.search("a href=\"(.*?)\"", streamColumnString)
                                if redirectUrl:
                                    alternativePart.url = redirectUrl.group(1)
                                else:
                                    continue
                            if streamCurCol == 2:
                                # there can exist multiple langs but i take just one
                                lang = re.search("lang/(..)\.png", etree.tostring(streamColumn))
                                if lang:
                                    lang = lang.group(1)
                                alternative.language = getLanguage(lang, 'de')
                            if streamCurCol == 3:
                                # there can exist multiple langs but i take just one
                                lang = re.search("lang/(..)\.png", etree.tostring(streamColumn))
                                if lang:
                                    lang = lang.group(1)
                                alternative.subtitle = getLanguage(lang)
                            if streamCurCol == 4:
                                alternativePart.size = streamColumn.text

        tags = []
        for i in ('Zielgruppe', 'Genres'):
            newTags = textextract(url.data, '
'+i+'
', '
')
            if newTags:
                newTags = textextract(newTags, '
', '')
                newTags = newTags.split(', ')
                tags.extend(newTags)
        year = textextract(url.data, '
Jahr
', '
')
        year = textextract(year, '
', '')
        try:
            media.year = int(year[:4])
        except ValueError:
            log.warning("Problem with year in %s", link)
        media.addTags(tags)
        return self.afterExtract(media)

def getLanguage(name, default=None):
    if name is None:
        name = default
    return name
def getLanguages(names):
    ret = []
    for i in names:
        ret.append(getLanguage(i))
    return ret
<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""Displays network traffic
   * No extra configuration needed

contributed by `izn <https://github.com/izn>`_ - many thanks!
"""

import psutil
import netifaces

import core.module
import core.widget

import util.format

WIDGET_NAME = "network_traffic"

class Module(core.module.Module):
    def __init__(self, config, theme):
        widgets = [
            core.widget.Widget(
                name="{0}.rx".format(WIDGET_NAME),
                full_text=self.download_rate,
            ),
            core.widget.Widget(
                name="{0}.tx".format(WIDGET_NAME),
                full_text=self.upload_rate,
            ),
        ]
        super().__init__(config, theme, widgets)

        self.widgets()[0].module = self
        self.widgets()[1].module = self

        self.widgets()[0].set("theme.minwidth", "0000000KiB/s")
        self.widgets()[1].set("theme.minwidth", "0000000KiB/s")

        try:
            self._bandwidth = BandwidthInfo()

            self._rate_recv = "?"
            self._rate_sent = "?"
            self._bytes_recv = self._bandwidth.bytes_recv()
            self._bytes_sent = self._bandwidth.bytes_sent()
        except Exception:
            """ We do not want do explode anything """
            pass

    def state(self, widget):
        """Return the widget state"""

        if widget.name == "{}.rx".format(WIDGET_NAME):
            return "rx"
        elif widget.name == "{}.tx".format(WIDGET_NAME):
            return "tx"

        return None

    def update(self):
        try:
            bytes_recv = self._bandwidth.bytes_recv()
            bytes_sent = self._bandwidth.bytes_sent()

            self._rate_recv = bytes_recv - self._bytes_recv
            self._rate_sent = bytes_sent - self._bytes_sent

            self._bytes_recv, self._bytes_sent = bytes_recv, bytes_sent
        except Exception:
            """ We do not want do explode anything """
            pass

    def download_rate(self, _):
        return "{}/s".format(util.format.byte(self._rate_recv))

    def upload_rate(self, _):
        return "{}/s".format(util.format.byte(self._rate_sent))

class BandwidthInfo(object):
    """Get received/sent bytes from network adapter"""

    def bytes_recv(self):
        """Return received bytes"""
        return self.bandwidth().bytes_recv

    def bytes_sent(self):
        """Return sent bytes"""
        return self.bandwidth().bytes_sent

    def bandwidth(self):
        """Return bandwidth information"""
        io_counters = self.io_counters()
        return io_counters[self.default_network_adapter()]

    @classmethod
    def default_network_adapter(cls):
        """Return default active network adapter"""
        gateway = netifaces.gateways()["default"]

        if not gateway:
            raise "No default gateway found"

        return gateway[netifaces.AF_INET][1]

    @classmethod
    def io_counters(cls):
        """Return IO counters"""
        return psutil.net_io_counters(pernic=True)

# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
<commit_msg>cleaning up to match style<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""Displays network traffic
   * No extra configuration needed

contributed by `izn <https://github.com/izn>`_ - many thanks!
"""

import psutil
import netifaces

import core.module
import core.widget

import util.format

WIDGET_NAME = "network_traffic"

class Module(core.module.Module):
    def __init__(self, config, theme):
        widgets = [
            core.widget.Widget(
                name="{0}.rx".format(WIDGET_NAME),
                full_text=self.download_rate,
            ),
            core.widget.Widget(
                name="{0}.tx".format(WIDGET_NAME),
                full_text=self.upload_rate,
            ),
        ]
        super().__init__(config, theme, widgets)

        self.widgets()[0].module = self
        self.widgets()[1].module = self

        self.widgets()[0].set("theme.minwidth", "0000000KiB/s")
        self.widgets()[1].set("theme.minwidth", "0000000KiB/s")

        try:
            self._bandwidth = BandwidthInfo()

            self._rate_recv = "?"
            self._rate_sent = "?"
            self._bytes_recv = self._bandwidth.bytes_recv()
            self._bytes_sent = self._bandwidth.bytes_sent()
        except Exception:
            """ We do not want do explode anything """
            pass

    def state(self, widget):
        """Return the widget state"""

        if widget.name == "{}.rx".format(WIDGET_NAME):
            return "rx"
        elif widget.name == "{}.tx".format(WIDGET_NAME):
            return "tx"

        return None

    def update(self):
        try:
            bytes_recv = self._bandwidth.bytes_recv()
            bytes_sent = self._bandwidth.bytes_sent()

            self._rate_recv = bytes_recv - self._bytes_recv
            self._rate_sent = bytes_sent - self._bytes_sent

            self._bytes_recv, self._bytes_sent = bytes_recv, bytes_sent
        except Exception:
            """ We do not want do explode anything """
            pass

    def download_rate(self, _):
        return "{}/s".format(util.format.byte(self._rate_recv))

    def upload_rate(self, _):
        return "{}/s".format(util.format.byte(self._rate_sent))

class BandwidthInfo(object):
    """Get received/sent bytes from network adapter"""

    def bytes_recv(self):
        """Return received bytes"""
        return self.bandwidth().bytes_recv

    def bytes_sent(self):
        """Return sent bytes"""
        return self.bandwidth().bytes_sent

    def bandwidth(self):
        """Return bandwidth information"""
        io_counters = self.io_counters()
        return io_counters[self.default_network_adapter()]

    @classmethod
    def default_network_adapter(cls):
        """Return default active network adapter"""
        gateway = netifaces.gateways()["default"]

        if not gateway:
            raise "No default gateway found"

        return gateway[netifaces.AF_INET][1]

    @classmethod
    def io_counters(cls):
        """Return IO counters"""
        return psutil.net_io_counters(pernic=True)

# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
<|endoftext|>


<commit_before>from .engine import FlaskFileUpload

__author__ = 'Arthur Holzner'
__version__ = '0.3.0'<commit_msg>added version<commit_after>from .engine import FlaskFileUpload

__author__ = 'Arthur Holzner'
__version__ = '0.3.1'<|endoftext|>


<commit_before># -*- coding: utf-8 -*-

from django.http import HttpResponseRedirect
from django.contrib.auth.decorators import login_required
from Instanssi.admin_base.misc.eventsel import get_selected_event

@login_required(login_url='/control/auth/login/')
def index(request):
    # Select latest event as default
    print get_selected_event(request)

    # Redirect to events page
    return HttpResponseRedirect("/control/events/")

@login_required(login_url='/control/auth/login/')
def eventchange(request, event_id):
    # Get redirect path
    if 'r' in request.GET:
        r = request.GET['r']
        if r[0] != "/":
            r = "/control/"
    else:
        r = "/control/"

    # Set session variable
    try:
        request.session['m_event_id'] = int(event_id)
    except:
        raise Http404

    # Redirect
    return HttpResponseRedirect(r)<commit_msg>admin_base: oops, get rid of print ...<commit_after># -*- coding: utf-8 -*-

from django.http import HttpResponseRedirect
from django.contrib.auth.decorators import login_required
from Instanssi.admin_base.misc.eventsel import get_selected_event

@login_required(login_url='/control/auth/login/')
def index(request):
    # Select latest event as default
    get_selected_event(request)

    # Redirect to events page
    return HttpResponseRedirect("/control/events/")

@login_required(login_url='/control/auth/login/')
def eventchange(request, event_id):
    # Get redirect path
    if 'r' in request.GET:
        r = request.GET['r']
        if r[0] != "/":
            r = "/control/"
    else:
        r = "/control/"

    # Set session variable
    try:
        request.session['m_event_id'] = int(event_id)
    except:
        raise Http404

    # Redirect
    return HttpResponseRedirect(r)<|endoftext|>


<commit_before># dataelem.py
"""Define the DataElement class - elements within a dataset.

DataElements have a DICOM value representation VR, a value multiplicity VM,
and a value.
"""
# Copyright (c) 2008-2012 Darcy Mason
# This file is part of pydicom, released under a modified MIT license.
#    See the file license.txt included with this distribution, also
#    available at http://pydicom.googlecode.com
#
from __future__ import absolute_import
import sys
from dicom import in_py3

import logging
logger = logging.getLogger('pydicom')

from dicom.datadict import dictionary_has_tag, dictionary_description
from dicom.datadict import private_dictionary_description, dictionaryVR
from dicom.tag import Tag

from dicom.UID import UID
from dicom.valuerep import IS, DS, PersonName
from decimal import Decimal

from collections import namedtuple

# os.stat is only available on Unix and Windows
# Not sure if on other platforms the import fails, or the call to it??
stat_available = True
try:
    from os import stat
except:
    stat_available = False
import os.path

from dicom.filebase import DicomFile
import warnings

# Helper functions:
def isMultiValue(value):
    """Helper function: return True if 'value' is 'list-like'."""
    if isString(value) or isinstance(value, bytes):
        return False
    try:
        iter(value)
    except TypeError:
        return False
    return True

def isString(val):
    """Helper function: return True if val is a string."""
    return isinstance(val, basestring)

def isStringOrStringList(val):
    """Return true if val consists only of strings. val may be a list/tuple."""
    if isMultiValue(val):
        for item in val:
            if not isString(item):
                return False
        return True
    else:  # single value - test for a string
        return isString(val)

_backslash = "\\"  # double '\' because it is used as escape chr in Python

class DataElement(object):
    """Contain and manipulate a Dicom data element, having a tag, VR, VM and value.

    Most user code will not create data elements using this class directly,
    but rather through 'named tags' in Dataset objects.
    See the Dataset class for a description of how Datasets, Sequences,
    and DataElements work.

    Class Data
    ----------
    For string display (via __str__), the following are used:

    descripWidth -- maximum width of description field (default 35).
    maxBytesToDisplay -- longer data will display "array of # bytes" (default 16).
    showVR -- True (default) to include the dicom VR just before the value.
    """
    descripWidth = 35
    maxBytesToDisplay = 16
    showVR = 1

    def __init__(self, tag, VR, value, file_value_tell=None,
                        is_undefined_length=False):
        """Create a data element instance.

        Most user code should instead use DICOM keywords, (formerly 'Named tags'
        in pydicom) to create data_elements, for which only the value is supplied,
        and the VR and tag are determined from the dicom dictionary.

        tag -- dicom (group, element) tag in any form accepted by Tag().
        VR -- dicom value representation (see DICOM standard part 6)
        value -- the value of the data element. One of the following:
            - a single string value
            - a number
            - a list or tuple with all strings or all numbers
            - a multi-value string with backslash separator
        file_value_tell -- used internally by Dataset, to store the write
            position for ReplaceDataElementValue method
        is_undefined_length -- used internally to store whether the length
            field in this data element was 0xFFFFFFFFL, i.e. "undefined length"

        """
        self.tag = Tag(tag)
        self.VR = VR  # Note!: you must set VR before setting value
        self.value = value
        self.file_tell = file_value_tell
        self.is_undefined_length = is_undefined_length

    @property
    def value(self):
        """The value (possibly multiple values) of this data_element"""
        return self._value

    @value.setter
    def value(self, val):
        """Set method for 'value' property"""
        # Check if is a string with multiple values separated by '\'
        # If so, turn them into a list of separate strings
        if isString(val) and self.VR not in \
           ['UT', 'ST', 'LT', 'FL', 'FD', 'AT', 'OB', 'OW', 'OF', 'SL', 'SQ', 'SS',
            'UL', 'OB/OW', 'OW/OB', 'OB or OW', 'OW or OB', 'UN'] and 'US' not in self.VR:  # latter covers 'US or SS' etc
            if _backslash in val:
                val = val.split(_backslash)
        self._value = self._convert_value(val)

    @property
    def VM(self):
        """The number of values in the data_element's 'value'"""
        if isMultiValue(self.value):
            return len(self.value)
        else:
            return 1

    def _convert_value(self, val):
        """Convert Dicom string values if possible to e.g. numbers. Handle the case
        of multiple value data_elements"""
        if self.VR == 'SQ':  # a sequence - leave it alone
            from dicom.sequence import Sequence
            if isinstance(val, Sequence):
                return val
            else:
                return Sequence(val)

        # if the value is a list, convert each element
        try:
            val.append
        except AttributeError:  # not a list
            return self._convert(val)
        else:
            returnvalue = []
            for subval in val:
                returnvalue.append(self._convert(subval))
            return returnvalue

    def _convert(self, val):
        """Take the value and convert to number, etc if possible"""
        if self.VR == 'IS':
            return IS(val)
        elif self.VR == 'DS':
            return DS(val)
        elif self.VR == "UI":
            return UID(val)
        # Later may need this for PersonName as for UI,
        #    but needs more thought
        # elif self.VR == "PN":
        #    return PersonName(val)
        else:  # is either a string or a type 2 optionally blank string
            return val  # this means a "numeric" value could be empty string ""
        #except TypeError:
            #print "Could not convert value '%s' to VR '%s' in tag %s" \
                                # % (repr(val), self.VR, self.tag)
        #except ValueError:
            #print "Could not convert value '%s' to VR '%s' in tag %s" \
                               # % (repr(val), self.VR, self.tag)

    def __str__(self):
        """Return str representation of this data_element"""
        repVal = self.repval
        if self.showVR:
            s = "%s %-*s %s: %s" % (str(self.tag), self.descripWidth,
                            self.description()[:self.descripWidth], self.VR, repVal)
        else:
            s = "%s %-*s %s" % (str(self.tag), self.descripWidth,
                            self.description()[:self.descripWidth], repVal)
        return s

    @property
    def repval(self):
        """Return a str representation of the current value for use in __str__"""
        if (self.VR in ['OB', 'OW', 'OW/OB', 'OW or OB', 'OB or OW', 'US or SS or OW', 'US or SS']
                  and len(self.value) > self.maxBytesToDisplay):
            repVal = "Array of %d bytes" % len(self.value)
        elif hasattr(self, 'original_string'):  # for VR of IS or DS
            repVal = repr(self.original_string)
        elif isinstance(self.value, Decimal):
            repVal = repr(self.value)
        elif isinstance(self.value, UID):
            repVal = self.value.name
        else:
            repVal = repr(self.value)  # will tolerate unicode too
        return repVal

    def __unicode__(self):
        """Return unicode representation of this data_element"""
        if isinstance(self.value, unicode):
            # start with the string rep then replace the value part with the unicode
            strVal = str(self)
            uniVal = unicode(strVal.replace(self.repval, "")) + self.value
            return uniVal
        else:
            return unicode(str(self))

    def __getitem__(self, key):
        """Returns the item from my value's Sequence, if it is one."""
        try:
            return self.value[key]
        except TypeError:
            raise TypeError("DataElement value is unscriptable (not a Sequence)")

    @property
    def name(self):
        return self.description()

    def description(self):
        """Return the DICOM dictionary description for this dicom tag."""
        if dictionary_has_tag(self.tag):
            name = dictionary_description(self.tag)
        elif self.tag.is_private:
            name = "Private tag data"  # default
            if hasattr(self, 'private_creator'):
                try:
                    # If have name from private dictionary, use it, but
                    #   but put in square brackets so is differentiated,
                    #   and clear that cannot access it by name
                    name = "[" + private_dictionary_description(self.tag, self.private_creator) + "]"
                except KeyError:
                    pass
            elif self.tag.elem >> 8 == 0:
                name = "Private Creator"
        elif self.tag.element == 0:  # implied Group Length dicom versions < 3
            name = "Group Length"
        else:
            name = ""
        return name

    def __repr__(self):
        """Handle repr(data_element)"""
        if self.VR == "SQ":
            return repr(self.value)
        else:
            return str(self)

class DeferredDataElement(DataElement):
    """Subclass of DataElement where value is not read into memory until needed"""
    def __init__(self, tag, VR, fp, file_mtime, data_element_tell, length):
        """Store basic info for the data element but value will be read later

        fp -- DicomFile object representing the dicom file being read
        file_mtime -- last modification time on file, used to make sure
           it has not changed since original read
        data_element_tell -- file position at start of data element,
           (not the start of the value part, but start of whole element)
        """
        self.tag = Tag(tag)
        self.VR = VR
        self._value = None  # flag as unread

        # Check current file object and save info needed for read later
        self.fp_is_implicit_VR = fp.is_implicit_VR
        self.fp_is_little_endian = fp.is_little_endian
        self.filepath = fp.name
        self.file_mtime = file_mtime
        self.data_element_tell = data_element_tell
        self.length = length

    @property
    def repval(self):
        if self._value is None:
            return "Deferred read: length %d" % self.length
        else:
            return DataElement.repval.fget(self)

    @property
    def value(self):
        """Get method for 'value' property"""
        # Must now read the value if haven't already
        if self._value is None:
            self.read_value()
        return DataElement.value.fget(self)

    @value.setter
    def value(self, val):
        DataElement.value.fset(self, val)

RawDataElement = namedtuple('RawDataElement',
                  'tag VR length value value_tell is_implicit_VR is_little_endian')

def DataElement_from_raw(raw_data_element):
    """Return a DataElement from a RawDataElement"""
    from dicom.values import convert_value  # XXX buried here to avoid circular import filereader->Dataset->convert_value->filereader (for SQ parsing)
    raw = raw_data_element
    VR = raw.VR
    if VR is None:  # Can be if was implicit VR
        try:
            VR = dictionaryVR(raw.tag)
        except KeyError:
            if raw.tag.is_private:
                VR = 'OB'  # just read the bytes, no way to know what they mean
            elif raw.tag.element == 0:  # group length tag implied in versions < 3.0
                VR = 'UL'
            else:
                raise KeyError("Unknown DICOM tag {0:s} - can't look up VR".format(str(raw.tag)))
    try:
        value = convert_value(VR, raw)
    except NotImplementedError as e:
        raise NotImplementedError("{0:s} in tag {1!r}".format(str(e), raw.tag))
    return DataElement(raw.tag, VR, value, raw.value_tell, raw.length == 0xFFFFFFFF)
<commit_msg>Adds encoding argument to DataElement_from_raw<commit_after># dataelem.py
"""Define the DataElement class - elements within a dataset.

DataElements have a DICOM value representation VR, a value multiplicity VM,
and a value.
"""
# Copyright (c) 2008-2012 Darcy Mason
# This file is part of pydicom, released under a modified MIT license.
#    See the file license.txt included with this distribution, also
#    available at http://pydicom.googlecode.com
#
from __future__ import absolute_import
import sys
from dicom import in_py3

import logging
logger = logging.getLogger('pydicom')

from dicom.datadict import dictionary_has_tag, dictionary_description
from dicom.datadict import private_dictionary_description, dictionaryVR
from dicom.tag import Tag

from dicom.UID import UID
from dicom.valuerep import IS, DS, PersonName
from decimal import Decimal

from collections import namedtuple

# os.stat is only available on Unix and Windows
# Not sure if on other platforms the import fails, or the call to it??
stat_available = True
try:
    from os import stat
except:
    stat_available = False
import os.path

from dicom.filebase import DicomFile
import warnings

# Helper functions:
def isMultiValue(value):
    """Helper function: return True if 'value' is 'list-like'."""
    if isString(value) or isinstance(value, bytes):
        return False
    try:
        iter(value)
    except TypeError:
        return False
    return True

def isString(val):
    """Helper function: return True if val is a string."""
    return isinstance(val, basestring)

def isStringOrStringList(val):
    """Return true if val consists only of strings. val may be a list/tuple."""
    if isMultiValue(val):
        for item in val:
            if not isString(item):
                return False
        return True
    else:  # single value - test for a string
        return isString(val)

_backslash = "\\"  # double '\' because it is used as escape chr in Python

class DataElement(object):
    """Contain and manipulate a Dicom data element, having a tag, VR, VM and value.

    Most user code will not create data elements using this class directly,
    but rather through 'named tags' in Dataset objects.
    See the Dataset class for a description of how Datasets, Sequences,
    and DataElements work.

    Class Data
    ----------
    For string display (via __str__), the following are used:

    descripWidth -- maximum width of description field (default 35).
    maxBytesToDisplay -- longer data will display "array of # bytes" (default 16).
    showVR -- True (default) to include the dicom VR just before the value.
    """
    descripWidth = 35
    maxBytesToDisplay = 16
    showVR = 1

    def __init__(self, tag, VR, value, file_value_tell=None,
                        is_undefined_length=False):
        """Create a data element instance.

        Most user code should instead use DICOM keywords, (formerly 'Named tags'
        in pydicom) to create data_elements, for which only the value is supplied,
        and the VR and tag are determined from the dicom dictionary.

        tag -- dicom (group, element) tag in any form accepted by Tag().
        VR -- dicom value representation (see DICOM standard part 6)
        value -- the value of the data element. One of the following:
            - a single string value
            - a number
            - a list or tuple with all strings or all numbers
            - a multi-value string with backslash separator
        file_value_tell -- used internally by Dataset, to store the write
            position for ReplaceDataElementValue method
        is_undefined_length -- used internally to store whether the length
            field in this data element was 0xFFFFFFFFL, i.e. "undefined length"

        """
        self.tag = Tag(tag)
        self.VR = VR  # Note!: you must set VR before setting value
        self.value = value
        self.file_tell = file_value_tell
        self.is_undefined_length = is_undefined_length

    @property
    def value(self):
        """The value (possibly multiple values) of this data_element"""
        return self._value

    @value.setter
    def value(self, val):
        """Set method for 'value' property"""
        # Check if is a string with multiple values separated by '\'
        # If so, turn them into a list of separate strings
        if isString(val) and self.VR not in \
           ['UT', 'ST', 'LT', 'FL', 'FD', 'AT', 'OB', 'OW', 'OF', 'SL', 'SQ', 'SS',
            'UL', 'OB/OW', 'OW/OB', 'OB or OW', 'OW or OB', 'UN'] and 'US' not in self.VR:  # latter covers 'US or SS' etc
            if _backslash in val:
                val = val.split(_backslash)
        self._value = self._convert_value(val)

    @property
    def VM(self):
        """The number of values in the data_element's 'value'"""
        if isMultiValue(self.value):
            return len(self.value)
        else:
            return 1

    def _convert_value(self, val):
        """Convert Dicom string values if possible to e.g. numbers. Handle the case
        of multiple value data_elements"""
        if self.VR == 'SQ':  # a sequence - leave it alone
            from dicom.sequence import Sequence
            if isinstance(val, Sequence):
                return val
            else:
                return Sequence(val)

        # if the value is a list, convert each element
        try:
            val.append
        except AttributeError:  # not a list
            return self._convert(val)
        else:
            returnvalue = []
            for subval in val:
                returnvalue.append(self._convert(subval))
            return returnvalue

    def _convert(self, val):
        """Take the value and convert to number, etc if possible"""
        if self.VR == 'IS':
            return IS(val)
        elif self.VR == 'DS':
            return DS(val)
        elif self.VR == "UI":
            return UID(val)
        # Later may need this for PersonName as for UI,
        #    but needs more thought
        # elif self.VR == "PN":
        #    return PersonName(val)
        else:  # is either a string or a type 2 optionally blank string
            return val  # this means a "numeric" value could be empty string ""
        #except TypeError:
            #print "Could not convert value '%s' to VR '%s' in tag %s" \
                                # % (repr(val), self.VR, self.tag)
        #except ValueError:
            #print "Could not convert value '%s' to VR '%s' in tag %s" \
                               # % (repr(val), self.VR, self.tag)

    def __str__(self):
        """Return str representation of this data_element"""
        repVal = self.repval
        if self.showVR:
            s = "%s %-*s %s: %s" % (str(self.tag), self.descripWidth,
                            self.description()[:self.descripWidth], self.VR, repVal)
        else:
            s = "%s %-*s %s" % (str(self.tag), self.descripWidth,
                            self.description()[:self.descripWidth], repVal)
        return s

    @property
    def repval(self):
        """Return a str representation of the current value for use in __str__"""
        if (self.VR in ['OB', 'OW', 'OW/OB', 'OW or OB', 'OB or OW', 'US or SS or OW', 'US or SS']
                  and len(self.value) > self.maxBytesToDisplay):
            repVal = "Array of %d bytes" % len(self.value)
        elif hasattr(self, 'original_string'):  # for VR of IS or DS
            repVal = repr(self.original_string)
        elif isinstance(self.value, Decimal):
            repVal = repr(self.value)
        elif isinstance(self.value, UID):
            repVal = self.value.name
        else:
            repVal = repr(self.value)  # will tolerate unicode too
        return repVal

    def __unicode__(self):
        """Return unicode representation of this data_element"""
        if isinstance(self.value, unicode):
            # start with the string rep then replace the value part with the unicode
            strVal = str(self)
            uniVal = unicode(strVal.replace(self.repval, "")) + self.value
            return uniVal
        else:
            return unicode(str(self))

    def __getitem__(self, key):
        """Returns the item from my value's Sequence, if it is one."""
        try:
            return self.value[key]
        except TypeError:
            raise TypeError("DataElement value is unscriptable (not a Sequence)")

    @property
    def name(self):
        return self.description()

    def description(self):
        """Return the DICOM dictionary description for this dicom tag."""
        if dictionary_has_tag(self.tag):
            name = dictionary_description(self.tag)
        elif self.tag.is_private:
            name = "Private tag data"  # default
            if hasattr(self, 'private_creator'):
                try:
                    # If have name from private dictionary, use it, but
                    #   but put in square brackets so is differentiated,
                    #   and clear that cannot access it by name
                    name = "[" + private_dictionary_description(self.tag, self.private_creator) + "]"
                except KeyError:
                    pass
            elif self.tag.elem >> 8 == 0:
                name = "Private Creator"
        elif self.tag.element == 0:  # implied Group Length dicom versions < 3
            name = "Group Length"
        else:
            name = ""
        return name

    def __repr__(self):
        """Handle repr(data_element)"""
        if self.VR == "SQ":
            return repr(self.value)
        else:
            return str(self)

class DeferredDataElement(DataElement):
    """Subclass of DataElement where value is not read into memory until needed"""
    def __init__(self, tag, VR, fp, file_mtime, data_element_tell, length):
        """Store basic info for the data element but value will be read later

        fp -- DicomFile object representing the dicom file being read
        file_mtime -- last modification time on file, used to make sure
           it has not changed since original read
        data_element_tell -- file position at start of data element,
           (not the start of the value part, but start of whole element)
        """
        self.tag = Tag(tag)
        self.VR = VR
        self._value = None  # flag as unread

        # Check current file object and save info needed for read later
        self.fp_is_implicit_VR = fp.is_implicit_VR
        self.fp_is_little_endian = fp.is_little_endian
        self.filepath = fp.name
        self.file_mtime = file_mtime
        self.data_element_tell = data_element_tell
        self.length = length

    @property
    def repval(self):
        if self._value is None:
            return "Deferred read: length %d" % self.length
        else:
            return DataElement.repval.fget(self)

    @property
    def value(self):
        """Get method for 'value' property"""
        # Must now read the value if haven't already
        if self._value is None:
            self.read_value()
        return DataElement.value.fget(self)

    @value.setter
    def value(self, val):
        DataElement.value.fset(self, val)

RawDataElement = namedtuple('RawDataElement',
                  'tag VR length value value_tell is_implicit_VR is_little_endian')

def DataElement_from_raw(raw_data_element, encoding=None):
    """Return a DataElement from a RawDataElement"""
    from dicom.values import convert_value  # XXX buried here to avoid circular import filereader->Dataset->convert_value->filereader (for SQ parsing)
    raw = raw_data_element
    VR = raw.VR
    if VR is None:  # Can be if was implicit VR
        try:
            VR = dictionaryVR(raw.tag)
        except KeyError:
            if raw.tag.is_private:
                VR = 'OB'  # just read the bytes, no way to know what they mean
            elif raw.tag.element == 0:  # group length tag implied in versions < 3.0
                VR = 'UL'
            else:
                raise KeyError("Unknown DICOM tag {0:s} - can't look up VR".format(str(raw.tag)))
    try:
        value = convert_value(VR, raw, encoding)
    except NotImplementedError as e:
        raise NotImplementedError("{0:s} in tag {1!r}".format(str(e), raw.tag))
    return DataElement(raw.tag, VR, value, raw.value_tell, raw.length == 0xFFFFFFFF)
<|endoftext|>


<commit_before>import requests
import simplejson
import os
from time import sleep
from datetime import datetime, timedelta
from dateutil.tz import tzlocal

API_URL = "http://127.0.0.1:8080/api/v1/job/"

data = {
    "name": "test_job",
    "command": "bash " + os.path.dirname(os.path.realpath(__file__)) + "/example-kala-commands/example-command.sh",
    "epsilon": "PT5S",
}

dt = datetime.isoformat(datetime.now(tzlocal()) + timedelta(0, 10))
data["schedule"] = "%s/%s/%s" % ("R2", dt, "PT10S")

if __name__ == "__main__":
    print "Sending request to %s" % API_URL
    print "Payload is: %s" % data

    r = requests.post(API_URL, data=simplejson.dumps(data))

    print "\n\n CREATING \n"
    job_id = simplejson.loads(r.content)['id']
    print "Job was created with an id of %s" % job_id

    print "\n\n GETTING \n"
    m = requests.get(API_URL + job_id)
    print m.content

    print "\n\n DELETING \n"

    print "Waiting to delete...."
    sleep(21)
    n = requests.delete(API_URL + job_id)

    print n.__dict__
<commit_msg>8080 -> 8000<commit_after>import requests
import simplejson
import os
from time import sleep
from datetime import datetime, timedelta
from dateutil.tz import tzlocal

API_URL = "http://127.0.0.1:8000/api/v1/job/"

data = {
    "name": "test_job",
    "command": "bash " + os.path.dirname(os.path.realpath(__file__)) + "/example-kala-commands/example-command.sh",
    "epsilon": "PT5S",
}

dt = datetime.isoformat(datetime.now(tzlocal()) + timedelta(0, 10))
data["schedule"] = "%s/%s/%s" % ("R2", dt, "PT10S")

if __name__ == "__main__":
    print "Sending request to %s" % API_URL
    print "Payload is: %s" % data

    r = requests.post(API_URL, data=simplejson.dumps(data))

    print "\n\n CREATING \n"
    job_id = simplejson.loads(r.content)['id']
    print "Job was created with an id of %s" % job_id

    print "\n\n GETTING \n"
    m = requests.get(API_URL + job_id)
    print m.content

    print "\n\n DELETING \n"

    print "Waiting to delete...."
    sleep(21)
    n = requests.delete(API_URL + job_id)

    print n.__dict__
<|endoftext|>


<commit_before>import sys
import time
from functools import wraps
from datetime import datetime
import signal

from flask import current_app
import greenlet
import gevent
import gevent.monkey
from gevent.hub import get_hub
from gevent.pool import Pool
from gevent.greenlet import Greenlet
from gevent.pywsgi import WSGIServer

from .app import Flask
from .utils import get_argv_opt, monkey_patch_meth

def _create_switch_time_tracer(max_blocking_time, logger):
    def _switch_time_tracer(what, origin_target):
        origin, target = origin_target
        if not hasattr(_switch_time_tracer, '_last_switch_time'):
            _switch_time_tracer._last_switch_time = None
        then = _switch_time_tracer._last_switch_time
        now = _switch_time_tracer._last_switch_time = time.time()
        if then is not None:
            blocking_time = now - then
            if origin is not get_hub():
                if blocking_time > max_blocking_time:
                    msg = "Greenlet blocked the eventloop for %.4f seconds\n"
                    logger.warning(msg, blocking_time)

    return _switch_time_tracer

def set_switch_time_tracer(max_blocking_time, logger):
    # based on http://www.rfk.id.au/blog/entry/detect-gevent-blocking-with-greenlet-settrace/
    greenlet.settrace(_create_switch_time_tracer(max_blocking_time, logger))

def set_hub_exception_logger(logger):
    # NOTE: traceback is not printed with logger, but with exception_stream
    # also see http://www.gevent.org/gevent.hub.html
    # get_hub().handle_error and exeption_stream
    @monkey_patch_meth(get_hub(), 'print_exception')
    def print_exception(orig, context, type, value, tb):
        logger.error('%s failed with %r', context, value)
        return orig(context, type, value, tb)

def app_context(app):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            with app.app_context():
                return func(*args, **kwargs)
        return wrapper
    return decorator

def app_greenlet_class(app):
    @wraps(Greenlet)
    def wrapper(run, *args, **kwargs):
        return Greenlet(app_context(app)(run), *args, **kwargs)
    return wrapper

class GeventFlask(Flask):
    def configure(self, *args, **kwargs):
        super().configure(*args, **kwargs)

        self.started_at = datetime.utcnow()
        self.pools = {}
        self.greenlet_class = app_greenlet_class(self)

        # if not gevent.monkey.is_module_patched('__builtin__'):
        #     raise RuntimeError('Looks like gevent.monkey is not applied')

        if 'sqlalchemy' in self.extensions:
            db = self.extensions['sqlalchemy'].db
            db.engine.pool._use_threadlocal = True

        switch_trace_seconds = self.config.get('GEVENT_SWITCH_TRACE_SECONDS')
        if switch_trace_seconds:
            set_switch_time_tracer(switch_trace_seconds, self.logger)

        set_hub_exception_logger(self.logger)

    def spawn(self, func, *args, **kwargs):
        return gevent.spawn(app_context(self)(func), *args, **kwargs)

    def spawn_later(self, seconds, func, *args, **kwargs):
        return gevent.spawn_later(seconds, app_context(self)(func), *args, **kwargs)

    def greenlet(self, *args, **kwargs):
        return self.greenlet_class(*args, **kwargs)

    def create_pool(self, name, size=None):
        assert name not in self.pools, 'Pool {} already created'.format(name.upper())
        size = size or self.config.get('{}_POOL_SIZE'.format(name))
        self.pools[name] = Pool(size, greenlet_class=self.greenlet_class)
        return self.pools[name]

    def work_forever(self, wait_seconds=None):
        wait_seconds = wait_seconds or self.config.get('WORK_FOREVER_WAIT_SECONDS', 0)

        def decorator(func):
            def wrapper():
                try:
                    while True:
                        func()
                        if wait_seconds:
                            self.logger.info('work_forever sleep for %s', wait_seconds)
                            gevent.sleep(wait_seconds)
                except Exception as exc:
                    # TODO: stop server and log error
                    self.logger.exception('work_forever failed: %r', exc)
                    print(exc, file=sys.stderr)
                    sys.exit(1)
            self.spawn(wrapper)
        return decorator

    def stop(self, timeout=None):
        """
        Use it to execute before server teardown.
        """
        if timeout:
            raise NotImplementedError()

        def decorator(func):
            self._stop = app_context(self)(func)
        return decorator

def _pool_status(pool):
    return 'Pool {:d}/{:d}'.format(pool.free_count(), pool.size)

def get_app_status():
    rv = {'started_at': current_app.started_at}
    if 'sqlalchemy' in current_app.extensions:
        rv['sqlalchemy'] = current_app.extensions['sqlalchemy'].db.session.bind.pool.status()
    for name, pool in current_app.pools.items():
        rv[name + '_pool'] = _pool_status(pool)
    return rv

def serve_forever(app, stop_signals=[signal.SIGTERM, signal.SIGINT], listen=None):
    host, port = (get_argv_opt('-l', '--listen') or listen or
                  app.config.get('GEVENT_LISTEN', '127.0.0.1:8088')).split(':')
    server = WSGIServer((host, int(port)), app, spawn=app.create_pool('server'))

    def stop():
        if server.closed:
            try:
                app.logger.warn('Multiple exit signals received - aborting.')
            finally:
                sys.exit('Multiple exit signals received - aborting.')
        app.logger.info('Stopping server')
        if hasattr(app, '_stop'):
            app._stop()
        server.stop(5)
    [gevent.signal(sig, stop) for sig in stop_signals]

    app.logger.info('Starting server %s:%s', host, port)
    server.serve_forever()
<commit_msg>gevent: fixed work_forver (moved to serve_forever)<commit_after>import sys
import time
from functools import wraps
from datetime import datetime
import signal

from flask import current_app
import greenlet
import gevent
import gevent.monkey
from gevent.hub import get_hub
from gevent.pool import Pool
from gevent.greenlet import Greenlet
from gevent.pywsgi import WSGIServer

from .app import Flask
from .utils import get_argv_opt, monkey_patch_meth

def _create_switch_time_tracer(max_blocking_time, logger):
    def _switch_time_tracer(what, origin_target):
        origin, target = origin_target
        if not hasattr(_switch_time_tracer, '_last_switch_time'):
            _switch_time_tracer._last_switch_time = None
        then = _switch_time_tracer._last_switch_time
        now = _switch_time_tracer._last_switch_time = time.time()
        if then is not None:
            blocking_time = now - then
            if origin is not get_hub():
                if blocking_time > max_blocking_time:
                    msg = "Greenlet blocked the eventloop for %.4f seconds\n"
                    logger.warning(msg, blocking_time)

    return _switch_time_tracer

def set_switch_time_tracer(max_blocking_time, logger):
    # based on http://www.rfk.id.au/blog/entry/detect-gevent-blocking-with-greenlet-settrace/
    greenlet.settrace(_create_switch_time_tracer(max_blocking_time, logger))

def set_hub_exception_logger(logger):
    # NOTE: traceback is not printed with logger, but with exception_stream
    # also see http://www.gevent.org/gevent.hub.html
    # get_hub().handle_error and exeption_stream
    @monkey_patch_meth(get_hub(), 'print_exception')
    def print_exception(orig, context, type, value, tb):
        logger.error('%s failed with %r', context, value)
        return orig(context, type, value, tb)

def app_context(app):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            with app.app_context():
                return func(*args, **kwargs)
        return wrapper
    return decorator

def app_greenlet_class(app):
    @wraps(Greenlet)
    def wrapper(run, *args, **kwargs):
        return Greenlet(app_context(app)(run), *args, **kwargs)
    return wrapper

class GeventFlask(Flask):
    def configure(self, *args, **kwargs):
        super().configure(*args, **kwargs)

        self.started_at = datetime.utcnow()
        self.pools = {}
        self.greenlet_class = app_greenlet_class(self)

        # if not gevent.monkey.is_module_patched('__builtin__'):
        #     raise RuntimeError('Looks like gevent.monkey is not applied')

        if 'sqlalchemy' in self.extensions:
            db = self.extensions['sqlalchemy'].db
            db.engine.pool._use_threadlocal = True

        switch_trace_seconds = self.config.get('GEVENT_SWITCH_TRACE_SECONDS')
        if switch_trace_seconds:
            set_switch_time_tracer(switch_trace_seconds, self.logger)

        set_hub_exception_logger(self.logger)

    def spawn(self, func, *args, **kwargs):
        return gevent.spawn(app_context(self)(func), *args, **kwargs)

    def spawn_later(self, seconds, func, *args, **kwargs):
        return gevent.spawn_later(seconds, app_context(self)(func), *args, **kwargs)

    def greenlet(self, *args, **kwargs):
        return self.greenlet_class(*args, **kwargs)

    def create_pool(self, name, size=None):
        assert name not in self.pools, 'Pool {} already created'.format(name.upper())
        size = size or self.config.get('{}_POOL_SIZE'.format(name))
        self.pools[name] = Pool(size, greenlet_class=self.greenlet_class)
        return self.pools[name]

    def work_forever(self, wait_seconds=None):
        wait_seconds = wait_seconds or self.config.get('WORK_FOREVER_WAIT_SECONDS', 0)

        def decorator(func):
            def wrapper():
                try:
                    while True:
                        func()
                        if wait_seconds:
                            self.logger.info('work_forever sleep for %s', wait_seconds)
                            gevent.sleep(wait_seconds)
                except Exception as exc:
                    # TODO: stop server and log error
                    self.logger.exception('work_forever failed: %r', exc)
                    print(exc, file=sys.stderr)
                    sys.exit(1)
            self._work_forever = app_context(self)(wrapper)
        return decorator

    def stop(self, timeout=None):
        """
        Use it to execute before server teardown.
        """
        if timeout:
            raise NotImplementedError()

        def decorator(func):
            self._stop = app_context(self)(func)
        return decorator

def _pool_status(pool):
    return 'Pool {:d}/{:d}'.format(pool.free_count(), pool.size)

def get_app_status():
    rv = {'started_at': current_app.started_at}
    if 'sqlalchemy' in current_app.extensions:
        rv['sqlalchemy'] = current_app.extensions['sqlalchemy'].db.session.bind.pool.status()
    for name, pool in current_app.pools.items():
        rv[name + '_pool'] = _pool_status(pool)
    return rv

def serve_forever(app, stop_signals=[signal.SIGTERM, signal.SIGINT], listen=None):
    host, port = (get_argv_opt('-l', '--listen') or listen or
                  app.config.get('GEVENT_LISTEN', '127.0.0.1:8088')).split(':')
    server = WSGIServer((host, int(port)), app, spawn=app.create_pool('server'))

    def stop():
        if server.closed:
            try:
                app.logger.warn('Multiple exit signals received - aborting.')
            finally:
                sys.exit('Multiple exit signals received - aborting.')
        app.logger.info('Stopping server')
        if hasattr(app, '_stop'):
            app._stop()
        server.stop(5)
    [gevent.signal(sig, stop) for sig in stop_signals]

    app.logger.info('Starting server %s:%s', host, port)
    if hasattr(app, '_work_forever'):
        gevent.spawn(app._work_forever)
    server.serve_forever()
<|endoftext|>