Пример #1
0
def collect_traceback(tb, output=True, submit=False):
    """Collects traceback which might be submitted
    @output: if it is to be printed
    @submit: if it is to be submitted immediately
    """
    _tracebacks.append(tb)
    if output:
        traceback.print_exception(*tb)

    if has_raven and not is_developer_mode():  # pragma no cover
        extra = collect_report()
        extra.pop("tracebacks")

        sentry_url = os.environ.get(
            "STOQ_SENTRY_URL",
            ("https://*****:*****@sentry.stoq.com.br/4"),
        )
        client = raven.Client(sentry_url, release=stoq.version)

        # Don't sent logs to sentry
        if "log" in extra:
            del extra["log"]
        if "log_name" in extra:
            del extra["log_name"]

        tags = {}
        for name in [
            "architecture",
            "cnpj",
            "system",
            "app_name",
            "bdist_type",
            "app_version",
            "distribution",
            "python_version",
            "psycopg_version",
            "pygtk_version",
            "gtk_version",
            "kiwi_version",
            "reportlab_version",
            "stoqdrivers_version",
            "postgresql_version",
        ]:
            value = extra.pop(name, None)
            if value is None:
                continue

            tags[name] = value

        client.captureException(tb, tags=tags, extra=extra)

    if is_developer_mode() and submit:
        rs = ReportSubmitter()
        r = rs.submit()
        r.get_response()
Пример #2
0
def collect_traceback(tb, output=True, submit=False):
    """Collects traceback which might be submitted
    @output: if it is to be printed
    @submit: if it is to be submitted immediately
    """
    _tracebacks.append(tb)
    if output:
        traceback.print_exception(*tb)

    if has_raven and not is_developer_mode():  # pragma no cover
        extra = collect_report()
        extra.pop('tracebacks')

        sentry_url = os.environ.get(
            'STOQ_SENTRY_URL',
            ('http://*****:*****@sentry.stoq.com.br/4'))
        sentry_args = {}
        if 'app_version' in sentry_args:
            sentry_args['release'] = sentry_args['app_version']
        client = raven.Client(sentry_url, **sentry_args)

        # Don't sent logs to sentry
        if 'log' in extra:
            del extra['log']
        if 'log_name' in extra:
            del extra['log_name']

        tags = {}
        for name in ['architecture', 'cnpj', 'system', 'app_name', 'bdist_type',
                     'app_version', 'distribution', 'python_version',
                     'psycopg_version', 'pygtk_version', 'gtk_version',
                     'kiwi_version', 'reportlab_version',
                     'stoqdrivers_version', 'postgresql_version']:
            value = extra.pop(name, None)
            if value is None:
                continue

            if isinstance(value, (tuple, list)):
                chr_ = '.' if name.endswith('_version') else ' '
                value = chr_.join(str(v) for v in value)

            tags[name] = value

        client.captureException(tb, tags=tags, extra=extra)

    if is_developer_mode() and submit:
        report()
Пример #3
0
    def _prepare_logfiles(self):
        from stoqlib.lib.osutils import get_application_dir

        stoqdir = get_application_dir("stoq")
        log_dir = os.path.join(stoqdir, 'logs', time.strftime('%Y'),
                               time.strftime('%m'))
        if not os.path.exists(log_dir):
            os.makedirs(log_dir)

        filename = 'stoq_%s.%s.log' % (time.strftime('%Y-%m-%d_%H-%M-%S'), os.getpid())
        self._log_filename = os.path.join(log_dir, filename)

        from kiwi.log import set_log_file
        self._stream = set_log_file(self._log_filename, 'stoq*')

        if platform.system() != 'Windows':
            link_file = os.path.join(stoqdir, 'stoq.log')
            if os.path.exists(link_file):
                os.unlink(link_file)
            os.symlink(self._log_filename, link_file)

        # We want developers to see deprecation warnings.
        from stoqlib.lib.environment import is_developer_mode
        if is_developer_mode() and not self._options.quiet:
            import warnings
            if self._options.non_fatal_warnings:
                action = "default"
            else:
                action = "error"
            warnings.filterwarnings(
                action, category=DeprecationWarning,
                module="^(stoq|kiwi)")
Пример #4
0
    def version(self, store, app_version):
        """Fetches the latest version
        :param store: a store
        :param app_version: application version
        :returns: a deferred with the version_string as a parameter
        """
        try:
            bdist_type = library.bdist_type
        except Exception:
            bdist_type = None

        if os.path.exists(os.path.join('etc', 'init.d', 'stoq-bootstrap')):
            source = 'livecd'
        elif bdist_type in ['egg', 'wheel']:
            source = 'pypi'
        elif is_developer_mode():
            source = 'devel'
        else:
            source = 'ppa'

        params = {
            'hash': sysparam.get_string('USER_HASH'),
            'demo': sysparam.get_bool('DEMO_MODE'),
            'dist': platform.dist(),
            'cnpj': get_main_cnpj(store),
            'plugins': InstalledPlugin.get_plugin_names(store),
            'product_key': get_product_key(),
            'time': datetime.datetime.today().isoformat(),
            'uname': platform.uname(),
            'version': app_version,
            'source': source,
        }
        params.update(self._get_company_details(store))
        params.update(self._get_usage_stats(store))
        return self._do_request('GET', 'version.json', **params)
Пример #5
0
    def _prepare_logfiles(self):
        from stoqlib.lib.osutils import get_application_dir

        stoqdir = get_application_dir("stoq")
        log_dir = os.path.join(stoqdir, 'logs', time.strftime('%Y'),
                               time.strftime('%m'))
        if not os.path.exists(log_dir):
            os.makedirs(log_dir)

        self._log_filename = os.path.join(log_dir, 'stoq_%s.log' %
                                          time.strftime('%Y-%m-%d_%H-%M-%S'))

        from kiwi.log import set_log_file
        self._stream = set_log_file(self._log_filename, 'stoq*')

        if hasattr(os, 'symlink'):
            link_file = os.path.join(stoqdir, 'stoq.log')
            if os.path.exists(link_file):
                os.unlink(link_file)
            os.symlink(self._log_filename, link_file)

        # We want developers to see deprecation warnings.
        from stoqlib.lib.environment import is_developer_mode
        if is_developer_mode():
            import warnings
            warnings.filterwarnings(
                "default", category=DeprecationWarning,
                module="^(stoq|kiwi)")
Пример #6
0
    def _prepare_logfiles(self):
        from stoqlib.lib.osutils import get_application_dir

        stoqdir = get_application_dir("stoq")
        log_dir = os.path.join(stoqdir, 'logs', time.strftime('%Y'),
                               time.strftime('%m'))
        if not os.path.exists(log_dir):
            os.makedirs(log_dir)

        filename = 'stoq_%s.%s.log' % (time.strftime('%Y-%m-%d_%H-%M-%S'),
                                       os.getpid())
        self._log_filename = os.path.join(log_dir, filename)

        from kiwi.log import set_log_file
        self._stream = set_log_file(self._log_filename, 'stoq*')

        if hasattr(os, 'symlink'):
            link_file = os.path.join(stoqdir, 'stoq.log')
            if os.path.exists(link_file):
                os.unlink(link_file)
            os.symlink(self._log_filename, link_file)

        # We want developers to see deprecation warnings.
        from stoqlib.lib.environment import is_developer_mode
        if is_developer_mode():
            import warnings
            if self._options.non_fatal_warnings:
                action = "default"
            else:
                action = "error"
            warnings.filterwarnings(action,
                                    category=DeprecationWarning,
                                    module="^(stoq|kiwi)")
Пример #7
0
    def _setup_widgets(self):
        self.set_ok_label(_(u'Activate'), gtk.STOCK_APPLY)
        self.ok_button.set_sensitive(False)
        plugins = []

        for name in sorted(self._manager.available_plugins_names):
            # FIXME: Remove when magento plugin is functional for end users
            if not is_developer_mode() and name == 'magento':
                continue
            if platform.system() == 'Windows':
                if name in ['ecf', 'tef']:
                    continue

            desc = self._manager.get_description_by_name(name)
            plugins.append(
                _PluginModel(name, name
                             in self._manager.installed_plugins_names, desc))

        self.klist = ObjectList(self._get_columns(), plugins,
                                gtk.SELECTION_BROWSE)
        self.klist.set_headers_visible(False)
        self.klist.connect("selection-changed",
                           self._on_klist__selection_changed)
        self.main.remove(self.main.get_child())
        self.main.add(self.klist)
        self.klist.show()
Пример #8
0
    def cmd_updateschema(self, options):
        """Update the database schema"""
        from stoqlib.database.migration import StoqlibSchemaMigration
        from stoqlib.lib.environment import is_developer_mode
        from stoqlib.net.server import ServerProxy

        self._read_config(options, check_schema=False, load_plugins=False,
                          register_station=False)

        # This is a little bit tricky to be able to apply the initial
        # plugin infrastructure
        migration = StoqlibSchemaMigration()

        if is_developer_mode():
            backup = False
        else:
            backup = options.disable_backup

        server = ServerProxy()
        running = server.check_running()
        if running:
            server.call('pause_tasks')

        try:
            retval = migration.update(backup=backup)
        finally:
            # The schema was upgraded. If it was running before,
            # restart it so it can load the new code
            if running:
                server.call('restart')

        return 0 if retval else 1
Пример #9
0
    def cmd_updateschema(self, options):
        """Update the database schema"""
        from stoqlib.database.migration import StoqlibSchemaMigration
        from stoqlib.lib.environment import is_developer_mode
        from stoqlib.net.server import ServerProxy

        self._read_config(options,
                          check_schema=False,
                          load_plugins=False,
                          register_station=False)

        # This is a little bit tricky to be able to apply the initial
        # plugin infrastructure
        migration = StoqlibSchemaMigration()

        if is_developer_mode():
            backup = False
        else:
            backup = options.disable_backup

        server = ServerProxy()
        running = server.check_running()
        if running:
            server.call('pause_tasks')

        try:
            retval = migration.update(backup=backup)
        finally:
            # The schema was upgraded. If it was running before,
            # restart it so it can load the new code
            if running:
                server.call('restart')

        return 0 if retval else 1
Пример #10
0
    def _setup_widgets(self):
        self.set_ok_label(_(u'Activate'), gtk.STOCK_APPLY)
        self.ok_button.set_sensitive(False)
        plugins = []

        for name in sorted(self._manager.available_plugins_names):
            # FIXME: Remove when magento plugin is functional for end users
            if not is_developer_mode() and name == 'magento':
                continue
            if platform.system() == 'Windows':
                if name in ['ecf', 'tef']:
                    continue

            desc = self._manager.get_description_by_name(name)
            plugins.append(_PluginModel(name, name in
                                        self._manager.installed_plugins_names,
                                        desc))

        self.klist = ObjectList(self._get_columns(), plugins,
                                gtk.SELECTION_BROWSE)
        self.klist.set_headers_visible(False)
        self.klist.connect("selection-changed",
                           self._on_klist__selection_changed)
        self.main.remove(self.main.get_child())
        self.main.add(self.klist)
        self.klist.show()
Пример #11
0
    def create_actions(self):
        group = get_accels('app.maintenance')
        actions = [
            # File
            ("OrderMenu", None, _(u"Order")),
            ("NewOrder", None, _(u"Work order..."), group.get("new_order")),
            ("SendOrders", None, _(u"Send orders...")),
            ("ReceiveOrders", None, _(u"Receive orders...")),

            # Search
            ("Products", None, _(u"Products..."), group.get("search_products")
             ),
            ("Services", None, _(u"Services..."),
             group.get("search_services")),
            ("Categories", None, _(u"Categories..."),
             group.get("search_categories")),
            ("Clients", STOQ_CLIENTS, _(u"Clients..."),
             group.get("search_clients")),

            # Order
            ("Edit", gtk.STOCK_EDIT, _(u"Edit..."), group.get('order_edit'),
             _(u"Edit the selected order")),
            ("Finish", gtk.STOCK_APPLY, _(u"Finish..."),
             group.get('order_finish'), _(u"Finish the selected order")),
            ("Cancel", gtk.STOCK_CANCEL, _(u"Cancel..."),
             group.get('order_cancel'), _(u"Cancel the selected order")),
            ("Details", gtk.STOCK_INFO, _(u"Details..."),
             group.get('order_details'),
             _(u"Show details of the selected order")),
            ("PrintQuote", None, _(u"Print quote..."),
             group.get('order_print_quote'),
             _(u"Print a quote report of the selected order")),
            ("PrintReceipt", None, _(u"Print receipt..."),
             group.get('order_print_receipt'),
             _(u"Print a receipt of the selected order")),
        ]
        self.maintenance_ui = self.add_ui_actions("",
                                                  actions,
                                                  filename="maintenance.xml")

        radio_actions = [
            ('ViewKanban', '', _("View as Kanban"), '',
             _("Show in Kanban mode")),
            ('ViewList', '', _("View as List"), '', _("Show in list mode")),
        ]
        self.add_ui_actions('', radio_actions, 'RadioActions', 'radio')

        if is_developer_mode():
            self.ViewList.props.active = True
        else:
            self.ViewList.props.visible = False
            self.ViewKanban.props.visible = False
        self.Edit.set_short_label(_(u"Edit"))
        self.Finish.set_short_label(_(u"Finish"))
        self.Edit.props.is_important = True
        self.Finish.props.is_important = True

        self.set_help_section(_(u"Maintenance help"), 'app-maintenance')
        self.popup = self.uimanager.get_widget('/MaintenanceSelection')
Пример #12
0
 def setup_device_port_combo(self):
     items = [(_("Choose..."), None)]
     items.extend([(unicode(device.device_name), unicode(device.device_name))
                   for device in self._device_manager.get_serial_devices()])
     if is_developer_mode():
         # Include virtual port for virtual printer
         items.append(('Virtual device', u'/dev/null'))
     self.device_combo.prefill(items)
Пример #13
0
def collect_traceback(tb, output=True, submit=False):
    """Collects traceback which might be submitted
    @output: if it is to be printed
    @submit: if it is to be submitted immediately
    """
    _tracebacks.append(tb)
    if output:
        traceback.print_exception(*tb)

    if has_raven and not is_developer_mode():  # pragma no cover
        extra = collect_report()
        extra.pop('tracebacks')

        sentry_url = os.environ.get(
            'STOQ_SENTRY_URL',
            ('https://*****:*****@sentry.stoq.com.br/4'))
        client = raven.Client(sentry_url, release=stoq.version)
        if hasattr(client, 'user_context'):
            client.user_context({'id': extra.get('hash', None),
                                 'username': extra.get('cnpj', None)})

        # Don't sent logs to sentry
        if 'log' in extra:
            del extra['log']
        if 'log_name' in extra:
            del extra['log_name']

        tags = {}
        for name in ['architecture', 'cnpj', 'system', 'app_name', 'bdist_type',
                     'app_version', 'distribution', 'python_version',
                     'psycopg_version', 'pygtk_version', 'gtk_version',
                     'kiwi_version', 'reportlab_version',
                     'stoqdrivers_version', 'postgresql_version']:
            value = extra.pop(name, None)
            if value is None:
                continue

            tags[name] = value

        client.captureException(tb, tags=tags, extra=extra)

    if is_developer_mode() and submit:
        rs = ReportSubmitter()
        r = rs.submit()
        r.get_response()
Пример #14
0
def collect_traceback(tb, output=True, submit=False):
    """Collects traceback which might be submitted
    @output: if it is to be printed
    @submit: if it is to be submitted immediately
    """
    _tracebacks.append(tb)
    if output:
        traceback.print_exception(*tb)

    if has_raven and not is_developer_mode():  # pragma no cover
        sentry_url = os.environ.get(
            'STOQ_SENTRY_URL',
            ('http://*****:*****@sentry.stoq.com.br/4'))
        client = raven.Client(sentry_url)

        extra = collect_report()
        extra.pop('tracebacks')

        # Don't sent logs to sentry
        if 'log' in extra:
            del extra['log']
        if 'log_name' in extra:
            del extra['log_name']

        tags = {}
        for name in ['architecture', 'cnpj', 'system', 'app_name',
                     'app_version', 'distribution', 'python_version',
                     'psycopg_version', 'pygtk_version', 'gtk_version',
                     'kiwi_version', 'reportlab_version',
                     'stoqdrivers_version', 'postgresql_version']:
            value = extra.pop(name, None)
            if value is None:
                continue

            if isinstance(value, (tuple, list)):
                chr_ = '.' if name.endswith('_version') else ' '
                value = chr_.join(str(v) for v in value)

            tags[name] = value

        client.captureException(tb, tags=tags, extra=extra)

    if is_developer_mode() and submit:
        report()
Пример #15
0
    def _try_show_html(self, data):
        if not data:
            return
        if not '<html>' in data:
            return
        if not is_developer_mode():
            return

        from stoqlib.gui.widgets.webview import show_html
        show_html(data)
Пример #16
0
    def __eq__(self, other):
        if type(self) is not type(other):
            return False

        from stoqlib.lib.environment import is_developer_mode
        if is_developer_mode():
            # Check this only in develper mode to get as many potential errors
            # as possible.
            assert Store.of(self) is Store.of(other)
        return self.id == other.id
Пример #17
0
    def __eq__(self, other):
        if type(self) is not type(other):
            return False

        from stoqlib.lib.environment import is_developer_mode
        if is_developer_mode():
            # Check this only in develper mode to get as many potential errors
            # as possible.
            assert Store.of(self) is Store.of(other)
        return self.id == other.id
Пример #18
0
    def _populate_serial_ports(self):
        values = []
        for device in DeviceManager.get_serial_devices():
            values.append(device.device_name)
        if not self.model.device_name in values:
            values.append(self.model.device_name)
        if sysparam.get_bool('DEMO_MODE') or is_developer_mode():
            values.append(u'/dev/null')

        self.device_name.prefill(values)
Пример #19
0
    def _try_show_html(self, data):
        if not data:
            return
        if not '<html>' in data:
            return
        if not is_developer_mode():
            return

        from stoqlib.gui.widgets.webview import show_html
        show_html(data)
Пример #20
0
 def _get_supported_types(self):
     if self.model.type == DeviceSettings.SCALE_DEVICE:
         supported_types = get_supported_scales()
     #elif self.model.type == DeviceSettings.CHEQUE_PRINTER_DEVICE:
     #    supported_types = get_supported_printers_by_iface(IChequePrinter)
     elif self.model.type == DeviceSettings.NON_FISCAL_PRINTER_DEVICE:
         supported_types = get_supported_printers_by_iface(INonFiscalPrinter,
                                                           include_virtual=is_developer_mode())
     else:
         raise TypeError("The selected device type isn't supported")
     return supported_types
Пример #21
0
 def _get_supported_types(self):
     if self.model.type == DeviceSettings.SCALE_DEVICE:
         supported_types = get_supported_scales()
     #elif self.model.type == DeviceSettings.CHEQUE_PRINTER_DEVICE:
     #    supported_types = get_supported_printers_by_iface(IChequePrinter)
     elif self.model.type == DeviceSettings.NON_FISCAL_PRINTER_DEVICE:
         supported_types = get_supported_printers_by_iface(INonFiscalPrinter,
                                                           include_virtual=is_developer_mode())
     else:
         raise TypeError("The selected device type isn't supported")
     return supported_types
Пример #22
0
    def __init__(self, port=None):
        threading.Thread.__init__(self)

        self.port = port
        if self.port is None and is_developer_mode():
            self.port = 8080
        # Indicate that this Thread is a daemon. Accordingly to the
        # documentation, the entire python program exits when no alive
        # non-daemon threads are left.
        self.daemon = True
        self.running = False
Пример #23
0
def run_flaskserver(port, debug=False, multiclient=False):
    from stoqlib.lib.environment import configure_locale
    # Force pt_BR for now.
    configure_locale('pt_BR')

    global is_multiclient
    is_multiclient = multiclient

    from .workers import WORKERS
    # For now we're disabling workers when stoqserver is serving multiple clients (multiclient mode)
    # FIXME: a proper solution would be to modify the workflow so that the clients ask the server
    # about devices health, the till status, etc. instead of the other way around.
    if not is_multiclient:
        for function in WORKERS:
            gevent.spawn(function, get_current_station(api.get_default_store()))

    try:
        from stoqserver.lib import stacktracer
        stacktracer.start_trace("/tmp/trace-stoqserver-flask.txt", interval=5, auto=True)
    except ImportError:
        pass

    app = bootstrap_app()
    app.debug = debug
    if not is_developer_mode():
        sentry.raven_client = Sentry(app, dsn=SENTRY_URL, client=raven_client)

    @app.after_request
    def after_request(response):
        # Add all the CORS headers the POS needs to have its ajax requests
        # accepted by the browser
        origin = request.headers.get('origin')
        if not origin:
            origin = request.args.get('origin', request.form.get('origin', '*'))
        response.headers['Access-Control-Allow-Origin'] = origin
        response.headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS, DELETE'
        response.headers['Access-Control-Allow-Headers'] = 'Authorization, Content-Type'
        response.headers['Access-Control-Allow-Credentials'] = 'true'
        return response

    from stoqserver.lib.restful import has_sat, has_nfe
    logger.info('Starting wsgi server (has_sat=%s, has_nfe=%s)', has_sat, has_nfe)
    http_server = WSGIServer(('0.0.0.0', port), app, spawn=gevent.spawn_raw, log=logger,
                             error_log=logger)

    if debug:
        gevent.spawn(_gtk_main_loop)

        @run_with_reloader
        def run_server():
            http_server.serve_forever()
        run_server()
    else:
        http_server.serve_forever()
Пример #24
0
    def _prepare_logfiles(self):
        from stoq.lib.logging import setup_logging
        self._log_filename, self.stream = setup_logging("stoq")

        from stoqlib.lib.environment import is_developer_mode
        # We want developers to see deprecation warnings.
        if is_developer_mode():
            import warnings
            warnings.filterwarnings(
                "default", category=DeprecationWarning,
                module="^(stoq|kiwi)")
Пример #25
0
def test_api():
    store = api.get_default_store()

    assert store is get_default_store()
    assert api.get_current_user(store) is get_current_user(store)
    assert api.db_settings is db_settings
    assert api.user_settings is get_settings()
    assert isinstance(api.device_manager, DeviceManager)
    with pytest.raises(NotImplementedError):
        assert isinstance(api.config, IStoqConfig)
    assert api.is_developer_mode() is is_developer_mode()
    assert api.get_l10n_field('CPF') is get_l10n_field('CPF')
Пример #26
0
    def __init__(self, port=None):
        super(Daemon, self).__init__()

        self.port = port
        if self.port is None and is_developer_mode():
            self.port = 8080
        elif self.port is None:
            self.port = get_random_port()
        # Indicate that this Thread is a daemon. Accordingly to the
        # documentation, the entire python program exits when no alive
        # non-daemon threads are left.
        self.daemon = True
Пример #27
0
def collect_traceback(tb, output=True, submit=False):
    """Collects traceback which might be submitted
    @output: if it is to be printed
    @submit: if it is to be submitted immediately
    """
    _tracebacks.append(tb)

    if output:
        traceback.print_exception(*tb)

    if is_developer_mode() and submit:
        report()
Пример #28
0
def collect_traceback(tb, output=True, submit=False):
    """Collects traceback which might be submitted
    @output: if it is to be printed
    @submit: if it is to be submitted immediately
    """
    _tracebacks.append(tb)

    if output:
        traceback.print_exception(*tb)

    if is_developer_mode() and submit:
        report()
Пример #29
0
    def _check_parent_running(self):
        # When developing, we usually kill stoq a lot with something that
        # will not allow it to stop the daemon (e.g. ctrl+q, ctrl+4) so
        # it is better to do the check every 1 second. On production this
        # shouldn't happen often, but if it happens, it is ok to have it
        # running for another 5 seconds.
        sleep_time = 1 if is_developer_mode() else 5

        while self.is_alive():
            # If the parent dies, ppid will change. In this case,
            # finalize this process. It shouldn't be running anymore.
            if os.getppid() != self._ppid:
                os._exit(0)
            time.sleep(sleep_time)
Пример #30
0
    def setup_device_port_combo(self):
        items = [(_("Choose..."), None)]
        items.extend([(str(device.device_name), str(device.device_name))
                      for device in DeviceManager.get_serial_devices()])
        items.extend(self._get_usb_devices())

        if is_developer_mode():
            # Include virtual port for virtual printer
            items.append(('Virtual device', u'/dev/null'))

        devices = [i[1] for i in items]
        if self.model.device_name not in devices:
            items.append(('Unkown device (%s)' % self.model.device_name,
                          self.model.device_name))
        self.device_combo.prefill(items)
Пример #31
0
    def _populate_printers(self):
        supported_ifaces = get_supported_printers_by_iface(ICouponPrinter).items()
        printers = []
        for brand, printer_classes in supported_ifaces:
            for printer_class in printer_classes:
                printer = _PrinterModel(brand, printer_class)
                printers.append((printer.get_description(), printer))

        # Allow to use virtual printer for both demo mode and developer mode
        # so it's easier for testers and developers to test ecf functionality
        if sysparam.get_bool('DEMO_MODE') or is_developer_mode():
            from stoqdrivers.printers.virtual.Simple import Simple
            printer = _PrinterModel('virtual', Simple)
            printers.append((printer.get_description(), printer))

        self.printer.prefill(locale_sorted(
            printers, key=operator.itemgetter(0)))
Пример #32
0
    def _populate_printers(self):
        supported_ifaces = get_supported_printers_by_iface(ICouponPrinter).items()
        printers = []
        for brand, printer_classes in supported_ifaces:
            for printer_class in printer_classes:
                printer = _PrinterModel(brand, printer_class)
                printers.append((printer.get_description(), printer))

        # Allow to use virtual printer for both demo mode and developer mode
        # so it's easier for testers and developers to test ecf functionality
        if sysparam(self.store).DEMO_MODE or is_developer_mode():
            from stoqdrivers.printers.virtual.Simple import Simple
            printer = _PrinterModel('virtual', Simple)
            printers.append((printer.get_description(), printer))

        self.printer.prefill(locale_sorted(
            printers, key=operator.itemgetter(0)))
Пример #33
0
    def cmd_updateschema(self, options):
        """Update the database schema"""
        from stoqlib.api import api
        from stoqlib.database.migration import StoqlibSchemaMigration
        from stoqlib.lib.environment import is_developer_mode
        from stoqlib.net.server import ServerProxy
        from twisted.internet import reactor

        self._read_config(options,
                          check_schema=False,
                          load_plugins=False,
                          register_station=False)

        # This is a little bit tricky to be able to apply the initial
        # plugin infrastructure
        migration = StoqlibSchemaMigration()

        if is_developer_mode():
            backup = False
        else:
            backup = options.disable_backup

        @api. async
        def migrate(retval):
            server = ServerProxy()
            running = yield server.check_running()
            if running:
                yield server.call('pause_tasks')

            try:
                retval[0] = yield migration.update_async(backup=backup)
            finally:
                # The schema was upgraded. If it was running before,
                # restart it so it can load the new code
                if running:
                    yield server.call('restart')

                if reactor.running:
                    reactor.stop()

        retval = [False]
        reactor.callWhenRunning(migrate, retval)
        reactor.run()

        return 0 if retval[0] else 1
Пример #34
0
    def cmd_updateschema(self, options):
        """Update the database schema"""
        from stoqlib.database.migration import StoqlibSchemaMigration
        from stoqlib.lib.environment import is_developer_mode

        self._read_config(options, check_schema=False, load_plugins=False,
                          register_station=False)

        # This is a little bit tricky to be able to apply the initial
        # plugin infrastructure
        migration = StoqlibSchemaMigration()

        if is_developer_mode():
            backup = False
        else:
            backup = options.disable_backup

        if not migration.update(backup=backup):
            return 1
Пример #35
0
    def _setup_gtk(self):
        from gi.repository import Gtk, Gdk
        from kiwi.environ import environ
        from stoqlib.lib.template import render_template_string

        # Total madness to make sure we can draw treeview lines,
        # this affects the GtkTreeView::grid-line-pattern style property
        #
        # Two bytes are sent in, see gtk_tree_view_set_grid_lines in gtktreeview.c
        # Byte 1 should be as high as possible, gtk+ 0x7F appears to be
        #        the highest allowed for Gtk+ 2.22 while 0xFF worked in
        #        earlier versions
        # Byte 2 should ideally be allowed to be 0, but neither C nor Python
        #        allows that.
        #
        data = environ.get_resource_string("stoq", "misc", "stoq.css")
        data = render_template_string(data)

        style_provider = Gtk.CssProvider()
        style_provider.load_from_data(data)
        Gtk.StyleContext.add_provider_for_screen(
            Gdk.Screen.get_default(), style_provider,
            Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)

        settings = Gtk.Settings.get_default()
        settings.props.gtk_button_images = True

        from stoqlib.lib.environment import is_developer_mode
        if is_developer_mode():
            # Install a Control-Q handler that forcefully exits
            # the program without saving any kind of state
            def event_handler(event):
                state = event.get_state()
                if isinstance(state, tuple):
                    state = state[1]
                if (event.type == Gdk.EventType.KEY_PRESS
                        and state & Gdk.ModifierType.CONTROL_MASK
                        and event.keyval == Gdk.KEY_q):
                    os._exit(0)
                Gtk.main_do_event(event)

            Gdk.event_handler_set(event_handler)
Пример #36
0
    def _setup_gtk(self):
        from gi.repository import Gtk, Gdk
        from kiwi.environ import environ
        from stoqlib.lib.template import render_template_string

        # Total madness to make sure we can draw treeview lines,
        # this affects the GtkTreeView::grid-line-pattern style property
        #
        # Two bytes are sent in, see gtk_tree_view_set_grid_lines in gtktreeview.c
        # Byte 1 should be as high as possible, gtk+ 0x7F appears to be
        #        the highest allowed for Gtk+ 2.22 while 0xFF worked in
        #        earlier versions
        # Byte 2 should ideally be allowed to be 0, but neither C nor Python
        #        allows that.
        #
        data = environ.get_resource_string("stoq", "misc", "stoq.css")
        data = render_template_string(data)

        style_provider = Gtk.CssProvider()
        style_provider.load_from_data(data)
        Gtk.StyleContext.add_provider_for_screen(
            Gdk.Screen.get_default(),
            style_provider,
            Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)

        settings = Gtk.Settings.get_default()
        settings.props.gtk_button_images = True

        from stoqlib.lib.environment import is_developer_mode
        if is_developer_mode():
            # Install a Control-Q handler that forcefully exits
            # the program without saving any kind of state
            def event_handler(event):
                state = event.get_state()
                if isinstance(state, tuple):
                    state = state[1]
                if (event.type == Gdk.EventType.KEY_PRESS and
                        state & Gdk.ModifierType.CONTROL_MASK and
                        event.keyval == Gdk.KEY_q):
                    os._exit(0)
                Gtk.main_do_event(event)
            Gdk.event_handler_set(event_handler)
Пример #37
0
    def version(self, store, app_version, **kwargs):
        """Fetches the latest version

        :param store: a store
        :param app_version: application version
        """
        import stoq
        try:
            bdist_type = library.bdist_type
        except Exception:
            bdist_type = None

        # We should use absolute paths when looking for /etc
        if os.path.exists(
                os.path.join(os.sep, 'etc', 'init.d', 'stoq-bootstrap')):
            source = 'livecd'
        elif stoq.trial_mode:
            source = 'trial'
        elif bdist_type in ['egg', 'wheel']:
            source = 'pypi'
        elif is_developer_mode():
            source = 'devel'
        else:
            source = 'ppa'

        params = {
            'demo': sysparam.get_bool('DEMO_MODE'),
            'dist': ' '.join(platform.dist()),
            'cnpj': get_main_cnpj(store),
            'plugins': ' '.join(InstalledPlugin.get_plugin_names(store)),
            'product_key': get_product_key(),
            'uname': ' '.join(platform.uname()),
            'version': app_version,
            'source': source,
        }
        params.update(self._get_company_details(store))
        params.update(self._get_usage_stats(store))

        endpoint = 'api/stoq/v1/version/%s' % (
            sysparam.get_string('USER_HASH'), )
        return self._do_request('POST', endpoint, json=params, **kwargs)
Пример #38
0
    def _check_version_policy(self):
        # No need to bother version checking when not running in developer mode
        from stoqlib.lib.environment import is_developer_mode
        if not is_developer_mode():
            return

        import stoq

        #
        # Policies for stoq/stoqlib versions,
        # All these policies here are made so that stoqlib version is tightly
        # tied to the stoq versioning
        #

        # We reserve the first 89 for the stable series.
        FIRST_UNSTABLE_MICRO_VERSION = 90

        # Stable series of Stoq must:
        # 1) have extra_version set to < 90
        # 2) Depend on a stoqlib version with extra_version < 90
        #
        if stoq.stable:
            if (stoq.micro_version >= FIRST_UNSTABLE_MICRO_VERSION and
                    not 'rc' in stoq.extra_version):
                # FIXME: Reenable this check for 1.13 series
                pass
                #raise SystemExit(
                #    "Stable stoq release should set micro_version to "
                #    "%d or lower" % (FIRST_UNSTABLE_MICRO_VERSION, ))
        # Unstable series of Stoq must have:
        # 1) have extra_version set to >= 90
        # 2) Must depend stoqlib version with extra_version >= 90
        #
        else:
            if stoq.micro_version < FIRST_UNSTABLE_MICRO_VERSION:
                raise SystemExit(
                    "Unstable stoq (%s) must set micro_version to %d or higher, "
                    "or did you forget to set stoq.stable to True?" % (
                        stoq.version, FIRST_UNSTABLE_MICRO_VERSION))
Пример #39
0
    def version(self, store, app_version, **kwargs):
        """Fetches the latest version

        :param store: a store
        :param app_version: application version
        """
        import stoq
        try:
            bdist_type = library.bdist_type
        except Exception:
            bdist_type = None

        # We should use absolute paths when looking for /etc
        if os.path.exists(os.path.join(os.sep, 'etc', 'init.d', 'stoq-bootstrap')):
            source = 'livecd'
        elif stoq.trial_mode:
            source = 'trial'
        elif bdist_type in ['egg', 'wheel']:
            source = 'pypi'
        elif is_developer_mode():
            source = 'devel'
        else:
            source = 'ppa'

        params = {
            'demo': sysparam.get_bool('DEMO_MODE'),
            'dist': ' '.join(platform.dist()),
            'cnpj': get_main_cnpj(store),
            'plugins': ' '.join(InstalledPlugin.get_plugin_names(store)),
            'product_key': get_product_key(),
            'uname': ' '.join(platform.uname()),
            'version': app_version,
            'source': source,
        }
        params.update(self._get_company_details(store))
        params.update(self._get_usage_stats(store))

        endpoint = 'api/stoq/v1/version/%s' % (sysparam.get_string('USER_HASH'), )
        return self._do_request('POST', endpoint, json=params, **kwargs)
Пример #40
0
    def _setup_gtk(self):
        import gtk
        from kiwi.environ import environ

        gtk.gdk.threads_init()
        # Total madness to make sure we can draw treeview lines,
        # this affects the GtkTreeView::grid-line-pattern style property
        #
        # Two bytes are sent in, see gtk_tree_view_set_grid_lines in gtktreeview.c
        # Byte 1 should be as high as possible, gtk+ 0x7F appears to be
        #        the highest allowed for Gtk+ 2.22 while 0xFF worked in
        #        earlier versions
        # Byte 2 should ideally be allowed to be 0, but neither C nor Python
        #        allows that.
        #
        data = environ.get_resource_string("stoq", "misc", "stoq.gtkrc")
        data = data.replace('\\x7f\\x01', '\x7f\x01')

        gtk.rc_parse_string(data)

        # Creating a button as a temporary workaround for bug
        # https://bugzilla.gnome.org/show_bug.cgi?id=632538, until gtk 3.0
        gtk.Button()
        settings = gtk.settings_get_default()
        settings.props.gtk_button_images = True

        from stoqlib.lib.environment import is_developer_mode
        if is_developer_mode() and gtk.gtk_version[0] == 2:
            from gtk import gdk

            # Install a Control-Q handler that forcefully exits
            # the program without saving any kind of state
            def event_handler(event):
                if (event.type == gdk.KEY_PRESS and
                    event.state & gdk.CONTROL_MASK and
                    event.keyval == gtk.keysyms.q):
                    os._exit(0)
                gtk.main_do_event(event)
            gdk.event_handler_set(event_handler)
Пример #41
0
    def _check_version_policy(self):
        # No need to bother version checking when not running in developer mode
        from stoqlib.lib.environment import is_developer_mode
        if not is_developer_mode():
            return

        import stoq

        #
        # Policies for stoq/stoqlib versions,
        # All these policies here are made so that stoqlib version is tightly
        # tied to the stoq versioning
        #

        # We reserve the first 89 for the stable series.
        FIRST_UNSTABLE_MICRO_VERSION = 90

        # Stable series of Stoq must:
        # 1) have extra_version set to < 90
        # 2) Depend on a stoqlib version with extra_version < 90
        #
        if stoq.stable:
            if (stoq.micro_version >= FIRST_UNSTABLE_MICRO_VERSION
                    and not 'rc' in stoq.extra_version):
                # FIXME: Reenable this check for 1.13 series
                pass
                #raise SystemExit(
                #    "Stable stoq release should set micro_version to "
                #    "%d or lower" % (FIRST_UNSTABLE_MICRO_VERSION, ))
        # Unstable series of Stoq must have:
        # 1) have extra_version set to >= 90
        # 2) Must depend stoqlib version with extra_version >= 90
        #
        else:
            if stoq.micro_version < FIRST_UNSTABLE_MICRO_VERSION:
                raise SystemExit(
                    "Unstable stoq (%s) must set micro_version to %d or higher, "
                    "or did you forget to set stoq.stable to True?" %
                    (stoq.version, FIRST_UNSTABLE_MICRO_VERSION))
Пример #42
0
    def _setup_gtk(self):
        import gtk
        from kiwi.environ import environ

        # Total madness to make sure we can draw treeview lines,
        # this affects the GtkTreeView::grid-line-pattern style property
        #
        # Two bytes are sent in, see gtk_tree_view_set_grid_lines in gtktreeview.c
        # Byte 1 should be as high as possible, gtk+ 0x7F appears to be
        #        the highest allowed for Gtk+ 2.22 while 0xFF worked in
        #        earlier versions
        # Byte 2 should ideally be allowed to be 0, but neither C nor Python
        #        allows that.
        #
        data = environ.get_resource_string("stoq", "misc", "stoq.gtkrc")
        data = data.replace('\\x7f\\x01', '\x7f\x01')

        gtk.rc_parse_string(data)

        # Creating a button as a temporary workaround for bug
        # https://bugzilla.gnome.org/show_bug.cgi?id=632538, until gtk 3.0
        gtk.Button()
        settings = gtk.settings_get_default()
        settings.props.gtk_button_images = True

        from stoqlib.lib.environment import is_developer_mode
        if is_developer_mode() and gtk.gtk_version[0] == 2:
            from gtk import gdk

            # Install a Control-Q handler that forcefully exits
            # the program without saving any kind of state
            def event_handler(event):
                if (event.type == gdk.KEY_PRESS
                        and event.state & gdk.CONTROL_MASK
                        and event.keyval == gtk.keysyms.q):
                    os._exit(0)
                gtk.main_do_event(event)

            gdk.event_handler_set(event_handler)
Пример #43
0
def collect_traceback(tb, output=True, submit=False):
    """Collects traceback which might be submitted
    @output: if it is to be printed
    @submit: if it is to be submitted immediately
    """
    _tracebacks.append(tb)
    if output:
        traceback.print_exception(*tb)

    if "STOQ_SENTRY_URL" in os.environ:
        try:
            from raven import Client

            has_raven = True
        except ImportError:
            has_raven = False

        if has_raven:
            client = Client(os.environ["STOQ_SENTRY_URL"])
            client.captureException(tb)

    if is_developer_mode() and submit:
        report()
Пример #44
0
logger = logging.getLogger(__name__)

_SENTRY_URL = ('http://*****:*****@sentry.stoq.com.br/11')
_LOGGING_FORMAT = '%(asctime)-15s %(name)-35s %(levelname)-8s %(message)s'
_LOGGING_DATE_FORMAT = '%y-%m-%d %H:%M:%S'

try:
    import raven
    _raven_client = raven.Client(_SENTRY_URL)
except ImportError:
    _raven_client = None

# Disable send sentry log if its is_developer_mode
if is_developer_mode():
    _raven_client = None

# Do this as soon as possible so we can log any early traceback
if _raven_client is not None:
    def _excepthook(exctype, value, tb):
        tags = {
            'version': ".".join(str(i) for i in stoqserver.__version__),
            'stoq_version': stoq.version,
            'architecture': platform.architecture(),
            'distribution': platform.dist(),
            'python_version': tuple(sys.version_info),
            'system': platform.system(),
            'uname': platform.uname(),
        }
        # Those are inside a try/except because thy require database access.
Пример #45
0
    def run(self):
        port = 8080 if is_developer_mode() else None
        self._xmlrpc = XMLRPCService(port)
        self._xmlrpc.serve()

        self.port = self._xmlrpc.port
Пример #46
0
 def _start_xmlrpc(self):
     port = None
     if is_developer_mode():
         port = 8080
     self._xmlrpc = XMLRPCService(port)
     self._xmlrpc.serve()
Пример #47
0
 def is_developer_mode(self):
     return is_developer_mode()
Пример #48
0
 def is_developer_mode(self):
     return is_developer_mode()
Пример #49
0
def bootstrap_app(debug=False, multiclient=False):
    app = Flask(__name__)
    app.debug = debug
    app.multiclient = multiclient

    # Indexing some session data by the USER_HASH will help to avoid maintaining
    # sessions between two different databases. This could lead to some errors in
    # the POS in which the user making the sale does not exist.
    app.config['SECRET_KEY'] = get_user_hash()
    app.config['PROPAGATE_EXCEPTIONS'] = True
    app.config['RESTFUL_JSON'] = {
        'cls': JsonEncoder,
    }
    flask_api = Api(app)
    if RequestID:
        RequestID(app)

    register_routes(flask_api)

    signal('StoqTouchStartupEvent').send()

    @app.errorhandler(Exception)
    def unhandled_exception(e):
        traceback_info = "\n".join(traceback.format_tb(e.__traceback__))
        traceback_hash = hashlib.sha1(
            traceback_info.encode('utf-8')).hexdigest()[:8]
        traceback_exception = traceback.format_exception_only(type(e), e)[-1]
        timestamp = localnow().strftime('%Y%m%d-%H%M%S')

        logger.exception(
            'Unhandled Exception: {timestamp} {error} {traceback_hash}'.format(
                timestamp=timestamp, error=e, traceback_hash=traceback_hash))

        sentry_report(type(e),
                      e,
                      e.__traceback__,
                      traceback_hash=traceback_hash)

        return Response(json.dumps({
            'error': _('bad request!'),
            'timestamp': timestamp,
            'exception': traceback_exception,
            'traceback_hash': traceback_hash
        }),
                        500,
                        mimetype='application/json')

    if not is_developer_mode():
        sentry.raven_client = Sentry(app, dsn=SENTRY_URL, client=raven_client)

    @app.after_request
    def after_request(response):
        # Add all the CORS headers the POS needs to have its ajax requests
        # accepted by the browser
        origin = request.headers.get('origin')
        if not origin:
            origin = request.args.get('origin',
                                      request.form.get('origin', '*'))
        response.headers['Access-Control-Allow-Origin'] = origin
        response.headers[
            'Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS, DELETE'
        response.headers[
            'Access-Control-Allow-Headers'] = 'Authorization, Content-Type'
        response.headers['Access-Control-Allow-Credentials'] = 'true'
        return response

    return app
Пример #50
0
 def _start_xmlrpc(self):
     port = None
     if is_developer_mode():
         port = 8080
     self._xmlrpc = XMLRPCService(port)
     self._xmlrpc.serve()
Пример #51
0
def post_ping_request(station):
    if is_developer_mode():
        return

    from .lib.restful import PDV_VERSION
    target = 'https://app.stoq.link:9000/api/ping'
    time_format = '%d-%m-%Y %H:%M:%S%Z'
    store = api.get_default_store()
    plugin_manager = get_plugin_manager()
    boot_time = datetime.datetime.fromtimestamp(
        psutil.boot_time()).strftime(time_format)

    def get_stoq_conf():
        with open(get_config().get_filename(), 'r') as fh:
            return fh.read().encode()

    def get_clisitef_ini():
        try:
            with open('CliSiTef.ini', 'r') as fh:
                return fh.read().encode()
        except FileNotFoundError:
            return ''.encode()

    while True:
        try:
            dpkg_list = subprocess.check_output('dpkg -l \\*stoq\\*',
                                                shell=True).decode()
        except subprocess.CalledProcessError:
            dpkg_list = ""
        stoq_packages = re.findall(r'ii\s*(\S*)\s*(\S*)', dpkg_list)
        if PDV_VERSION:
            logger.info('Running stoq_pdv {}'.format(PDV_VERSION))
        logger.info('Running stoq {}'.format(stoq_version))
        logger.info('Running stoq-server {}'.format(stoqserver_version))
        logger.info('Running stoqdrivers {}'.format(stoqdrivers_version))
        local_time = tzlocal.get_localzone().localize(datetime.datetime.now())

        response = requests.post(
            target,
            headers={
                'Stoq-Backend':
                '{}-portal'.format(api.sysparam.get_string('USER_HASH'))
            },
            data={
                'station_id':
                station.id,
                'data':
                json.dumps({
                    'platform': {
                        'architecture': platform.architecture(),
                        'distribution': platform.dist(),
                        'system': platform.system(),
                        'uname': platform.uname(),
                        'python_version': platform.python_version_tuple(),
                        'postgresql_version': get_database_version(store)
                    },
                    'system': {
                        'boot_time': boot_time,
                        'cpu_times': psutil.cpu_times(),
                        'load_average': os.getloadavg(),
                        'disk_usage': psutil.disk_usage('/'),
                        'virtual_memory': psutil.virtual_memory(),
                        'swap_memory': psutil.swap_memory()
                    },
                    'plugins': {
                        'available':
                        plugin_manager.available_plugins_names,
                        'installed':
                        plugin_manager.installed_plugins_names,
                        'active':
                        plugin_manager.active_plugins_names,
                        'versions':
                        getattr(plugin_manager, 'available_plugins_versions',
                                None)
                    },
                    'running_versions': {
                        'pdv': PDV_VERSION,
                        'stoq': stoq_version,
                        'stoqserver': stoqserver_version,
                        'stoqdrivers': stoqdrivers_version
                    },
                    'stoq_packages':
                    dict(stoq_packages),
                    'local_time':
                    local_time.strftime(time_format),
                    'stoq_conf_md5':
                    md5(get_stoq_conf()).hexdigest(),
                    'clisitef_ini_md5':
                    md5(get_clisitef_ini()).hexdigest()
                })
            })

        logger.info("POST {} {} {}".format(target, response.status_code,
                                           response.elapsed.total_seconds()))
        gevent.sleep(3600)
Пример #52
0
    def create_actions(self):
        group = get_accels('app.maintenance')
        actions = [
            # File
            ("OrderMenu", None, _(u"Order")),
            ("NewOrder", None, _(u"Work order..."),
             group.get("new_order")),
            ("SendOrders", None, _(u"Send orders...")),
            ("ReceiveOrders", None, _(u"Receive orders...")),

            # Search
            ("Products", None, _(u"Products..."),
             group.get("search_products")),
            ("Services", None, _(u"Services..."),
             group.get("search_services")),
            ("Categories", None, _(u"Categories..."),
             group.get("search_categories")),
            ("Clients", STOQ_CLIENTS, _(u"Clients..."),
             group.get("search_clients")),

            # Order
            ("Edit", gtk.STOCK_EDIT, _(u"Edit..."),
             group.get('order_edit'),
             _(u"Edit the selected order")),
            ("Finish", gtk.STOCK_APPLY, _(u"Finish..."),
             group.get('order_finish'),
             _(u"Finish the selected order")),
            ("Cancel", gtk.STOCK_CANCEL, _(u"Cancel..."),
             group.get('order_cancel'),
             _(u"Cancel the selected order")),
            ("DeliverOrder", None, _(u"Delivered...")),
            ("Details", gtk.STOCK_INFO, _(u"Details..."),
             group.get('order_details'),
             _(u"Show details of the selected order")),
            ("PrintQuote", None, _(u"Print quote..."),
             group.get('order_print_quote'),
             _(u"Print a quote report of the selected order")),
            ("PrintReceipt", None, _(u"Print receipt..."),
             group.get('order_print_receipt'),
             _(u"Print a receipt of the selected order")),
            ("Approve", None, _(u"Approve...")),
            ("Pause", None, _(u"Pause the work...")),
            ("Work", None, _(u"Start the work...")),
            ("Reject", None, _(u"Reject order...")),
            ("UndoRejection", None, _(u"Undo order rejection...")),
            ("Reopen", None, _(u"Reopen order...")),
        ]
        self.maintenance_ui = self.add_ui_actions("", actions,
                                                  filename="maintenance.xml")

        radio_actions = [
            ('ViewKanban', '', _("View as Kanban"),
             '', _("Show in Kanban mode")),
            ('ViewList', '', _("View as List"),
             '', _("Show in list mode")),
        ]
        self.add_ui_actions('', radio_actions, 'RadioActions',
                            'radio')

        if is_developer_mode():
            self.ViewList.props.active = True
        else:
            self.ViewList.props.visible = False
            self.ViewKanban.props.visible = False
        self.Edit.set_short_label(_(u"Edit"))
        self.Finish.set_short_label(_(u"Finish"))
        self.Edit.props.is_important = True
        self.Finish.props.is_important = True

        self.set_help_section(_(u"Maintenance help"), 'app-maintenance')
        self.popup = self.uimanager.get_widget('/MaintenanceSelection')