Exemplo n.º 1
0
    def _create_facebook_button(self, url, locale):
        width = self._facebook_width
        font = self._facebook_font
        layout = self._facebook_layout

        params = {
            'width': width,
            'font': font,
            'layout': layout,
            'send': 'false',
            'action': 'like'
        }
        if url:
            params['url'] = url
        if locale:
            params['locale'] = locale
        src = '//www.facebook.com/plugins/like.php?' + unicode_urlencode(
            params)
        style = 'border:none;overflow:hidden;width:%(width)spx;height:21px' \
                % {'width': width}
        return [
            tag.iframe(src=src,
                       scrolling='no',
                       frameborder='0',
                       style=style,
                       allowTransparency='true'),
        ]
Exemplo n.º 2
0
def execute_query(env, req, query_args):
    # set maximum number of returned tickets to 0 to get all tickets at once
    query_args['max'] = 0
    # urlencode the args, converting back a few vital exceptions:
    # see the authorized fields in the query language in
    # http://trac.edgewall.org/wiki/TracQuery#QueryLanguage
    query_string = unicode_urlencode(query_args)\
                        .replace('%21=', '!=')\
                        .replace('%21%7E=', '!~=')\
                        .replace('%7E=', '~=')\
                        .replace('%5E=', '^=')\
                        .replace('%24=', '$=')\
                        .replace('%21%5E=', '!^=')\
                        .replace('%21%24=', '!$=')\
                        .replace('%7C', '|')\
                        .replace('+', ' ')\
                        .replace('%23', '#')\
                        .replace('%28', '(')\
                        .replace('%29', ')')\
                        .replace('%2F', '/')
    env.log.debug("query_string: %s" % query_string)
    query = Query.from_string(env, query_string)

    tickets = query.execute(req)

    tickets = [t for t in tickets
               if ('TICKET_VIEW' or 'TICKET_VIEW_CC') in req.perm('ticket', t['id'])]

    return tickets
Exemplo n.º 3
0
    def _post(self, url, req, author, content, ip):
        # Split up author into name and email, if possible
        author_name, author_email = parseaddr(author)
        if not author_name and not author_email:
            author_name = author
        elif not author_name and author_email.find('@') < 1:
            author_name = author
            author_email = None

        params = {
            'blog': req.base_url,
            'user_ip': ip,
            'user_agent': req.get_header('User-Agent'),
            'referrer': req.get_header('Referer') or 'unknown',
            'comment_author': author_name,
            'comment_type': 'trac',
            'comment_content': content
        }
        if author_email:
            params['comment_author_email'] = author_email
        for k, v in req.environ.items():
            if k.startswith('HTTP_') and k not in self.noheaders:
                params[k] = v
        urlreq = urllib2.Request(url, unicode_urlencode(params),
                                 {'User-Agent': user_agent})

        resp = urllib2.urlopen(urlreq)
        return resp.read()
Exemplo n.º 4
0
def execute_query(env, req, query_args):
    # set maximum number of returned tickets to 0 to get all tickets at once
    query_args['max'] = 0
    # urlencode the args, converting back a few vital exceptions:
    # see the authorized fields in the query language in
    # http://trac.edgewall.org/wiki/TracQuery#QueryLanguage
    query_string = unicode_urlencode(query_args).replace('%21=', '!=') \
                                                .replace('%21%7E=', '!~=') \
                                                .replace('%7E=', '~=') \
                                                .replace('%5E=', '^=') \
                                                .replace('%24=', '$=') \
                                                .replace('%21%5E=', '!^=') \
                                                .replace('%21%24=', '!$=') \
                                                .replace('%7C', '|') \
                                                .replace('+', ' ') \
                                                .replace('%23', '#') \
                                                .replace('%28', '(') \
                                                .replace('%29', ')')
    env.log.debug("query_string: %s", query_string)
    query = Query.from_string(env, query_string)

    tickets = query.execute(req)

    tickets = [
        t for t in tickets
        if ('TICKET_VIEW' or 'TICKET_VIEW_CC') in req.perm('ticket', t['id'])
    ]

    return tickets
Exemplo n.º 5
0
    def post_process_request(self, req, template, data, content_type):
        """Adds a 'Lint' context navigation menu item in source view and
           links to the annotation in report summary.
        """
        if not 'BUILD_VIEW' in req.perm:
            return template, data, content_type
        resource = data and data.get('context') \
                        and data.get('context').resource or None
        if not resource or not isinstance(resource, Resource):
            pass
        elif resource.realm == 'source' and data.get('file') \
                    and not req.args.get('annotate') == 'lint':
            add_ctxtnav(req, 'Lint',
                    title='Annotate file with lint result '
                          'data (if available)',
                    href=req.href.browser(resource.id,
                        annotate='lint', rev=data.get('rev')))

        elif resource.realm == 'build' and data.get('build', {}).get('steps'):
            # in report summary, set link to lint annotation
            steps = data['build']['steps']
            rev = data['build']['rev']
            for step in steps:
                for report in step.get('reports', []):
                    if report.get('category') != 'lint':
                        continue
                    for item in report.get('data', {}).get('data', []):
                        href = item.get('href')
                        if not href or 'annotate' in href:
                            continue
                        sep = ('?' in href) and '&' or '?'
                        param = {'rev': rev, 'annotate': 'lint'}
                        href = href + sep + unicode_urlencode(param)
                        item['href'] = href + '#Lint1'
        return template, data, content_type
Exemplo n.º 6
0
 def test_unicode_urlencode(self):
     self.assertEqual(
         'thing=%C3%9C&%C3%9C=thing&%C3%9Cthing',
         unicode_urlencode({
             u'Ü': 'thing',
             'thing': u'Ü',
             u'Üthing': empty
         }))
Exemplo n.º 7
0
 def pre_process_request(self, req, handler):
     rmodule = ReportModule(self.env)
     #report's match request. if it's gonna be true then we'll stick in our translator,
     #but only if there's a report id (i.e. it's actually a report page)
     if rmodule.match_request(req) and req.args.get('id', -1) != -1 and req.args.get('action', 'view') == 'view':
         href = ''
         params = rmodule.get_var_args(req)
         if params:
             href = '&' + unicode_urlencode(params)
         add_link(req, 'alternate', '?format=rss&changes=true' + href, _('Changes RSS Feed'),
             'application/xhtml+xml', 'rss')
     return handler
Exemplo n.º 8
0
 def _add_alternate_links(self, req):
     params = {}
     for arg in req.args.keys():
         if not arg.isupper():
             continue
         params[arg] = req.args.get(arg)
     if "USER" not in params:
         params["USER"] = req.authname
     if "sort" in req.args:
         params["sort"] = req.args["sort"]
     if "asc" in req.args:
         params["asc"] = req.args["asc"]
     href = ""
     if params:
         href = "&" + unicode_urlencode(params)
     add_link(req, "alternate", "?format=xlshtml" + href, "Excel HTML", "application/vnd.ms-excel", "html")
Exemplo n.º 9
0
 def _add_alternate_links(self, req):
     params = {}
     for arg in req.args.keys():
         if not arg.isupper():
             continue
         params[arg] = req.args.get(arg)
     if 'USER' not in params:
         params['USER'] = req.authname
     if 'sort' in req.args:
         params['sort'] = req.args['sort']
     if 'asc' in req.args:
         params['asc'] = req.args['asc']
     href = ''
     if params:
         href = '&' + unicode_urlencode(params)
     add_link(req, 'alternate', '?format=xls' + href, _("Excel"),
              'application/vnd.ms-excel')
Exemplo n.º 10
0
 def _add_alternate_links(self, req):
     params = {}
     for arg in req.args.keys():
         if not arg.isupper():
             continue
         params[arg] = req.args.get(arg)
     if 'USER' not in params:
         params['USER'] = req.authname
     if 'sort' in req.args:
         params['sort'] = req.args['sort']
     if 'asc' in req.args:
         params['asc'] = req.args['asc']
     href = ''
     if params:
         href = '&' + unicode_urlencode(params)
     add_link(req, 'alternate', '?format=xls' + href, _("Excel"),
              'application/vnd.ms-excel')
Exemplo n.º 11
0
 def add_alternate_links(self, req, args):
     params = args
     if req.args.has_key('sort'):
         params['sort'] = req.args['sort']
     if req.args.has_key('asc'):
         params['asc'] = req.args['asc']
     href = ''
     if params:
         href = '&' + unicode_urlencode(params)
     add_link(req, 'alternate', '?format=rss' + href, 'RSS Feed',
              'application/rss+xml', 'rss')
     add_link(req, 'alternate', '?format=csv' + href,
              'Comma-delimited Text', 'text/plain')
     add_link(req, 'alternate', '?format=tab' + href,
              'Tab-delimited Text', 'text/plain')
     if req.perm.has_permission('REPORT_SQL_VIEW'):
         add_link(req, 'alternate', '?format=sql', 'SQL Query',
                  'text/plain')
Exemplo n.º 12
0
 def add_alternate_links(self, req, args):
     params = args
     if req.args.has_key('sort'):
         params['sort'] = req.args['sort']
     if req.args.has_key('asc'):
         params['asc'] = req.args['asc']
     href = ''
     if params:
         href = '&' + unicode_urlencode(params)
     add_link(req, 'alternate', '?format=rss' + href, 'RSS Feed',
              'application/rss+xml', 'rss')
     add_link(req, 'alternate', '?format=csv' + href,
              'Comma-delimited Text', 'text/plain')
     add_link(req, 'alternate', '?format=tab' + href, 'Tab-delimited Text',
              'text/plain')
     if req.perm.has_permission('REPORT_SQL_VIEW'):
         add_link(req, 'alternate', '?format=sql', 'SQL Query',
                  'text/plain')
Exemplo n.º 13
0
    def _create_facebook_button(self, url, locale):
        width = self._facebook_width
        font = self._facebook_font
        layout = self._facebook_layout

        params = {'width': width, 'font': font, 'layout': layout,
                  'send': 'false', 'action': 'like'}
        if url:
            params['url'] = url
        if locale:
            params['locale'] = locale
        src = '//www.facebook.com/plugins/like.php?' + unicode_urlencode(params)
        style = 'border:none;overflow:hidden;width:%(width)spx;height:21px' \
                % {'width': width}
        return [
            tag.iframe(src=src, scrolling='no', frameborder='0', style=style,
                       allowTransparency='true'),
        ]
Exemplo n.º 14
0
 def add_alternate_links(self, req, args):
     params = args.copy()
     if 'sort' in req.args:
         params['sort'] = req.args['sort']
     if 'asc' in req.args:
         params['asc'] = req.args['asc']
     href = ''
     if params:
         href = '&' + unicode_urlencode(params)
     add_link(req, 'alternate', '?format=rss' + href, _('RSS Feed'),
              'application/rss+xml', 'rss')
     add_link(req, 'alternate', '?format=csv' + href,
              _('Comma-delimited Text'), 'text/plain')
     add_link(req, 'alternate', '?format=tab' + href,
              _('Tab-delimited Text'), 'text/plain')
     if 'REPORT_SQL_VIEW' in req.perm:
         add_link(req, 'alternate', '?format=sql', _('SQL Query'),
                  'text/plain')
Exemplo n.º 15
0
 def _add_alternate_links(self, req):
     params = {}
     for arg in req.args.keys():
         if not arg.isupper():
             continue
         params[arg] = req.args.get(arg)
     if 'USER' not in params:
         params['USER'] = req.authname
     if 'sort' in req.args:
         params['sort'] = req.args['sort']
     if 'asc' in req.args:
         params['asc'] = req.args['asc']
     href = ''
     if params:
         href = '&' + unicode_urlencode(params)
     format = get_excel_format(self.env)
     mimetype = get_excel_mimetype(format)
     add_link(req, 'alternate', '?format=' + format + href, _("Excel"),
              mimetype)
Exemplo n.º 16
0
    def verify_key(self, req, api_url=None, api_key=None):
        if api_url is None:
            api_url = self.api_url
        if api_key is None:
            api_key = self.api_key

        if api_key != self.verified_key:
            self.log.debug("Verifying Akismet API key")
            params = {'blog': req.base_url, 'key': api_key}
            req = urllib2.Request('http://%sverify-key' % api_url,
                                  unicode_urlencode(params),
                                  {'User-Agent': user_agent})
            resp = urllib2.urlopen(req).read()
            if resp.strip().lower() == 'valid':
                self.log.debug("Akismet API key is valid")
                self.verified = True
                self.verified_key = api_key

        return self.verified_key is not None
Exemplo n.º 17
0
    def __call__(self, *args, **kw):
        href = self.base
        params = []

        def add_param(name, value):
            if isinstance(value, (list, tuple)):
                for i in [i for i in value if i is not None]:
                    params.append((name, i))
            elif value is not None:
                params.append((name, value))

        # Skip Jinja2 context (#13244)
        # Only needed for Jinja versions 2.11.0 and 2.11.1
        if args and isinstance(args[0], Jinja2Context):
            args = args[1:]
        if args:
            lastp = args[-1]
            if isinstance(lastp, dict):
                for k, v in lastp.items():
                    add_param(k, v)
                args = args[:-1]
            elif isinstance(lastp, (list, tuple)):
                for k, v in lastp:
                    add_param(k, v)
                args = args[:-1]

        # build the path
        path = '/'.join(
            unicode_quote(unicode(arg).strip('/'), self.path_safe)
            for arg in args if arg is not None)
        if path:
            href += '/' + slashes_re.sub('/', path).lstrip('/')
        elif not href:
            href = '/'

        # assemble the query string
        for k, v in kw.items():
            add_param(k[:-1] if k.endswith('_') else k, v)
        if params:
            href += '?' + unicode_urlencode(params, self.query_safe)

        return href
Exemplo n.º 18
0
def execute_query(env, req, query_args):
    # set maximum number of returned tickets to 0 to get all tickets at once
    query_args['max'] = 0
    # urlencode the args, converting back a few vital exceptions:
    query_string = unicode_urlencode(query_args)\
                        .replace('%21=', '!=')\
                        .replace('%7C', '|')\
                        .replace('+', ' ')\
                        .replace('%23', '#')\
                        .replace('%28', '(')\
                        .replace('%29', ')')
    env.log.debug("query_string: %s" % query_string)
    query = Query.from_string(env, query_string)

    tickets = query.execute(req)

    tickets = [t for t in tickets
               if ('TICKET_VIEW' or 'TICKET_VIEW_CC') in req.perm('ticket', t['id'])]

    return tickets
Exemplo n.º 19
0
    def __call__(self, *args, **kw):
        href = self.base
        if href and href[-1] == '/':
            href = href[:-1]
        params = []

        def add_param(name, value):
            if type(value) in (list, tuple):
                for i in [i for i in value if i != None]:
                    params.append((name, i))
            elif v != None:
                params.append((name, value))

        if args:
            lastp = args[-1]
            if lastp and type(lastp) is dict:
                for k, v in lastp.items():
                    add_param(k, v)
                args = args[:-1]
            elif lastp and type(lastp) in (list, tuple):
                for k, v in lastp:
                    add_param(k, v)
                args = args[:-1]

        # build the path
        path = '/'.join([
            unicode_quote(unicode(arg).strip('/')) for arg in args
            if arg != None
        ])
        if path:
            href += '/' + path

        # assemble the query string
        for k, v in kw.items():
            add_param(k, v)

        if params:
            href += '?' + unicode_urlencode(params)

        return href
Exemplo n.º 20
0
def execute_query(env, req, query_args):
    # set maximum number of returned tickets to 0 to get all tickets at once
    query_args['max'] = 0
    # urlencode the args, converting back a few vital exceptions:
    query_string = unicode_urlencode(query_args)\
                        .replace('%21=', '!=')\
                        .replace('%7C', '|')\
                        .replace('+', ' ')\
                        .replace('%23', '#')\
                        .replace('%28', '(')\
                        .replace('%29', ')')
    env.log.debug("query_string: %s" % query_string)
    query = Query.from_string(env, query_string)

    tickets = query.execute(req)

    tickets = [
        t for t in tickets
        if ('TICKET_VIEW' or 'TICKET_VIEW_CC') in req.perm('ticket', t['id'])
    ]

    return tickets
Exemplo n.º 21
0
    def __call__(self, *args, **kw):
        href = self.base
        if href and href[-1] == '/':
            href = href[:-1]
        params = []

        def add_param(name, value):
            if type(value) in (list, tuple):
                for i in [i for i in value if i != None]:
                    params.append((name, i))
            elif v != None:
                params.append((name, value))

        if args:
            lastp = args[-1]
            if lastp and type(lastp) is dict:
                for k,v in lastp.items():
                    add_param(k, v)
                args = args[:-1]
            elif lastp and type(lastp) in (list, tuple):
                for k,v in lastp:
                    add_param(k, v)
                args = args[:-1]

        # build the path
        path = '/'.join([unicode_quote(unicode(arg).strip('/')) for arg in args
                         if arg != None])
        if path:
            href += '/' + path

        # assemble the query string
        for k,v in kw.items():
            add_param(k, v)

        if params:
            href += '?' + unicode_urlencode(params)

        return href
Exemplo n.º 22
0
    def __call__(self, *args, **kw):
        href = self.base
        params = []

        def add_param(name, value):
            if isinstance(value, (list, tuple)):
                for i in [i for i in value if i is not None]:
                    params.append((name, i))
            elif value is not None:
                params.append((name, value))

        if args:
            lastp = args[-1]
            if isinstance(lastp, dict):
                for k, v in lastp.items():
                    add_param(k, v)
                args = args[:-1]
            elif isinstance(lastp, (list, tuple)):
                for k, v in lastp:
                    add_param(k, v)
                args = args[:-1]

        # build the path
        path = '/'.join(
            unicode_quote(unicode(arg).strip('/'), self.path_safe)
            for arg in args if arg is not None)
        if path:
            href += '/' + path
        elif not href:
            href = '/'

        # assemble the query string
        for k, v in kw.items():
            add_param(k[:-1] if k.endswith('_') else k, v)
        if params:
            href += '?' + unicode_urlencode(params, self.query_safe)

        return href
Exemplo n.º 23
0
    def __call__(self, *args, **kw):
        href = self.base
        params = []

        def add_param(name, value):
            if isinstance(value, (list, tuple)):
                for i in [i for i in value if i is not None]:
                    params.append((name, i))
            elif value is not None:
                params.append((name, value))

        if args:
            lastp = args[-1]
            if isinstance(lastp, dict):
                for k, v in lastp.items():
                    add_param(k, v)
                args = args[:-1]
            elif isinstance(lastp, (list, tuple)):
                for k, v in lastp:
                    add_param(k, v)
                args = args[:-1]

        # build the path
        path = '/'.join(unicode_quote(unicode(arg).strip('/'), self.path_safe)
                        for arg in args if arg is not None)
        if path:
            href += '/' + slashes_re.sub('/', path).lstrip('/')
        elif not href:
            href = '/'

        # assemble the query string
        for k, v in kw.items():
            add_param(k[:-1] if k.endswith('_') else k, v)
        if params:
            href += '?' + unicode_urlencode(params, self.query_safe)

        return href
Exemplo n.º 24
0
    def post_process_request(self, req, template, data, content_type):
        """Adds a 'Lint' context navigation menu item in source view and
           links to the annotation in report summary.
        """
        if not 'BUILD_VIEW' in req.perm:
            return template, data, content_type
        resource = data and data.get('context') \
                        and data.get('context').resource or None
        if not resource or not isinstance(resource, Resource):
            pass
        elif resource.realm == 'source' and data.get('file') \
                    and not req.args.get('annotate') == 'lint':
            add_ctxtnav(req,
                        'Lint',
                        title='Annotate file with lint result '
                        'data (if available)',
                        href=req.href.browser(resource.id,
                                              annotate='lint',
                                              rev=data.get('rev')))

        elif resource.realm == 'build' and data.get('build', {}).get('steps'):
            # in report summary, set link to lint annotation
            steps = data['build']['steps']
            rev = data['build']['rev']
            for step in steps:
                for report in step.get('reports', []):
                    if report.get('category') != 'lint':
                        continue
                    for item in report.get('data', {}).get('data', []):
                        href = item.get('href')
                        if not href or 'annotate' in href:
                            continue
                        sep = ('?' in href) and '&' or '?'
                        param = {'rev': rev, 'annotate': 'lint'}
                        href = href + sep + unicode_urlencode(param)
                        item['href'] = href + '#Lint1'
        return template, data, content_type
Exemplo n.º 25
0
    def expand_macro(self, formatter, name, content):
        req = formatter.req
        db = self.env.get_db_cnx()
        # prepare options
        options, query_args = parse_options(db, content,
                                            copy.copy(DEFAULT_OPTIONS))

        query_args[self.estimation_field + "!"] = None
        tickets = execute_query(self.env, req, query_args)

        sum = 0.0
        estimations = {}
        for ticket in tickets:
            if ticket['status'] in self.closed_states:
                continue
            try:
                estimation = float(ticket[self.estimation_field] or 0.0)

                if options.get('remainingworkload'):

                    completion_cursor = db.cursor()

                    completion_cursor.execute(
                        "SELECT t.value AS totalhours, c.value AS complete, d.value AS due_close FROM ticket tk LEFT JOIN ticket_custom t ON (tk.id = t.ticket AND t.name = 'totalhours') LEFT JOIN ticket_custom c ON (tk.id = c.ticket AND c.name = 'complete') LEFT JOIN ticket_custom d ON (tk.id = d.ticket AND d.name = 'due_close') WHERE tk.id = %s"
                        % ticket['id'])

                    for row in completion_cursor:

                        ticket['totalhours'], ticket['complete'], ticket[
                            'due_close'] = row
                        break

                    # skip ticket ticket if due date is later than 'enddate':
                    if options.get('showdueonly'):

                        if not ticket['due_close']:
                            continue  # skip tickets with empty ETA when in 'showdueonly' mode
                        due_close = parse_date(ticket['due_close'],
                                               ["%Y/%m/%d"])
                        startdate = options.get('startdate')
                        enddate = options.get('enddate')

                        if startdate and startdate > due_close:
                            continue  # skip tickets with ETA in the past

                        if enddate and enddate < due_close:
                            continue  # skip tickets with ETA in the future

                        pass

                    totalhours = float(ticket['totalhours'] or 0.0)

                    completed = (float(ticket['complete'] or 0.0) /
                                 100) * estimation
                    completed_hours = min(estimation,
                                          max(totalhours, completed))

                    estimation -= completed_hours

                    pass

                owner = ticket['owner']

                sum += estimation
                if estimations.has_key(owner):
                    estimations[owner] += estimation
                else:
                    estimations[owner] = estimation
            except:
                raise

        # Title
        title = 'Workload'

        days_remaining = None

        # calculate remaining work time
        if options.get('today') and options.get('enddate'):
            currentdate = options['today']
            day = timedelta(days=1)
            days_remaining = 0
            while currentdate <= options['enddate']:
                if currentdate.weekday() < 5:
                    days_remaining += 1
                currentdate += day
            title += ' %g%s (~%s workdays left)' % (round(
                sum, 2), self.estimation_suffix, days_remaining)

        estimations_string = []
        labels = []
        workhoursperday = max(float(options.get('workhoursperday')), 0.0)
        chts = '000000'

        for owner, estimation in estimations.iteritems():
            # Note: Unconditional obfuscation of owner in case it represents
            # an email adress, and as the chart API doesn't support SSL
            # (plain http transfer only, from either client or server).
            label = "%s %g%s" % (obfuscate_email_address(owner),
                                 round(estimation, 2), self.estimation_suffix)

            if days_remaining != None:

                user_remaining_hours = days_remaining * workhoursperday

                if not user_remaining_hours or (estimation /
                                                user_remaining_hours) > 1:
                    label = "%s (~%g hours left)!" % (
                        label, round(user_remaining_hours, 2)
                    )  # user does not have enough hours left
                    chts = 'FF0000'  # set chart title style to red
                    pass
                pass

            labels.append(label)

            estimations_string.append(str(int(estimation)))

            pass

        chart_args = unicode_urlencode({
            'chs':
            '%sx%s' % (options['width'], options['height']),
            'chf':
            'bg,s,00000000',
            'chd':
            't:%s' % ",".join(estimations_string),
            'cht':
            'p3',
            'chtt':
            title,
            'chts':
            chts,
            'chl':
            "|".join(labels),
            'chco':
            options['color']
        })

        self.log.debug("WorkloadChart data: %s" % repr(chart_args))
        if self.serverside_charts:
            return tag.image(
                src="%s?data=%s" %
                (req.href.estimationtools('chart'), unicode_quote(chart_args)),
                alt="Workload Chart (server)")
        else:
            return tag.image(src="https://chart.googleapis.com/chart?%s" %
                             chart_args,
                             alt="Workload Chart (client)")
Exemplo n.º 26
0
    def filter_stream(self, req, method, filename, stream, data):
#        self.list_namespaces()
        # generate TracLink string
        resource = None
        if filename in ['ticket.html', 'wiki_view.html', 'report_view.html', 'milestone_view.html', 'agilo_ticket_view.html'] \
                and 'context' in data:
            resource = copy(data['context'].resource)
        elif filename in ['search.html']:  # search:
            resource = Resource('search', data['query'])
        elif filename in ['browser.html']:  # source:
            resource = copy(data['context'].resource)
            if resource.parent and resource.parent.realm == 'repository':
                resource.id = '%s/%s' % (resource.parent.id, resource.id)
                resource.parent = None
        elif filename in ['revisionlog.html']:  # log:
            resource = copy(data['context'].resource)
            resource.realm = 'log'
            if resource.parent and resource.parent.realm == 'repository':
                resource.id = '%s/%s' % (resource.parent.id, resource.id)
                resource.parent = None
            revranges = data.get('revranges', None)
            rev = data.get('rev', None)
            if revranges:
                resource.version = '%s:%s' % (revranges.a, revranges.b)
            elif rev:
                resource.version = rev
        elif filename in ['attachment.html']:
            if isinstance(data['attachment'], Attachment):  # attachment:
                resource = copy(data['attachment'].resource)
            else:
                pass  # attachment list page of the ticket; no TracLinks defined
        elif filename in ['timeline.html']:  # timeline:
            resource = Resource('timeline', format_datetime(data['precisedate'], 'iso8601'))
        elif filename in ['changeset.html']:
            if data['changeset']:  # changeset:
                resource = copy(data['context'].resource)
                if resource.parent and resource.parent.realm == 'repository':
                    resource.id = '%s/%s' % (resource.id, resource.parent.id)  # OK, I know
                    resource.parent = None
                if data['restricted']:
                    resource.id = '%s/%s' % (resource.id, data['new_path'])
            else:  # diff:
                args = req.args
                old_path, new_path = args.get('old_path', ''), args.get('new_path', '')
                old_rev, new_rev = args.get('old'), args.get('new')
                if old_path == new_path:  # diff:path@1:3 style
                    resource = Resource('diff', old_path, '%s:%s' % (old_rev, new_rev))
                else:  # diff:path@1//path@3 style
                    if old_rev:
                        old_path += '@%s' % old_rev
                    if new_rev:
                        new_path += '@%s' % new_rev
                    resource = Resource('diff', '%s//%s' % (old_path, new_path))
        elif filename in ['query.html']:
            if 'report_resource' in data:
                resource = copy(data['report_resource'])
            else:
                resource = Resource('query', data['query'].to_string().replace("\n", "")[7:])
        else:
            pass

        # link hash TODO: check wiki_view for agilo
        if filename in ['browser.html', 'changeset.html', 'ticket.html', 'agilo_ticket_view.html', 'wiki_view.html']:
            add_script(req, 'traclinks/js/jquery.ba-hashchange.js')
            add_script(req, 'traclinks/js/onhashchange.js')
        #
        if resource:
            traclinks = '%s' % (resource.id)
            if resource.version != None:
                traclinks += (resource.realm == 'ticket' and '?version=%s' or '@%s') % resource.version
            parent = resource.parent
            while parent and parent.id:
                traclinks += ':%s:%s' % (parent.realm, parent.id)
                if parent.version != None:
                    traclinks += '@%s' % parent.version
                parent = parent.parent
            if ' ' in traclinks:
                traclinks = '"%s"' % traclinks  # surround quote if needed
            traclinks = '%s:%s' % (resource.realm, traclinks)
            # new ticket template
            if resource.id == None and resource.realm == 'ticket':
                query_string = unicode_urlencode(
                    [(k, v) for k, v in data['ticket'].values.iteritems()
                            if v not in (None, '')])
                traclinks = '[/newticket?%s]' % query_string

            #return stream | Transformer('//input[@id="proj-search"]').attr('placeholder', traclinks).attr('size', '50')
            _input = tag.input(value=traclinks, readonly='', style=self.style)
            div = tag.div(_input, id="banner-traclink", style="float:right")
            return stream | Transformer('//div[@id="header"]').before(div)

        return stream
Exemplo n.º 27
0
    def expand_macro(self, formatter, name, content):

        # prepare options
        req = formatter.req
        options, query_args = parse_options(self.env.get_db_cnx(), content,
                                            copy.copy(DEFAULT_OPTIONS))

        if not options['startdate']:
            raise TracError("No start date specified!")

        # minimum time frame is one day
        if (options['startdate'] >= options['enddate']):
            options['enddate'] = options['startdate'] + timedelta(days=1)

        # calculate data
        timetable = self._calculate_timetable(options, query_args, req)

        # remove weekends
        if not options['weekends']:
            for date in timetable.keys():
                if date.weekday() >= 5:
                    del timetable[date]

        # scale data
        xdata, ydata, maxhours = self._scale_data(timetable, options)

        # build html for google chart api
        dates = sorted(timetable.keys())
        bottomaxis = "0:|" + ("|").join([str(date.day) for date in dates]) + \
            "|1:|%s/%s|%s/%s" % (dates[0].month, dates[0].year,
                                 dates[ - 1].month, dates[ - 1].year)
        leftaxis = "2,0,%s" % maxhours

        # add line for expected progress
        if options['expected'] == '0':
            expecteddata = ""
        else:
            expecteddata = "|0,100|%s,0" % (round(
                Decimal(options['expected']) * 100 / maxhours, 2))

        # prepare gridlines
        if options['gridlines'] == '0':
            gridlinesdata = "100.0,100.0,1,0"  # create top and right bounding line by using grid
        else:
            gridlinesdata = "%s,%s" % (xdata[1], (round(
                Decimal(options['gridlines']) * 100 / maxhours, 4)))

        # mark weekends
        weekends = []
        saturday = None
        index = 0
        halfday = self._round(Decimal("0.5") / (len(dates) - 1))
        for date in dates:
            if date.weekday() == 5:
                saturday = index
            if saturday and date.weekday() == 6:
                weekends.append(
                    "R,%s,0,%s,%s" %
                    (options['wecolor'],
                     self._round((Decimal(xdata[saturday]) / 100) - halfday),
                     self._round((Decimal(xdata[index]) / 100) + halfday)))
                saturday = None
            index += 1
        # special handling if time period starts with Sundays...
        if len(dates) > 0 and dates[0].weekday() == 6:
            weekends.append("R,%s,0,0.0,%s" % (options['wecolor'], halfday))
        # or ends with Saturday
        if len(dates) > 0 and dates[-1].weekday() == 5:
            weekends.append("R,%s,0,%s,1.0" %
                            (options['wecolor'], Decimal(1) - halfday))

        # chart title
        title = options.get('title', None)
        if title is None and options.get('milestone'):
            title = options['milestone'].split('|')[0]

        chart_args = unicode_urlencode({
            'chs':
            '%sx%s' % (options['width'], options['height']),
            'chf':
            'c,s,%s|bg,s,00000000' % options['bgcolor'],
            'chd':
            't:%s|%s%s' % (",".join(xdata), ",".join(ydata), expecteddata),
            'cht':
            'lxy',
            'chxt':
            'x,x,y',
            'chxl':
            bottomaxis,
            'chxr':
            leftaxis,
            'chm':
            "|".join(weekends),
            'chg':
            gridlinesdata,
            'chco':
            '%s,%s' % (options['color'], options['colorexpected']),
            'chtt':
            title
        })
        self.log.debug("BurndownChart data: %s" % repr(chart_args))
        if self.serverside_charts:
            return tag.image(
                src="%s?data=%s" %
                (req.href.estimationtools('chart'), unicode_quote(chart_args)),
                alt="Burndown Chart (server)")
        else:
            return tag.image(src="http://chart.googleapis.com/chart?%s" %
                             chart_args,
                             alt="Burndown Chart (client)")
Exemplo n.º 28
0
    def render_widget(self, name, context, options):
        """Count ocurrences of values assigned to given ticket field.
        """
        req = context.req
        params = ('field', 'query', 'verbose', 'threshold', 'max', 'title',
                  'view')
        fieldnm, query, verbose, threshold, maxitems, title, view = \
                self.bind_params(name, options, *params)

        field_maps = {
            'type': {
                'admin_url': 'type',
                'title': 'Types',
            },
            'status': {
                'admin_url': None,
                'title': 'Statuses',
            },
            'priority': {
                'admin_url': 'priority',
                'title': 'Priorities',
            },
            'milestone': {
                'admin_url': 'milestones',
                'title': 'Milestones',
            },
            'component': {
                'admin_url': 'components',
                'title': 'Components',
            },
            'version': {
                'admin_url': 'versions',
                'title': 'Versions',
            },
            'severity': {
                'admin_url': 'severity',
                'title': 'Severities',
            },
            'resolution': {
                'admin_url': 'resolution',
                'title': 'Resolutions',
            },
        }
        _field = []

        def check_field_name():
            if fieldnm is None:
                raise InvalidWidgetArgument('field', 'Missing ticket field')
            tsys = self.env[TicketSystem]
            if tsys is None:
                raise TracError(_('Error loading ticket system (disabled?)'))
            for field in tsys.get_ticket_fields():
                if field['name'] == fieldnm:
                    _field.append(field)
                    break
            else:
                if fieldnm in field_maps:
                    admin_suffix = field_maps.get(fieldnm)['admin_url']
                    if 'TICKET_ADMIN' in req.perm and admin_suffix is not None:
                        hint = _(
                            'You can add one or more '
                            '<a href="%(url)s">here</a>.',
                            url=req.href.admin('ticket', admin_suffix))
                    else:
                        hint = _(
                            'Contact your administrator for further details')
                    return 'widget_alert.html', \
                            {
                                'title' : Markup(_('%(field)s',
                                            field=field_maps[fieldnm]['title'])),
                                'data' : dict(msgtype='info',
                                    msglabel="Note",
                                    msgbody=Markup(_('''No values are
                                        defined for ticket field
                                        <em>%(field)s</em>. %(hint)s''',
                                        field=fieldnm, hint=hint))
                                    )
                            }, context
                else:
                    raise InvalidWidgetArgument(
                        'field', 'Unknown ticket field %s' % (fieldnm, ))
            return None

        if query is None:
            data = check_field_name()
            if data is not None:
                return data
            field = _field[0]
            if field.get('custom'):
                sql = "SELECT COALESCE(value, ''), count(COALESCE(value, ''))" \
                        " FROM ticket_custom " \
                        " WHERE name='%(name)s' GROUP BY COALESCE(value, '')"
            else:
                sql = "SELECT COALESCE(%(name)s, ''), " \
                        "count(COALESCE(%(name)s, '')) FROM ticket " \
                        "GROUP BY COALESCE(%(name)s, '')"
            sql = sql % field
            # TODO : Implement threshold and max

            db_query = req.perm.env.db_query \
                if isinstance(req.perm.env, ProductEnvironment) \
                else req.perm.env.db_direct_query
            with db_query as db:
                cursor = db.cursor()
                cursor.execute(sql)
                items = cursor.fetchall()

            QUERY_COLS = [
                'id', 'summary', 'owner', 'type', 'status', 'priority'
            ]
            item_link = lambda item: req.href.query(col=QUERY_COLS + [fieldnm],
                                                    **{fieldnm: item[0]})
        else:
            query = Query.from_string(self.env, query, group=fieldnm)
            if query.group is None:
                data = check_field_name()
                if data is not None:
                    return data
                raise InvalidWidgetArgument(
                    'field', 'Invalid ticket field for ticket groups')

            fieldnm = query.group
            sql, v = query.get_sql()
            sql = "SELECT COALESCE(%(name)s, '') , count(COALESCE(%(name)s, ''))"\
                    "FROM (%(sql)s) AS foo GROUP BY COALESCE(%(name)s, '')" % \
                    { 'name' : fieldnm, 'sql' : sql }
            db = self.env.get_db_cnx()
            try:
                cursor = db.cursor()
                cursor.execute(sql, v)
                items = cursor.fetchall()
            finally:
                cursor.close()

            query_href = query.get_href(req.href)
            item_link= lambda item: query_href + \
                    '&' + unicode_urlencode([(fieldnm, item[0])])

        if fieldnm in self.DASH_ITEM_HREF_MAP:

            def dash_item_link(item):
                if item[0]:
                    args = self.DASH_ITEM_HREF_MAP[fieldnm] + (item[0], )
                    return req.href(*args)
                else:
                    return item_link(item)
        else:
            dash_item_link = item_link

        if title is None:
            heading = _(fieldnm.capitalize())
        else:
            heading = None

        return 'widget_cloud.html', \
                {
                    'title' : title,
                    'data' : dict(
                            bounds=minmax(items, lambda x: x[1]),
                            item_link=dash_item_link,
                            heading=heading,
                            items=items,
                            verbose=verbose,
                            view=view,
                        ),
                }, \
                context
Exemplo n.º 29
0
    def expand_macro(self, formatter, name, content, args=None):
        req = formatter.req
        # prepare options
        options, query_args = parse_options(self.env, content,
                                            copy.copy(DEFAULT_OPTIONS))

        query_args[self.remaining_field + "!"] = None
        tickets = execute_query(self.env, req, query_args)

        sum = 0.0
        estimations = {}
        for ticket in tickets:
            if ticket['status'] in self.closed_states:
                continue
            try:
                estimation = float(ticket[self.remaining_field])
                owner = ticket['owner']
                sum += estimation
                if owner in estimations:
                    estimations[owner] += estimation
                else:
                    estimations[owner] = estimation
            except:
                pass

        estimations_string = []
        labels = []
        for owner, estimation in estimations.iteritems():
            # Note: Unconditional obfuscation of owner in case it represents
            # an email adress, and as the chart API doesn't support SSL
            # (plain http transfer only, from either client or server).
            labels.append("%s %g%s" % (obfuscate_email_address(owner),
                                       round(estimation, 2),
                                       self.estimation_suffix))
            estimations_string.append(str(int(estimation)))

        # Title
        title = 'Workload'

        # calculate remaining work time
        if options.get('today') and options.get('enddate'):
            currentdate = options['today']
            day = timedelta(days=1)
            days_remaining = 0
            while currentdate <= options['enddate']:
                if currentdate.weekday() < 5:
                    days_remaining += 1
                currentdate += day
            title += ' %g%s (~%s workdays left)' % (round(sum, 2),
                                                    self.estimation_suffix,
                                                    days_remaining)

        chart_args = unicode_urlencode(
            {'chs': '%sx%s' % (options['width'], options['height']),
             'chf': 'bg,s,00000000',
             'chd': 't:%s' % ",".join(estimations_string),
             'cht': 'p3',
             'chtt': title,
             'chl': "|".join(labels),
             'chco': options['color']})
        self.log.debug("WorkloadChart data: %s", chart_args)
        if self.serverside_charts:
            return tag.image(
                src="%s?data=%s" % (req.href.estimationtools('chart'),
                                    unicode_quote(chart_args)),
                alt="Workload Chart (server)")
        else:
            return tag.image(
                src="http://chart.googleapis.com/chart?%s" % chart_args,
                alt="Workload Chart (client)")
Exemplo n.º 30
0
 def test_unicode_urlencode(self):
     self.assertEqual(
         "thing=%C3%9C&%C3%9C=thing&%C3%9Cthing", unicode_urlencode({u"Ü": "thing", "thing": u"Ü", u"Üthing": empty})
     )
Exemplo n.º 31
0
 def test_unicode_urlencode(self):
     self.assertEqual('thing=%C3%9C&%C3%9C=thing&%C3%9Cthing',
                      unicode_urlencode({u'Ü': 'thing',
                                         'thing': u'Ü',
                                         u'Üthing': empty}))
Exemplo n.º 32
0
    def render_widget(self, name, context, options):
        """Count ocurrences of values assigned to given ticket field.
        """
        req = context.req
        params = ('field', 'query', 'verbose', 'threshold', 'max', 'title',
                  'view')
        fieldnm, query, verbose, threshold, maxitems, title, view = \
                self.bind_params(name, options, *params)
        
        field_maps = {'type': {'admin_url': 'type',
                               'title': 'Types',
                               },
                      'status': {'admin_url': None,
                                 'title': 'Statuses',
                                 },
                      'priority': {'admin_url': 'priority',
                                   'title': 'Priorities',
                                   },
                      'milestone': {'admin_url': 'milestones',
                                    'title': 'Milestones',
                                    },
                      'component': {'admin_url': 'components',
                                    'title': 'Components',
                                    },
                      'version': {'admin_url': 'versions',
                                  'title': 'Versions',
                                  },
                      'severity': {'admin_url': 'severity',
                                   'title': 'Severities',
                                   },
                      'resolution': {'admin_url': 'resolution',
                                     'title': 'Resolutions',
                                     },
                      }
        _field = []
        def check_field_name():
            if fieldnm is None:
                raise InvalidWidgetArgument('field', 'Missing ticket field')
            tsys = self.env[TicketSystem]
            if tsys is None:
                raise TracError(_('Error loading ticket system (disabled?)'))
            for field in tsys.get_ticket_fields():
                if field['name'] == fieldnm:
                    _field.append(field)
                    break
            else:
                if fieldnm in field_maps:
                    admin_suffix = field_maps.get(fieldnm)['admin_url']
                    if 'TICKET_ADMIN' in req.perm and admin_suffix is not None:
                        hint = _('You can add one or more '
                                 '<a href="%(url)s">here</a>.',
                                url=req.href.admin('ticket', admin_suffix))
                    else:
                        hint = _('Contact your administrator for further details')
                    return 'widget_alert.html', \
                            {
                                'title' : Markup(_('%(field)s',
                                            field=field_maps[fieldnm]['title'])),
                                'data' : dict(msgtype='info',
                                    msglabel="Note",
                                    msgbody=Markup(_('''No values are
                                        defined for ticket field
                                        <em>%(field)s</em>. %(hint)s''',
                                        field=fieldnm, hint=hint))
                                    )
                            }, context
                else:
                    raise InvalidWidgetArgument('field', 
                            'Unknown ticket field %s' % (fieldnm,))
            return None
        
        if query is None :
            data = check_field_name()
            if data is not None:
                return data
            field = _field[0]
            if field.get('custom'):
                sql = "SELECT COALESCE(value, ''), count(COALESCE(value, ''))" \
                        " FROM ticket_custom " \
                        " WHERE name='%(name)s' GROUP BY COALESCE(value, '')"
            else:
                sql = "SELECT COALESCE(%(name)s, ''), " \
                        "count(COALESCE(%(name)s, '')) FROM ticket " \
                        "GROUP BY COALESCE(%(name)s, '')"
            sql = sql % field
            # TODO : Implement threshold and max

            db_query = req.perm.env.db_query \
                if isinstance(req.perm.env, ProductEnvironment) \
                else req.perm.env.db_direct_query
            with db_query as db:
                cursor = db.cursor()
                cursor.execute(sql)
                items = cursor.fetchall()

            QUERY_COLS = ['id', 'summary', 'owner', 'type', 'status', 'priority']
            item_link= lambda item: req.href.query(col=QUERY_COLS + [fieldnm], 
                                                    **{fieldnm:item[0]})
        else:
            query = Query.from_string(self.env, query, group=fieldnm)
            if query.group is None:
                data = check_field_name()
                if data is not None:
                    return data
                raise InvalidWidgetArgument('field', 
                        'Invalid ticket field for ticket groups')

            fieldnm = query.group
            sql, v = query.get_sql() 
            sql = "SELECT COALESCE(%(name)s, '') , count(COALESCE(%(name)s, ''))"\
                    "FROM (%(sql)s) AS foo GROUP BY COALESCE(%(name)s, '')" % \
                    { 'name' : fieldnm, 'sql' : sql }
            db = self.env.get_db_cnx()
            try :
                cursor = db.cursor()
                cursor.execute(sql, v)
                items = cursor.fetchall()
            finally:
                cursor.close()

            query_href = query.get_href(req.href)
            item_link= lambda item: query_href + \
                    '&' + unicode_urlencode([(fieldnm, item[0])])

        if fieldnm in self.DASH_ITEM_HREF_MAP:
            def dash_item_link(item):
                if item[0]:
                    args = self.DASH_ITEM_HREF_MAP[fieldnm] + (item[0],)
                    return req.href(*args)
                else:
                    return item_link(item)
        else:
            dash_item_link = item_link

        if title is None:
            heading = _(fieldnm.capitalize())
        else:
            heading = None

        return 'widget_cloud.html', \
                {
                    'title' : title,
                    'data' : dict(
                            bounds=minmax(items, lambda x: x[1]),
                            item_link=dash_item_link,
                            heading=heading,
                            items=items,
                            verbose=verbose,
                            view=view,
                        ), 
                }, \
                context
Exemplo n.º 33
0
    def expand_macro(self, formatter, name, content, args=None):

        # prepare options
        req = formatter.req
        options, query_args = parse_options(self.env, content,
                                            copy.copy(DEFAULT_OPTIONS))

        if not options['startdate']:
            raise TracError("No start date specified!")

        # minimum time frame is one day
        if options['startdate'] >= options['enddate']:
            options['enddate'] = options['startdate'] + timedelta(days=1)

        # calculate data
        timetable = self._calculate_timetable(options, query_args, req)
        timetable_spent = self._calculate_timetable_spent(options, query_args, req)
        
        # remove weekends
        if not options['weekends']:
            for date in timetable.keys():
                if date.weekday() >= 5:
                    del timetable[date]
                    del timetable_spent[date]

        # scale data
        xdata, ydata, maxhours = self._scale_data(timetable, options)
        xdata_spent, ydata_spent, maxhours_spent = self._scale_data(timetable_spent, options)
        if not options['spent']:
            spentdata = "|0,0|0,0"
        else:
            spentdata = "|%s|%s" % (",".join(xdata_spent), ",".join(ydata_spent))

        # build html for google chart api
        dates = sorted(timetable.keys())
        bottomaxis = "0:|" + "|".join([str(date.day) for date in dates]) + \
                     "|1:|%s/%s|%s/%s" % (dates[0].month, dates[0].year,
                                          dates[- 1].month, dates[- 1].year)
        leftaxis = "2,0,%s" % maxhours

        # add line for expected progress
        if options['expected'] == '0':
            expecteddata = ""
        else:
            expecteddata = "|0,100|%s,0" % (
                round(Decimal(options['expected']) * 100 / maxhours, 2))

        # prepare gridlines
        if options['gridlines'] == '0':
            # create top and right bounding line by using grid
            gridlinesdata = "100.0,100.0,1,0"
        else:
            gridlinesdata = "%s,%s" % (xdata[1], (
                round(Decimal(options['gridlines']) * 100 / maxhours, 4)))

        # mark weekends
        weekends = []
        saturday = None
        index = 0
        halfday = self._round(Decimal("0.5") / (len(dates) - 1))
        for date in dates:
            if date.weekday() == 5:
                saturday = index
            if saturday and date.weekday() == 6:
                weekends.append("R,%s,0,%s,%s" %
                                (options['wecolor'],
                                 self._round((Decimal(
                                     xdata[saturday]) / 100) - halfday),
                                 self._round(
                                     (Decimal(xdata[index]) / 100) + halfday)))
                saturday = None
            index += 1
        # special handling if time period starts with Sundays...
        if len(dates) > 0 and dates[0].weekday() == 6:
            weekends.append("R,%s,0,0.0,%s" % (options['wecolor'], halfday))
        # or ends with Saturday
        if len(dates) > 0 and dates[- 1].weekday() == 5:
            weekends.append(
                "R,%s,0,%s,1.0" % (options['wecolor'], Decimal(1) - halfday))

        # chart title
        title = options.get('title', None)
        if title is None and options.get('milestone'):
            title = options['milestone'].split('|')[0]

        chart_args = unicode_urlencode(
                    {'chs': '%sx%s' % (options['width'], options['height']),
                     'chf': 'c,s,%s|bg,s,00000000' % options['bgcolor'],
                     'chd': 't:%s|%s%s%s' % (",".join(xdata), ",".join(ydata), spentdata, expecteddata),
                     'cht': 'lxy',
                     'chxt': 'x,x,y',
                     'chxl': bottomaxis,
                     'chxr': leftaxis,
                     'chm': "|".join(weekends),
                     'chg': gridlinesdata,
                     'chco': '%s,%s,%s' % (options['color'], options['colorspent'], options['colorexpected']),
                     'chdl': 'Remaining|Spent|Estimated',
                     'chtt': title})
        self.log.debug("BurndownChart data: %s", chart_args)
        if self.serverside_charts:
            return tag.image(
                src="%s?data=%s" % (req.href.estimationtools('chart'),
                                    unicode_quote(chart_args)),
                alt="Burndown Chart (server)")
        else:
            return tag.image(
                src="http://chart.googleapis.com/chart?%s" % chart_args,
                alt="Burndown Chart (client)")
Exemplo n.º 34
0
    def filter_stream(self, req, method, filename, stream, data):
        #        self.list_namespaces()
        # generate TracLink string
        resource = None
        if filename in ['ticket.html', 'wiki_view.html', 'report_view.html', 'milestone_view.html', 'agilo_ticket_view.html'] \
                and 'context' in data:
            resource = data['context'].resource
        elif filename in ['search.html']:  # search:
            resource = Resource('search', data['query'])
        elif filename in ['browser.html']:  # source:
            resource = data['context'].resource
            if resource.parent and resource.parent.realm == 'repository':
                resource.id = '%s/%s' % (resource.parent.id, resource.id)
                resource.parent = None
        elif filename in ['revisionlog.html']:  # log:
            resource = data['context'].resource
            resource.realm = 'log'
            if resource.parent and resource.parent.realm == 'repository':
                resource.id = '%s/%s' % (resource.parent.id, resource.id)
                resource.parent = None
            revranges = data.get('revranges', None)
            rev = data.get('rev', None)
            if revranges:
                resource.version = '%s:%s' % (revranges.a, revranges.b)
            elif rev:
                resource.version = rev
        elif filename in ['attachment.html']:
            if isinstance(data['attachment'], Attachment):  # attachment:
                resource = data['attachment'].resource
            else:
                pass  # attachment list page of the ticket; no TracLinks defined
        elif filename in ['timeline.html']:  # timeline:
            resource = Resource(
                'timeline', format_datetime(data['precisedate'], 'iso8601'))
        elif filename in ['changeset.html']:
            if data['changeset']:  # changeset:
                resource = data['context'].resource
                if resource.parent and resource.parent.realm == 'repository':
                    resource.id = '%s/%s' % (resource.id, resource.parent.id
                                             )  # OK, I know
                    resource.parent = None
                if data['restricted']:
                    resource.id = '%s/%s' % (resource.id, data['new_path'])
            else:  # diff:
                args = req.args
                old_path, new_path = args.get('old_path',
                                              ''), args.get('new_path', '')
                old_rev, new_rev = args.get('old'), args.get('new')
                if old_path == new_path:  # diff:path@1:3 style
                    resource = Resource('diff', old_path,
                                        '%s:%s' % (old_rev, new_rev))
                else:  # diff:path@1//path@3 style
                    if old_rev:
                        old_path += '@%s' % old_rev
                    if new_rev:
                        new_path += '@%s' % new_rev
                    resource = Resource('diff',
                                        '%s//%s' % (old_path, new_path))
        elif filename in ['query.html']:
            if 'report_resource' in data:
                resource = data['report_resource']
            else:
                resource = Resource(
                    'query', data['query'].to_string().replace("\n", "")[7:])
        else:
            pass
        # link hash TODO: check wiki_view for agilo
        if filename in [
                'browser.html', 'ticket.html', 'agilo_ticket_view.html',
                'wiki_view.html'
        ]:
            add_script(req, 'traclinks/js/jquery.ba-hashchange.js')
            add_script(req, 'traclinks/js/onhashchange.js')
        #
        if resource:
            traclinks = '%s' % (resource.id)
            if resource.version != None:
                traclinks += (resource.realm == 'ticket' and '?version=%s'
                              or '@%s') % resource.version
            if resource.parent and resource.parent.id:
                traclinks += ':%s:%s' % (resource.parent.realm,
                                         resource.parent.id)
                if resource.parent.version != None:
                    traclinks += '@%s' % resource.parent.version
            if ' ' in traclinks:
                traclinks = '"%s"' % traclinks  # surround quote if needed
            traclinks = '%s:%s' % (resource.realm, traclinks)
            # new ticket template
            if resource.id == None and resource.realm == 'ticket':
                query_string = unicode_urlencode([
                    (k, v) for k, v in data['ticket'].values.iteritems()
                    if v not in (None, '')
                ])
                traclinks = '[/newticket?%s]' % query_string

            return stream | Transformer('//input[@id="proj-search"]').attr(
                'value', traclinks).attr('size', '50')
        return stream
Exemplo n.º 35
0
    def process_request(self, req):
        """The appropriate mode of operation is inferred from the request
        parameters:

         * If `new_path` and `old_path` are equal (or `old_path` is omitted)
           and `new` and `old` are equal (or `old` is omitted),
           then we're about to view a revision Changeset: `chgset` is True.
           Furthermore, if the path is not the root, the changeset is
           ''restricted'' to that path (only the changes affecting that path,
           its children or its ancestor directories will be shown).
         * In any other case, the set of changes corresponds to arbitrary
           differences between path@rev pairs. If `new_path` and `old_path`
           are equal, the ''restricted'' flag will also be set, meaning in this
           case that the differences between two revisions are restricted to
           those occurring on that path.

        In any case, either path@rev pairs must exist.
        """
        req.perm.assert_permission('CHANGESET_VIEW')

        # -- retrieve arguments
        new_path = req.args.get('new_path')
        new = req.args.get('new')
        old_path = req.args.get('old_path')
        old = req.args.get('old')

        if old and '@' in old:
            old_path, old = unescape(old).split('@')
        if new and '@' in new:
            new_path, new = unescape(new).split('@')

        # -- normalize and check for special case
        repos = self.env.get_repository(req.authname)
        new_path = repos.normalize_path(new_path)
        new = repos.normalize_rev(new)

        repos.authz.assert_permission_for_changeset(new)

        old_path = repos.normalize_path(old_path or new_path)
        old = repos.normalize_rev(old or new)

        if old_path == new_path and old == new: # revert to Changeset
            old_path = old = None

        diff_options = get_diff_options(req)

        # -- setup the `chgset` and `restricted` flags, see docstring above.
        chgset = not old and not old_path
        if chgset:
            restricted = new_path not in ('', '/') # (subset or not)
        else:
            restricted = old_path == new_path # (same path or not)

        # -- redirect if changing the diff options
        if req.args.has_key('update'):
            if chgset:
                if restricted:
                    req.redirect(req.href.changeset(new, new_path))
                else:
                    req.redirect(req.href.changeset(new))
            else:
                req.redirect(req.href.changeset(new, new_path, old=old,
                                                old_path=old_path))

        # -- preparing the diff arguments
        if chgset:
            prev = repos.get_node(new_path, new).get_previous()
            if prev:
                prev_path, prev_rev = prev[:2]
            else:
                prev_path, prev_rev = new_path, repos.previous_rev(new)
            diff_args = DiffArgs(old_path=prev_path, old_rev=prev_rev,
                                 new_path=new_path, new_rev=new)
        else:
            if not new:
                new = repos.youngest_rev
            elif not old:
                old = repos.youngest_rev
            if not old_path:
                old_path = new_path
            diff_args = DiffArgs(old_path=old_path, old_rev=old,
                                 new_path=new_path, new_rev=new)
        if chgset:
            chgset = repos.get_changeset(new)
            message = chgset.message or '--'
            if self.wiki_format_messages:
                message = wiki_to_html(message, self.env, req,
                                              escape_newlines=True)
            else:
                message = html.PRE(message)
            req.check_modified(chgset.date, [
                diff_options[0],
                ''.join(diff_options[1]),
                repos.name,
                repos.rev_older_than(new, repos.youngest_rev),
                message,
                pretty_timedelta(chgset.date, None, 3600)])
        else:
            message = None # FIXME: what date should we choose for a diff?

        req.hdf['changeset'] = diff_args

        format = req.args.get('format')

        if format in ['diff', 'zip']:
            req.perm.assert_permission('FILE_VIEW')
            # choosing an appropriate filename
            rpath = new_path.replace('/','_')
            if chgset:
                if restricted:
                    filename = 'changeset_%s_r%s' % (rpath, new)
                else:
                    filename = 'changeset_r%s' % new
            else:
                if restricted:
                    filename = 'diff-%s-from-r%s-to-r%s' \
                                  % (rpath, old, new)
                elif old_path == '/': # special case for download (#238)
                    filename = '%s-r%s' % (rpath, old)
                else:
                    filename = 'diff-from-%s-r%s-to-%s-r%s' \
                               % (old_path.replace('/','_'), old, rpath, new)
            if format == 'diff':
                self._render_diff(req, filename, repos, diff_args,
                                  diff_options)
                return
            elif format == 'zip':
                self._render_zip(req, filename, repos, diff_args)
                return

        # -- HTML format
        self._render_html(req, repos, chgset, restricted, message,
                          diff_args, diff_options)
        if chgset:
            diff_params = 'new=%s' % new
        else:
            diff_params = unicode_urlencode({'new_path': new_path,
                                             'new': new,
                                             'old_path': old_path,
                                             'old': old})
        add_link(req, 'alternate', '?format=diff&'+diff_params, 'Unified Diff',
                 'text/plain', 'diff')
        add_link(req, 'alternate', '?format=zip&'+diff_params, 'Zip Archive',
                 'application/zip', 'zip')
        add_stylesheet(req, 'common/css/changeset.css')
        add_stylesheet(req, 'common/css/diff.css')
        add_stylesheet(req, 'common/css/code.css')
        return 'changeset.cs', None
Exemplo n.º 36
0
    def process_request(self, req):
        """The appropriate mode of operation is inferred from the request
        parameters:

         * If `new_path` and `old_path` are equal (or `old_path` is omitted)
           and `new` and `old` are equal (or `old` is omitted),
           then we're about to view a revision Changeset: `chgset` is True.
           Furthermore, if the path is not the root, the changeset is
           ''restricted'' to that path (only the changes affecting that path,
           its children or its ancestor directories will be shown).
         * In any other case, the set of changes corresponds to arbitrary
           differences between path@rev pairs. If `new_path` and `old_path`
           are equal, the ''restricted'' flag will also be set, meaning in this
           case that the differences between two revisions are restricted to
           those occurring on that path.

        In any case, either path@rev pairs must exist.
        """
        req.perm.assert_permission('CHANGESET_VIEW')

        # -- retrieve arguments
        new_path = req.args.get('new_path')
        new = req.args.get('new')
        old_path = req.args.get('old_path')
        old = req.args.get('old')

        if old and '@' in old:
            old_path, old = unescape(old).split('@')
        if new and '@' in new:
            new_path, new = unescape(new).split('@')

        # -- normalize and check for special case
        repos = self.env.get_repository(req.authname)
        new_path = repos.normalize_path(new_path)
        new = repos.normalize_rev(new)

        repos.authz.assert_permission_for_changeset(new)

        old_path = repos.normalize_path(old_path or new_path)
        old = repos.normalize_rev(old or new)

        if old_path == new_path and old == new: # revert to Changeset
            old_path = old = None

        diff_options = get_diff_options(req)

        # -- setup the `chgset` and `restricted` flags, see docstring above.
        chgset = not old and not old_path
        if chgset:
            restricted = new_path not in ('', '/') # (subset or not)
        else:
            restricted = old_path == new_path # (same path or not)

        # -- redirect if changing the diff options
        if req.args.has_key('update'):
            if chgset:
                if restricted:
                    req.redirect(req.href.changeset(new, new_path))
                else:
                    req.redirect(req.href.changeset(new))
            else:
                req.redirect(req.href.changeset(new, new_path, old=old,
                                                old_path=old_path))

        # -- preparing the diff arguments
        if chgset:
            prev = repos.get_node(new_path, new).get_previous()
            if prev:
                prev_path, prev_rev = prev[:2]
            else:
                prev_path, prev_rev = new_path, repos.previous_rev(new)
            diff_args = DiffArgs(old_path=prev_path, old_rev=prev_rev,
                                 new_path=new_path, new_rev=new)
        else:
            if not new:
                new = repos.youngest_rev
            elif not old:
                old = repos.youngest_rev
            if not old_path:
                old_path = new_path
            diff_args = DiffArgs(old_path=old_path, old_rev=old,
                                 new_path=new_path, new_rev=new)
        if chgset:
            chgset = repos.get_changeset(new)
            message = chgset.message or '--'
            if self.wiki_format_messages:
                message = wiki_to_html(message, self.env, req,
                                              escape_newlines=True)
            else:
                message = html.PRE(message)
            req.check_modified(chgset.date, [
                diff_options[0],
                ''.join(diff_options[1]),
                repos.name,
                repos.rev_older_than(new, repos.youngest_rev),
                message,
                pretty_timedelta(chgset.date, None, 3600)])
        else:
            message = None # FIXME: what date should we choose for a diff?

        req.hdf['changeset'] = diff_args

        format = req.args.get('format')

        if format in ['diff', 'zip']:
            req.perm.assert_permission('FILE_VIEW')
            # choosing an appropriate filename
            rpath = new_path.replace('/','_')
            if chgset:
                if restricted:
                    filename = 'changeset_%s_r%s' % (rpath, new)
                else:
                    filename = 'changeset_r%s' % new
            else:
                if restricted:
                    filename = 'diff-%s-from-r%s-to-r%s' \
                                  % (rpath, old, new)
                elif old_path == '/': # special case for download (#238)
                    filename = '%s-r%s' % (rpath, old)
                else:
                    filename = 'diff-from-%s-r%s-to-%s-r%s' \
                               % (old_path.replace('/','_'), old, rpath, new)
            if format == 'diff':
                self._render_diff(req, filename, repos, diff_args,
                                  diff_options)
                return
            elif format == 'zip':
                self._render_zip(req, filename, repos, diff_args)
                return

        # -- HTML format
        self._render_html(req, repos, chgset, restricted, message,
                          diff_args, diff_options)
        if chgset:
            diff_params = 'new=%s' % new
        else:
            diff_params = unicode_urlencode({'new_path': new_path,
                                             'new': new,
                                             'old_path': old_path,
                                             'old': old})
        add_link(req, 'alternate', '?format=diff&'+diff_params, 'Unified Diff',
                 'text/plain', 'diff')
        add_link(req, 'alternate', '?format=zip&'+diff_params, 'Zip Archive',
                 'application/zip', 'zip')
        add_stylesheet(req, 'common/css/changeset.css')
        add_stylesheet(req, 'common/css/diff.css')
        add_stylesheet(req, 'common/css/code.css')
        return 'changeset.cs', None