Example #1
0
    def test_doesnt_overwrite_custom_favicons(self):
        custom_favicon = 'fnord'
        project_section = AgiloConfig(self.env).get_section('project')
        project_section.change_option('icon', custom_favicon)
        self.assert_equals(custom_favicon, project_section.get('icon'))

        initialize_config(self.env, {})
        project_section = AgiloConfig(self.env).get_section('project')
        self.assert_equals(custom_favicon, project_section.get('icon'))
Example #2
0
 def test_reload_config(self):
     """Tests the reload of the config"""
     types = AgiloConfig(self.env).get_section(AgiloConfig.AGILO_TYPES)
     
     # Add a ticket type
     types.change_option('my_type', ', '.join([Key.PRIORITY, Key.COMPONENT]))
     types.change_option('my_type.alias', 'My Type')
     types.save()
     self.assert_true('my_type' in AgiloConfig(self.env).ALIASES, 
                      "Type not found in aliases, AgiloConfig not reloaded?")
Example #3
0
    def _hide_fields_not_configured_for_this_type(self, req, data):
        ticket_type = req.args[Key.TYPE]
        ats = AgiloTicketSystem(self.env)
        normalized_type = ats.normalize_type(ticket_type)
        data[Key.TYPE] = normalized_type
        fields_for_type = AgiloConfig(self.env).TYPES.get(normalized_type, [])
        create_perms = CoreTemplateProvider(self.env).create_permissions(req)

        if normalized_type in create_perms:
            for data_field in data['fields']:
                field_name = data_field[Key.NAME]
                if field_name == Key.TYPE:
                    current_options = data_field.get('options', [])
                    data_field['options'] = \
                        self._ticket_types_the_user_can_create_or_modify(normalized_type, current_options, create_perms)
                    data['type_selection'] = data_field
                    data_field[Key.SKIP] = True
                elif not field_name in fields_for_type:
                    # Skip the field and the value if it's not for this type
                    data_field[Key.SKIP] = True
                elif data_field[Key.SKIP] and (field_name
                                               not in MANDATORY_FIELDS):
                    # We have to make all fields visible which belong to
                    # this ticket type. Unfortunately, Trac just creates
                    # a Ticket (though an AgiloTicket due to our monkey
                    # patching) and we can't influence the instantiation
                    # itself.
                    # Therefore it just depends on the default ticket type
                    # set in the environment what fields this ticket has.
                    # Therefore some fields are marked skipped although they
                    # should be displayed.
                    # trac itself skips some fields because it want to have
                    # more control over the positioning. We have to respect
                    # that.

                    # fs, 04.11.2008: I thought about moving this condition
                    #  to_prepare_fields where I think this code should live
                    # but then I would have to copy all the conditions and
                    # probably the code is here for a good reason so I'm
                    # just adding it here.
                    data_field[Key.SKIP] = False
                elif field_name == Key.OWNER and ats.restrict_owner:
                    # we need to transform the field into a list of users
                    ats.eventually_restrict_owner(data_field)
        elif len(create_perms) > 0:
            # Redirect to the first allowed type for the given user.
            first_allowed_type = create_perms[0]
            req.redirect(req.href.newticket(type=first_allowed_type))
        else:
            if ticket_type not in AgiloConfig(self.env).ALIASES:
                raise TracError(u"Unkown type '%s'!" % ticket_type)
            raise TracError("You are not allowed to create a %s!" %
                            ticket_type)
        return data
Example #4
0
    def testCanDisableSprintStartDateNormalization(self):
        config = AgiloConfig(self.env).get_section(AgiloConfig.AGILO_GENERAL)
        option_name = 'sprints_can_start_or_end_on_weekends'
        self.assert_false(config.get_bool(option_name))
        config.change_option(option_name, True, save=True)
        self.assert_true(
            AgiloConfig(self.env).sprints_can_start_or_end_on_weekends)

        start = datetime(2009, 05, 30, tzinfo=utc)
        sprint = self.teh.create_sprint('Foo', start=start)
        self.assert_equals(start, sprint.start)
        self.assert_equals(utc, sprint.start.tzinfo)
Example #5
0
 def testTimeRenderer(self):
     """Tests the time renderer"""
     task = self.teh.create_ticket(Type.TASK,
                                   props={Key.REMAINING_TIME: '2.5'})
     r = Renderer(task, Key.REMAINING_TIME)
     # force hours
     AgiloConfig(self.teh.get_env()).use_days = False
     self.assert_equals('2.5h', r())
     self.assert_equals('2.5h', '%s' % r)
     # force days
     AgiloConfig(self.teh.get_env()).use_days = True
     self.assert_equals('2.5d', r())
     self.assert_equals('2.5d', '%s' % r)
Example #6
0
 def _filter_info(self):
     config = AgiloConfig(self.env)
     if not config.backlog_filter_attribute:
         return dict()
     return dict(should_filter_by_attribute=config.backlog_filter_attribute,
                 should_reload_burndown_on_filter_change_when_filtering_by_component= \
                 config.should_reload_burndown_on_filter_change_when_filtering_by_component)
Example #7
0
    def _prepare_fields(self, req, ticket, field_changes=None):
        """Set specific renderer for the ticket fields"""
        fields = super(AgiloTicketModule, self)._prepare_fields(req, ticket)
        if not AgiloConfig(self.env).is_agilo_enabled:
            return fields

        from agilo.scrum import SprintController
        sp_controller = SprintController(self.env)

        for field in fields:
            field[Key.RENDERED] = self._rendered_ticket_value(ticket, field)
            # makes the nice Sprint pulldown to emulate the milestone one
            if field[Key.NAME] == Key.SPRINT:
                get_options = SprintController.GetSprintOptionListCommand(
                    self.env, sprint_names=field[Key.OPTIONS])
                closed, running, to_start = sp_controller.process_command(
                    get_options)
                field[Key.OPTIONS] = []
                field[Key.OPTIONS_GROUP] = [
                    {
                        Key.LABEL: _('Running (by Start Date)'),
                        Key.OPTIONS: running
                    },
                    {
                        Key.LABEL: _('To Start (by Start Date)'),
                        Key.OPTIONS: to_start
                    },
                    {
                        Key.LABEL: _('Closed (by Start Date)'),
                        Key.OPTIONS: closed
                    },
                ]
        return fields
Example #8
0
    def environment_created(self):
        for table in db_default.schema:
            create_table(self.env, table)

        cache_manager = HttpRequestCacheManager(self.env)
        po_manager = PersistentObjectManager(self.env)
        for manager in cache_manager.managers:
            model_class = manager.for_model()
            if issubclass(model_class, PersistentObject):
                module_name = model_class.__module__
                # We don't want to create tables for dummy classes automatically
                # but the test finder may load some of these managers so we
                # need to exclude them here.
                if ('tests.' not in module_name):
                    po_manager.create_table(model_class)

        # Need to create Agilo types in the database before writing to the
        # configuration - otherwise we get a warning during config setup (you'll
        # see it in every test case during setUp)
        db_default.create_default_types(self.env)
        initialize_config(self.env, __CONFIG_PROPERTIES__)
        db_default.create_default_backlogs(self.env)
        super(AgiloInit, self).environment_created()
        for listener in self.setup_listeners:
            listener.agilo_was_installed()
        # Reload the AgiloConfig to make sure all the changes have been updated
        AgiloConfig(self.env).reload()
        info(self, 'Agilo environment initialized')
Example #9
0
 def _filter_by(self, data):
     filter_by = None
     if AgiloConfig(
             self.env
     ).should_reload_burndown_on_filter_change_when_filtering_by_component:
         filter_by = data.get('filter_by')
     return filter_by
Example #10
0
    def detail_view(self, req, cat, page, name, backlog_config=None):
        backlog_config = self._backlog_config_with_changed_ticket_types(
            req, cat, page, name, backlog_config=backlog_config)

        # REFACT: Maybe we should use JSON here rather than xml?
        if ajax.is_ajax(req):
            # we got called by an Ajax request -> get available fields
            fields_for_selected_types = backlog_config.columns_as_fields(
                all_fields=False)
            items = [field[Key.NAME] for field in fields_for_selected_types]
            return 'ajax_response.xml', {'items': items}

        # TODO: Go for ticket configuration
        agilo_config = AgiloConfig(self.env)
        data = {
            'view':
            'detail',
            'backlog':
            backlog_config,
            'backlog_types':
            BacklogType.LABELS,
            't_types': [(t_type, t_type in backlog_config.ticket_types,
                         agilo_config.ALIASES.get(t_type, t_type))
                        for t_type in agilo_config.TYPES.keys()],
            'fields':
            backlog_config.columns_as_fields(all_fields=True),
        }
        add_script(req, 'agilo/js/backlog_admin.js')
        add_script(req, 'common/js/wikitoolbar.js')
        return 'agilo_admin_backlog.html', data
Example #11
0
 def testTimeRendererWithIntegers(self):
     task = self.teh.create_ticket(Type.TASK,
                                   props={Key.REMAINING_TIME: '2'})
     r = Renderer(task, Key.REMAINING_TIME)
     # force hours
     AgiloConfig(self.teh.get_env()).use_days = False
     self.assert_equals('2.0h', r())
 def remove_all_account_manager_components_from_config(self):
     env = self._testenv.get_trac_environment()
     components = AgiloConfig(env).get_section('components')
     for name in components.get_options_by_prefix('acct_mgr',
                                                  chop_prefix=False):
         components.remove_option(name, save=False)
     components.save()
Example #13
0
 def _all_field_names(self):
     all_field_names = set()
     ticket_configuration = AgiloConfig(self.env).ticket_configuration
     for field_names in ticket_configuration.fieldnames_per_type.values():
         for field_name in field_names:
             all_field_names.add(field_name)
     return all_field_names
Example #14
0
 def initialize_agilo(self, project_name, db_url, svn_repo, demo=False):
     try:
         self.do_initenv(
             '%s %s %s %s' %
             (project_name, db_url, 'svn', svn_repo or 'somewhere'))
         # Now add agilo and the template path
         env = Environment(self.envname)
         ac = AgiloConfig(env)
         if not svn_repo:
             # remove the fake from the config
             ac.change_option('repository_dir', '', 'trac')
         # sets the restric_owner option
         ac.change_option('restrict_owner', 'true', 'ticket')
         # this is also saving the config
         ac.enable_agilo()
         # update wiki
         wiki = WikiPage(env, name='WikiStart')
         wiki.text = agilo_wiki
         wiki.save('admin', 'Updated to Agilo', '127.0.0.1')
         # reset the env
         self.env_set(envname=self.envname, env=env)
         # Now initialize Agilo
         self.do_upgrade('upgrade --no-backup')
         # Now create the demo if needed
         if demo:
             try:
                 from create_demo_data import _create_demo_data
                 _create_demo_data(env)
             except ImportError, e:
                 env.log.error(exception_to_unicode(e))
     except:
         pass
Example #15
0
 def config_reloaded(self):
     """Recreate mapping dictionaries when needed"""
     config = AgiloConfig(self.env)
     if config.ALIASES is not None:
         self._alias_to_type = dict(
             zip(config.ALIASES.values(), config.ALIASES.keys()))
     self.cp = CommandParser(self.env, config.ALIASES, self._alias_to_type)
Example #16
0
 def test_changing_type_restore_correct_fields(self):
     """Tests that changing a ticket type restores the correct fields for
     that type"""
     t = AgiloTicket(self.env, t_type=Type.TASK)
     self.assert_true(self._matching_properties(t))
     # Now change that to a story
     t[Key.TYPE] = Type.USER_STORY
     self.assert_true(self._matching_properties(t))
     # Now reload config and change to bug
     ac = AgiloConfig(self.env)
     ac.reload()
     t[Key.TYPE] = Type.BUG
     self.assert_true(self._matching_properties(t))
     # Now add a field on the fly and see if it is adapting to it
     agilo_types = ac.get_section(ac.AGILO_TYPES)
     ticket_custom = ac.get_section(ac.TICKET_CUSTOM)
     ticket_custom.change_option('customer', 'text')
     ticket_custom.change_option('customer.label', 'Customer')
     fields = agilo_types.get_list(Type.BUG)
     fields.append('customer')
     # notice the save to force the reload of the config
     agilo_types.change_option('story', ','.join(fields), save=True)
     t[Key.TYPE] = Type.USER_STORY
     self.assert_true('customer' in t.fields_for_type, \
                     "No 'customer' in %s" % t.fields_for_type)
     t['customer'] = 'My Own Customer'
     self.assert_true(self._matching_properties(t))
     t.insert()
     self.assert_true(self._matching_properties(t))
     self.assert_equals('My Own Customer', t['customer'])
Example #17
0
 def _all_configured_ticket_fields(self):
     field_names = set()
     ticket_config = AgiloConfig(self.env).ticket_configuration
     for field_names_for_type in ticket_config.fieldnames_per_type.values():
         for field_name in field_names_for_type:
             field_names.add(field_name)
     return list(field_names)
Example #18
0
def is_email_verification_enabled(env):
    AgiloConfig(env).clear_trac_component_cache()
    try:
        from acct_mgr.web_ui import EmailVerificationModule
        return env.is_component_enabled(EmailVerificationModule)
    except ImportError:
        return None
Example #19
0
    def test_can_extract_remaining_time_with_unit(self):
        task_id = self.teh.create_task().id
        parsed = [('rem', "%s" % task_id, '3h')]
        self.assert_equals(parsed, self.parse('rem #%s:3h' % task_id))

        AgiloConfig(self.env).use_days = True
        parsed = [('TIME', "%s" % task_id, '3d')]
        self.assert_equals(parsed, self.parse('TIME #%s:3d' % task_id))
Example #20
0
 def _days_to_remove_from_burndown(self, sprint, viewer_timezone):
     if not AgiloConfig(self.env).burndown_should_show_working_days_only:
         return []
     if sprint.team is None:
         return []
     days_to_remove = sprint.team.capacity(viewer_timezone).days_without_capacity_in_interval(sprint.start, sprint.end)
     
     return days_to_remove
Example #21
0
 def _set_duration(self, value):
     """Sets the duration of the Sprint and recalculates the end Date"""
     if value is not None:
         week_days_off = None
         if AgiloConfig(self.env).sprints_can_start_or_end_on_weekends:
             week_days_off = []
         self.end = add_to_date(self.start, value, week_days_off=week_days_off)
         debug(self, "Setting Sprint end date to: %s" % self.end)
Example #22
0
 def _set_default_type(self, new_value):
     agilo_config = AgiloConfig(self.env)
     old_value = agilo_config.get('default_type', 'ticket')
     agilo_config.change_option('default_type',
                                new_value,
                                section='ticket',
                                save=True)
     return old_value
Example #23
0
 def test_do_not_sets_default_logo_if_changed(self):
     test_src = 'my_logo'
     agilo_config = AgiloConfig(self.env)
     header_logo = agilo_config.get_section('header_logo')
     header_logo.change_option('src', test_src)
     self.assert_equals(test_src, header_logo.get('src'))
     set_default_agilo_logo(agilo_config)
     self.assert_equals(test_src, header_logo.get('src'))
Example #24
0
 def get_actions_for_custom_types(self):
     for typename in AgiloConfig(self.env).get_available_types():
         plain_name = str('CREATE_' + typename.upper())
         aliased_permission_name = getattr(Action, plain_name, plain_name)
         if aliased_permission_name not in self.actions:
             self.actions.append(aliased_permission_name)
             # Trac admin will get all these permissions implicitly so we
             # don't need to give him the permission explicitly.
             self._add_permission_for_role(Role.TICKET_ADMIN, aliased_permission_name)
Example #25
0
 def _set_restrict_owner_option(self, new_value):
     env = self._testenv.get_trac_environment()
     agilo_config = AgiloConfig(env)
     old_value = agilo_config.get_bool('restrict_owner', 'ticket')
     agilo_config.change_option('restrict_owner',
                                new_value,
                                section='ticket',
                                save=True)
     return old_value
Example #26
0
 def render(self):
     """Returns the rendered property with a d or h"""
     if self.value_is_a_number() or isinstance(self.value,
                                               (float, int, Decimal)):
         if AgiloConfig(self.env).use_days:
             return u"%sd" % round(float(self.value), 2)
         else:
             return u"%sh" % round(float(self.value), 1)
     return self.value
Example #27
0
    def initialize(self):
        """Initialize the links configuration from the give config key"""
        self._currently_initializing = True

        # Prevent recursive imports (AgiloConfig needs to import the ticket
        # module)
        from agilo.utils.config import AgiloConfig
        if self._initialized and AgiloConfig(self.env).is_agilo_enabled:
            return

        links = AgiloConfig(self.env).get_section(AgiloConfig.AGILO_LINKS)
        for pair in links.get_list(LinkOption.ALLOW):
            if pair.find('-') == -1:
                continue
            self._parse_option(pair, links)
        # Set to initialized
        self._initialized = True
        self._currently_initializing = False
Example #28
0
def _update_configuration(env):
    my_config = copy(__CONFIG_PROPERTIES__)
    del my_config[AgiloConfig.AGILO_LINKS]
    del my_config[AgiloConfig.AGILO_TYPES]
    initialize_config(env, my_config)

    config = AgiloConfig(env).tc  # Only the trac config wrapper
    _update_agilo_types(config)
    _update_calculated_properties(config, env)
 def set_sprint_can_start_or_end_on_weekends(self):
     # The sprint must be running only for exactly one day, otherwise
     # confirm commitment is not possible anymore (and the total capacity
     # might be different)
     env = self.testenv.get_trac_environment()
     config = AgiloConfig(env)
     config.change_option('sprints_can_start_or_end_on_weekends',
                          True,
                          section='agilo-general')
     config.save()
Example #30
0
 def validate_includes_configured_unit_in_remaining_time(self, remaining_time):
     if len(remaining_time) > 0 and remaining_time[-1] not in ('h', 'd'):
         self.validation_errors.append("Need h(our) or d(ay) unit for remaining time '%s'" % remaining_time)
         return
     
     config = AgiloConfig(self.env)
     if config.use_days and remaining_time.endswith('h'):
         self.validation_errors.append("Wrong unit used in remaining time '%s' (Agilo is configured to use days)" % remaining_time)
     if not config.use_days and remaining_time.endswith('d'):
         self.validation_errors.append("Wrong unit used in remaining time '%s' (Agilo is configured to use hours)" % remaining_time)