Esempio n. 1
0
    def _get_settings_enum(self):
        settings = None
        rows = self.select('settings', 'code_name val'.split())
        (names, vals) = zip(*rows)
        settings = Enum(names, vals)

        return settings
Esempio n. 2
0
class App(object):
    APP_TYPES = Enum('GUI CMD_LINE'.split())

    ## Constructor
    # @param self
    # @param app_name (string) module name (name of a file from the app/ directory) of the app being started
    # @param app_type (int) a value from the static enum App.APP_TYPES, indicating whether or not to initialize GUI stuff.
    # @param app_icon_filename (string=None) path to the icon to use for this application (pass None if this is not a GUI-based app). This icon will be shown in the upper left corner of the title bar of all windows. The path may be absolute, or may be relative to the directory from which launcher.py is being called (typically this is the same directory that is specified by the BLL_APP_ROOT_DIR constant in launcher.py).
    def __init__(self, app_name, app_type, app_icon_filename=None):
        self.app_type = app_type

        BackendUtils.setup_logging(
            'logs/%s.log' % (app_name)
            )

        if app_type == App.APP_TYPES.GUI:
            # this sets some project-wide GTK settings and
            # sets the app-specific window icon
            UIUtils.setup_gtk(app_icon_filename)

    ## This method must be overridden by subclasses to
    # launch their main startup code.
    # @param self
    def start(self):
        pass

    ## This method starts the gtk+ event loop. This causes the app to start accepting input from input devices like the keyboard and mouse. launcher.py only calls this if the app instance is App.APP_TYPES.GUI
    def event_loop(self):
        gtk.main()
Esempio n. 3
0
    def _get_combo_options_enum(self):
        options = {}
        groups = self._get_combo_groups_enum()
        for i in range(len(groups)):
            rows = self.select('combo_options', 'id code_name'.split(),
                               'combo_group_id=?', [groups[i]], 'id ASC')
            ids, code_names = zip(*rows)
            options[groups[i]] = Enum(code_names, ids)

        return options
Esempio n. 4
0
    def __init__(self, trs_parser, seg, remove_bad_trans_codes):
        #since this file contains multiple classes, set up the logger so we can see which class messages are coming from
        self.logger = logging.getLogger(__name__ + '.' +
                                        self.__class__.__name__)

        self.trs_parser = trs_parser
        self.seg = seg
        self.remove_bad_trans_codes = remove_bad_trans_codes

        self.utter_list = [
        ]  #list of Utterances parsed so far. These are not guarenteed to be complete (eg. may have no end time assigned) until the finish() method has been executed.
        self.States = Enum(
            ['INITIAL', 'INITIAL_SYNC_TAG', 'WHO_TAG']
        )  #possible states - see the drive() routine for descriptions of each of them
        self.cur_state = self.States.INITIAL
Esempio n. 5
0
import textwrap

from django.conf import settings
from django.core.mail import send_mail
from django.template.loader import render_to_string
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
from lxml import html

from auth.models import CustomUser as User
from messages.models import Message, SYSTEM_NOTIFICATION
from utils.enum import Enum
from utils.taskqueue import job

Notifications = Enum('Notifications', [
    ('ROLE_CHANGED', _('Role changed')),
])

def notify_users(notification, user_list, subject, template_name,
                 context, send_email=None):
    """
    Send notification messages to a list of users

    Arguments:
        notification: member from the Notifications enum
        user_list: list/iterable of CustomUser objects to notify
        template_name: template to render the notification with
        context: context dict to use for the 2 templates
        send_email: Should we send an email alongside the message?  Use
            True/False to force an email to be sent or not sent.  None, the
            default means use the notify_by_email flag from CustomUser.
Esempio n. 6
0
class StateMachine():
    STATES = Enum('INITIAL SINGLE NUMBERED_MULTI UNNUMBERED_MULTI ERROR'.split())
    
    def __init__(self):
        self._reset_data_structs()

    def _reset_data_structs(self):
        self.single = []
        self.numbered_multi = []
        self.unnumbered_multi = []

        self.state = StateMachine.STATES.INITIAL
        self._container = None

    def divide_segs(self, segs, use_lena_segmentation=False):
        single = []
        numbered_multi = []
        unnumbered_multi = []
        for i in range(len(segs)):

            if use_lena_segmentation:
                segs[i].utters = self._combine_dot_split_utters(segs[i].utters)

            for j in range(len(segs[i].utters)):
                self._drive(segs[i].utters[j])
            self.finish()

            if self.state == StateMachine.STATES.ERROR:
                print 'The state machine has reached the error state. You should look into that.'

            single.extend(self.single)
            numbered_multi.extend(self.numbered_multi)
            unnumbered_multi.extend(self.unnumbered_multi)

            self._reset_data_structs()

        return single, numbered_multi, unnumbered_multi

    def _combine_dot_split_utters(self, utters):
        combined = []

        i = 0
        while i < len(utters):
            j = i + 1
            source = utters[i]
            while (j < len(utters) and
                   utters[j].is_dot_split and source.is_dot_split and
                   utters[j].start == source.start and
                   utters[j].end == source.end
            ):
                if utters[j].trans_phrase:
                    if source.trans_phrase is None:
                        source.trans_phrase = ''
                    source.trans_phrase += ' ' + utters[j].trans_phrase
                j += 1

            #source.is_dot_split = False
            combined.append(source)
            i = j

        return combined

    def _drive(self, utter):
        if self.state != StateMachine.STATES.ERROR:
            {
                StateMachine.STATES.INITIAL: self._state_initial,
                StateMachine.STATES.SINGLE: self._state_single,
                StateMachine.STATES.NUMBERED_MULTI: self._state_numbered_multi,
                StateMachine.STATES.UNNUMBERED_MULTI: self._state_unnumbered_multi,
                }[self.state](utter)

    def _state_initial(self, utter):
        if utter.is_dot_split:# and False:
            self.single.append([utter])
            
        elif not utter.is_dot_split:# or True:
            self._container = [utter]
            self.state = StateMachine.STATES.SINGLE

        # else:
        #     self.state = StateMachine.STATES.ERROR

    def _state_single(self, utter):
        if utter.is_dot_split:# and False:
            self.single.append(self._container)
            self.single.append([utter])
            self._container = None
            self.state = StateMachine.STATES.INITIAL
            
        elif (utter.start == self._container[0].start and
            utter.end == self._container[0].end):
            self._container.append(utter)
            if utter.speaker:
                self.state = StateMachine.STATES.NUMBERED_MULTI
            else:
                self.state = StateMachine.STATES.UNNUMBERED_MULTI

        elif (utter.start != self._container[0].start or
              utter.end != self._container[0].end):
            self.single.append(self._container)
            self._container = [utter]

        else:
            self.state = StateMachine.STATES.ERROR

    def _state_numbered_multi(self, utter):
        if (utter.start == self._container[-1].start and
            utter.end == self._container[-1].end):
            if utter.is_dot_split:# and False:
                self.state = StateMachine.STATES.ERROR
            else:
                self._container.append(utter)

        elif (utter.start != self._container[-1].start or
            utter.end != self._container[-1].end):
            if utter.is_dot_split:# and False:
                self.numbered_multi.append(self._container)
                self.single.append([utter])
                self._container = None
                self.state = StateMachine.STATES.INITIAL
            else:
                self.numbered_multi.append(self._container)
                self._container = [utter]
                self.state = StateMachine.STATES.SINGLE

        else:
            self.state = StateMachine.STATES.ERROR

    def _state_unnumbered_multi(self, utter):
        if (utter.start == self._container[-1].start and
            utter.end == self._container[-1].end):
            self._container.append(utter)
            if utter.speaker:
                self.state = StateMachine.STATES.NUMBERED_MULTI

        elif (utter.start != self._container[-1].start or
            utter.end != self._container[-1].end):
            if utter.is_dot_split:# and False:
                self.unnumbered_multi.append(self._container)
                self.single.append([utter])
                self._container = None
                self.state = StateMachine.STATES.INITIAL
            else:
                self.unnumbered_multi.append(self._container)
                self._container = [utter]
                self.state = StateMachine.STATES.SINGLE

        else:
            self.state = StateMachine.STATES.ERROR

    def finish(self):
        if self.state == StateMachine.STATES.SINGLE:
            self.single.append(self._container)
        elif self.state == StateMachine.STATES.NUMBERED_MULTI:
            self.numbered_multi.append(self._container)
        elif self.state == StateMachine.STATES.UNNUMBERED_MULTI:
            self.unnumbered_multi.append(self._container)

    def _print_container(self, array):
        array_name = '?'
        if array == self.single:
            array_name = 'single'
        elif array == self.numbered_multi:
            array_name = 'numbered_multi'
        elif array == self.unnumbered_multi:
            array_name = 'unnumbered_multi'
        
        container = array[-1]
        container_str = '%s - [' % (array_name)
        for i in range(len(container)):
            speaker = container[i].speaker.speaker_codeinfo.code if container[i].speaker else 'None'
            time_range = '%s-%s' % ( get_time_str(container[i].start), get_time_str(container[i].end) )
            trans_phrase = container[i].trans_phrase if container[i].trans_phrase else 'None'
            container_str += '%s:%s;%s' % (speaker, time_range, trans_phrase)
            if i < len(container) - 1:
                container_str += ', '
        container_str += ']'

        print container_str
Esempio n. 7
0
class VerificationWindow():
    ERROR_STATES = Enum(['NONE', 'WARNING', 'ERROR'])

    def __init__(self, filename, progress_dialog):
        self.logger = logging.getLogger(__name__)
        self.window = gtk.Window(gtk.WindowType.TOPLEVEL)
        self.window.set_title('Transcription Verifier')
        self.window.connect('destroy', lambda x: self.window.destroy())
        self.window.set_border_width(10)
        self.window.set_default_size(580, 500)

        self.trs_parser = TRSParser(filename)
        self.trs_parser.parse(
            progress_update_fcn=progress_dialog.set_fraction,
            progress_next_phase_fcn=progress_dialog.next_phase,
            remove_bad_trans_codes=False)
        self.wav_parser = None

        progress_dialog.next_phase()
        self.filter_errors = True
        self.toolbar = self.build_toolbar()
        self.treeview = self.build_treeview(progress_dialog.set_fraction)
        self.treeview.expand_all()

        scrolled_win = gtk.ScrolledWindow()
        scrolled_win.set_policy(gtk.PolicyType.AUTOMATIC,
                                gtk.PolicyType.AUTOMATIC)
        scrolled_win.add(self.treeview)

        vbox = gtk.VBox(False, 2)
        vbox.pack_start(self.toolbar, False, False, 0)
        vbox.pack_start(scrolled_win, True, True, 0)

        self.window.add(vbox)

        self.window.show_all()

    def build_toolbar(self):
        toolbar = gtk.Toolbar()
        toolbar.set_orientation(gtk.Orientation.HORIZONTAL)

        filter_errors_button = gtk.ToggleToolButton()
        filter_errors_button.set_active(
            True
        )  #set this before the connecting the clicked handler so it doesn't cause trouble
        filter_errors_button.connect(
            'toggled', lambda w: self.toggle_filter_errors(w.get_active()))
        filter_errors_icon = gtk.Image()
        filter_errors_icon.set_from_file(
            UIUtils.get_icon_path(UIUtils.BUTTON_ICONS.FLAG))
        filter_errors_button.set_label('Show Errors Only')
        filter_errors_button.set_icon_widget(filter_errors_icon)

        expand_button = gtk.ToolButton()
        expand_icon = gtk.Image()
        expand_icon.set_from_file(
            UIUtils.get_icon_path(UIUtils.BUTTON_ICONS.EXPAND))
        expand_button.set_label('Expand All')
        expand_button.set_icon_widget(expand_icon)
        expand_button.connect('clicked', lambda w: self.treeview.expand_all())

        collapse_button = gtk.ToolButton()
        collapse_icon = gtk.Image()
        collapse_icon.set_from_file(
            UIUtils.get_icon_path(UIUtils.BUTTON_ICONS.COLLAPSE))
        collapse_button.set_label('Collapse All')
        collapse_button.set_icon_widget(collapse_icon)
        collapse_button.connect('clicked',
                                lambda w: self.treeview.collapse_all())

        rescan_button = gtk.ToolButton()
        rescan_icon = gtk.Image()
        rescan_icon.set_from_file(
            UIUtils.get_icon_path(UIUtils.BUTTON_ICONS.REFRESH))
        rescan_button.set_label('Rescan File')
        rescan_button.set_icon_widget(rescan_icon)
        rescan_button.connect('clicked', lambda w: self._rescan_file())

        play_seg_button = gtk.ToolButton()
        play_icon = gtk.Image()
        play_icon.set_from_file(
            UIUtils.get_icon_path(UIUtils.BUTTON_ICONS.PLAY))
        play_seg_button.set_label('Play Seg')
        play_seg_button.set_icon_widget(play_icon)
        play_seg_button.connect('clicked', lambda w: self.play_selected_seg())

        close_button = gtk.ToolButton()
        close_icon = gtk.Image()
        close_icon.set_from_file(
            UIUtils.get_icon_path(UIUtils.BUTTON_ICONS.CLOSE))
        close_button.set_label('Close')
        close_button.set_icon_widget(close_icon)
        close_button.connect('clicked', lambda w: self.window.destroy())

        exit_button = gtk.ToolButton()
        exit_icon = gtk.Image()
        exit_icon.set_from_file(
            UIUtils.get_icon_path(UIUtils.BUTTON_ICONS.EXIT))
        exit_button.set_label('Exit')
        exit_button.set_icon_widget(exit_icon)
        exit_button.connect('clicked', lambda w: gtk.main_quit())

        toolbar.insert(filter_errors_button, -1)
        toolbar.insert(expand_button, -1)
        toolbar.insert(collapse_button, -1)
        toolbar.insert(gtk.SeparatorToolItem(), -1)
        toolbar.insert(play_seg_button, -1)
        toolbar.insert(rescan_button, -1)
        toolbar.insert(gtk.SeparatorToolItem(), -1)
        toolbar.insert(close_button, -1)
        toolbar.insert(exit_button, -1)

        return toolbar

    def _rescan_file(self):
        self.window.set_sensitive(False)

        progress_dialog = ProgressDialog(
            'Processing File...',
            ['Parsing trs file...', 'Validating data...', 'Building UI...'])
        progress_dialog.show()

        #this causes the parser to invalidate all cache, re-open and re-parse the file
        self.trs_parser.re_parse(
            progress_update_fcn=progress_dialog.set_fraction,
            progress_next_phase_fcn=progress_dialog.next_phase)

        #build a new treeview model based on the new data
        progress_dialog.next_phase()
        filter_model = self._build_tree_store(progress_dialog.set_fraction)
        self.treeview.set_model(filter_model)

        #Presumably the most common cause for rescanning is to check if errors have been fixed.
        #If the error filter is on, automatically expand all rows to show any remaining errors.
        if self.filter_errors:
            self.treeview.expand_all()

        self.window.set_sensitive(True)

    def _build_tree_store(self, progress_update_fcn):
        #segment/utter id, description, error_state (0 = none, 1 = warning, 2 = error)
        tree_store = gtk.TreeStore(gobject.TYPE_INT, gobject.TYPE_STRING,
                                   gobject.TYPE_INT)

        #note: these may be errors or warnings
        cur_utter = 0
        for seg in self.trs_parser.parse():
            seg_speakers = ''
            if seg.speakers:
                for i in range(len(seg.speakers)):
                    seg_speakers += seg.speakers[i].speaker_codeinfo.get_code()
                    if i < len(seg.speakers) - 1:
                        seg_speakers += ' + '
            else:
                seg_speakers = ' - '

            seg_iter = tree_store.append(None, [
                seg.num,
                '%s [%s - %s]' %
                (seg_speakers, BackendUtils.get_time_str(
                    seg.start), BackendUtils.get_time_str(seg.end)),
                VerificationWindow.ERROR_STATES.NONE
            ])

            for utter in seg.utters:
                speaker_cd = '?'  #question mark indicates an error occured - if we have utter.speaker, we should have an utter code. Errors occur if the utter code isn't in the DB lookup table (which means that utter.speaker != None, but utter.speaker.speaker_codeinfo == None. This is the condition that falls through the if-else blocks below).
                if utter.speaker:
                    if utter.speaker.speaker_codeinfo:
                        speaker_cd = utter.speaker.speaker_codeinfo.get_code()
                else:
                    speaker_cd = ' - '

                desc_str = '%s [%s - %s]' % (
                    speaker_cd, BackendUtils.get_time_str(
                        utter.start), BackendUtils.get_time_str(utter.end))
                if utter.lena_notes:
                    desc_str += ' %s' % (utter.lena_notes)
                if utter.trans_phrase:
                    desc_str += ' %s' % (utter.trans_phrase)
                if utter.lena_codes:
                    desc_str += ' |%s|' % ('|'.join(utter.lena_codes))
                if utter.trans_codes:
                    if not utter.lena_codes:
                        desc_str += ' |'
                    desc_str += '%s|' % ('|'.join(utter.trans_codes))

                utter_iter = tree_store.append(
                    seg_iter,
                    [utter.id, desc_str, VerificationWindow.ERROR_STATES.NONE])

                cur_utter += 1
                progress_update_fcn(
                    float(cur_utter) / float(self.trs_parser.total_utters))

                error_list = self.trs_parser.error_collector.get_errors_by_utter(
                    utter)
                for error in error_list:
                    error_type = VerificationWindow.ERROR_STATES.ERROR
                    if isinstance(error, ParserWarning):
                        error_type = VerificationWindow.ERROR_STATES.WARNING

                    error_iter = tree_store.append(
                        utter_iter, [-1, '%s' % (error.msg), error_type])

                    parent_it = utter_iter
                    while parent_it:
                        parent_error_type = tree_store.get_value(parent_it, 2)
                        if parent_error_type < error_type:
                            tree_store.set_value(parent_it, 2, error_type)

                        parent_it = tree_store.iter_parent(parent_it)

        filter_model = tree_store.filter_new()
        filter_model.set_visible_func(self.filter)

        return filter_model

    def build_treeview(self, progress_update_fcn):
        filter_model = self._build_tree_store(progress_update_fcn)
        treeview = gtk.TreeView(filter_model)

        col = gtk.TreeViewColumn('ID', gtk.CellRendererText(), text=0)
        col.set_visible(False)
        treeview.append_column(col)

        renderer = gtk.CellRendererText()
        col = gtk.TreeViewColumn('Description', renderer, text=1)
        col.set_cell_data_func(renderer, self.cell_render_fcn)
        treeview.append_column(col)

        col = gtk.TreeViewColumn('Error State', gtk.CellRendererText(), text=2)
        col.set_visible(False)
        treeview.append_column(col)

        return treeview

    def cell_render_fcn(self, col, cell_renderer, model, it, user_data=None):
        error_state = model.get_value(it, 2)
        if error_state == VerificationWindow.ERROR_STATES.WARNING:
            cell_renderer.set_property('foreground', 'orange')
        elif error_state == VerificationWindow.ERROR_STATES.ERROR:
            cell_renderer.set_property('foreground', 'red')
        else:
            cell_renderer.set_property('foreground', 'black')

        return

    #returns true if row pointed to by 'it' should be visible
    def filter(self, model, it, user_data):
        result = True
        if self.filter_errors:
            result = model.get_value(it,
                                     2) > VerificationWindow.ERROR_STATES.NONE

        return result

    def toggle_filter_errors(self, filter_errors):
        self.filter_errors = not self.filter_errors
        self.treeview.get_model().refilter()

    def play_selected_seg(self):
        (model, it) = self.treeview.get_selection().get_selected()
        if it:
            #if they've selected an error row, find the top level parent (the segment) and use it instead
            parent = model.iter_parent(it)
            while parent:
                it = parent
                parent = model.iter_parent(it)

            seg_num = model.get_value(it, 0) if it else None
            seg = self.trs_parser.parse()[seg_num]

            if not self.wav_parser:
                dialog = gtk.FileChooserDialog(
                    title='Select WAV File',
                    action=gtk.FileChooserAction.OPEN,
                    buttons=(gtk.STOCK_CANCEL, gtk.ResponseType.CANCEL,
                             gtk.STOCK_OPEN, gtk.ResponseType.OK))
                dialog.set_default_response(gtk.ResponseType.OK)

                for filter_opt in (('wav Files', '*.wav'), ('All Files', '*')):
                    file_filter = gtk.FileFilter()
                    file_filter.set_name(filter_opt[0])
                    file_filter.add_pattern(filter_opt[1])
                    dialog.add_filter(file_filter)

                response = dialog.run()
                if response == gtk.ResponseType.OK:
                    filename = dialog.get_filename()
                    self.wav_parser = WavParser(filename)

                dialog.destroy()

            if self.wav_parser:
                self.wav_parser.play_seg(seg)

            else:
                UIUtils.show_no_sel_dialog()
        else:
            UIUtils.show_no_sel_dialog()
Esempio n. 8
0
from datetime import datetime
import os

from calculations.moving_averages import sma, ema
from trade import trading
from utils.enum import Enum

DIR = os.path.dirname(__file__)
INPUT_FILE = '../data/closing_prices_all_per_hour.txt'

Signal = Enum(['BUY', 'SELL', 'HODL'])


class Simulator:
    coins = None
    fiat = None
    prices = []

    ema1_n = None
    ema2_n = None

    from_date = datetime.strptime('2012-01-11', '%Y-%m-%d').date()
    to_date = datetime.now().date()

    display_orders = False

    def __init__(self,
                 from_date=None,
                 to_date=None,
                 starting_coins=1.00,
                 starting_fiat=0,
Esempio n. 9
0
class UIUtils(object):
    #stores the last directory accessed by the user from a filechooser dialog (see the show_file_dialog() and show_file_dialog_with_checks() methods)
    last_filechooser_location = None

    #These static members store gtk.FileFilter constants created by the _get_constants method() of the ui_utils module. They are populated when this file is processed by the Python iterpreter.
    WAV_FILE_FILTER = None
    TRS_FILE_FILTER = None
    ITS_FILE_FILTER = None
    ALL_FILE_FILTER = None
    CSV_FILE_FILTER = None
    TRS_CSV_FILE_FILTER = None

    #this is a date-time format string (of the type accepted by the Python datetime.strptime() method - see Python docs) that corresponds to the format in which timestamps come out of the database.
    DB_DT_OUTPUT_FMT = '%Y-%m-%d %H:%M:%S'
    #this is a date-time format string that corresponds to the format in which timestamps should be shown in the UI. Timestamps coming out of the database are converted to this format by get_db_timestamp_str().
    DT_DISPLAY_FMT = '%b %d, %Y %I:%M %p'

    #The UI contains lots of buttons that perform common actions. This is a lookup structure (an Enum) that maps actions to (the file path to) descriptive icons. You can use it to create buttons with icons on them.
    #See the create_button() method for more info. The '%s' placeholder will be filled with the name of the directory corresponding to the desired size of the icon - this is done in create_button().
    BUTTON_ICONS = Enum.from_dict({
        'CREATE':
        'icons/open_icon_library-standard/icons/png/%s/actions/document-new-8.png',
        'OPEN':
        'icons/open_icon_library-standard/icons/png/%s/actions/document-open-8.png',
        'ADD':
        'icons/open_icon_library-standard/icons/png/%s/actions/list-add-5.png',
        'EDIT':
        'icons/open_icon_library-standard/icons/png/%s/actions/edit.png',
        'REMOVE':
        'icons/open_icon_library-standard/icons/png/%s/actions/list-remove-5.png',
        'DELETE':
        'icons/open_icon_library-standard/icons/png/%s/actions/edit-delete-3.png',
        'RUN':
        'icons/open_icon_library-standard/icons/png/%s/actions/system-run-2.png',
        'CLOSE':
        'icons/open_icon_library-standard/icons/png/%s/actions/application-exit-4.png',
        'EXIT':
        'icons/open_icon_library-standard/icons/png/%s/actions/application-exit.png',
        'EXPAND':
        'icons/open_icon_library-standard/icons/png/%s/actions/edit-add-3.png',
        'COLLAPSE':
        'icons/open_icon_library-standard/icons/png/%s/actions/edit-remove-2.png',
        'REFRESH':
        'icons/open_icon_library-standard/icons/png/%s/actions/view-refresh-6.png',
        'PLAY':
        'icons/open_icon_library-standard/icons/png/%s/apps/exaile-2.png',
        'FLAG':
        'icons/open_icon_library-standard/icons/png/%s/actions/flag.png',
        'EXPORT':
        'icons/open_icon_library-standard/icons/png/%s/actions/document-export.png',
        'SPLIT':
        'icons/open_icon_library-standard/icons/png/%s/actions/edit-copy-9.png',
        'MERGE':
        'icons/open_icon_library-standard/icons/png/%s/actions/edit-text-frame-update.png',
        'CLEAR':
        'icons/open_icon_library-standard/icons/png/%s/actions/edit-clear-2.png',
        'FILTER':
        'icons/open_icon_library-standard/icons/png/%s/actions/filter.png',
        'PRAAT':
        'icons/open_icon_library-standard/icons/png/%s/apps/praat.png',
        'SAVE':
        'icons/open_icon_library-standard/icons/png/%s/actions/document-save-as-6.png',
        'UPDATE':
        'icons/open_icon_library-standard/icons/png/%s/apps/system-software-update-4.png',
        'VOLUME_OFF':
        'icons/open_icon_library-standard/icons/png/%s/status/volume-0.png',
        'VOLUME_ON':
        'icons/open_icon_library-standard/icons/png/%s/status/audio-volume-high-5.png',
    })

    #This enum allows you to select the size of the image you want for your button (see create_button()). The values correspond to the names of subdirectories in the 'bll_app/icons/png/' directory.
    #The selected value is interpolated into the value from the BUTTON_ICONS enum (above) within the create_button() method.
    BUTTON_ICON_SIZES = Enum.from_dict({
        'PX8': '8x8',
        'PX16': '16x16',
        'PX22': '22x22',
        'PX24': '24x24',
        'PX32': '32x32',
        'PX48': '48x48',
        'PX64': '64x64',
        'PX128': '128x128',
    })

    ## Sets some common GTK properties that all of the apps use. This only needs to be called once at appliation startup.
    # @param app_icon_filename (string) path to an image file. This icons will be used as the default application icon (appears in the top left-hand corner of all windows)
    @staticmethod
    def setup_gtk(app_icon_filename):
        #allow images to appear on buttons
        gtk.Settings.get_default().set_long_property('gtk-button-images', True,
                                                     'main')
        #set default program icon
        gtk.Window.set_default_icon_list(
            [pixbuf.Pixbuf.new_from_file(app_icon_filename)])

    ## Sets the font size for a given widget
    # @param widget (Gtk Container) the widget whose font size you'd like to set
    # @param pt_size (int, possibly float too?) the font size (pt)
    # @param bold (boolean=False) Set to True to make font bold
    @staticmethod
    def set_font_size(widget, pt_size, bold=False):
        font = widget.get_style_context().get_font(gtk.StateFlags.NORMAL)
        font.set_size(pt_size * Pango.SCALE)
        if bold:
            font.set_weight(Pango.Weight.BOLD)
        widget.override_font(font)

    ## Constructs the full path to an icon, given a value from the BUTTON_ICONS enum, and a value from the BUTTON_ICON_SIZES enum.
    # @param img_path (string) this must be a value from the BUTTON_ICONS enum
    # @param icon_size_dir (string=BUTTON_ICON_SIZES.PX32) this must be a value from the BUTTON_ICON_SIZES enum. Size defaults to 32x32 pixels.
    # @returns (string) the full path to the icon file
    @staticmethod
    def get_icon_path(img_path, icon_size_dir=BUTTON_ICON_SIZES.PX32):
        return img_path % (icon_size_dir)

    ## Creates a gtk.Button with an icon on it. You can create predefined types of buttons (corresponding to common actions) of any given size by passing in parameters from this class' button enums.
    # Note: in order for this to work, you must first tell gtk to allow images on button - this is done in the setup_gtk() method, so you should call that first.
    # @param label (string) the text to display on the button.
    # @param img_path (string) a value from the BUTTON_ICONS enum (indicates the button action)
    # @param icon_size_dir (string=BUTTON_ICON_SIZES.PX32) a value from the BUTTON_ICON_SIZES enum, indicating the size of the icon that will be placed on the button. Default is 32x32 pixels.
    # @returns (gtk.Button) a gtk.Button object with the specified text and image.
    @staticmethod
    def create_button(
        label,
        img_path,
        icon_size_dir=BUTTON_ICON_SIZES.PX32
    ):  #use BUTTON_ICONS enum for 2nd param, BUTTON_ICON_SIZES enum for 3rd param
        button = gtk.Button(label)
        img = gtk.Image()
        full_path = UIUtils.get_icon_path(img_path, icon_size_dir)
        img.set_from_file(full_path)
        button.set_image(img)

        return button

    ## Displays a popup confirmation dialog with yes/no buttons. This method will block until one of the buttons is clicked, at which point it will return a boolean value (indicating which button was clicked) and the dialog will auto-destruct.
    # @param msg (string) the confirmation message to display (should be a yes/no question so the buttons make sense)
    # @returns (boolean) True if "yes" was clicked, False otherwise.
    @staticmethod
    def show_confirm_dialog(msg):
        dialog = gtk.MessageDialog(buttons=gtk.ButtonsType.YES_NO,
                                   type=gtk.MessageType.INFO,
                                   message_format=msg)
        response = dialog.run()
        dialog.destroy()

        return response == gtk.ResponseType.YES

    ## Displays a popup dialog (with an ok button) that tells the user to select a row (presumably in some type of UI list).
    # This method blocks until the user clicks ok.
    # @param alt_msg (string=None) alternate text to display in place of the default. The default is 'Please select a row.'
    @staticmethod
    def show_no_sel_dialog(alt_msg=None):
        default_msg = 'Please select a row.'
        UIUtils.show_message_dialog(default_msg or alt_msg)

    ## Displays a popup dialog (with an ok button) that tells the user to make sure all options in a form have been filled out.
    # This method blocks until the user clicks ok.
    # @param alt_msg (string=None) alternate text to display in place of the default. The default is 'Please make sure that all options have been filled out.'
    @staticmethod
    def show_empty_form_dialog(alt_msg=None):
        default_msg = 'Please make sure that all options have been filled out.'
        UIUtils.show_message_dialog(default_msg or alt_msg)

    ## Displays a popup dialog (with an ok button) that presents a textual message.
    # This method blocks until the user clicks ok.
    # @param message (string) the text to display in the dialog box.
    # @param dialog_type (int) one of the gtk message type constants (see gtk docs for the MessageDialog class), indicating the type of icon to display in the dialog. This icon indicates whether the
    # dialog is an info/question/warning/error message. Possible values are gtk.MESSAGE_INFO, gtk.MESSAGE_WARNING, gtk.MESSAGE_QUESTION, or gtk.MESSAGE_ERROR.
    @staticmethod
    def show_message_dialog(message, dialog_type=gtk.MessageType.INFO):
        dialog = gtk.MessageDialog(buttons=gtk.ButtonsType.OK,
                                   message_format=message,
                                   type=dialog_type)

        #this call blocks until the OK button is clicked
        dialog.run()
        dialog.destroy()

    ## Creates a set of gtk.SpinButton inputs to allow the user to input a time in the format hh:mm:ss.
    # These entries are packing into a horizontal gtk.HBox container, which is fitted with a label.
    # Here's what the container looks like when it's displayed in the UI:
    # <img src="../images/time_spinners.png">
    # @param label (string=None) an optional label to pack at the left side of the container
    # @param hours (int=0) value to default the hours spinbutton to
    # @param mins (int=0) value to default the minutes spinbutton to
    # @param secs (int=0) value to default the seconds spinbutton to
    # @returns (tuple) returns a tuple of 4 items: (hbox_container, hours_spinbutton, mins_spinbutton, secs_spinbutton). The spinbuttons are already packed into the hbox container. They are returned individually as well just for convenience
    # (so the caller can easily hook up signals without having to extract them from the container first).
    @staticmethod
    def get_time_spinners(label=None, hours=0, mins=0, secs=0):
        entry_box = gtk.HBox()
        entry_box.pack_start(gtk.Alignment(xalign=0.25, yalign=0), False,
                             False, 0)

        if label:
            entry_box.pack_start(label, False, False, 0)

        hours_adj = gtk.Adjustment(
            value=0, lower=0, upper=1000, step_incr=1, page_incr=5
        )  #note: upper is a required param - set it to something that won't be exceeded
        hours_spinner = gtk.SpinButton()
        hours_spinner.set_adjustment(hours_adj)
        hours_spinner.set_value(hours)
        entry_box.pack_start(hours_spinner, False, False, 0)
        entry_box.pack_start(gtk.Label(':'), False, False, 0)

        mins_adj = gtk.Adjustment(value=0,
                                  lower=0,
                                  upper=59,
                                  step_incr=1,
                                  page_incr=5)
        mins_spinner = gtk.SpinButton()
        mins_spinner.set_adjustment(mins_adj)
        mins_spinner.set_value(mins)
        entry_box.pack_start(mins_spinner, False, False, 0)
        entry_box.pack_start(gtk.Label(':'), False, False, 0)

        secs_adj = gtk.Adjustment(value=0,
                                  lower=0,
                                  upper=59,
                                  step_incr=1,
                                  page_incr=5)
        secs_spinner = gtk.SpinButton()
        secs_spinner.set_adjustment(secs_adj)
        secs_spinner.set_value(secs)
        entry_box.pack_start(secs_spinner, False, False, 0)
        entry_box.pack_start(gtk.Alignment(xalign=0.25, yalign=0), False,
                             False, 0)

        return entry_box, hours_spinner, mins_spinner, secs_spinner

    ## Returns a string containing the current date and time.
    # @returns (string) the current timestamp, formatted according to the UIUtils.DT_DISPLAY_FMT pattern.
    @staticmethod
    def get_cur_timestamp_str():
        return datetime.now().strftime(UIUtils.DT_DISPLAY_FMT)

    ## Accepts a string representing a datetime that was retrieved from the database, and converts it into a format suitable for display in the UI.
    # @param timestamp (string) a timestamp string (retrieved from the DB) in the format UIUtils.DB_DT_OUTPUT_FMT
    # @returns (string) a timestamp string in the format UIUtils.DT_DISPLAY_FMT
    @staticmethod
    def get_db_timestamp_str(timestamp):
        return datetime.strptime(timestamp, UIUtils.DB_DT_OUTPUT_FMT).strftime(
            UIUtils.DT_DISPLAY_FMT)

    @staticmethod
    def utc_to_local_str(utc_timestamp):
        from_zone = tz.tzutc()
        to_zone = tz.tzlocal()

        # utc = datetime.utcnow()
        utc = datetime.strptime(utc_timestamp, UIUtils.DB_DT_OUTPUT_FMT)

        # Tell the datetime object that it's in UTC time zone since
        # datetime objects are 'naive' by default
        utc = utc.replace(tzinfo=from_zone)

        # Convert time zone
        local = utc.astimezone(to_zone)

        return local.strftime(UIUtils.DT_DISPLAY_FMT)

    ## Constructs a gtk.FileFilter object for a set of file extensions.
    # @param title (string) the title for this filer. This title is displayed in the dropdown combobox of file types in filechooser dialogs
    # @param patterns (list) a list of strings, where each is a shell-expandible file extension (like '*.wav' or '*.trs')
    # @return (gtk.FileFilter) a gtk.FileFilter object that can be passed to a filechooser dialog
    @staticmethod
    def build_file_filter(title, patterns):
        file_filter = gtk.FileFilter()
        file_filter.set_name(title)
        map(file_filter.add_pattern, patterns)

        return file_filter

    ## Builds a simple combo box. Each entry has a title and a value.
    # The title is displayed, the value is hidden to the user. Here's what it looks like:
    # <img src="../images/simple_combo.png">
    # By default, the first option is selected. Note: You can make this a row with a label that is an empty string (and value None) if you want it to appear as though nothing is selected by default (as in the above image).
    # @param types (tuple) a 2-tuple of type functions (e.g. int, float, str). The
    # first element is the type of the label, and the second is the type of the value.
    # In most cases, the type of the label should be string, so you should pass the the str function as the first element.
    # Alternatively, you can also use the type constants from the gobject module (gobject.TYPE_STRING, gobject.TYPE_FLOAT, etc.).
    # @param labels (list) a list of strings - these will be the options made available for the user to select.
    # @param vals (list) a list of anything - the length must be equal to the length of the labels param. These are the values that
    # the labels will be given in the combobox model (assigned in the same order as the elements in the labels list appear).
    # These values can be retrieved when you query the combobox selection state.
    # @returns (gtk.ComboBox) a gtk.ComboBox object that can be used in the UI
    @staticmethod
    def build_simple_combo(types, labels, vals):
        model = gtk.ListStore(*types)
        map(model.append, zip(labels, vals))

        combobox = gtk.ComboBox(model=model)
        renderer = gtk.CellRendererText()
        combobox.pack_start(renderer, True, False, 0)
        combobox.add_attribute(renderer, 'text', 0)
        combobox.set_active(0)

        return combobox

    ## Builds a simple gtk.ListStore. This is the data store backing for a combobox or treeview.
    # @param labels (list) list of strings that will be displayed in the list of treeview
    # @param vals (list) list of objects, must be same length as labels list. These values are assigned to the rows/options in the widget, and
    # can be retrieved when the widget's selection state is queried.
    # @param val_type (function pointer) this is function pointer corresponding to a type (like str, int, float, etc.) or it is a type constant from the gobject module (eg. gobject.TYPE_STRING, gobject.TYPE_FLOAT, etc.).
    # It indicates the type of the elements in the vals array.
    # @returns (gtk.ListStore) a liststore object for use in the creation of a combobox or treeview (or potentially other types of widgets).
    @staticmethod
    def build_simple_liststore(labels, vals, val_type):
        list_store = gtk.ListStore(gobject.TYPE_STRING, val_type)

        for i in range(len(labels)):
            list_store.append([labels[i], vals[i]])

        return list_store

    ## Builds a treeview (a grid with selectable rows) with a single column. The user may select multiple rows at once.
    # The treeview has a hidden 'ID' column appended to it - you can use this to track the indices of the selected rows (or you can use the vals parameter).
    # See the gtk docs for more info on treeviews. Here is what the treeview looks like:
    # <img src="../images/multiselect_treeview.png">
    # @param labels (list) list of strings. These are the values to display in the rows (one element per row).
    # @param vals (list) list of anything. These values will be assigned to the rows in the same order as the labels list (therefore it must be of the same length). You can retrieve the values of selected rows when
    # querying the treeview widget's selection state.
    # @param val_type (function pointer) this is function pointer corresponding to a type (like str, int, float, etc.) or it is a type constant from the gobject module (eg. gobject.TYPE_STRING, gobject.TYPE_FLOAT, etc.).
    # It indicates the type of the elements in the vals array.
    # @param header_text (string) text to display at the top of the single column.
    # @returns (gtk.TreeView) a gtk.TreeView object that's set up and ready to embed in the UI
    @staticmethod
    def build_multiselect_treeview(labels, vals, val_type, header_text):
        list_store = UIUtils.build_simple_liststore(labels, vals, val_type)
        treeview = gtk.TreeView(list_store)
        treeview.get_selection().set_mode(gtk.SelectionMode.MULTIPLE)

        col = gtk.TreeViewColumn(header_text, gtk.CellRendererText(), text=0)
        treeview.append_column(col)
        col.set_sizing(gtk.TreeViewColumnSizing.AUTOSIZE)

        col = gtk.TreeViewColumn('ID', gtk.CellRendererText(), text=1)
        col.set_visible(False)
        col.set_sizing(gtk.TreeViewColumnSizing.AUTOSIZE)
        treeview.append_column(col)

        return treeview

    ## Builds a gtk.ListStore that contains a group of common combo options stored in the  DBConstants.COMBO_OPTIONS enum (these ultimately come from the database).
    # For example, you could create a liststore of all LENA speaker codes, then display them in a treeview - this is what was done to create the screenshot below:
    # <img src="../images/multiselect_treeview.png">
    # You could just as easily use this liststore to create a combobox, or something else.
    # @param group_id (int) a value from the DBConstants.COMBO_GROUPS enum, indicating which group of options to insert into the liststore. Combo options are grouped according to their type.
    # For example, passing a group_id of DBConstants.COMBO_GROUPS.SPEAKER_CODES would create a liststore like the one used in the screenshot shown above.
    # @param include_empty_option (boolean=True) if True, an option with an empty string label will be pre-pended to the liststore. This can be used as a "nothing-selected" option.
    # @returns (gtk.ListStore) a liststore object that contains all of the options from the specified group. This object can be used as a data-store backing for other widgets.
    @staticmethod
    def build_options_liststore(group_id, include_empty_option=True):
        list_store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_INT)

        group_keys_enum = DBConstants.COMBO_OPTIONS[group_id]
        for i in range(int(not include_empty_option), len(group_keys_enum)):
            group_option_key = group_keys_enum[i]
            option = DBConstants.COMBOS[group_id][group_option_key]
            if not option.hidden:
                list_store.append([option.disp_desc, option.db_id])

        return list_store

    ## Computes the minimum number of pixels (width) needed to show a treeview column with the specified title text.
    # This is an approximation that was emperically determined, and uses magic numbers. It is not guarenteed to work, and
    # should probably be removed. But you can try it if you feel frustrated.
    # @param col_name (string) the text that will be displayed in the column header
    # @returns (int) an approximation of the number of pixel you will need to applocate for the width of the treeview column, in order for the whole col_name header string to be displayed.
    @staticmethod
    def calc_treeview_col_min_width(col_name):
        return 90 + (len(col_name) / 15) * 50

    ## Builds a gtk.ComboBox widget that contains a group of common combo options stored in the  DBConstants.COMBO_OPTIONS enum (these ultimately come from the database).
    # For example, you could create a combobox that allows you to select one of the LENA speaker codes.
    # @param group_id (int) a value from the DBConstants.COMBO_GROUPS enum, indicating which group of options to insert into the liststore.
    # @param active_index (int=0) the row index of the entry to auto-select. If include_empty_option is True, and this is zero, then the empty entry will be selected.
    # @param include_empty_option (boolean=True) if True, an option with an empty string label will be pre-pended to the list of options. This can be used as a "nothing-selected" option.
    # @returns (gtk.ComboBox) a combobox widget containing all of the options for the specified group.
    @staticmethod
    def build_options_combo(group_id,
                            active_index=0,
                            include_empty_option=True):
        list_store = UIUtils.build_options_liststore(group_id,
                                                     include_empty_option)

        combobox = gtk.ComboBox(model=list_store)
        renderer = gtk.CellRendererText()
        combobox.pack_start(renderer, True)
        combobox.add_attribute(renderer, 'text', 0)

        combobox.set_active(active_index)

        return combobox

    ## Builds a gtk.ComboBox containing options for "common regexs" (COMBO_GROUPS.COMMON_REGEXS).
    # When the selected option changes, a text entry box is populated with the regex string.
    # (This is just a wrapper around the build_options_combo() method for common regexs, to add the ability to connect
    # the 'changed' signal.)
    # @param entry (gtk.Entry) a text entry box that will be populated with a regular expression string when the selection changes
    # @returns (gtk.ComboBox) a combobox with the 'changed' signal set up
    @staticmethod
    def build_regex_helper_combo(entry):
        combo = UIUtils.build_options_combo(
            DBConstants.COMBO_GROUPS.COMMON_REGEXS)
        combo.connect('changed', UIUtils._fill_entry, entry)

        return combo

    ## This is an internal helper method for build_regex_helper_combo(). It populates a text entry with a regex string corresponding to the
    # selected option in the combobox. It is called every time the combobox selection changes.
    # @param combo (gtk.ComboBox) this is a combobox created with the options for the DBConstants.COMBO_GROUPS.COMMON_REGEXS group
    # @param entry (gtk.Entry) a text entry to populate with the regex string for the selected combobox option
    @staticmethod
    def _fill_entry(combo, entry):
        opt_id = combo.get_model()[combo.get_active()][1]
        db = BLLDatabase()
        # Ideally, the regex info should come out of an enum in the DBConstants class (such as DBConstants.COMMON_REGEXS).
        # However, we only have the combobox option id of the selected option, and this isn't enough to figure out which enum value we need.
        # To solve this problem, I've reverted to a database query here, but this should really be fixed in the future...we need something other
        # than the option id to identify the selected combo option.
        rows = db.select('common_regexs', 'regex'.split(), 'combo_option_id=?',
                         [opt_id])
        if rows and rows[0]:
            regex = rows[0][0]
            highlight_start = regex.find('\<')
            highlight_end = regex.find('\>')

            entry.set_text(regex.replace('\<', '<').replace('\>', '>'))

            entry.grab_focus()
            if highlight_start > -1 and highlight_end > -1:
                entry.select_region(highlight_start, highlight_end)

            db.close()

    ## This method opens an "open file" dialog, and populates a text entry widget with the resulting path.
    # It's useful to hook up to a "browse" button in the UI. This method blocks until the user clicks ok.
    # @param title (string) text to display in the titlebar of the "open file" dialog
    # @param entry (gtk.Entry) an entry widget to populate with the path name after the user clicks ok in the "open file" dialog
    # @param filters (list=[]) list of gtk.FileFilter objects. A dropdown list of file types displaying these is shown in the "open file" dialog.
    # You can use the constants in this class to build a list (UIUtils.ALL_FILE_FILTER, UIUtils.WAV_FILE_FILTER, UIUtils.TRS_FILE_FILTER, etc.)
    # @param auto_fill_entry (gtk.Entry=None) an optional gtk entry. It is possible to automatically locate another file with the same name as the one the user selects, but a different file extension.
    # This is useful, for example, when the user is locating a trs file, and you want to automatically locate the corresponding wav file. If this param is not None, an automatic search will be done
    # for the corresponding wav file and, if it is found, the entry will be populated with the path. The search encompasses the current directory (the one the user's selected file is in) and the parent directory.
    # @param auto_fill_file_extension (string='wav') an optional file extension string, used together with auto_fill_entry. This dictates the type of file extension that the search described in
    # the auto_fill_entry parameter documentation.
    @staticmethod
    def browse_file(title,
                    entry,
                    filters=[],
                    auto_fill_entry=None,
                    auto_fill_file_extension='wav'):
        filename = UIUtils.open_file(title, filters, save_last_location=True)
        if filename:
            entry.set_text(filename)
            search_name = filename[:-3] + auto_fill_file_extension
            #try to automatically find a corresponding wav file in the current or parent directories (in that order)
            #if one is found, and auto_fill_entry is not None, then the gtk.Entry pointed to be auto_fill_entry will be populated with the path of the found wav file
            try:
                if auto_fill_entry and auto_fill_entry.get_text() == '':
                    if os.path.exists(search_name):
                        auto_fill_entry.set_text(search_name)
                    else:
                        parent_dir = os.path.abspath(
                            os.path.dirname(filename) + os.path.sep +
                            os.path.pardir
                        )  #find absolute name of directory 'filename_dir/../'
                        search_name = parent_dir + os.path.sep + os.path.basename(
                            search_name)  #search for file in parent directory
                        if os.path.exists(search_name):
                            auto_fill_entry.set_text(search_name)
            except Exception as e:
                print 'Unable to find matching %s file: %s' % (
                    auto_fill_file_extension, e)

    ## This method opens an "open folder" dialog, and populates a text entry widget with the resulting path.
    # It's useful to hook up to a "browse" button in the UI. This method blocks until the user clicks ok.
    # @param title (string) text to display in the titlebar of the "open folder" dialog
    # @param entry (gtk.Entry) an entry widget to populate with the path name after the user clicks ok in the "open folder" dialog
    # @param filters (list=[]) list of gtk.FileFilter objects. This specifies the types of files (via their extensions) that will be visible in the "open folder" dialog.
    # Since the dialog doesn't let you select files (only folders), any visible files will appear "greyed out", and this param really just affects with the user can see, not what they can do.
    # In general, it is probably most useful to either leave this empty or set it to UIUtils.ALL_FILE_FILTER.
    @staticmethod
    def browse_folder(title, entry, filters=[]):
        foldername = UIUtils.open_folder(title,
                                         filters,
                                         save_last_location=True)
        if foldername:
            entry.set_text(foldername)

    ## Shows an "open file" dialog, returning a user-selected filename (if any). This method blocks until the user clicks ok.
    # @param title (string='Open File') string to display in the dialog box titlebar
    # @param filters (list=[]) list of gtk.FileFilter objects for the dialog to use. A combobox is displayed listing these filters (generally file extensions). Only files matching the pattern will be viewable in the browse pane.
    # If no filters are specified, all files will be visible.
    # @param save_last_location (boolean=False) if True, the directory containing the selected file will be saved (to UIUtils.last_filechoose_location), and the next "open" or "save" dialog will use it as the current directory
    # @param cur_location (string=None) if this is non-None, it specifies the path to the folder to use as the current directory - this is the directory initially displayed when the dialog pops up
    # @returns (string) the path to the user-selected file. If the user did not select a file, and instead clicked the cancel button or closed the dialog, this method will return None.
    @staticmethod
    def open_file(title='Open File',
                  filters=[],
                  save_last_location=False,
                  cur_location=None):
        if not filters:
            filters = [UIUtils.ALL_FILE_FILTER]
        filename, open_now = UIUtils.show_file_dialog(
            title,
            filters,
            gtk.FileChooserAction.OPEN,
            gtk.STOCK_OPEN,
            save_last_location=save_last_location,
            cur_location=cur_location)

        return filename

    ## Shows an "open folder" dialog, returning a user-selected foldername (if any). This method blocks until the user clicks ok.
    # @param title (string='Open Folder') string to display in the dialog box titlebar
    # @param filters (list=[]) list of gtk.FileFilter objects. This specifies the types of files (via their extensions) that will be visible in the "open folder" dialog.
    # Since the dialog doesn't let you select files (only folders), any visible files will appear "greyed out", and this param really just affects with the user can see, not what they can do.
    # In general, it is probably most useful to either leave this empty or set it to UIUtils.ALL_FILE_FILTER.
    # @param save_last_location (boolean=False) if True, the directory containing the selected file will be saved (to UIUtils.last_filechoose_location), and the next "open" dialog will use it as the current directory
    # @param cur_location (string=None) if this is non-None, it specifies the path to the folder to use as the current directory - this is the directory initially displayed when the dialog pops up
    # @returns (string) the path to the user-selected folder. If the user did not select a folder, and instead clicked the cancel button or closed the dialog, this method will return None.
    @staticmethod
    def open_folder(title='Select Folder',
                    filters=[],
                    save_last_location=False,
                    cur_location=None):
        if not filters:
            filters = [UIUtils.ALL_FILE_FILTER]
        foldername, open_now = UIUtils.show_file_dialog(
            title,
            filters,
            gtk.FileChooserAction.SELECT_FOLDER,
            gtk.STOCK_OPEN,
            save_last_location=save_last_location,
            cur_location=cur_location)

        return foldername

    ## Shows a "Save file" dialog, returning the path to a user-selected location. This method blocks until the user clicks ok.
    # @param title (string="Save File") text to display in the dialog box titlebar
    # @param filters (list=[]) list of gtk.FileFilter objects. This specifies the types of files (via their extensions) that will be visible in the "save" dialog.
    # @param open_now_opt (boolean=False) if True, a checkbox will be displayed along the bottom of the save dialog box that allows the use to open the saved file as soon as it is finished being written to disk (opened in Excel).
    # @param save_last_location (boolean=False) if True, the directory containing the selected file will be saved (to UIUtils.last_filechoose_location), and the next "open" or "save" dialog will use it as the current directory
    # @param cur_location (string=None) a path to a folder to set the dialog to show when it opens. If None, this will display whatever directory GTK feels like.
    # @returns (string) the save path. If the user did not enter one, and instead clicked the cancel button or closed the dialog, this method will return None.
    @staticmethod
    def save_file(title='Save File',
                  filters=[],
                  open_now_opt=False,
                  save_last_location=False,
                  cur_location=None):
        if not filters:
            filters = [UIUtils.ALL_FILE_FILTER]
        return UIUtils.show_file_dialog(title,
                                        filters,
                                        gtk.FileChooserAction.SAVE,
                                        gtk.STOCK_SAVE,
                                        open_now_opt,
                                        save_last_location=save_last_location,
                                        cur_location=cur_location)

    ## Shows a dialog box with a message, a single text entry, and a set of buttons (e.g. ok/cancel). This allows the user to enter a string value. This method blocks until the user clicks ok.
    # Here is what the dialog looks like, (the red message at the bottom is shown only if the user clicks ok after entering invalid text/no text).
    # <img src="../images/entry_dialog.png">
    # @param msg (string) message to display above the entry. This is generally some instructions about what to type in the entry.
    # @param entry_title (string) This text will be displayed directly to the left of the entry. Usually it is some text with a colon that acts as a title for the entry.
    # @param default_text (string='') The entry will be prepopulated with this text when the dialog box opens.
    # @param validate_regex (string=r'^.+$') a regular expression that will be used to validate the text in the entry when the user clicks ok. If the regex does not match the text, invalid_msg will be displayed and the dialog will remain open.
    # The default value for this parameter is a regex that matches any text except the empty string (this just makes sure the user enters something).
    # @param invalid_msg (string='Please enter a value') this text will be shown below the dialog, in red, if the user clicks ok and the text they entered does not match validate_regex. In this case, the dialog will not close.
    # @returns (string) The string that the user typed into the entry, or None if they clicked the cancel button or closed the dialog.
    @staticmethod
    def show_entry_dialog(msg,
                          entry_title,
                          default_text='',
                          validate_regex=r'^.+$',
                          invalid_msg='Please enter a value.'):
        dialog = gtk.MessageDialog(buttons=gtk.ButtonsType.OK_CANCEL,
                                   message_format=msg,
                                   type=gtk.MessageType.QUESTION)

        message_area = dialog.get_message_area()

        vbox = gtk.VBox()

        entry_label = gtk.Label(entry_title)
        entry = gtk.Entry()
        entry.set_text(default_text)
        invalid_label = gtk.Label('')

        hbox = gtk.HBox()
        hbox.pack_start(entry_label, False, False, 0)
        hbox.pack_start(entry, False, False, 0)
        vbox.pack_start(hbox, False, False, 0)
        vbox.pack_start(invalid_label, False, False, 0)

        message_area.pack_end(vbox, False, False, 0)
        vbox.show_all()

        done = False
        text = None
        while text == None and dialog.run() == gtk.ResponseType.OK:
            entry_input = entry.get_text()
            if re.match(validate_regex, entry_input):
                text = entry_input
            else:
                invalid_label.set_markup('<span foreground="red">%s</span>' %
                                         (invalid_msg))

        dialog.destroy()

        return text

    ## This method shows a a file dialog box (for "open" or "save") that (in addition to its regular buttons and controls) contains one or more checkboxes that the user can toggle.
    # The checkboxes' states are returned, along with the user-specified path string (corresponding to the filesystem location they chose). This method blocks until the user clicks ok.
    # @param title (string) text to display in the dialog box titlebar
    # @param filters (list=[]) list of gtk.FileFilter objects. This specifies the types of files (via their extensions) that will be visible in the dialog.
    # @param action (int) This is a gtk filechooser action constant (one of gtk.FILE_CHOOSER_ACTION_OPEN, gtk.FILE_CHOOSER_ACTION_SAVE, gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER or gtk.FILE_CHOOSER_ACTION_CREATE_FOLDER),
    # indicating the type of dialog to display.
    # @param confirm_button_stock (int) a gtk stock icon constant (e.g. gtk.STOCK_OK, gtk.STOCK_OPEN), indicating what type of text and icon to display on the "ok" button. For a complete list of stock constants, see
    # <a href="http://www.pygtk.org/docs/pygtk/gtk-stock-items.html">the PyGTK docs here</a>.
    # @param checkbuttons (list) a list of gtk.CheckButton objects (i.e. checkboxes) to display in the dialog. See return value description for how to obtain their state when the ok button is pressed.
    # @param save_last_location (boolean=False) if True, the directory containing the selected file will be saved (to UIUtils.last_filechoose_location), and the next "open" or "save" dialog will use it as the current directory
    # @returns (string, list) a 2-tuple. The first element is the path the user has selected using the dialog controls (for example, the path to the file to open). The second element is a list of boolean values. Each value corresponds to one checkbutton.
    # A value of True indicates that the checkbox was checked when the user clicked ok - False indicates it was unchecked.
    @staticmethod
    def show_file_dialog_with_checks(title,
                                     filters,
                                     action,
                                     confirm_button_stock,
                                     checkbuttons,
                                     save_last_location=False):
        filename = None
        check_results = []

        dialog = gtk.FileChooserDialog(
            title=title,
            action=action,
            buttons=(gtk.STOCK_CANCEL, gtk.ResponseType.CANCEL,
                     confirm_button_stock, gtk.ResponseType.OK))
        dialog.set_default_response(gtk.ResponseType.OK)
        if save_last_location and UIUtils.last_filechooser_location:
            dialog.set_current_folder(UIUtils.last_filechooser_location)

        for cur_filter in filters:
            dialog.add_filter(cur_filter)

        if checkbuttons:
            content_area = dialog.get_content_area()
            vbox = gtk.VBox()
            for button in checkbuttons:
                align = gtk.Alignment(xalign=1.0, yalign=1.0)
                align.add(button)
                vbox.pack_start(align, False, False, 0)

            content_area.pack_end(vbox, False, False, 0)
            vbox.show_all()

        response = dialog.run()
        if response == gtk.ResponseType.OK:
            filename = dialog.get_filename()
            for button in checkbuttons:
                check_results.append(button.get_active())

        dialog.destroy()

        if save_last_location and filename:
            UIUtils.last_filechooser_location = os.path.dirname(filename)

        return filename, check_results

    ## This method shows a a file dialog box (for "open" or "save") with controls that allow the user to select a file. This method blocks until the user clicks ok.
    # @param title (string) text to display in the dialog box titlebar
    # @param filters (list=[]) list of gtk.FileFilter objects. This specifies the types of files (via their extensions) that will be visible in the dialog.
    # @param action (int) This is a gtk filechooser action constant (one of gtk.FILE_CHOOSER_ACTION_OPEN, gtk.FILE_CHOOSER_ACTION_SAVE, gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER or gtk.FILE_CHOOSER_ACTION_CREATE_FOLDER),
    # indicating the type of dialog to display.
    # @param confirm_button_stock (int) a gtk stock icon constant (e.g. gtk.STOCK_OK, gtk.STOCK_OPEN), indicating what type of text and icon to display on the "ok" button. For a complete list of stock constants, see
    # <a href="http://www.pygtk.org/docs/pygtk/gtk-stock-items.html">the PyGTK docs here</a>.
    # @param open_now_opt (boolean=False) if True, a checkbox will be displayed in the dialog with the title "Open Immediately". Its value (True=checked, False=unchecked) is returned along with the path when this method returns. Typically this is used
    # in save dialogs to allow the user to indicate that they would like to open a file immediately after it is saved to disk.
    # @param save_last_location (boolean=False) if True, the directory containing the selected file will be saved (to UIUtils.last_filechoose_location), and the next "open" or "save" dialog will use it as the current directory
    # @param cur_location (string=None) a path to a folder to set the dialog to show when it opens. If None, this will display whatever directory GTK feels like.
    # @returns (string, list) a 2-tuple. The first element is the path the user has selected using the dialog controls (for example, the path to the file to open). The second element is a boolean value indicating the status of the "open now" checkbox (if present).
    # A value of True indicates that the checkbox was checked when the user clicked ok - False indicates it was unchecked (or that the checkbox is not being shown).
    @staticmethod
    def show_file_dialog(title,
                         filters,
                         action,
                         confirm_button_stock,
                         open_now_opt=False,
                         save_last_location=False,
                         cur_location=None):
        filename = None
        open_now_checkbox = None
        open_now = False

        dialog = gtk.FileChooserDialog(
            title=title,
            action=action,
            buttons=(gtk.STOCK_CANCEL, gtk.ResponseType.CANCEL,
                     confirm_button_stock, gtk.ResponseType.OK))
        dialog.set_default_response(gtk.ResponseType.OK)
        if cur_location:
            dialog.set_current_folder(cur_location)
        elif save_last_location and UIUtils.last_filechooser_location:
            dialog.set_current_folder(UIUtils.last_filechooser_location)

        map(lambda f: dialog.add_filter(f), filters)

        if open_now_opt:
            #splice in the 'open immediately checkbox'
            content_area = dialog.get_content_area()
            open_now_checkbox = gtk.CheckButton('Open Immediately')
            open_now_checkbox.set_active(True)
            align = gtk.Alignment(xalign=1.0, yalign=1.0)
            align.add(open_now_checkbox)
            content_area.pack_end(align, False, False, 0)
            open_now_checkbox.show()
            align.show()

        response = dialog.run()
        if response == gtk.ResponseType.OK:
            filename = dialog.get_filename()
            if open_now_opt:
                open_now = open_now_checkbox.get_active()

        dialog.destroy()

        if save_last_location and filename:
            UIUtils.last_filechooser_location = os.path.dirname(filename)

        return filename, open_now
Esempio n. 10
0
    def _get_common_regexs_enum(self):
        rows = self.select('common_regexs', 'code_name regex'.split())
        code_names, regexs = zip(*rows)

        return Enum(code_names, regexs)
Esempio n. 11
0
 def _get_speaker_props_enum(self):
     #Note: for now, it doesn't really pay to have a table for this - just don't change the ordering in the enum...
     return Enum(['MEDIA', 'OVERLAPPING', 'NON_VERBAL_NOISE'])
Esempio n. 12
0
class CSVDatabase(MemDatabase):
    TABLE_NAME = 'data'
    COL_PREFIX = 'col'  #column names are like "COL_PREFIX<index>" - e.g. col0, col1, col2, ...
    DATA_TYPES = {
        str: 'TEXT',
        float: 'REAL',
        int: 'INTEGER',
        bool:
        'INTEGER',  #sqlite does not have a separate boolean type. It's no trouble to convert these to integers for DB operations.
        datetime:
        'TEXT',  #sqlite doesn't have a datetime type, but provides functions that allows us to interpret strings as dates.
        #These should be entered in the form 'yyyy-mm-dd hh:mm:ss.sss'
    }
    ORDER_DIRS = Enum(['ASC', 'DESC'], ['ASC', 'DESC'])

    ## Constructor
    # @param self
    # @param header_row (list of Strings) List of names of the columns in the csv file (generally this is just the top row of the csv file
    # @param col_datatypes (list) List of data type functions (these must be keys from the static CSVDatabase.DATA_TYPES dictionary) corresponding to the columns in your csv file.
    def __init__(self, header_row, col_datatypes):
        super(CSVDatabase, self).__init__()

        self.name_lookup = OrderedDict(
            zip(header_row, range(len(col_datatypes))))
        self.header_row = list(header_row)
        self.col_datatypes = list(col_datatypes)
        self._create_data_table()

    ## Convenience method to create a database from a list of rows that have already been read from a csv file.
    #  @param rows (list) List of lists, where inner lists are rows of csv data. First row must be column names.
    #  @param col_datatypes (list) List of data type functions (these must be keys from the static CSVDatabase.DATA_TYPES dictionary) corresponding to the columns in your csv file.
    @staticmethod
    def create_with_rows(rows, col_datatypes):
        db = CSVDatabase(rows[0], col_datatypes)

        for i in range(1, len(rows)):
            db.csv_insert(rows[i])

        return db

    ## Convenience method to create a database from a bunch of files that all have the same columns (and column order).
    #  Note: This method will complain if it finds that any of the files you pass it have different column names.
    #  @param file_list (List) list of paths (Strings) to the files whose data you want to put into the new database
    #  @param col_datatypes (list) List of data type functions (these must be keys from the static CSVDatabase.DATA_TYPES dictionary) corresponding to the columns in your csv file.
    #  @returns (CSVDatabase) a CSVDatabase object containing the rows from all of the files. This won't have a primary key, so if the data is large you may want to add some indices before you start querying.
    @staticmethod
    def create_with_files(file_list, col_datatypes):
        file_in = open(file_list[0], 'rb')
        reader = csv.reader(file_in)
        db = CSVDatabase(reader.next(), col_datatypes)
        file_in.close()

        for cur_file in file_list:
            file_in = open(cur_file, 'rb')
            reader = csv.reader(file_in)
            cur_header = reader.next()

            if db.header_row == cur_header:
                for row in reader:
                    db.csv_insert(row)

                file_in.close()
            else:
                raise Exception(
                    'File %s has different column headers than the other files.'
                    % (cur_file))

        return db

    ## Creates the single table used by this in-memory database.
    # @param self
    def _create_data_table(self):
        col_sql = 'id INTEGER PRIMARY KEY AUTOINCREMENT'
        for i in range(len(self.col_datatypes)):
            col_sql += ', %s%d %s NULL' % (
                CSVDatabase.COL_PREFIX, i,
                CSVDatabase.DATA_TYPES[self.col_datatypes[i]])

        data_sql = 'CREATE TABLE ' + CSVDatabase.TABLE_NAME + '(' + col_sql + ')'

        self.cursor.execute(data_sql)

    ## Inserts a row of data straight from a csv file. The data must have the types given in the col_datatypes param that was passed to the constructor or this will cause an exception.
    # @param self
    # @param csv_row (list) list of data from a csv file (corresponding to a single row)
    # @returns (list) list of all the primary key values of the inserted rows
    def csv_insert(self, csv_row):
        return super(CSVDatabase, self).insert(
            'data',
            map(lambda num: '%s%d' % (CSVDatabase.COL_PREFIX, num),
                range(len(self.col_datatypes))), [csv_row])

    ## Selects data from the database. This method works using the indices of the columns in the CSV file that you'd like to select.
    # @param col_indices (list=None) a list of the indices of the columns you'd like to select.
    # @param where_cond (String=None) see database.select()
    # @param params (list=[]) see database.select()
    # @param order_by_indices (list=None) list of indices of columns you'd like to order by
    # @param order_by_dirs (list=None) list of strings (each must be either 'ASC', 'DESC') that indicate the direction in which you want to order the columns specified by order_by_indices.
    # @param dump_sql (boolean=False) if True, prints the generated SQL statement to stdout
    # @param fcn_indices (list=None) list of indices of columns you'd like to apply SQL aggregate functions to ('avg', 'sum', etc.).
    # @param fcns (list=None) list of Strings (SQL functions like 'avg', 'sum', etc.) to apply to the columns specified by fcn_indices
    # @param group_by_index (int=None) index of column you'd like to group by
    # @returns (list) list of lists, one sub-list per row. Each sublist contains data in the order specified by col_indices.
    def csv_select_by_index(self,
                            col_indices=None,
                            where_cond=None,
                            params=[],
                            order_by_indices=None,
                            order_by_dirs=None,
                            dump_sql=False,
                            fcn_indices=None,
                            fcns=None,
                            group_by_index=None):
        if col_indices == None:
            col_indices = range(len(self.col_datatypes))

        cols = []
        for index in col_indices:
            name = '%s%d' % (CSVDatabase.COL_PREFIX, index)
            cols.append(name)

        #add in any aggregate functions
        if fcn_indices and fcns:
            for i in range(len(fcn_indices)):
                for j in range(len(col_indices)):
                    if fcn_indices[i] == col_indices[j]:
                        cols[j] = '%s(%s)' % (fcns[i], cols[j])

        group_by = None
        if group_by_index != None:
            group_by = '%s%d' % (CSVDatabase.COL_PREFIX, group_by_index)

        order_by = None
        if order_by_indices != None:
            order_by = ''
            for i in range(len(order_by_indices)):
                index = order_by_indices[i]
                order_by += '%s%d %s' % (CSVDatabase.COL_PREFIX, index,
                                         order_by_dirs[i])
                if i < len(order_by_indices) - 1:
                    order_by += ', '

        return super(CSVDatabase, self).select(CSVDatabase.TABLE_NAME,
                                               cols,
                                               where_cond=where_cond,
                                               params=params,
                                               order_by=order_by,
                                               dump_sql=dump_sql,
                                               group_by=group_by)

    ## Gets a list of the indices of columns you specify by name.
    #  @param self
    #  @param col_names (list) list of column names (Strings)
    #  @returns (list) list of the indices that correspond to the column names you specified
    def _get_col_indices(self, col_names):
        col_indices = None
        if col_names == None:
            col_indices = self.name_lookup.values()
        else:
            col_indices = [self.name_lookup[name] for name in col_names]

        return col_indices

    ## Translates CSV column names to DB column names to build a SQL where clause like 'x = y'. This will presumably be attached to a SQL statement to form '... where x = y'.
    #  @param self
    #  @param where_body (String) body of the where clause, containing placeholders (%s) for the column names (Eg. '%s = ?')
    #  @param where_cols (list) list of csv names of columns. These will be translated to DB column names and placed in the where_body (these go in the %s placeholders).
    #  @returns (String) the clause. This contains db column names.
    def _build_where_clause(self, where_body, where_cols):
        where_cond = None
        if where_body and where_cols:
            db_col_names = []
            for col in where_cols:
                db_col_names.append(
                    '%s%d' % (CSVDatabase.COL_PREFIX, self.name_lookup[col]))
            where_cond = where_body % tuple(db_col_names)

        return where_cond

    ## Fetches a list of all of the DB column names from the DB table.
    #  @param self
    #  @returns (list)
    def get_db_col_names(self):
        return dict(
            zip(
                self.header_row,
                map(lambda i: '%s%d' % (CSVDatabase.COL_PREFIX, i),
                    self._get_col_indices(self.header_row))))

    ## Selects data from the database. This method works using the CSV names of the columns you want to select.
    # @param col_names (list=None) a list of the csv names of the columns you'd like to select.
    # @param where_cond (String=None) a string like ('%s = ?'). This will be translated into 'where age = 14' using the where_cols and params parameters (see below).
    # @param where_cols (list) list of csv names of columns to put in the %s placeholders in where_cond.
    # @param params (list=[]) see database.select(). These values will be placed in the ? placeholders in where_cond.
    # @param order_by (list=None) list of csv names of columns you'd like to order by
    # @param order_by_dirs (list=None) list of strings (each must be either 'ASC', 'DESC') that indicate the direction in which you want to order the columns specified by order_by.
    # @param dump_sql (boolean=False) if True, prints the generated SQL statement to stdout
    # @param fcn_col_names (list=None) list of csv names of columns you'd like to apply SQL aggregate functions to ('avg', 'sum', etc.).
    # @param fcns (list=None) list of Strings (SQL functions like 'avg', 'sum', etc.) to apply to the columns specified by fcn_col_names
    # @param group_by (int=None) csv name of column you'd like to group by
    # @returns (list) list of lists, one sub-list per row. Each sublist contains data in the order specified by col_names.
    def csv_select_by_name(self,
                           col_names=None,
                           where_body=None,
                           where_cols=None,
                           params=[],
                           order_by=None,
                           order_by_dirs=None,
                           dump_sql=False,
                           fcn_col_names=None,
                           fcns=None,
                           group_by=None):
        col_indices = self._get_col_indices(col_names)
        where_cond = self._build_where_clause(where_body, where_cols)
        fcn_indices = self._get_col_indices(fcn_col_names)

        group_by_index = None
        if group_by != None:
            group_by_index = self._get_col_indices([group_by])[0]

        order_by_indices = None
        if order_by != None:
            order_by_indices = self._get_col_indices(order_by)
            #order_by_index = self._get_col_indices([order_by])[0]

        return self.csv_select_by_index(col_indices=col_indices,
                                        where_cond=where_cond,
                                        params=params,
                                        order_by_indices=order_by_indices,
                                        order_by_dirs=order_by_dirs,
                                        dump_sql=dump_sql,
                                        fcn_indices=fcn_indices,
                                        fcns=fcns,
                                        group_by_index=group_by_index)

    ## Generates and executes a SQL update statement. This method uses the indices of the columns in the csv file. See csv_select_by_index() for a description of the parameters.
    # @param self
    # @param col_indices (list)
    # @param where_cond (String=None)
    # @param params (list)
    # @param dump_sql (boolean=False)
    # @returns (int) number of rows updated
    def csv_update_by_index(self,
                            col_indices,
                            where_cond=None,
                            params=[],
                            dump_sql=False):
        cols = map(lambda num: '%s%d' % (CSVDatabase.COL_PREFIX, num),
                   col_indices)

        return super(CSVDatabase, self).update(CSVDatabase.TABLE_NAME,
                                               cols,
                                               where_cond=where_cond,
                                               params=params,
                                               dump_sql=dump_sql)

    ## Generates and executes a SQL delete statement. This method uses the indices of the columns in the csv file. See csv_select_by_index() for a description of the parameters.
    # @param self
    # @param where_cond (String=None)
    # @param params (list)
    # @returns (int) number of rows deleted
    def csv_delete_by_index(self, where_cond=None, params=[]):
        return super(CSVDatabase, self).delete(CSVDatabase.TABLE_NAME,
                                               where_cond, params)

    ## Generates and executes a SQL delete statement. This method uses the names of the columns in the csv file. See csv_select_by_name() for a description of the parameters.
    # @param self
    # @param where_body (String=None)
    # @param where_cols (list=None)
    # @param params (list)
    # @returns (int) number of rows deleted
    def csv_delete_by_name(self, where_body=None, where_cols=None, params=[]):
        where_cond = self._build_where_clause(where_body, where_cols)

        return self.csv_delete_by_index(where_cond, params)

    ## Generates and executes a SQL update statement. This method uses the names of the columns in the csv file. See csv_select_by_name() for a description of the parameters.
    #Sample usage:
    #col_names = ['File_Name', 'Child_Gender']
    #where_body = '%s > ? and %s > ?'
    #where_cols = ('FAN, 'CHN')
    #params = (23.3, 45.5, 20.0, 10.0)
    #Using these parameters will generate the following SQL:
    # 'update data set col0=23.3, col3=45.5 where col10 > 20.0 and col11 > 10.0;'
    # Assuming 'File_Name' -> col0, 'Child_Gender' -> col3, 'FAN' -> col10, 'CHN' -> col11.
    # @param self
    # @param where_body (String=None)
    # @param where_cols (list=None)
    # @param params (list)
    # @param dump_sql (boolean=False)
    def csv_update_by_name(self,
                           col_names,
                           where_body=None,
                           where_cols=None,
                           params=[],
                           dump_sql=False):
        col_indices = None
        if col_names == None:
            col_indices = self.name_lookup.values()
        else:
            col_indices = [self.name_lookup[name] for name in col_names]

        where_cond = None
        if where_body and where_cols:
            db_col_names = []
            for col in where_cols:
                db_col_names.append(
                    '%s%d' % (CSVDatabase.COL_PREFIX, self.name_lookup[col]))
            where_cond = where_body % tuple(db_col_names)

        return self.csv_update_by_index(col_indices, where_cond, params,
                                        dump_sql)

    def get_db_col_name(self, text_name):
        return '%s%d' % (CSVDatabase.COL_PREFIX, self.name_lookup[name])

    ## Adds a named column to the this database's single table.
    # The values in the newly added column are all set to NULL.
    # @param self
    # @param name (string) name of the column to add.
    # @param datatype (fcn) a data-type function (must be in the keys of the static CSVDatabase.DATA_TYPES dictionary) corresponding to the type of data that this column will hold
    def add_column(self, name, datatype):
        col_index = len(self.col_datatypes)

        self.cursor.execute('ALTER TABLE %s ADD COLUMN %s %s NULL' % (
            CSVDatabase.TABLE_NAME,
            '%s%d' % (CSVDatabase.COL_PREFIX, col_index),
            CSVDatabase.DATA_TYPES[datatype],
        ))

        self.col_datatypes.append(datatype)
        self.header_row.append(name)
        self.name_lookup[name] = col_index

    ## Takes a row (list) of data and removes the specified columns from the list. This is a convenience method and does not affect the data in the DB in any way.
    # @param self
    # @param row (list) a row of values from the database or csv file
    # @param col_indices (list) list of the column indices that you want to remove from the row
    # @returns (list) a new row that does not contain any of the columns specified using col_indices.
    def _remove_cols(self, row, col_indices):
        filtered_row = []
        for i in range(len(row)):
            if not (i in col_indices):
                filtered_row.append(row[i])

        return filtered_row

    ## Writes out the data in this CSVDatabase contains to a csv file.
    # A header row (column names) will be written at the top of the file.
    # @param self
    # @param path (String) path to the csv file to write to
    # @param omit_col_indices (list=[]) list of indices of columns that you want to omit from the exported csv file.
    def write_to_file(self, path, omit_col_indices=[]):
        file_out = open(path, 'wb')
        writer = csv.writer(file_out)
        rows = self.csv_select_by_index()  #select *

        header = self.header_row
        if omit_col_indices:
            header = self._remove_cols(header, omit_col_indices)

        writer.writerow(header)
        for cur_row in rows:
            if omit_col_indices:
                cur_row = self._remove_cols(cur_row, omit_col_indices)
            writer.writerow(cur_row)

        file_out.close()

    ## Sets all values in all columns to NULL if they are equal to the empty string.
    # @param self
    def set_blanks_to_null(self):
        for col in self.header_row:
            self.csv_update_by_name([col],
                                    where_body="%s = ?",
                                    where_cols=[col],
                                    params=[None, ''])
Esempio n. 13
0
File: taxonomy.py Progetto: gem/sidd
class Taxonomy(object):
    """
    main Taxonomy class
    with serializing and serializing functions
    """
    Separators = Enum("AttributeGroup", "Attribute", "AttributeValue")

    def __init__(self):
        """ constructor """
        raise NotImplementedError("abstract method not implemented")

    @property
    def name(self):
        raise NotImplementedError("abstract method not implemented")

    @property
    def description(self):
        raise NotImplementedError("abstract method not implemented")

    @property
    def version(self):
        raise NotImplementedError("abstract method not implemented")

    @property
    def attribute_groups(self):
        raise NotImplementedError("abstract method not implemented")

    @property
    def attributes(self):
        raise NotImplementedError("abstract method not implemented")

    @property
    def codes(self):
        raise NotImplementedError("abstract method not implemented")

    def get_attribute_group_by_name(self, name):
        raise NotImplementedError("abstract method not implemented")

    def get_attribute_by_name(self, name):
        raise NotImplementedError("abstract method not implemented")

    def get_code_by_name(self, name):
        raise NotImplementedError("abstract method not implemented")

    def get_code_by_attribute(self, attribute_name, parent_code=None):
        raise NotImplementedError("abstract method not implemented")

    def has_rule(self, attribute_name):
        raise NotImplementedError("abstract method not implemented")

    def parse(self, string):
        raise NotImplementedError("abstract method not implemented")

    def get_separator(self, separator_type):
        if separator_type == Taxonomy.Separators.AttributeGroup:
            return TaxonomyAttributeGroup.Separator
        elif separator_type == Taxonomy.Separators.Attribute:
            return TaxonomyAttribute.Separator
        elif separator_type == Taxonomy.Separators.AttributeValue:
            return TaxonomyAttributeValue.Separator
        else:
            raise TaxonomyError("Separator Type (%s) not supported" %
                                separator_type)

    def to_string(self, attributes):
        raise NotImplementedError("abstract method not implemented")

    def is_valid_string(self, tax_string):
        raise NotImplementedError("abstract method not implemented")
Esempio n. 14
0
import textwrap

from django.conf import settings
from django.core.mail import send_mail
from django.template.loader import render_to_string
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
from lxml import html

from auth.models import CustomUser as User
from messages.models import Message, SYSTEM_NOTIFICATION
from utils.enum import Enum
from utils.taskqueue import job

Notifications = Enum('Notifications', [
    ('ROLE_CHANGED', _('Role changed')),
    ('TEAM_INVITATION', _('Team invitation')),
])


def notify_users(notification,
                 user_list,
                 subject,
                 template_name,
                 context,
                 send_email=None):
    """
    Send notification messages to a list of users

    Arguments:
        notification: member from the Notifications enum
        user_list: list/iterable of CustomUser objects to notify
Esempio n. 15
0
import os
import glob
import csv

input_path = 'C:/Users/Wayne/Documents/baby-lab/bll/reliability/confusion/input/'
output_file = 'C:/Users/Wayne/Documents/baby-lab/bll/reliability/confusion/output/AWC.csv'
envs = (
    'home',
    'home daycare',
    'daycare centre',
)
#envs = ('test',)

lena_db_path = 'C:/Users/Wayne/Documents/baby-lab/bll/reliability/confusion/output/'

container_types = Enum('TRANS_NO_OVERLAP TRANS_ALL_SPEECH LENA_NO_OVERLAP LENA_ALL_SPEECH'.split())

def get_trans_awc(container_list, lena_db, filename, exclude_angle=False, exclude_nonunderstandable=True, print_utters=False):
    trans_awc = 0
    lena_awc = 0
    utter_count = 0
    for container in container_list:
        if container[0].speaker:
            lena_code = container[0].speaker.speaker_codeinfo.code
            if lena_code in ('FAN', 'MAN'):
                if print_utters:
                    print 'Container:'

                found_utter = False
                for utter in container:
                    if not exclude_utter(utter, exclude_angle, exclude_nonunderstandable):
Esempio n. 16
0
File: data.py Progetto: gem/sidd
from sidd.constants import logAPICall

OperatorDataTypes = Enum(
    # input for loader
    "File",
    "StringAttribute",
    "NumericAttribute",

    # internal data types
    "Population",
    "Footprint",
    "FootprintHt",
    "Survey",
    "Zone",
    "ZoneBldgCount",
    "ZoneStatistic",
    "MappingScheme",
    "Grid",
    "Layer",
    "Exposure",
    "Report",

    # formula
    "PopulationToBuilding",

    # data format
    "Shapefile",
    "XMLFile",
)

Esempio n. 17
0
    class TestStateMachine():
        STATES = Enum('INITIAL MARKER_UNPLAYED MARKER_PLAYED'.split())
        ACTIONS = Enum('NEXT PREV PLAY ADJUST'.split())

        def __init__(self, controls, test2):
            self.controls = controls
            self.test2 = test2

            self.seg_len = self.controls.scale.get_adjustment().get_upper()

            self.route_dict = {
                TestWindow.TestStateMachine.STATES.INITIAL:
                lambda action: self._initial(),
                TestWindow.TestStateMachine.STATES.MARKER_UNPLAYED:
                self._marker_unplayed,
                TestWindow.TestStateMachine.STATES.MARKER_PLAYED:
                self._marker_played,
            }

            if self.test2.ui_save_data:
                self.markers = self.test2.ui_save_data['markers']
                self.marker_index = self.test2.ui_save_data['marker_index']
                self.state = self.test2.ui_save_data['sm_state']
            else:
                self.markers = []
                self.marker_index = -1
                self.state = TestWindow.TestStateMachine.STATES.INITIAL
                self.drive(None)

        def _update_clip_spinner(self):
            self.controls.handler_man.block_handler(self.controls.clip_spinner,
                                                    'value-changed')

            enabled = (self.marker_index == len(self.markers) - 2)
            self.controls.clip_spinner.set_sensitive(enabled)

            val = self.markers[self.marker_index +
                               1] - self.markers[self.marker_index]
            self.controls.clip_spinner.set_value(val)

            self.controls.handler_man.unblock_handler(
                self.controls.clip_spinner, 'value-changed')

        def _append_marker(self, pos, append_to_self=True):
            if append_to_self:
                self.markers.append(pos)
            self.controls.scale.add_mark(
                pos, gtk.POS_BOTTOM,
                BackendUtils.get_time_str(pos,
                                          pad_hour_min=False,
                                          show_hours=False,
                                          show_decimals=False))

        def _update_scale_pos(self):
            self.controls.handler_man.block_handler(
                self.controls.scale.get_adjustment(), 'value-changed')
            self.controls.scale.set_value(self.markers[self.marker_index])
            self.controls.handler_man.unblock_handler(
                self.controls.scale.get_adjustment(), 'value-changed')

        def _update_scale_fill_lev(self, lev):
            if self.controls.scale.get_fill_level() < lev:
                self.controls.scale.set_fill_level(lev)

        def drive(self, action):
            #old_state = self.state
            self.route_dict[self.state](action)
            self.controls.trans_entry.grab_focus()
            #new_state = self.state
            #states = TestWindow.TestStateMachine.STATES.get_ordered_keys()
            #print '%s -> %s' % (states[old_state], states[new_state])

        def get_ui_save_data(self):
            return {
                'markers': self.markers,
                'marker_index': self.marker_index,
                'sm_state': self.state,
                'fill_lev': self.controls.scale.get_fill_level(),
            }

        def _play_clip(self, start, end):
            wav_parser = WavParser(self.test2.wav_filename)
            wav_parser.play_clip(start, end)
            wav_parser.close()

        def _initial(self):
            self.marker_index = 0
            self._append_marker(0)
            next_pos = self.controls.clip_spinner.get_value_as_int()

            max_pos = self.controls.scale.get_adjustment().get_upper()
            if next_pos >= max_pos:
                next_pos = max_pos

            self._append_marker(next_pos)
            self.state = TestWindow.TestStateMachine.STATES.MARKER_UNPLAYED

        def _marker_unplayed(self, action):
            if action == TestWindow.TestStateMachine.ACTIONS.NEXT:
                pass

            elif action == TestWindow.TestStateMachine.ACTIONS.PREV:
                #go back if we're not at the initial mark
                if self.marker_index > 0:
                    self.marker_index -= 1
                    self._update_scale_pos()
                    self.state = TestWindow.TestStateMachine.STATES.MARKER_PLAYED
                    self._update_clip_spinner()

            elif action == TestWindow.TestStateMachine.ACTIONS.PLAY:
                fill_lev = self.markers[self.marker_index + 1]
                if self.controls.scale.get_fill_level() < fill_lev:
                    self.controls.scale.set_fill_level(fill_lev)
                self.state = TestWindow.TestStateMachine.STATES.MARKER_PLAYED

                wav_offset_sec = self.test2.get_start_time_offset()
                start = wav_offset_sec + self.markers[self.marker_index]
                end = wav_offset_sec + self.markers[self.marker_index + 1]
                t = threading.Thread(target=self._play_clip, args=(start, end))
                t.start()

            elif action == TestWindow.TestStateMachine.ACTIONS.ADJUST:
                #assume we are at the second-last marker (this is enforced by setting clip_spinner to insensitive at all other times)
                max_pos = self.controls.scale.get_adjustment().get_upper()
                fill_lev = self.controls.scale.get_fill_level()
                new_pos = self.markers[
                    self.
                    marker_index] + self.controls.clip_spinner.get_value_as_int(
                    )
                if new_pos > max_pos:
                    new_pos = max_pos

                self.controls.scale.clear_marks()
                self.markers.pop(-1)
                for mark in self.markers:
                    self._append_marker(mark, False)
                self._append_marker(new_pos)

                self.controls.scale.set_fill_level(fill_lev)
                self._update_scale_pos()

        def _marker_played(self, action):
            if action == TestWindow.TestStateMachine.ACTIONS.NEXT:
                max_pos = self.controls.scale.get_adjustment().get_upper()

                if self.markers[self.marker_index + 1] != max_pos:
                    self.marker_index += 1
                    self._update_scale_pos()

                    if self.marker_index == len(self.markers) - 1:
                        next_pos = self.markers[
                            self.
                            marker_index] + self.controls.clip_spinner.get_value_as_int(
                            )
                        if next_pos > max_pos:
                            next_pos = max_pos

                        self._append_marker(next_pos)

                    self._update_clip_spinner()
                    if self.controls.scale.get_fill_level() == self.markers[
                            self.marker_index]:
                        self.state = TestWindow.TestStateMachine.STATES.MARKER_UNPLAYED

            elif action == TestWindow.TestStateMachine.ACTIONS.PREV:
                #go back if we're not at the initial mark
                if self.marker_index > 0:
                    self.marker_index -= 1
                    self._update_scale_pos()
                    self._update_clip_spinner()

            elif action == TestWindow.TestStateMachine.ACTIONS.PLAY:
                self.controls.trans_entry.grab_focus()
                wav_offset_sec = self.test2.get_start_time_offset()
                start = wav_offset_sec + self.markers[self.marker_index]
                end = wav_offset_sec + self.markers[self.marker_index + 1]
                t = threading.Thread(target=self._play_clip, args=(start, end))
                t.start()

            elif action == TestWindow.TestStateMachine.ACTIONS.ADJUST:
                #assume we are at the second-last marker (this is enforced by setting clip_spinner to insensitive at all other times)
                max_pos = self.controls.scale.get_adjustment().get_upper()
                new_pos = self.markers[
                    self.
                    marker_index] + self.controls.clip_spinner.get_value_as_int(
                    )
                if new_pos > max_pos:
                    new_pos = max_pos

                self.controls.scale.clear_marks()
                self.markers.pop(-1)
                for mark in self.markers:
                    self._append_marker(mark, False)
                self._append_marker(new_pos)

                self.controls.scale.set_fill_level(
                    self.markers[-2])  #last segment is now unplayed
                self._update_scale_pos()

                if self.marker_index == len(self.markers) - 2:
                    self.state = TestWindow.TestStateMachine.STATES.MARKER_UNPLAYED
Esempio n. 18
0
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2018/10/11
# @Author  : Wenhao Shan

from utils.enum import Enum

KazooMsg = Enum(
    Node_Exist="Node Exist",
    Node_Not_Exist="Node Not Exist",
    Create_Failed="Create Node Failed",
    Get_Failed="Inquire Node Failed",
    Update_Failed="Update Node Failed",
    Delete_Failed="Delete Node Failed",
    Get_Children_Failed="Get Children List Of Given Node Failed",
)
Esempio n. 19
0
 def _get_speaker_distances_enum(self):
     #Note: for now, it doesn't really pay to have a table for this - just don't change the ordering in the enum...the items' values should map directly to the id used the database
     return Enum(['NA', 'NEAR', 'FAR'])
Esempio n. 20
0
class PitchStudyProps(DBObject):
    PROPS = Enum([
        'CLIPS_DB_PATH', 'CLIPS_DIR_PATH', 'MAX_PARTS_PER_BATCH',
        'NUM_OPTIONS', 'BREAK_INTERVAL', 'INTER_CLIP_SOUND_DEL'
    ], [
        'clips_db_path', 'clips_dir_path', 'max_parts_per_batch',
        'num_options', 'break_interval', 'inter_clip_sound_del'
    ])

    def __init__(self,
                 clips_db_path,
                 clips_dir_path,
                 max_parts_per_batch,
                 num_options,
                 break_interval,
                 inter_clip_sound_del,
                 db_id=None):
        super(PitchStudyProps, self).__init__()

        self.clips_db_path = clips_db_path
        self.clips_dir_path = clips_dir_path
        self.max_parts_per_batch = max_parts_per_batch
        self.num_options = num_options
        self.break_interval = break_interval
        self.inter_clip_sound_del = inter_clip_sound_del
        self.db_id = db_id

    @staticmethod
    def db_select(db, ids=[]):
        DBObject.db_select(db, ids)

        where_cond = None
        if ids:
            where_cond = DBObject._build_where_cond_from_ids(ids)

        rows = db.select(
            'pitch_study_props',
            'clips_db_path clips_dir_path max_parts_per_batch num_options break_interval inter_clip_sound_del id'
            .split(),
            where_cond=where_cond)

        props = []
        for cur_row in rows:
            props.append(PitchStudyProps(*cur_row))
        return props

    def db_delete(self, db):
        super(PitchStudyProps, self).db_delete(db)

        num_rows = db.delete('pitch_study_props', 'id = ?', [self.db_id])
        self.db_id = None

        return num_rows

    #prop must be a  value from the PitchStudyApp.PROPS enum
    def update_prop(self, db, prop, val):
        rowcount = db.update(
            'pitch_study_props',
            [
                prop
            ],  #I know...it's not right - but there is no risk of SQL injection in the lab
            where_cond='id = ?',
            params=[val, self.db_id])

        if rowcount > 0:
            setattr(self, prop, val)
Esempio n. 21
0
    def _get_combo_groups_enum(self):
        rows = self.select('combo_groups', 'id code_name'.split())
        ids, code_names = zip(*rows)

        return Enum(code_names, ids)
Esempio n. 22
0
class FilterWindow():
    FILTER_TYPES = Enum('FILE FOLDER'.split())
    def __init__(self, filter_type):
        self.filter_type = filter_type
        
        self.window = gtk.Window(gtk.WindowType.TOPLEVEL)
        self.window.set_title('Naptime Filter')
        self.window.connect('destroy', lambda x: self.window.destroy())
        self.window.set_border_width(10)
        self.window.set_default_size(210, 150)

        self._build_window()
        
        self.window.show_all()

    def _build_window(self):
        vbox = gtk.VBox()
        
        #table = gtk.Table(2,3, False)
        grid = gtk.Grid()
        
        src_label = gtk.Label('Source:')
        #table.attach(src_label, 0, 1, 0, 1, gtk.EXPAND, gtk.EXPAND)
        grid.attach(src_label, 0, 0, 1, 1)
        src_entry = gtk.Entry()
        src_entry.set_width_chars(50)
        #table.attach(src_entry, 1, 2, 0, 1, gtk.EXPAND, gtk.EXPAND)
        grid.attach(src_entry, 1, 0, 1, 1)
        src_browse_button = gtk.Button('Browse')
        #table.attach(src_browse_button, 2, 3, 0, 1, gtk.EXPAND, gtk.EXPAND)
        grid.attach(src_browse_button, 2, 0, 1, 1)

        if self.filter_type == FilterWindow.FILTER_TYPES.FILE:
            src_browse_button.connect('clicked', lambda w: UIUtils.browse_file('Select file', src_entry, [UIUtils.CSV_FILE_FILTER, UIUtils.ALL_FILE_FILTER]))
        elif self.filter_type == FilterWindow.FILTER_TYPES.FOLDER:
            src_browse_button.connect('clicked', lambda w: UIUtils.browse_folder('Select folder', src_entry)) #[UIUtils.CSV_FILE_FILTER, UIUtils.ALL_FILE_FILTER]))

        dest_label = gtk.Label('Destination:')
        #table.attach(dest_label, 0, 1, 1, 2, gtk.EXPAND, gtk.EXPAND)
        grid.attach(dest_label, 0, 1, 1, 1)
        dest_entry = gtk.Entry()
        dest_entry.set_width_chars(50)
        #table.attach(dest_entry, 1, 2, 1, 2, gtk.EXPAND, gtk.EXPAND)
        grid.attach(dest_entry, 1, 1, 1, 1)
        dest_browse_button = gtk.Button('Browse')
        #table.attach(dest_browse_button, 2, 3, 1, 2, gtk.EXPAND, gtk.EXPAND)
        grid.attach(dest_browse_button, 2, 1, 1, 1)

        dest_browse_button.connect('clicked', lambda w: UIUtils.browse_folder('Select folder', dest_entry))#, [UIUtils.CSV_FILE_FILTER, UIUtils.ALL_FILE_FILTER]))

        vbox.pack_start(grid, True, True, 0)
            
        button_box = gtk.HButtonBox()
        button_box.set_layout(gtk.ButtonBoxStyle.EDGE)
        cancel_button = gtk.Button(stock=gtk.STOCK_CANCEL, label='Cancel')
        cancel_button.connect('clicked', lambda w: self.window.destroy())
        button_box.add(cancel_button)

        ok_button = gtk.Button(stock=gtk.STOCK_OK, label='Ok')
        ok_button.connect('clicked', lambda w: self._process(src_entry.get_text(), dest_entry.get_text()))
        button_box.add(ok_button)

        vbox.pack_start(button_box, True, True, 0)
        
        self.window.add(vbox)

    def _process(self, src, dest):
        in_files = None
        out_files = None

        if src and os.path.exists(src):
            src = src.replace('\\', '/')

            if self.filter_type == FilterWindow.FILTER_TYPES.FILE:
                if not src.endswith('.csv'):
                    src += '.csv'
            elif self.filter_type == FilterWindow.FILTER_TYPES.FOLDER:
                if src.endswith('/'):
                    src = src[:-1]
            
            if os.path.isdir(src):
                in_files = map(lambda name: name.replace('\\', '/'), glob.glob('%s/*.csv' % (src)))
            else:
                in_files = [src]

        else:
            UIUtils.show_message_dialog('Source path does not exist!')
            return

        if dest and os.path.exists(dest):
            dest = dest.replace('\\', '/')
            if dest.endswith('/'):
                dest = dest[:-1]
            out_files = map(lambda name: '%s/%s-noNaps.csv' % (dest, os.path.basename(name)[:-4]), in_files)

        else:
            UIUtils.show_message_dialog('Destination path does not exist!')
            return

        self.window.destroy()
        prog_diag = ProgressDialog(
            title='Processing...',
            phases=['Please Wait']
        )
        prog_diag.show()

        db = BLLDatabase()
        
        for i in range(len(in_files)):
            Naptime.filter_file(db, in_files[i], out_files[i])
            prog_diag.set_fraction(float(i + 1) / float(len(in_files)))
            
        db.close()
        prog_diag.ensure_finish()        
Esempio n. 23
0
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2018/10/10
# @Author  : Wenhao Shan

from utils.enum import Enum

# zk连接状态标签
KazooStatus = Enum(Lost="Kazoo Session Lost",
                   Suspended="Kazoo Not Connected",
                   Conn="Kazoo Connected",
                   ConnFailed="Kazoo Connected Failed")

# zk操作日志标签
ZkControlStatus = Enum(
    Create="Create Node",
    Get="Inquire Node",
    Update="Update Node",
    Delete="Delete Node",
)

Code = Enum(
    EnCode="En_Code Error",
    DeCode="De_Code Error",
)

# Django User Register
DjangoStatus = Enum(
    Register="Zk Register",
    Login="******",
)
Esempio n. 24
0
class StateMachine():
    STATES = Enum('INITIAL SINGLE NUMBERED_MULTI UNNUMBERED_MULTI ERROR'.split())
    
    def __init__(self):
        self.single = []
        self.numbered_multi = []
        self.unnumbered_multi = []

        self.state = StateMachine.STATES.INITIAL
        self._container = None

    def drive(self, utter):
        if self.state != StateMachine.STATES.ERROR:
            {
                StateMachine.STATES.INITIAL: self._state_initial,
                StateMachine.STATES.SINGLE: self._state_single,
                StateMachine.STATES.NUMBERED_MULTI: self._state_numbered_multi,
                StateMachine.STATES.UNNUMBERED_MULTI: self._state_unnumbered_multi,
                }[self.state](utter)

    def _state_initial(self, utter):
        if utter.is_dot_split and False:
            self.single.append([utter])
            #self._print_container(self.single)
            
        elif not utter.is_dot_split or True:
            self._container = [utter]
            self.state = StateMachine.STATES.SINGLE

        # else:
        #     self.state = StateMachine.STATES.ERROR

    def _state_single(self, utter):
        if utter.is_dot_split and False:
            self.single.append(self._container)
            #self._print_container(self.single)
            self.single.append([utter])
            #self._print_container(self.single)
            self._container = None
            self.state = StateMachine.STATES.INITIAL
            
        elif (utter.start == self._container[0].start and
            utter.end == self._container[0].end):
            self._container.append(utter)
            if utter.speaker:
                self.state = StateMachine.STATES.NUMBERED_MULTI
            else:
                self.state = StateMachine.STATES.UNNUMBERED_MULTI

        elif (utter.start != self._container[0].start or
              utter.end != self._container[0].end):
            self.single.append(self._container)
            #self._print_container(self.single)
            self._container = [utter]

        else:
            self.state = StateMachine.STATES.ERROR

    def _state_numbered_multi(self, utter):
        if (utter.start == self._container[-1].start and
            utter.end == self._container[-1].end):
            if utter.is_dot_split and False:
                self.state = StateMachine.STATES.ERROR
            else:
                self._container.append(utter)

        elif (utter.start != self._container[-1].start or
            utter.end != self._container[-1].end):
            if utter.is_dot_split and False:
                self.numbered_multi.append(self._container)
                #self._print_container(self.numbered_multi)
                self.single.append([utter])
                #self._print_container(self.single)
                self._container = None
                self.state = StateMachine.STATES.INITIAL
            else:
                self.numbered_multi.append(self._container)
                #self._print_container(self.numbered_multi)
                self._container = [utter]
                self.state = StateMachine.STATES.SINGLE

        else:
            self.state = StateMachine.STATES.ERROR

    def _state_unnumbered_multi(self, utter):
        if (utter.start == self._container[-1].start and
            utter.end == self._container[-1].end):
            self._container.append(utter)
            if utter.speaker:
                self.state = StateMachine.STATES.NUMBERED_MULTI

        elif (utter.start != self._container[-1].start or
            utter.end != self._container[-1].end):
            if utter.is_dot_split and False:
                self.numbered_multi.append(self._container)
                #self._print_container(self.numbered_multi)
                self.single.append([utter])
                #self._print_container(self.single)
                self._container = None
                self.state = StateMachine.STATES.INITIAL
            else:
                self.numbered_multi.append(self._container)
                #self._print_container(self.numbered_multi)
                self._container = [utter]
                self.state = StateMachine.STATES.SINGLE

        else:
            self.state = StateMachine.STATES.ERROR

    def finish(self):
        if self.state == StateMachine.STATES.SINGLE:
            self.single.append(self._container)
            #self._print_container(self.single)
        elif self.state == StateMachine.STATES.NUMBERED_MULTI:
            self.numbered_multi.append(self._container)
            #self._print_container(self.numbered_multi)
        elif self.state == StateMachine.STATES.UNNUMBERED_MULTI:
            self.unnumbered_multi.append(self._container)
            #self._print_container(self.unnumbered_multi)

    def _print_container(self, array):
        array_name = '?'
        if array == self.single:
            array_name = 'single'
        elif array == self.numbered_multi:
            array_name = 'numbered_multi'
        elif array == self.unnumbered_multi:
            array_name = 'unnumbered_multi'
        
        container = array[-1]
        container_str = '%s - [' % (array_name)
        for i in range(len(container)):
            speaker = container[i].speaker.speaker_codeinfo.code if container[i].speaker else 'None'
            time_range = '%s-%s' % ( get_time_str(container[i].start), get_time_str(container[i].end) )
            trans_phrase = container[i].trans_phrase if container[i].trans_phrase else 'None'
            container_str += '%s:%s;%s' % (speaker, time_range, trans_phrase)
            if i < len(container) - 1:
                container_str += ', '
        container_str += ']'

        print container_str
Esempio n. 25
0
    def _get_speaker_types_enum(self):
        rows = self.select('speaker_types', 'id code_name'.split())
        ids, code_names = zip(*rows)

        return Enum(code_names, ids)
Esempio n. 26
0
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2018/11/23
# @Author  : Wenhao Shan

from utils.enum import Enum

WebErr = Enum(PostErr="Only POST Request allowed", )

WebResp = Enum(
    ActionErr=1,
    ActionSuccess=0,
)

WebReq = Enum(
    ModifyAct="Modify",
    DeleteAct="Delete",
)
Esempio n. 27
0
LAT_FIELD_NAME = "LAT"
HT_FIELD_NAME = "HT"
ZONE_FIELD_NAME = "ZONE"
TAX_FIELD_NAME = "TAXONOMY"
CNT_FIELD_NAME = "NUM_BLDGS"
AREA_FIELD_NAME = "AREA"
COST_FIELD_NAME = "REPCOST"
GRP_FIELD_NAME = "GROUP"

# names for template files
###########################
FILE_PROJ_TEMPLATE = '%s/data/bsddb.template' % get_app_dir()

# enumerations
########################### input data related
FootprintTypes = Enum("None", "FootprintHt", "Footprint")
ZonesTypes = Enum("None", "Landuse", "LanduseCount")
SurveyTypes = Enum("None", "CompleteSurvey", "SampledSurvey")
OutputTypes = Enum("Zone", "Grid")
PopGridTypes = Enum("None", "Grid")
ExportTypes = Enum("Shapefile", "KML", "NRML", "CSV")
MSExportTypes = Enum("XML", "CSV")
SyncModes = Enum("Read", "Write")

# project related
ProjectStatus = Enum('NotVerified', 'ReadyForExposure', 'ReadyForMS')
# processing options
ExtrapolateOptions = Enum('RandomWalk', 'Fraction', 'FractionRounded')

# exception constants
ProjectErrors = Enum("FileNotSet", "FileFormatError")
Esempio n. 28
0
class FilterManager(object):
    #Used to indicate the beginning or end of a chain
    ENDPOINT_TYPES = Enum('HEAD TAIL'.split(), ['prev', 'next'])

    ## Constructor
    #  @param self
    #  @param segs (list) list of Segment objects
    def __init__(self, segs):
        self.segs = segs        #list of all segments
        self.chains = None      #list containing the heads of chains that have been parsed from self.segs (see get_chains() for how this is done) - this is build upon request
        self.seg_index = None   #dictionary that allows fast access (via segment number) to individual segments in self.segs - built upon request
        self.chain_index = None #dictionary that allows fast access (via the head utterance's id) to individual utterances in self.chains - built upon request

    ## Retreives a list of all of the segments in this FilterManager
    #  @param self
    #  @returns (list) list of Segments
    def get_segs(self):
        return self.segs

    ## Retreives a list of all of the chains in this FilterManager
    #  @param self
    #  @returns (list) list containing Utterance objects - each element is the head of a chain. Chains are parsed from the segs element of the constructor - see get_chains() for how this is done.
    def get_chains(self):
        #'cache' the chains so we don't have to parse them again if this method is called in the future
        if not self.chains:
            self.chains = FilterManager.get_chains(self.segs)

        return self.chains

    ## Retreives a segment by segment number (Segment class's 'num' attribute).
    #  Note: this number is unique to all Segments parsed by the TRSParser class <em>for a single file.</em>
    #  @param self
    #  @param num (int) the segment number to lookup
    #  @returns (Segment) the Segment with the requested number, or None if not found.
    def get_seg_by_num(self, num):
        #use a dictionary to provide a basic index/cache mechanism to speed up future lookups
        if not self.seg_index:
            self.seg_index = {}
            for seg in self.segs:
                self.seg_index[seg.num] = seg

        result = None
        if num in self.seg_index:
            result = self.seg_index[num]
            
        return result

    ## Retreives a chain by the utterance id of the head node (head node is the first Utterance object in the chain)
    #  Note: this number is unique to all Utterances parsed by the TRSParser class <em>for a single file.</em>
    #  @param self
    #  @param num (int) the utterance id to lookup.
    #  @returns (Utterance) the head of the chain, or None if no matching chain was found.
    def get_chain_by_num(self, num):
        #use a dictionary to provide a basic index/cache mechanism to speed up future lookups
        if not self.chain_index:
            self.chain_index = {}
            for cur_head in self.get_chains():
                self.chain_index[cur_head.id] = cur_head

        result = None
        if num in self.chain_index:
            result = self.chain_index[num]

        return result

    ## Retreives a list of chains using the specified list of segments.
    #  The method iterates over all utterances within the specified segments. On each iteration, it follows the 'prev' pointer back to the start of the utterance chain.
    # This means that this method returns a list of (the heads of) all chains have a node that is in the utterance list of one of the specified segments.
    # Steps are taken to ensure that if two utterances lead back to the same head, that head is only included once in the returned list (duplicate heads are discarded).
    # The list that is returned is sorted ascending by the start time of the head nodes.
    #  @param segs (list) list of Segments
    #  @returns (list) list of the (unique) head nodes (utterance objects) of all chains found. The list is sorted in ascending order by the start time of the head utterances.
    @staticmethod
    def get_chains(segs):
        #Note: we use an OrderedDict here to address cases where we have two identical start times.
        #If we used a regular dict in these cases, the ordering sometimes swaps. This appears strange to the user because
        #when clicking the 'Group Linked Segments' checkbox, the ordering changes even when there are no chained utterances
        #in the list.
        #The swap that occurs in these cases is not due to the sort (according to the python docs it's guarenteed to be stable) - it's
        #due to the order that the keys are retreived from the dictionary.
        #Using an OrderedDict causes the keys to be retreived in the same order they were inserted.
        heads = OrderedDict()
        for seg in segs:
            for utter in seg.utters:
                cur = utter
                prev = cur
                while cur != None:
                    prev = cur
                    cur = cur.prev

                heads[prev] = True #dictionary weeds out duplicates

        result = heads.keys()
        result.sort(key=lambda cur_utter: cur_utter.start)
        
        return result
        
    ## Constructs a string containing the transcription phrases or all utterances in a given chain.
    #  @param head (Utterance) the Utterance object at the head of the chain
    #  @returns (string) a string containing the transcription phrases of all nodes in the chain, separated by an arrow (' -> ')
    @staticmethod
    def get_chain_phrase(head):
        result = ''
        cur =  head
        prev = head
        while cur:
            result += cur.trans_phrase

            prev = cur
            cur = cur.next
            if cur:
                result += '\n -> '

        return result, prev

    @staticmethod
    def get_chain_lena_speakers(head):
        result = ''
        cur =  head
        prev = head
        while cur:
            if cur.speaker and cur.speaker.speaker_codeinfo:
                result += cur.speaker.speaker_codeinfo.code
            else:
                result += '?'

            prev = cur
            cur = cur.next
            if cur:
                result += '\n -> '

        return result, prev

    @staticmethod
    def get_chain_trans_codes(head):
        result = ''
        cur =  head
        prev = head
        while cur:
            result += '|%s|' % ('|'.join(cur.trans_codes)) if cur.trans_codes else 'None'

            prev = cur
            cur = cur.next
            if cur:
                result += '\n -> '

        return result, prev

    ## Finds the start/end node of a chain.
    #  @param endpoint_type (int) a member of the enum FilterManager.ENDPOINT_TYPES, indicating whether we're searching for the start or end of the chain
    #  @param utter (Utterance) any utterance in the chain
    #  @returns (Utterance) the start or end node of the chain, as specified by the 'endpoint_type' parameter
    @staticmethod
    def get_endpoint(endpoint_type, utter):
        cur = utter
        while getattr(cur, endpoint_type) != None:
            cur = getattr(cur, endpoint_type)
            
        return cur