def get_search_results(self, req, query, filters):
        if 'repo' not in filters:
            return

        for filename, reponame in self.search_backend.find_words(query):
            repo = self.env.get_repository(reponame=reponame, authname=req.authname)
            node = repo.get_node(filename)

            if node.kind == Node.DIRECTORY:
                yield (self.env.href.browser(reponame, filename),
                       "%s (in %s)" % (filename, reponame), change.date, change.author,
                       'Directory')
            else:
                found = 0
                mimeview = Mimeview(self.env)
                content = mimeview.to_unicode(node.get_content().read(), node.get_content_type())
                for n, line in enumerate(content.splitlines()):
                    line = line.lower()
                    for q in query:
                        idx = line.find(q)
                        if idx != -1:
                            found = n + 1
                            break
                    if found:
                        break

                change = repo.get_changeset(node.rev)

                yield (self.env.href.browser(reponame, filename
                                             ) + (found and '#L%i' % found or ''
                                                  ),
                       "%s (in %s)" % (filename, reponame), change.date, change.author,
                       shorten_result(content, query))
Beispiel #2
0
    def expand_macro(self, formatter, name, content):
        from trac.mimeview.api import Mimeview
        mime_map = Mimeview(self.env).mime_map
        mime_type_filter = ''
        args, kw = parse_args(content)
        if args:
            mime_type_filter = args.pop(0).strip().rstrip('*')

        mime_types = {}
        for key, mime_type in mime_map.iteritems():
            if (not mime_type_filter or
                mime_type.startswith(mime_type_filter)) and key != mime_type:
                mime_types.setdefault(mime_type, []).append(key)

        return tag.div(class_='mimetypes')(
            tag.table(class_='wiki')(
                tag.thead(tag.tr(
                    tag.th(_("MIME Types")),  # always use plural
                    tag.th(tag.a("WikiProcessors",
                                 href=formatter.context.href.wiki(
                                     'WikiProcessors'))))),
                tag.tbody(
                    tag.tr(tag.th(tag.tt(mime_type),
                                  style="text-align: left"),
                           tag.td(tag.code(
                               ' '.join(sorted(mime_types[mime_type])))))
                    for mime_type in sorted(mime_types.keys()))))
Beispiel #3
0
    def _render_file(self, req, context, repos, node, rev=None):
        """ trac.versioncontrol.web_ui.browser.BrowserModule._render_file()
        copy with just the essentials needed for our purpose. """

        req.perm(context.resource).require('FILE_VIEW')

        mimeview = Mimeview(self.env)
        # MIME type detection
        CHUNK_SIZE = 4096
        content = node.get_content()
        chunk = content.read(CHUNK_SIZE)
        mime_type = node.content_type
        if not mime_type or mime_type == 'application/octet-stream':
            mime_type = mimeview.get_mimetype(node.name, chunk) or \
                        mime_type or 'text/plain'

        self.log.debug("Rendering ReposReadMe of node %s@%s with mime-type %s"
                       % (node.name, str(rev), mime_type))
        del content # the remainder of that content is not needed
        add_stylesheet(req, 'common/css/code.css')

        annotations = []
        force_source = False
        raw_href = ''
        return mimeview.preview_data(context, node.get_content(),
                                             node.get_content_length(),
                                             mime_type, node.created_path,
                                             raw_href,
                                             annotations=annotations,
                                             force_source=force_source)
Beispiel #4
0
 def test_extra_mimetypes(self):
     """
     The text/x-ini mimetype is normally not known by Trac, but
     Pygments supports it.
     """
     mimeview = Mimeview(self.env)
     self.assertEqual('text/x-ini; charset=utf-8',
                      mimeview.get_mimetype('file.ini'))
     self.assertEqual('text/x-ini; charset=utf-8',
                      mimeview.get_mimetype('file.cfg'))
     self.assertEqual('text/x-ini; charset=utf-8',
                      mimeview.get_mimetype('file.text/x-ini'))
Beispiel #5
0
 def _test_convert_content(self, expected, content, iterable):
     mimeview = Mimeview(self.env)
     output = mimeview.convert_content(self._make_req(), self.in_mimetype,
                                       content, 'text', iterable=iterable)
     if iterable:
         self.assertNotIn(type(output[0]), (str, unicode))
         self.assertEqual(expected, ''.join(output[0]))
     else:
         self.assertEqual(type(expected), type(output[0]))
         self.assertEqual(expected, output[0])
     self.assertEqual('text/plain', output[1])
     self.assertEqual('txt', output[2])
 def setUp(self):
     self.env = EnvironmentStub()
     self.ticket_module = TicketModule(self.env)
     self.mimeview = Mimeview(self.env)
     self.req = Mock(hdf=HDFWrapper(['./templates']),
                     base_path='/trac.cgi', path_info='',
                     href=Href('/trac.cgi'))
Beispiel #7
0
    def __init__(self, env, node, root, base):
        super(FilePage, self).__init__(env, node, root, base)
        self.mimeview = Mimeview(self.env)
        self.exists = (node is not None)

        self.mime_type = None
        self.chunk = None
Beispiel #8
0
class ProductTicketConversionTestCase(TicketConversionTestCase, \
        MultiproductTestCase):

    def setUp(self):
        self._mp_setup()
        self.global_env = self.env
        self.env = ProductEnvironment(self.global_env, self.default_product)

        # Product name inserted in RSS feed
        self.env.product._data['name'] = 'My Project'

        self.env.config.set('trac', 'templates_dir',
                            os.path.join(os.path.dirname(self.env.path),
                                         'templates'))
        self.ticket_module = ProductTicketModule(self.env)
        self.mimeview = Mimeview(self.env)
        self.req = Mock(base_path='/trac.cgi', path_info='',
                        href=Href('/trac.cgi'), chrome={'logo': {}},
                        abs_href=Href('http://example.org/trac.cgi'),
                        environ={}, perm=[], authname='-', args={}, tz=None,
                        locale='', session=None, form_token=None)

    def test_csv_conversion(self):
        ticket = self._create_a_ticket()
        csv = self.mimeview.convert_content(self.req, 'trac.ticket.Ticket',
                                            ticket, 'csv')
        self.assertEqual(('\xef\xbb\xbf'
                          'id,summary,reporter,owner,description,status,'
                          'product,keywords,cc\r'
                          '\n1,Foo,santa,,Bar,,,,\r\n',
                          'text/csv;charset=utf-8', 'csv'), csv)

    def test_tab_conversion(self):
        ticket = self._create_a_ticket()
        csv = self.mimeview.convert_content(self.req, 'trac.ticket.Ticket',
                                            ticket, 'tab')
        self.assertEqual(('\xef\xbb\xbf'
                          'id\tsummary\treporter\towner\tdescription\tstatus\t'
                          'product\tkeywords\tcc\r\n'
                          '1\tFoo\tsanta\t\tBar\t\t\t\t\r\n',
                          'text/tab-separated-values;charset=utf-8', 'tsv'),
                         csv)

    def tearDown(self):
        self.global_env.reset_db()
Beispiel #9
0
 def setUp(self):
     env = EnvironmentStub(enable=[Chrome, PatchRenderer])
     req = Mock(base_path='', chrome={'static_hash': None}, args={},
                session={}, abs_href=Href('/'), href=Href('/'), locale='',
                perm=MockPerm(), authname=None, tz=None)
     self.context = web_context(req)
     self.patch = Mimeview(env).renderers[0]
     patch_html = open(os.path.join(os.path.split(__file__)[0],
                                    'patch.html'))
     self.patch_html = Stream(list(HTMLParser(patch_html, encoding='utf-8')))
Beispiel #10
0
 def setUp(self):
     env = EnvironmentStub(enable=[Chrome, PatchRenderer])
     req = Mock(base_path='', chrome={}, args={}, session={},
                abs_href=Href('/'), href=Href('/'),
                perm=MockPerm(), authname=None, tz=None)
     self.context = Context.from_request(req)
     self.patch = Mimeview(env).renderers[0]
     patch_html = open(os.path.join(os.path.split(__file__)[0],
                                    'patch.html'))
     self.patch_html = Stream(list(HTMLParser(patch_html)))
Beispiel #11
0
 def setUp(self):
     self.env = EnvironmentStub(enable=[Chrome, PygmentsRenderer])
     self.pygments = Mimeview(self.env).renderers[0]
     self.req = Mock(base_path='', chrome={}, args={},
                     abs_href=Href('/'), href=Href('/'),
                     session={}, perm=None, authname=None, tz=None)
     self.context = web_context(self.req)
     pygments_html = open(os.path.join(os.path.split(__file__)[0],
                                    'pygments.html'))
     self.pygments_html = Stream(list(HTMLParser(pygments_html, encoding='utf-8')))
Beispiel #12
0
 def setUp(self):
     self.env = EnvironmentStub()
     self.env.config.set('trac', 'templates_dir',
                         os.path.join(os.path.dirname(self.env.path),
                                      'templates'))
     self.ticket_module = TicketModule(self.env)
     self.mimeview = Mimeview(self.env)
     self.req = Mock(base_path='/trac.cgi', path_info='',
                     href=Href('/trac.cgi'), chrome={'logo': {}},
                     abs_href=Href('http://example.org/trac.cgi'),
                     environ={}, perm=[], authname='-', args={}, tz=None,
                     session=None, form_token=None)
Beispiel #13
0
    def test_get_supported_conversions(self):
        class Converter0(Component):
            implements(IContentConverter)
            def get_supported_conversions(self):
                yield 'key0', 'Format 0', 'c0', 'text/x-sample', 'text/html', 8

        class Converter2(Component):
            implements(IContentConverter)
            def get_supported_conversions(self):
                yield 'key2', 'Format 2', 'c2', 'text/x-sample', 'text/html', 2

        class Converter1(Component):
            implements(IContentConverter)
            def get_supported_conversions(self):
                yield 'key1', 'Format 1', 'c1', 'text/x-sample', 'text/html', 4

        mimeview = Mimeview(self.env)
        conversions = mimeview.get_supported_conversions('text/x-sample')
        self.assertEqual(Converter0(self.env), conversions[0][-1])
        self.assertEqual(Converter1(self.env), conversions[1][-1])
        self.assertEqual(Converter2(self.env), conversions[2][-1])
Beispiel #14
0
 def process_combinewiki(self, req, format, title, pages):
     # Dump all pages to HTML files
     files = [self._page_to_file(req, p) for p in pages]
     titlefile = self._page_to_file(req, title, self.TITLE_HTML%title)
         
     # File to write PDF to
     pfile, pfilename = mkstemp('tracpdf')
     os.close(pfile)       
      
     # Render
     os.environ["HTMLDOC_NOCGI"] = 'yes'
     codepage = Mimeview(self.env).default_charset
     htmldoc_format = {'pdf': 'pdf14', 'ps':'ps3'}[format]
     htmldoc_args = { 'book': None, 'format': htmldoc_format, 'left': '1.5cm',
                      'right': '1.5cm', 'top': '1.5cm', 'bottom': '1.5cm',
                      'charset': codepage.replace('iso-', ''), 'title': None,
                      'titlefile': titlefile}
     htmldoc_args.update(dict(self.env.config.options('pagetopdf')))
     htmldoc_args.update(dict(self.env.config.options('combinewiki')))
     args_string = ' '.join(['--%s %s' % (arg, value or '') for arg, value
                             in htmldoc_args.iteritems()])
     cmd_string = 'htmldoc %s %s -f %s'%(args_string, ' '.join(files), pfilename)
     self.log.info('CombineWikiModule: Running %r', cmd_string)
     os.system(cmd_string)
         
     out = open(pfilename, 'rb').read()
         
     # Clean up
     os.unlink(pfilename)
     for f in files:
         os.unlink(f)
     os.unlink(titlefile)
           
     # Send the output
     req.send_response(200)
     req.send_header('Content-Type', {'pdf':'application/pdf', 'ps':'application/postscript'}[format])
     req.send_header('Content-Length', len(out))
     req.end_headers()
     req.write(out)
     raise RequestDone
Beispiel #15
0
    def _types(self):
        types = {}
        for lexer_name, aliases, _, mimetypes in get_all_lexers():
            name = aliases[0] if aliases else lexer_name
            for mimetype in mimetypes:
                types[mimetype] = (name, self.QUALITY_RATIO)

        # Pygments < 1.4 doesn't know application/javascript
        if 'application/javascript' not in types:
            js_entry = types.get('text/javascript')
            if js_entry:
                types['application/javascript'] = js_entry

        types.update(Mimeview(self.env).configured_modes_mapping('pygments'))
        return types
Beispiel #16
0
    def expand_macro(self, formatter, name, content):
        add_stylesheet(formatter.req, 'lineno/css/lineno.css')

        i = 1
        self._anchor = 'a1'
        while self._anchor in formatter._anchors:
            self._anchor = 'a' + str(i)
            i += 1
        formatter._anchors[self._anchor] = True

        mt = 'txt'
        match = WikiParser._processor_re.match(content)
        if match:
            try: #Trac 0.12+
                mt = match.group(2)
                content = content[match.end(2)+1:]
            except IndexError: #Trac 0.11
                mt = match.group(1)
                content = content[match.end(1)+1:]
        
        mimeview = Mimeview(formatter.env)
        mimetype = mimeview.get_mimetype(mt) or mimeview.get_mimetype('txt')        
        return mimeview.render(formatter.context, mimetype,
                               content, annotations=['codeblock-lineno'])
Beispiel #17
0
 def test_python_hello_mimeview(self):
     """
     Simple Python highlighting with Pygments (through Mimeview.render)
     """
     result = Mimeview(self.env).render(
         self.context, self.python_mimetype,
         textwrap.dedent("""
         def hello():
                 return "Hello World!"
         """))
     self.assertTrue(result)
     if pygments_version < parse_version('2.1'):
         self._test('python_hello_mimeview', result)
     else:
         self._test('python_hello_mimeview_pygments_2.1plus', result)
Beispiel #18
0
    def test_get_supported_conversions(self):
        class Converter0(Component):
            implements(IContentConverter)

            def get_supported_conversions(self):
                yield 'key0', 'Format 0', 'c0', 'text/x-sample', 'text/html', 8

        class Converter2(Component):
            implements(IContentConverter)

            def get_supported_conversions(self):
                yield 'key2', 'Format 2', 'c2', 'text/x-sample', 'text/html', 2

        class Converter1(Component):
            implements(IContentConverter)

            def get_supported_conversions(self):
                yield 'key1', 'Format 1', 'c1', 'text/x-sample', 'text/html', 4

        mimeview = Mimeview(self.env)
        conversions = mimeview.get_supported_conversions('text/x-sample')
        self.assertEqual(Converter0(self.env), conversions[0].converter)
        self.assertEqual(Converter1(self.env), conversions[1].converter)
        self.assertEqual(Converter2(self.env), conversions[2].converter)
Beispiel #19
0
    def render(self, context, mimetype, content, filename=None, rev=None):
        req = context.req
        content = content_to_unicode(self.env, content, mimetype)
        changes = self._diff_to_hdf(content.splitlines(),
                                    Mimeview(self.env).tab_width)
        if not changes or not any(c['diffs'] for c in changes):
            self.log.debug("Invalid unified diff content: %.40r... (%d "
                           "characters)", content, len(content))
            return
        data = {'diff': {'style': 'inline'}, 'no_id': True,
                'changes': changes, 'longcol': 'File', 'shortcol': ''}

        add_script(req, 'common/js/diff.js')
        add_stylesheet(req, 'common/css/diff.css')
        return Chrome(self.env).render_fragment(req, 'diff_div.html', data)
Beispiel #20
0
    def _init_types(self):
        self._types = {}
        for lexname, aliases, _, mimetypes in get_all_lexers():
            name = aliases and aliases[0] or lexname
            for mimetype in mimetypes:
                self._types[mimetype] = (name, self.QUALITY_RATIO)

        # Pygments currently doesn't know application/javascript
        if 'application/javascript' not in self._types:
            js_entry = self._types.get('text/javascript')
            if js_entry:
                self._types['application/javascript'] = js_entry

        self._types.update(
            Mimeview(self.env).configured_modes_mapping('pygments')
        )
Beispiel #21
0
    def render(self, req, mimetype, content, filename=None, rev=None):
        from trac.web.clearsilver import HDFWrapper

        content = content_to_unicode(self.env, content, mimetype)
        d = self._diff_to_hdf(content.splitlines(),
                              Mimeview(self.env).tab_width)
        if not d:
            raise TracError, 'Invalid unified diff content'
        hdf = HDFWrapper(loadpaths=[
            self.env.get_templates_dir(),
            self.config.get('trac', 'templates_dir')
        ])
        hdf['diff.files'] = d

        add_stylesheet(req, 'common/css/diff.css')
        return hdf.render(hdf.parse(self.diff_cs))
Beispiel #22
0
 def _test_send_converted(self, expected, content, use_chunked_encoding):
     self.env.config.set('trac', 'use_chunked_encoding',
                         'true' if use_chunked_encoding else 'false')
     mimeview = Mimeview(self.env)
     req = MockRequest(self.env)
     self.assertRaises(RequestDone, mimeview.send_converted, req,
                       self.in_mimetype, content, 'text')
     result = req.response_sent.getvalue()
     if use_chunked_encoding:
         self.assertNotIn('Content-Length', req.headers_sent)
     else:
         self.assertIn('Content-Length', req.headers_sent)
         self.assertEqual(str(len(expected)),
                          req.headers_sent['Content-Length'])
     self.assertEqual('text/plain', req.headers_sent['Content-Type'])
     self.assertEqual(set(expected), set(result))
     self.assertEqual(expected, result)
Beispiel #23
0
 def _test_send_converted(self, expected, content, use_chunked_encoding):
     self.env.config.set('trac', 'use_chunked_encoding',
                         'true' if use_chunked_encoding else 'false')
     mimeview = Mimeview(self.env)
     req = self._make_req()
     self.assertRaises(RequestDone, mimeview.send_converted, req,
                       self.in_mimetype, content, 'text')
     result = self.buf.getvalue()
     if use_chunked_encoding:
         self.assertNotIn('content-length', self.headers)
     else:
         self.assertIn('content-length', self.headers)
         self.assertEqual(str(len(expected)),
                          self.headers['content-length'])
     self.assertEqual('text/plain', self.headers['content-type'])
     self.assertEqual(set(expected), set(result))
     self.assertEqual(expected, result)
Beispiel #24
0
 def _test_send_converted(self, expected, content, use_chunked_encoding):
     self.env.config.set('trac', 'use_chunked_encoding',
                         'true' if use_chunked_encoding else 'false')
     mimeview = Mimeview(self.env)
     req = MockRequest(self.env)
     self.assertRaises(RequestDone, mimeview.send_converted, req,
                       self.in_mimetype, content, 'text')
     sent_bytes = req.response_sent.getvalue()  # always a bytes instance
     expected_bytes = expected.encode('utf-8') \
                      if isinstance(expected, str) else expected
     if use_chunked_encoding:
         self.assertNotIn('Content-Length', req.headers_sent)
     else:
         self.assertIn('Content-Length', req.headers_sent)
         self.assertEqual(str(len(expected_bytes)),
                          req.headers_sent['Content-Length'])
     self.assertEqual('text/plain', req.headers_sent['Content-Type'])
     self.assertEqual(expected_bytes, sent_bytes)
Beispiel #25
0
    def setUp(self):
        self._mp_setup()
        self.global_env = self.env
        self.env = ProductEnvironment(self.global_env, self.default_product)

        # Product name inserted in RSS feed
        self.env.product._data['name'] = 'My Project'

        self.env.config.set('trac', 'templates_dir',
                            os.path.join(os.path.dirname(self.env.path),
                                         'templates'))
        self.ticket_module = ProductTicketModule(self.env)
        self.mimeview = Mimeview(self.env)
        self.req = Mock(base_path='/trac.cgi', path_info='',
                        href=Href('/trac.cgi'), chrome={'logo': {}},
                        abs_href=Href('http://example.org/trac.cgi'),
                        environ={}, perm=[], authname='-', args={}, tz=None,
                        locale='', session=None, form_token=None)
Beispiel #26
0
    def get_search_results(self, req, query, filters):
        if 'repo' not in filters:
            return
        repo = self.env.get_repository(authname=req.authname)
        if not isinstance(query, list):
            query = query.split()
        query = [q.lower() for q in query]
        db = self.env.get_db_cnx()
        include, excludes = self._get_filters()

        to_unicode = Mimeview(self.env).to_unicode

        # Use indexer if possible, otherwise fall back on brute force search.
        try:
            from tracreposearch.indexer import Indexer
            self.indexer = Indexer(self.env)
            self.indexer.reindex()
            walker = lambda repo, query: [
                repo.get_node(filename)
                for filename in self.indexer.find_words(query)
            ]
        except TracError, e:
            self.env.log.warning(e)
            self.env.log.warning('Falling back on full repository walk')

            def full_walker(repo, query):
                for node in self.walk_repo(repo):
                    # Search content
                    matched = 1
                    content = node.get_content()
                    if not content:
                        continue
                    content = to_unicode(content.read().lower(),
                                         node.get_content_type())
                    for term in query:
                        if term not in content:
                            matched = 0
                            break
                    if matched:
                        yield node

            walker = full_walker
 def setUp(self):
     self.env = EnvironmentStub()
     self.env.config.set("trac", "templates_dir", os.path.join(os.path.dirname(self.env.path), "templates"))
     self.ticket_module = TicketModule(self.env)
     self.mimeview = Mimeview(self.env)
     self.req = Mock(
         base_path="/trac.cgi",
         path_info="",
         href=Href("/trac.cgi"),
         chrome={"logo": {}},
         abs_href=Href("http://example.org/trac.cgi"),
         environ={},
         perm=PermissionCache(self.env, "-"),
         authname="-",
         args={},
         tz=None,
         locale="",
         session=None,
         form_token=None,
     )
Beispiel #28
0
    def get_search_results(self, req, query, filters):
        if 'repo' not in filters or not req.perm.has_permission('REPO_SEARCH'):
            return

        if not self.indexer:
            raise TracError('RepoSearch plugin not configured correctly. '
                            'You need to set "repo-search.indexer".')

        db = self.env.get_db_cnx()
        to_unicode = Mimeview(self.env).to_unicode

        self._update_index()

        for hit in self.framework.search(' '.join(query)):
            node = self.repo.get_node(hit.uri)
            change = self.repo.get_changeset(node.rev)
            if node.kind == Node.DIRECTORY:
                yield (self.env.href.browser(node.path), node.path,
                       change.date, change.author, 'Directory')
            else:
                found = 0
                content = to_unicode(node.get_content().read(),
                                     node.get_content_type())
                for n, line in enumerate(content.splitlines()):
                    line = line.lower()
                    for q in query:
                        idx = line.find(q)
                        if idx != -1:
                            found = n + 1
                            break
                    if found:
                        break

                yield (self.env.href.browser(node.path) +
                       (found and '#L%i' % found or ''), node.path,
                       change.date, change.author,
                       shorten_result(content, query))
Beispiel #29
0
class PatchRendererTestCase(unittest.TestCase):
    def setUp(self):
        env = EnvironmentStub(enable=[Chrome, PatchRenderer])
        req = Mock(base_path='',
                   chrome={},
                   args={},
                   session={},
                   abs_href=Href('/'),
                   href=Href('/'),
                   locale='',
                   perm=MockPerm(),
                   authname=None,
                   tz=None)
        self.context = Context.from_request(req)
        self.patch = Mimeview(env).renderers[0]
        patch_html = open(
            os.path.join(os.path.split(__file__)[0], 'patch.html'))
        self.patch_html = Stream(list(HTMLParser(patch_html)))

    def _expected(self, expected_id):
        return self.patch_html.select('//div[@id="%s"]/div' % expected_id)

    def _test(self, expected_id, result):
        expected = str(self._expected(expected_id))
        result = str(XML(result))
        expected, result = expected.splitlines(), result.splitlines()
        for exp, res in zip(expected, result):
            self.assertEquals(exp, res)
        self.assertEquals(len(expected), len(result))

    def test_simple(self):
        """
        Simple patch rendering
        """
        result = self.patch.render(
            self.context, None, """
--- README.orig 2006-10-27 14:42:04.062500000 +0200
+++ README      2006-10-27 14:42:28.125000000 +0200
@@ -1,5 +1,5 @@
 ----
-base
-base
-base
+be
+the base
+base modified
 .
""")
        self.assertTrue(result)
        self._test('simple', result)

    def test_no_newline_in_base(self):
        """
        Simple regression test for #4027 ("No newline at end of file")
        """
        result = self.patch.render(
            self.context, None, """
--- nonewline   2006-10-27 08:36:48.453125000 +0200
+++ newline     2006-10-27 08:36:57.187500000 +0200
@@ -1 +1 @@
-ONELINE
\ No newline at end of file
+ONELINE        
""")
        self.assertTrue(result)
        self._test('no_newline_in_base', result)

    def test_no_newline_in_changed(self):
        """
        Another simple regression test for #4027 ("No newline at end of file")
        """
        result = self.patch.render(
            self.context, None, """
--- newline     2006-10-27 08:36:57.187500000 +0200
+++ nonewline   2006-10-27 08:36:48.453125000 +0200
@@ -1 +1 @@
-ONELINE
+ONELINE
\ No newline at end of file
""")
        self.assertTrue(result)
        self._test('no_newline_in_changed', result)

    def test_diff_to_hdf_expandtabs(self):
        """Regression test related to #4557"""
        changes = self.patch._diff_to_hdf([
            '--- hello.c 1', '+++ hello.c 2', '@@ -1 +1 @@', '-aa\tb', '+aaxb'
        ], 8)
        self.assertEquals('aa<del>&nbsp; &nbsp; &nbsp; </del>b',
                          str(changes[0]['diffs'][0][0]['base']['lines'][0]))
        self.assertEquals(
            'aa<ins>x</ins>b',
            str(changes[0]['diffs'][0][0]['changed']['lines'][0]))

    def test_diff_to_hdf_leading_ws(self):
        """Regression test related to #5795"""
        changes = self.patch._diff_to_hdf(
            ['--- hello.c 1', '+++ hello.c 2', '@@ -1 +1 @@', '-*a', '+ *a'],
            8)
        self.assertEquals('<del></del>*a',
                          str(changes[0]['diffs'][0][0]['base']['lines'][0]))
        self.assertEquals(
            '<ins>&nbsp;</ins>*a',
            str(changes[0]['diffs'][0][0]['changed']['lines'][0]))
Beispiel #30
0
 def format_wiki_text(text):
     from trac.mimeview.api import Mimeview
     mimeview = Mimeview(self.env)
     mimetype = 'text/x-trac-wiki'
     return mimeview.render(req, mimetype, text)
Beispiel #31
0
    def _render_view(self, req, page):
        version = page.resource.version

        # Add registered converters
        if page.exists:
            for conversion in Mimeview(self.env) \
                              .get_supported_conversions('text/x-trac-wiki'):
                conversion_href = req.href.wiki(page.name, version=version,
                                                format=conversion.key)
                add_link(req, 'alternate', conversion_href, conversion.name,
                         conversion.in_mimetype)

        data = self._page_data(req, page)
        if page.name == self.START_PAGE:
            data['title'] = ''

        ws = WikiSystem(self.env)
        context = web_context(req, page.resource)
        higher, related = [], []
        if not page.exists:
            if 'WIKI_CREATE' not in req.perm(page.resource):
                raise ResourceNotFound(_("Page %(name)s not found",
                                         name=page.name))
            formatter = OneLinerFormatter(self.env, context)
            if '/' in page.name:
                parts = page.name.split('/')
                for i in xrange(len(parts) - 2, -1, -1):
                    name = '/'.join(parts[:i] + [parts[-1]])
                    if not ws.has_page(name):
                        higher.append(ws._format_link(formatter, 'wiki',
                                                      '/' + name, name, False))
            else:
                name = page.name
            name = name.lower()
            related = [each for each in ws.pages
                       if name in each.lower()
                          and 'WIKI_VIEW' in req.perm(self.realm, each)]
            related.sort()
            related = [ws._format_link(formatter, 'wiki', '/' + each, each,
                                       False)
                       for each in related]

        latest_page = WikiPage(self.env, page.name)

        prev_version = next_version = None
        if version:
            version = as_int(version, None)
            if version is not None:
                for hist in latest_page.get_history():
                    v = hist[0]
                    if v != version:
                        if v < version:
                            if not prev_version:
                                prev_version = v
                                break
                        else:
                            next_version = v

        prefix = self.PAGE_TEMPLATES_PREFIX
        templates = [template[len(prefix):]
                     for template in ws.get_pages(prefix)
                     if 'WIKI_VIEW' in req.perm(self.realm, template)]

        # -- prev/up/next links
        if prev_version:
            add_link(req, 'prev',
                     req.href.wiki(page.name, version=prev_version),
                     _("Version %(num)s", num=prev_version))

        parent = None
        if version:
            add_link(req, 'up', req.href.wiki(page.name, version=None),
                     _("View latest version"))
        elif '/' in page.name:
            parent = page.name[:page.name.rindex('/')]
            add_link(req, 'up', req.href.wiki(parent, version=None),
                     _("View parent page"))

        if next_version:
            add_link(req, 'next',
                     req.href.wiki(page.name, version=next_version),
                     _('Version %(num)s', num=next_version))

        # Add ctxtnav entries
        if version:
            prevnext_nav(req, _("Previous Version"), _("Next Version"),
                         _("View Latest Version"))
        else:
            if parent:
                add_ctxtnav(req, _('Up'), req.href.wiki(parent))
            self._wiki_ctxtnav(req, page)

        # Plugin content validation
        fields = {'text': page.text}
        for manipulator in self.page_manipulators:
            manipulator.prepare_wiki_page(req, page, fields)
        text = fields.get('text', '')

        data.update({
            'context': context,
            'text': text,
            'latest_version': latest_page.version,
            'attachments': AttachmentModule(self.env).attachment_data(context),
            'start_page': self.START_PAGE,
            'default_template': self.DEFAULT_PAGE_TEMPLATE,
            'templates': templates,
            'version': version,
            'higher': higher, 'related': related,
            'resourcepath_template': 'wiki_page_path.html',
            'fullwidth': req.session.get('wiki_fullwidth'),
        })
        add_script(req, 'common/js/wiki.js')
        return 'wiki_view.html', data
Beispiel #32
0
class PygmentsRendererTestCase(unittest.TestCase):

    def setUp(self):
        self.env = EnvironmentStub(enable=[Chrome, LineNumberAnnotator,
                                           PygmentsRenderer])
        self.pygments = Mimeview(self.env).renderers[0]
        self.req = MockRequest(self.env)
        self.context = web_context(self.req)
        self.pygments_html = {}
        testcase = []
        html_file = os.path.join(os.path.dirname(__file__), 'pygments.data')
        with open(html_file, 'rb') as f:
            for line in f.readlines():
                if line.startswith('#'):
                    self.pygments_html[line[1:].strip()] = testcase = []
                else:
                    testcase.append(unicode(line.rstrip(), 'utf-8'))

    def _expected(self, expected_id):
        return self.pygments_html[expected_id]

    def _test(self, expected_id, result):
        expected = self._expected(expected_id)
        result = unicode(result).splitlines()
        # from pprint import pformat
        # print("\nE: " + expected_id + "\n" + pformat(expected))
        # print("\nR: " + expected_id + "\n" + pformat(result))
        self.maxDiff = None
        def split(s):
            sp = re.split('(>)', s)
            return [a + b for (a, b) in zip(sp[0::2], sp[1::2])]
        for exp, res in zip(expected, result):
            self.assertEqual(split(exp), split(res))
        self.assertEqual(len(expected), len(result))

    def test_python_hello(self):
        """
        Simple Python highlighting with Pygments (direct)
        """
        result = self.pygments.render(self.context, 'text/x-python',
                                      textwrap.dedent("""\
            def hello():
                    return "Hello World!"
            """))
        self.assertTrue(result)
        if pygments_version < parse_version('2.1'):
            self._test('python_hello', result)
        else:
            self._test('python_hello_pygments_2.1plus', result)

    def test_python_hello_mimeview(self):
        """
        Simple Python highlighting with Pygments (through Mimeview.render)
        """
        result = Mimeview(self.env).render(self.context, 'text/x-python',
                                           textwrap.dedent("""
            def hello():
                    return "Hello World!"
            """))
        self.assertTrue(result)
        if pygments_version < parse_version('2.1'):
            self._test('python_hello_mimeview', result)
        else:
            self._test('python_hello_mimeview_pygments_2.1plus', result)

    def test_python_with_lineno(self):
        result = format_to_html(self.env, self.context, textwrap.dedent("""\
            {{{#!text/x-python lineno
            print 'this is a python sample'
            a = b+3
            z = "this is a string"
            print 'this is the end of the python sample'
            }}}
            """))
        self.assertTrue(result)
        if pygments_version < parse_version('2.1'):
            self._test('python_with_lineno_1', result)
        else:
            self._test('python_with_lineno_1_pygments_2.1plus', result)

        result = format_to_html(self.env, self.context, textwrap.dedent("""\
            {{{#!text/x-python lineno=3
            print 'this is a python sample'
            a = b+3
            z = "this is a string"
            print 'this is the end of the python sample'
            }}}
            """))
        self.assertTrue(result)
        if pygments_version < parse_version('2.1'):
            self._test('python_with_lineno_2', result)
        else:
            self._test('python_with_lineno_2_pygments_2.1plus', result)

    def test_python_with_lineno_and_markups(self):
        """Python highlighting with Pygments and lineno annotator
        """
        result = format_to_html(self.env, self.context, textwrap.dedent("""\
            {{{#!text/x-python lineno=3 id=b marks=4-5
            print 'this is a python sample'
            a = b+3
            z = "this is a string"
            print 'this is the end of the python sample'
            }}}
            """))
        self.assertTrue(result)
        if pygments_version < parse_version('2.1'):
            self._test('python_with_lineno_and_markups', result)
        else:
            self._test('python_with_lineno_and_markups_pygments_2.1plus',
                       result)

    def test_python_with_invalid_arguments(self):
        result = format_to_html(self.env, self.context, textwrap.dedent("""\
            {{{#!text/x-python lineno=-10
            print 'this is a python sample'
            a = b+3
            z = "this is a string"
            print 'this is the end of the python sample'
            }}}
            """))
        self.assertTrue(result)
        if pygments_version < parse_version('2.1'):
            self._test('python_with_invalid_arguments_1', result)
        else:
            self._test('python_with_invalid_arguments_1_pygments_2.1plus',
                       result)

        result = format_to_html(self.env, self.context, textwrap.dedent("""\
            {{{#!text/x-python lineno=a id=d marks=a-b
            print 'this is a python sample'
            a = b+3
            z = "this is a string"
            print 'this is the end of the python sample'
            }}}
            """))
        self.assertTrue(result)
        if pygments_version < parse_version('2.1'):
            self._test('python_with_invalid_arguments_2', result)
        else:
            self._test('python_with_invalid_arguments_2_pygments_2.1plus',
                       result)

    def test_pygments_lexer_options(self):
        self.env.config.set('pygments-lexer',
                            'php.startinline', True)
        self.env.config.set('pygments-lexer',
                            'php.funcnamehighlighting', False)
        result = format_to_html(self.env, self.context, textwrap.dedent("""
            {{{#!php
            if (class_exists('MyClass')) {
                $myclass = new MyClass();
            }
            }}}
            """))
        self.assertTrue(result)
        self._test('pygments_lexer_options', result)

    def test_pygments_lexer_arguments(self):
        result = format_to_html(self.env, self.context, textwrap.dedent("""
            {{{#!php startinline=True funcnamehighlighting=False
            if (class_exists('MyClass')) {
                $myclass = new MyClass();
            }
            }}}
            """))
        self.assertTrue(result)
        self._test('pygments_lexer_arguments', result)

    def test_pygments_lexer_arguments_override_options(self):
        self.env.config.set('pygments-lexer',
                            'php.startinline', True)
        self.env.config.set('pygments-lexer',
                            'php.funcnamehighlighting', False)
        result = format_to_html(self.env, self.context, textwrap.dedent("""
            {{{#!php funcnamehighlighting=True
            if (class_exists('MyClass')) {
                $myclass = new MyClass();
            }
            }}}
            """))
        self.assertTrue(result)
        self._test('pygments_lexer_arguments_override_options', result)

    def test_newline_content(self):
        """Regression test for newline-stripping behavior in Pygments.

        http://trac.edgewall.org/ticket/7705
        """
        result = self.pygments.render(self.context, 'text/x-python',
                                      '\n\n\n\n')
        self.assertTrue(result)
        t = result

        self.assertEqual("\n\n\n\n", t)

    def test_empty_content(self):
        """
        A '\n' token is generated for an empty file, so we have to bypass
        pygments when rendering empty files.
        """
        result = self.pygments.render(self.context, 'text/x-python', '')
        self.assertIsNone(result)

    def test_extra_mimetypes(self):
        """
        The text/x-ini mimetype is normally not known by Trac, but
        Pygments supports it.
        """
        mimeview = Mimeview(self.env)
        self.assertIn(mimeview.get_mimetype('file.ini'),
                      ('text/x-ini; charset=utf-8',
                       'text/inf; charset=utf-8'))  # Pygment 2.1+
        self.assertIn(mimeview.get_mimetype('file.cfg'),
                      ('text/x-ini; charset=utf-8',
                       'text/inf; charset=utf-8'))  # Pygment 2.1+
        self.assertEqual('text/x-ini; charset=utf-8',
                         mimeview.get_mimetype('file.text/x-ini'))
Beispiel #33
0
class FilePage(Page):

    def __init__(self, env, node, root, base):
        super(FilePage, self).__init__(env, node, root, base)
        self.mimeview = Mimeview(self.env)
        self.exists = (node is not None)

        self.mime_type = None
        self.chunk = None

    def get_html(self, req):
        """
        Get the raw content from the repository and convert to html.
        """
        mime_type, chunk = self.get_raw()
        if not mime_type.startswith('text'):
            raise TracError("Invalid mime-type: %s" % mime_type)

        # Hack to support images, we change the path from relative
        # the document being requested to absolute.
        # 1: Ignore http and ftp urls to allow images to be fetched
        # 2: Assume URLS beginning with "/" are relative to top-level
        # 3: Assume URLS that do not include "http/ftp" are relative to
        #    current path.
        def fixup(m):
            text = m.group(1)
            if text.startswith('http:') or text.startswith('ftp:'):
                return m.group(0)
            if text.startswith('/'):
                text = text[1:]
            dir = self.dir
            if dir.endswith('/'):
                dir = dir[:-1] 
            return '.. image:: %s/%s' % (req.href.docs(dir), text)
        chunk = re.sub('\.\. image\:\:\s*(\S+)', fixup, chunk, re.MULTILINE)

        # Assume all wiki pages are ReStructuredText documents 
        result = self.mimeview.render(req, mime_type, chunk)

        if not isinstance(result, (str, unicode)):
            result = unicode(result)

        # Hack to pretty-print source code (assumes all literal-blocks 
        # contain source code).
        result = result.replace('<pre class="literal-block">',
                                '<pre class="literal-block prettyprint">')

        if 'prettyprint' in result:
            # FIXME: Add as an event listener instead?
            result += """
                <script type="text/javascript">
                var origOnLoad = window.onload;
                function onLoad() {
                    if (origOnLoad) {
                      if(typeof(origOnLoad) == "string") {
                        eval(origOnLoad);
                      }
                      else {
                        origOnLoad();
                      }
                    } 
                    prettyPrint();
                }
                window.onload = onLoad;
                </script>
            """

        return Markup(result)

    def get_raw(self):
        """
        Load the raw content from the repository.
        """
        if self.mime_type is not None:
            return self.mime_type, self.chunk

        node = self.node
        content_length = node.get_content_length()
        if content_length > (1024 * 1024):
            raise TracError("Docs is too large: %d" % content_length)
        content = node.get_content()
        chunk = content.read(content_length)
        mime_type = node.content_type

        # Guess the mime-type when possible to be text/plain.
        if not mime_type or mime_type == 'application/octet-stream':
            mime_type = self.mimeview.get_mimetype(node.name, chunk) or \
            mime_type or 'text/plain'

        if mime_type.startswith('text/plain'):
            mime_type = 'text/x-rst; charset=utf8' 

        self.mime_type = mime_type
        self.chunk = chunk

        return mime_type, chunk 

    def save(self, req, text, comment):
        """
        Save the specified text into this document.
        """
        if not isinstance(self.node.repos, SubversionRepository):
            raise TracError("The '%s' repository is not supported" % type(self.node.repos))

        from svn import core as _core
        from svn import fs as _fs
        from svn import repos as _repos

        repos = self.node.repos.repos #.repos
        revnum = self.node._requested_rev
        author = req.authname
        message = 'Edited %s' % self.base[1:]
        if comment:
            message += ' (%s)' % comment

        pool = _core.Pool()
        fs_txn = _repos.fs_begin_txn_for_commit(repos, revnum, author, message, pool)
        fs_root = _fs.svn_fs_txn_root(fs_txn, pool)
        if hasattr(self.node, '_scoped_svn_path'):
            fs_path = self.node._scoped_svn_path
        else:
            fs_path = self.node._scoped_path_utf8
        stream = _fs.svn_fs_apply_text(fs_root, fs_path, None, pool)
        _core.svn_stream_write(stream, text)
        _core.svn_stream_close(stream) 
        return _repos.fs_commit_txn(repos, fs_txn, pool)
Beispiel #34
0
    def _render_file(self, req, context, repos, node, rev=None):
        req.perm(node.resource).require("FILE_VIEW")

        mimeview = Mimeview(self.env)

        # MIME type detection
        content = node.get_processed_content()
        chunk = content.read(CHUNK_SIZE)
        mime_type = node.content_type
        if not mime_type or mime_type == "application/octet-stream":
            mime_type = mimeview.get_mimetype(node.name, chunk) or mime_type or "text/plain"

        # Eventually send the file directly
        format = req.args.get("format")
        if format in ("raw", "txt"):
            req.send_response(200)
            req.send_header("Content-Type", "text/plain" if format == "txt" else mime_type)
            req.send_header("Last-Modified", http_date(node.last_modified))
            if rev is None:
                req.send_header("Pragma", "no-cache")
                req.send_header("Cache-Control", "no-cache")
                req.send_header("Expires", "Fri, 01 Jan 1999 00:00:00 GMT")
            if not self.render_unsafe_content:
                # Force browser to download files instead of rendering
                # them, since they might contain malicious code enabling
                # XSS attacks
                req.send_header("Content-Disposition", "attachment")
            req.end_headers()
            # Note: don't pass an iterable instance to RequestDone, instead
            # call req.write() with each chunk here to avoid SEGVs (#11805)
            while chunk:
                req.write(chunk)
                chunk = content.read(CHUNK_SIZE)
            raise RequestDone
        else:
            # The changeset corresponding to the last change on `node`
            # is more interesting than the `rev` changeset.
            changeset = repos.get_changeset(node.created_rev)

            # add ''Plain Text'' alternate link if needed
            if not is_binary(chunk) and mime_type != "text/plain":
                plain_href = req.href.browser(repos.reponame or None, node.path, rev=rev, format="txt")
                add_link(req, "alternate", plain_href, _("Plain Text"), "text/plain")

            # add ''Original Format'' alternate link (always)
            raw_href = req.href.export(rev or repos.youngest_rev, repos.reponame or None, node.path)
            add_link(req, "alternate", raw_href, _("Original Format"), mime_type)

            self.log.debug("Rendering preview of node %s@%s with mime-type %s", node.name, rev, mime_type)

            content = None  # the remainder of that content is not needed

            add_stylesheet(req, "common/css/code.css")

            annotations = ["lineno"]
            annotate = req.args.get("annotate")
            if annotate:
                annotations.insert(0, annotate)
            preview_data = mimeview.preview_data(
                context,
                node.get_processed_content(),
                node.get_content_length(),
                mime_type,
                node.created_path,
                raw_href,
                annotations=annotations,
                force_source=bool(annotate),
            )
            return {"changeset": changeset, "size": node.content_length, "preview": preview_data, "annotate": annotate}
Beispiel #35
0
	def filter_stream(self, req, method, template, stream, data):
		if not (template == 'browser.html' and data.get('dir')):
			if ((not data.get('dir')) and (data.get('path')) and (data.get('path').endswith('.md'))):	# Rendering single markdown file preview
				stream = stream | Transformer("//head/script[not(@src)][1]").after(
					tag.script(
						Markup(
							"jQuery(document).ready(function($) {"
							"  $('#preview').each(function() {"
							"    $(this).html(marked( $(this).children('pre').first().text() ));"
							"  });"
							"});"
						),
						type = "text/javascript"
					)
				)
			return stream

		add_stylesheet(req, 'common/css/code.css')

		repos = data.get('repos') or self.env.get_repository()
		rev = req.args.get('rev', None)

		for entry in data['dir']['entries']:						# Rendering all READMEs in a directory preview
			try:
				if not entry.isdir and entry.name.lower().startswith('readme'):
					node = repos.get_node(entry.path, rev)
					req.perm(data['context'].resource).require('FILE_VIEW')
					mimeview = Mimeview(self.env)
					content = node.get_content()
					mimetype = node.content_type
					divclass = 'searchable'
					if entry.name.lower().endswith('.wiki'):
						mimetype = 'text/x-trac-wiki'
						divclass = 'searchable wiki'
					elif entry.name.lower().endswith('.md'):
						mimetype = 'text/x-markdown'
						divclass = 'searchable markdown'
					if not mimetype or mimetype == 'application/octet-stream':
						mimetype = mimeview.get_mimetype(node.name, content.read(4096)) or mimetype or 'text/plain'
					del content
					self.log.debug("ReadmeRenderer: rendering node %s@%s as %s" % (node.name, str(rev), mimetype))
					output = mimeview.preview_data(
						data['context'],
						node.get_content(),
						node.get_content_length(),
						mimetype,
						node.created_path,
						'',
						annotations = [],
						force_source = False
					)

					if output:
						if isinstance(output['rendered'], Stream):
							#content = output['rendered'].select('./pre/node()')
							#content = output['rendered'].select('./pre')
							content = output['rendered'].select('.')
						else:
							self.log.debug("GOT THERE")
							content = output['rendered']
						insert = tag.div(
							tag.h1(entry.name,
								tag.a(Markup(' &para;'),
									class_ = "anchor",
									href   = '#' + entry.name,
									title  = 'Link to file'
								),
								id_ = entry.name
							),
							tag.div(
								content,
								#xml:space = "preserve",
								class_ = divclass,
								title = entry.name
							),
							class_ = "readme",
							style  = "padding-top: 1em;"
						)
						stream = stream | Transformer("//div[@id='content']/div[@id='help']").before(insert)
			except Exception, e:
				self.log.debug(to_unicode(e))
Beispiel #36
0
class TicketConversionTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub()
        self.env.config.set(
            'trac', 'templates_dir',
            os.path.join(os.path.dirname(self.env.path), 'templates'))
        self.ticket_module = TicketModule(self.env)
        self.mimeview = Mimeview(self.env)
        self.req = MockRequest(self.env, authname='anonymous')

    def tearDown(self):
        self.env.reset_db()

    def _create_a_ticket(self):
        return insert_ticket(self.env,
                             owner='',
                             reporter='santa',
                             summary='Foo',
                             description='Bar',
                             foo='This is a custom field')

    def _create_a_ticket_with_email(self):
        return insert_ticket(self.env,
                             owner='*****@*****.**',
                             reporter='*****@*****.**',
                             cc='cc1, [email protected]',
                             summary='Foo',
                             description='Bar')

    def test_conversions(self):
        conversions = self.mimeview.get_supported_conversions(
            'trac.ticket.Ticket')
        expected = sorted(
            [('csv', 'Comma-delimited Text', 'csv', 'trac.ticket.Ticket',
              'text/csv', 8, self.ticket_module),
             ('tab', 'Tab-delimited Text', 'tsv', 'trac.ticket.Ticket',
              'text/tab-separated-values', 8, self.ticket_module),
             ('rss', 'RSS Feed', 'xml', 'trac.ticket.Ticket',
              'application/rss+xml', 8, self.ticket_module)],
            key=lambda i: i[-1],
            reverse=True)
        self.assertEqual(expected, conversions)

    def test_csv_conversion(self):
        ticket = self._create_a_ticket()
        csv = self.mimeview.convert_content(self.req, 'trac.ticket.Ticket',
                                            ticket, 'csv')
        self.assertEqual(('\xef\xbb\xbf'
                          'id,summary,reporter,owner,description,status,'
                          'keywords,cc\r\n1,Foo,santa,,Bar,,,\r\n',
                          'text/csv;charset=utf-8', 'csv'), csv)

    def test_csv_conversion_with_obfuscation(self):
        ticket = self._create_a_ticket_with_email()
        csv = self.mimeview.convert_content(self.req, 'trac.ticket.Ticket',
                                            ticket, 'csv')
        self.assertEqual(
            ('\xef\xbb\xbf'
             'id,summary,reporter,owner,description,status,keywords,cc\r\n'
             '1,Foo,santa@…,joe@…,Bar,,,cc1 cc2@…\r\n',
             'text/csv;charset=utf-8', 'csv'), csv)
        self.req.perm = MockPerm()
        csv = self.mimeview.convert_content(self.req, 'trac.ticket.Ticket',
                                            ticket, 'csv')
        self.assertEqual(
            ('\xef\xbb\xbf'
             'id,summary,reporter,owner,description,status,keywords,cc\r\n'
             '1,Foo,[email protected],[email protected],Bar,,,'
             'cc1 [email protected]\r\n', 'text/csv;charset=utf-8', 'csv'), csv)

    def test_tab_conversion(self):
        ticket = self._create_a_ticket()
        csv = self.mimeview.convert_content(self.req, 'trac.ticket.Ticket',
                                            ticket, 'tab')
        self.assertEqual(('\xef\xbb\xbf'
                          'id\tsummary\treporter\towner\tdescription\tstatus\t'
                          'keywords\tcc\r\n1\tFoo\tsanta\t\tBar\t\t\t\r\n',
                          'text/tab-separated-values;charset=utf-8', 'tsv'),
                         csv)

    def test_tab_conversion_with_obfuscation(self):
        ticket = self._create_a_ticket_with_email()
        csv = self.mimeview.convert_content(self.req, 'trac.ticket.Ticket',
                                            ticket, 'tab')
        self.assertEqual(
            ('\xef\xbb\xbf'
             'id\tsummary\treporter\towner\tdescription\tstatus\tkeywords\t'
             'cc\r\n'
             '1\tFoo\tsanta@…\tjoe@…\tBar\t\t\tcc1 cc2@…\r\n',
             'text/tab-separated-values;charset=utf-8', 'tsv'), csv)
        self.req.perm = MockPerm()
        csv = self.mimeview.convert_content(self.req, 'trac.ticket.Ticket',
                                            ticket, 'tab')
        self.assertEqual(
            ('\xef\xbb\xbf'
             'id\tsummary\treporter\towner\tdescription\tstatus\tkeywords\t'
             'cc\r\n'
             '1\tFoo\[email protected]\[email protected]\tBar\t\t\t'
             'cc1 [email protected]\r\n',
             'text/tab-separated-values;charset=utf-8', 'tsv'), csv)

    def test_rss_conversion(self):
        ticket = self._create_a_ticket()
        content, mimetype, ext = self.mimeview.convert_content(
            self.req, 'trac.ticket.Ticket', ticket, 'rss')
        self.maxDiff = None
        self.assertEqual(("""<?xml version="1.0"?>



<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">

  <channel>
    <title>My Project: Ticket #1: Foo</title>
    <link>http://example.org/trac.cgi/ticket/1</link>
    <description>&lt;p&gt;
Bar
&lt;/p&gt;
</description>
    <language>en-us</language>
    <image>
      <title>My Project</title>
      <url>http://example.org/trac.cgi/chrome/site/your_project_logo.png</url>
      <link>http://example.org/trac.cgi/ticket/1</link>
    </image>
    <generator>Trac %s</generator>

 </channel>
</rss>""" % self.env.trac_version, 'application/rss+xml', 'xml'),
                         (content.replace('\r', ''), mimetype, ext))
Beispiel #37
0
    def render_macro(self, req, name, content):
        args = [x.strip() for x in content.split(',')]
        #        return args
        if len(args) == 1:
            args.append(None)
        elif len(args) != 2:
            return system_message('Invalid arguments "%s"' % content)

        # Pull out the arguments
        source, theader = args
        try:
            source_format, source_obj = source.split(':', 1)
        except ValueError:  # If no : is present, assume its a wiki page
            source_format, source_obj = 'source', source

        # Apply a default format if needed
        try:
            if theader is not None:
                isTheader, theader_content = theader.split("=", 1)
        except AttributeError:
            pass

        try:
            dest_format = self.default_formats[source_format]
        except KeyError:
            pass

        if source_format == 'source':
            if not req.perm.has_permission('FILE_VIEW'):
                return ''
            repo = self.env.get_repository(req.authname)
            node = repo.get_node(source_obj)
            out = node.get_content().read()
            if dest_format is None:
                dest_format = node.content_type or get_mimetype(
                    source_obj, out)
            ctxt = Context.from_request(req, 'source', source_obj)
        # RFE: Add ticket: and comment: sources. <NPK>
        # RFE: Add attachment: source. <NPK>
        else:
            return system_message('Unsupported include source %s' % source)

        # If we have a preview format, use it

        # Escape if needed
#        if not self.config.getbool('wiki', 'render_unsafe_content', False):
#            try:
#                out = HTMLParser(StringIO(out)).parse() | HTMLSanitizer()
#            except ParseError:
#                out = escape(out)
#        reader = str(out).split("||")
        need_header = 1
        foo = ''
        foo += '<table class="sortable"  style="border:1px solid #000;">'
        try:
            if theader is not None:
                if isTheader == "header":
                    custom_theader = theader_content.split(";")
                    foo += '<tr>'
                    for theader_cell in custom_theader:
                        foo += '<th style="border:1px solid #000;">' + str(
                            theader_cell) + '</th>'
                    foo += "</tr>\n"
        except AttributeError:
            pass

        for row in str(out).splitlines():
            foo += "<tr>\n"
            for cell in row.split("||"):
                if cell.startswith("|"):
                    foo += '<td align="right" style="border:1px solid #000;">'
                    if dest_format:
                        foo += (str(
                            Mimeview(self.env).render(
                                None, "text/x-trac-wiki",
                                str(cell.lstrip("|"))))[16:])[:-19]

                    foo += "</td>"
                else:
                    foo += '<td align="right" style="border:1px solid #000;">'
                    if dest_format:
                        foo += (str(
                            Mimeview(self.env).render(
                                None, "text/x-trac-wiki",
                                str(cell))).lstrip("<p>")[16:])[:-19]
                    foo += "</td>"
#            foo +=str(row)
#            for cell in row:
#                foo += cell
#                foo += "-"
        foo += "</tr></table>"

        return foo
Beispiel #38
0
 def setUp(self):
     PatchRendererTestCase.setUp(self)
     self.patch = Mimeview(self.env).renderers[0]
Beispiel #39
0
class PatchRendererTestCase(unittest.TestCase):

    def setUp(self):
        env = EnvironmentStub(enable=[Chrome, PatchRenderer])
        req = Mock(base_path='', chrome={'static_hash': None}, args={},
                   session={}, abs_href=Href('/'), href=Href('/'), locale='',
                   perm=MockPerm(), authname=None, tz=None)
        self.context = web_context(req)
        self.patch = Mimeview(env).renderers[0]
        patch_html = open(os.path.join(os.path.split(__file__)[0],
                                       'patch.html'))
        self.patch_html = Stream(list(HTMLParser(patch_html, encoding='utf-8')))

    def _expected(self, expected_id):
        return self.patch_html.select('//div[@id="%s"]/div' % expected_id)

    def _test(self, expected_id, result):
        expected = self._expected(expected_id).render(encoding='utf-8')
        result = XML(result.render(encoding='utf-8')).render(encoding='utf-8')
        expected, result = expected.splitlines(), result.splitlines()
        for exp, res in zip(expected, result):
            self.assertEquals(exp, res)
        self.assertEquals(len(expected), len(result))

    def test_simple(self):
        """
        Simple patch rendering
        """
        result = self.patch.render(self.context, None, """
--- README.orig 2006-10-27 14:42:04.062500000 +0200
+++ README      2006-10-27 14:42:28.125000000 +0200
@@ -1,5 +1,5 @@
 ----
-base
-base
-base
+be
+the base
+base modified
 .
""")
        self.assertTrue(result)
        self._test('simple', result)

    def test_no_newline_in_base(self):
        """
        Simple regression test for #4027 ("No newline at end of file")
        """
        result = self.patch.render(self.context, None, """
--- nonewline   2006-10-27 08:36:48.453125000 +0200
+++ newline     2006-10-27 08:36:57.187500000 +0200
@@ -1 +1 @@
-ONELINE
\ No newline at end of file
+ONELINE        
""")
        self.assertTrue(result)
        self._test('no_newline_in_base', result)

    def test_no_newline_in_changed(self):
        """
        Another simple regression test for #4027 ("No newline at end of file")
        """
        result = self.patch.render(self.context, None, """
--- newline     2006-10-27 08:36:57.187500000 +0200
+++ nonewline   2006-10-27 08:36:48.453125000 +0200
@@ -1 +1 @@
-ONELINE
+ONELINE
\ No newline at end of file
""")
        self.assertTrue(result)
        self._test('no_newline_in_changed', result)
    def test_diff_to_hdf_expandtabs(self):
        """Regression test related to #4557"""
        changes = self.patch._diff_to_hdf(
            ['--- hello.c 1',
             '+++ hello.c 2',
             '@@ -1 +1 @@',
             '-aa\tb',
             '+aaxb'], 8)
        self.assertEquals('aa<del>&nbsp; &nbsp; &nbsp; </del>b',
                          str(changes[0]['diffs'][0][0]['base']['lines'][0]))
        self.assertEquals('aa<ins>x</ins>b',
                          str(changes[0]['diffs'][0][0]['changed']['lines'][0]))

    def test_diff_to_hdf_leading_ws(self):
        """Regression test related to #5795"""
        changes = self.patch._diff_to_hdf(
            ['--- hello.c 1',
             '+++ hello.c 2',
             '@@ -1 +1 @@',
             '-*a',
             '+ *a'], 8)
        self.assertEquals('<del></del>*a',
                          str(changes[0]['diffs'][0][0]['base']['lines'][0]))
        self.assertEquals('<ins>&nbsp;</ins>*a',
                          str(changes[0]['diffs'][0][0]['changed']['lines'][0]))
Beispiel #40
0
    def process_request(self, req):
        req.perm.assert_permission('TICKET_VIEW')

        action = req.args.get('action', 'view')

        db = self.env.get_db_cnx()
        id = int(req.args.get('id'))

        ticket = Ticket(self.env, id, db=db)

        if req.method == 'POST':
            if not req.args.has_key('preview'):
                self._do_save(req, db, ticket)
            else:
                # Use user supplied values
                ticket.populate(req.args)
                self._validate_ticket(req, ticket)

                req.hdf['ticket.action'] = action
                req.hdf['ticket.ts'] = req.args.get('ts')
                req.hdf['ticket.reassign_owner'] = req.args.get('reassign_owner') \
                                                   or req.authname
                req.hdf['ticket.resolve_resolution'] = req.args.get(
                    'resolve_resolution')
                comment = req.args.get('comment')
                if comment:
                    req.hdf['ticket.comment'] = comment
                    # Wiki format a preview of comment
                    req.hdf['ticket.comment_preview'] = wiki_to_html(
                        comment, self.env, req, db)
        else:
            req.hdf['ticket.reassign_owner'] = req.authname
            # Store a timestamp in order to detect "mid air collisions"
            req.hdf['ticket.ts'] = ticket.time_changed

        self._insert_ticket_data(req, db, ticket,
                                 get_reporter_id(req, 'author'))

        mime = Mimeview(self.env)
        format = req.args.get('format')
        if format:
            mime.send_converted(req, 'trac.ticket.Ticket', ticket, format,
                                'ticket_%d' % ticket.id)

        # If the ticket is being shown in the context of a query, add
        # links to help navigate in the query result set
        if 'query_tickets' in req.session:
            tickets = req.session['query_tickets'].split()
            if str(id) in tickets:
                idx = tickets.index(str(ticket.id))
                if idx > 0:
                    add_link(req, 'first', req.href.ticket(tickets[0]),
                             u'Ticket #%s' % tickets[0])
                    add_link(req, 'prev', req.href.ticket(tickets[idx - 1]),
                             u'Ticket #%s' % tickets[idx - 1])
                if idx < len(tickets) - 1:
                    add_link(req, 'next', req.href.ticket(tickets[idx + 1]),
                             u'Ticket #%s' % tickets[idx + 1])
                    add_link(req, 'last', req.href.ticket(tickets[-1]),
                             u'Ticket #%s' % tickets[-1])
                add_link(req, 'up', req.session['query_href'])

        add_stylesheet(req, 'common/css/ticket.css')

        # Add registered converters
        for conversion in mime.get_supported_conversions('trac.ticket.Ticket'):
            conversion_href = req.href.ticket(ticket.id, format=conversion[0])
            add_link(req, 'alternate', conversion_href, conversion[1],
                     conversion[3])

        return 'ticket.cs', None
 def send_as_email(self, req, sender, recipients, subject, text, mode,  *resources):
     """
     `authname` Trac username of sender
     `sender` Tuple of (real name, email address)
     `recipients` List of (real name, email address) recipient address tuples
     `subject` The e-mail subject
     `text` The text body of the e-mail
     `files` List of paths to the files to send
     """
     assert len(resources) > 0, 'Nothing to send!'
     mailsys = self.distributor(self.env)
     from_addr = sender[1]
     root = MIMEMultipart('related')
     root.set_charset(self._make_charset())
     root.preamble = 'This is a multi-part message in MIME format.'
     headers = {}
     recp = [r[1] for r in recipients]
     headers['Subject'] = subject
     headers['To'] = ', '.join(recp)
     headers['From'] = from_addr
     headers['Date'] = formatdate()
     authname = req.authname
     files = []
     links = []
     attachments = []
     mimeview = Mimeview(self.env)
     for r in resources:
         repo = RepositoryManager(self.env).get_repository(r.parent.id)
         n = repo.get_node(r.id, rev=r.version)
         files.append(n.path)
         f = os.path.join(repo.repos.path, n.path)
         if mode in (self.LINKS_ONLY, self.LINKS_ATTACHMENTS):
             links.append((req.abs_href.browser(repo.reponame or None, n.path, format='raw'), os.path.basename(f)))
         if mode in (self.ATTACHMENTS_ONLY, self.LINKS_ATTACHMENTS):
             content = n.get_content().read()                
             mtype = n.get_content_type() or mimeview.get_mimetype(f, content)
             if not mtype:
                 mtype = 'application/octet-stream'
             if '; charset=' in mtype:
                 # What to use encoding for?
                 mtype, encoding = mtype.split('; charset=', 1)
             attachments.append(os.path.basename(f))
             maintype, subtype = mtype.split('/', 1)
             part = MIMEBase(maintype, subtype)
             part.set_payload(content)
             part.add_header('content-disposition', 'attachment', filename=os.path.basename(f))
             encode_base64(part)
             root.attach(part)
     body = self._format_email(authname, sender, recipients, subject, text, mode, links, attachments)
     msg = MIMEText(body, 'html', 'utf-8')
     root.attach(msg)
     del root['Content-Transfer-Encoding']
     for k, v in headers.items():
         set_header(root, k, v)
     email = (from_addr, recp, root.as_string())
     # Write mail to /tmp
     #import logging
     #if self.log.isEnabledFor(logging.DEBUG):
     #   (fd, tmpname) = mkstemp()
     #   os.write(fd, email[2])
     #   os.close(fd)
     #   self.log.debug('Wrote mail from %s to %s to %s', email[0], email[1], tmpname)
     self.log.info('Sending mail with items %s from %s to %s', resources, from_addr, recp)
     try:
         if using_announcer:
             if mailsys.use_threaded_delivery:
                 mailsys.get_delivery_queue().put(email)
             else:
                 mailsys.send(*email)
         else:
             mailsys.send_email(*email)
     except Exception, e:
         raise TracError(e.message)
Beispiel #42
0
     if fragment_name:
         for line in out.splitlines():
             res = re.search(r'FRAGMENT\(([^)]*)\)', line)
             if res:
                 current_fragment_name = res.groups()[0]
             else:
                 if current_fragment_name == fragment_name:
                     fragment.append(line)
         out = '\n'.join(fragment)
         
     # If we have a preview format, use it
     if dest_format:
         # We can trust the output and do not need to call the HTML sanitizer
         # below.  The HTML sanitization leads to whitespace being stripped.
         safe_content = True
         out = Mimeview(self.env).render(ctxt, dest_format, out, force_source=True)
     
     # Escape if needed
     if not safe_content and not self.config.getbool('wiki', 'render_unsafe_content', False):
         try:
             out = HTMLParser(StringIO(out)).parse() | HTMLSanitizer()
         except ParseError:
             out = escape(out)
     
     return out
         
 # IPermissionRequestor methods
 def get_permission_actions(self):
     yield 'INCLUDE_URL'
         
     
Beispiel #43
0
    def _render_file(self, req, context, repos, node, rev=None):
        req.perm(node.resource).require('FILE_VIEW')

        mimeview = Mimeview(self.env)

        # MIME type detection
        content = node.get_content()
        chunk = content.read(CHUNK_SIZE)
        mime_type = node.content_type
        if not mime_type or mime_type == 'application/octet-stream':
            mime_type = mimeview.get_mimetype(node.name, chunk) or \
                        mime_type or 'text/plain'

        # Eventually send the file directly
        format = req.args.get('format')
        if format in ('raw', 'txt'):
            req.send_response(200)
            req.send_header('Content-Type',
                            'text/plain' if format == 'txt' else mime_type)
            req.send_header('Content-Length', node.content_length)
            req.send_header('Last-Modified', http_date(node.last_modified))
            if rev is None:
                req.send_header('Pragma', 'no-cache')
                req.send_header('Cache-Control', 'no-cache')
                req.send_header('Expires', 'Fri, 01 Jan 1999 00:00:00 GMT')
            if not self.render_unsafe_content:
                # Force browser to download files instead of rendering
                # them, since they might contain malicious code enabling
                # XSS attacks
                req.send_header('Content-Disposition', 'attachment')
            req.end_headers()

            while 1:
                if not chunk:
                    raise RequestDone
                req.write(chunk)
                chunk = content.read(CHUNK_SIZE)
        else:
            # The changeset corresponding to the last change on `node`
            # is more interesting than the `rev` changeset.
            changeset = repos.get_changeset(node.created_rev)

            # add ''Plain Text'' alternate link if needed
            if not is_binary(chunk) and mime_type != 'text/plain':
                plain_href = req.href.browser(repos.reponame or None,
                                              node.path, rev=rev, format='txt')
                add_link(req, 'alternate', plain_href, _('Plain Text'),
                         'text/plain')

            # add ''Original Format'' alternate link (always)
            raw_href = req.href.export(rev or repos.youngest_rev,
                                       repos.reponame or None, node.path)
            add_link(req, 'alternate', raw_href, _('Original Format'),
                     mime_type)

            self.log.debug("Rendering preview of node %s@%s with mime-type %s"
                           % (node.name, str(rev), mime_type))

            del content # the remainder of that content is not needed

            add_stylesheet(req, 'common/css/code.css')

            annotations = ['lineno']
            annotate = req.args.get('annotate')
            if annotate:
                annotations.insert(0, annotate)
            preview_data = mimeview.preview_data(context, node.get_content(),
                                                 node.get_content_length(),
                                                 mime_type, node.created_path,
                                                 raw_href,
                                                 annotations=annotations,
                                                 force_source=bool(annotate))
            return {
                'changeset': changeset,
                'size': node.content_length,
                'preview': preview_data,
                'annotate': annotate,
                }
Beispiel #44
0
class TicketConversionTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub()
        self.env.config.set(
            'trac', 'templates_dir',
            os.path.join(os.path.dirname(self.env.path), 'templates'))
        self.ticket_module = TicketModule(self.env)
        self.mimeview = Mimeview(self.env)
        self.req = Mock(base_path='/trac.cgi',
                        path_info='',
                        href=Href('/trac.cgi'),
                        chrome={'logo': {}},
                        abs_href=Href('http://example.org/trac.cgi'),
                        environ={},
                        perm=[],
                        authname='-',
                        args={},
                        tz=None,
                        locale='',
                        session=None,
                        form_token=None)

    def tearDown(self):
        self.env.reset_db()

    def _create_a_ticket(self):
        # 1. Creating ticket
        ticket = Ticket(self.env)
        ticket['reporter'] = 'santa'
        ticket['summary'] = 'Foo'
        ticket['description'] = 'Bar'
        ticket['foo'] = 'This is a custom field'
        ticket.insert()
        return ticket

    def test_conversions(self):
        conversions = self.mimeview.get_supported_conversions(
            'trac.ticket.Ticket')
        expected = sorted(
            [('csv', 'Comma-delimited Text', 'csv', 'trac.ticket.Ticket',
              'text/csv', 8, self.ticket_module),
             ('tab', 'Tab-delimited Text', 'tsv', 'trac.ticket.Ticket',
              'text/tab-separated-values', 8, self.ticket_module),
             ('rss', 'RSS Feed', 'xml', 'trac.ticket.Ticket',
              'application/rss+xml', 8, self.ticket_module)],
            key=lambda i: i[-1],
            reverse=True)
        self.assertEqual(expected, conversions)

    def test_csv_conversion(self):
        ticket = self._create_a_ticket()
        csv = self.mimeview.convert_content(self.req, 'trac.ticket.Ticket',
                                            ticket, 'csv')
        self.assertEqual((u'id,summary,reporter,owner,description,status,'
                          'keywords,cc\r\n1,Foo,santa,,Bar,,,\r\n',
                          'text/csv;charset=utf-8', 'csv'), csv)

    def test_tab_conversion(self):
        ticket = self._create_a_ticket()
        csv = self.mimeview.convert_content(self.req, 'trac.ticket.Ticket',
                                            ticket, 'tab')
        self.assertEqual(
            (u'id\tsummary\treporter\towner\tdescription\tstatus\t'
             'keywords\tcc\r\n1\tFoo\tsanta\t\tBar\t\t\t\r\n',
             'text/tab-separated-values;charset=utf-8', 'tsv'), csv)

    def test_rss_conversion(self):
        ticket = self._create_a_ticket()
        content, mimetype, ext = self.mimeview.convert_content(
            self.req, 'trac.ticket.Ticket', ticket, 'rss')
        self.assertEqual(("""<?xml version="1.0"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
  <channel>
    <title>My Project: Ticket #1: Foo</title>
    <link>http://example.org/trac.cgi/ticket/1</link>
    <description>&lt;p&gt;
Bar
&lt;/p&gt;
</description>
    <language>en-us</language>
    <generator>Trac %s</generator>
 </channel>
</rss>""" % (TRAC_VERSION), 'application/rss+xml', 'xml'),
                         (content.replace('\r', ''), mimetype, ext))
Beispiel #45
0
class PygmentsRendererTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub(
            enable=[Chrome, LineNumberAnnotator, PygmentsRenderer])
        self.pygments = Mimeview(self.env).renderers[0]
        self.req = Mock(base_path='',
                        chrome={},
                        args={},
                        abs_href=Href('/'),
                        href=Href('/'),
                        session={},
                        perm=None,
                        authname=None,
                        tz=None)
        self.context = web_context(self.req)
        pygments_html = open(
            os.path.join(os.path.split(__file__)[0], 'pygments.html'))
        self.pygments_html = Stream(
            list(HTMLParser(pygments_html, encoding='utf-8')))

    def _expected(self, expected_id):
        return self.pygments_html.select(
            '//div[@id="%s"]/*|//div[@id="%s"]/text())' %
            (expected_id, expected_id))

    def _test(self, expected_id, result):
        expected = unicode(self._expected(expected_id))
        result = unicode(result)
        #print("\nE: " + repr(expected))
        #print("\nR: " + repr(result))
        expected, result = expected.splitlines(), result.splitlines()
        for exp, res in zip(expected, result):
            self.assertEqual(exp, res)
        self.assertEqual(len(expected), len(result))

    def test_python_hello(self):
        """
        Simple Python highlighting with Pygments (direct)
        """
        result = self.pygments.render(
            self.context, 'text/x-python', """
def hello():
        return "Hello World!"
""")
        self.assertTrue(result)
        self._test('python_hello', result)

    def test_python_hello_mimeview(self):
        """
        Simple Python highlighting with Pygments (through Mimeview.render)
        """
        result = Mimeview(self.env).render(
            self.context, 'text/x-python', """
def hello():
        return "Hello World!"
""")
        self.assertTrue(result)
        self._test('python_hello_mimeview', result)

    def test_python_with_lineno(self):
        result = format_to_html(
            self.env, self.context, """\
{{{#!text/x-python lineno
print 'this is a python sample'
a = b+3
z = "this is a string"
print 'this is the end of the python sample'
}}}
""")
        self.assertTrue(result)
        self._test('python_with_lineno_1', result)

        result = format_to_html(
            self.env, self.context, """\
{{{#!text/x-python lineno=3
print 'this is a python sample'
a = b+3
z = "this is a string"
print 'this is the end of the python sample'
}}}
""")
        self.assertTrue(result)
        self._test('python_with_lineno_2', result)

    def test_python_with_lineno_and_markups(self):
        """Python highlighting with Pygments and lineno annotator
        """
        result = format_to_html(
            self.env, self.context, """\
{{{#!text/x-python lineno=3 id=b marks=4-5
print 'this is a python sample'
a = b+3
z = "this is a string"
print 'this is the end of the python sample'
}}}
""")
        self.assertTrue(result)
        self._test('python_with_lineno_and_markups', result)

    def test_python_with_invalid_arguments(self):
        result = format_to_html(
            self.env, self.context, """\
{{{#!text/x-python lineno=-10
print 'this is a python sample'
a = b+3
z = "this is a string"
print 'this is the end of the python sample'
}}}
""")
        self.assertTrue(result)
        self._test('python_with_invalid_arguments_1', result)

        result = format_to_html(
            self.env, self.context, """\
{{{#!text/x-python lineno=a id=d marks=a-b
print 'this is a python sample'
a = b+3
z = "this is a string"
print 'this is the end of the python sample'
}}}
""")
        self.assertTrue(result)
        self._test('python_with_invalid_arguments_2', result)

    def test_pygments_lexer_options(self):
        self.env.config.set('pygments-lexer', 'php.startinline', True)
        self.env.config.set('pygments-lexer', 'php.funcnamehighlighting',
                            False)
        result = format_to_html(
            self.env, self.context, """
{{{#!php
if (class_exists('MyClass')) {
    $myclass = new MyClass();
}
}}}
""")
        self.assertTrue(result)
        self._test('pygments_lexer_options', result)

    def test_pygments_lexer_arguments(self):
        result = format_to_html(
            self.env, self.context, """
{{{#!php startinline=True funcnamehighlighting=False
if (class_exists('MyClass')) {
    $myclass = new MyClass();
}
}}}
""")
        self.assertTrue(result)
        self._test('pygments_lexer_arguments', result)

    def test_pygments_lexer_arguments_override_options(self):
        self.env.config.set('pygments-lexer', 'php.startinline', True)
        self.env.config.set('pygments-lexer', 'php.funcnamehighlighting',
                            False)
        result = format_to_html(
            self.env, self.context, """
{{{#!php funcnamehighlighting=True
if (class_exists('MyClass')) {
    $myclass = new MyClass();
}
}}}
""")
        self.assertTrue(result)
        self._test('pygments_lexer_arguments_override_options', result)

    def test_newline_content(self):
        """
        The behavior of Pygments changed post-Pygments 0.11.1, and now
        contains all four newlines.  In Pygments 0.11.1 and prior, it only
        has three since stripnl defaults to True.

        See http://trac.edgewall.org/ticket/7705.
        """
        from pkg_resources import parse_version, get_distribution

        result = self.pygments.render(self.context, 'text/x-python',
                                      '\n\n\n\n')
        self.assertTrue(result)
        t = "".join([r[1] for r in result if r[0] is TEXT])

        if parse_version(pygments.__version__) > parse_version('0.11.1') \
           or pygments.__version__ == '0.11.1' and 'dev' in \
           get_distribution('Pygments').version:
            self.assertEqual("\n\n\n\n", t)
        else:
            self.assertEqual("\n\n\n", t)

    def test_empty_content(self):
        """
        A '\n' token is generated for an empty file, so we have to bypass
        pygments when rendering empty files.
        """
        result = self.pygments.render(self.context, 'text/x-python', '')
        self.assertIsNone(result)

    def test_extra_mimetypes(self):
        """
        The text/x-ini mimetype is normally not known by Trac, but
        Pygments supports it.
        """
        mimeview = Mimeview(self.env)
        self.assertEqual('text/x-ini; charset=utf-8',
                         mimeview.get_mimetype('file.ini'))
        self.assertEqual('text/x-ini; charset=utf-8',
                         mimeview.get_mimetype('file.cfg'))
        self.assertEqual('text/x-ini; charset=utf-8',
                         mimeview.get_mimetype('file.text/x-ini'))
Beispiel #46
0
class PygmentsRendererTestCase(unittest.TestCase):

    def setUp(self):
        self.env = EnvironmentStub(enable=[Chrome, PygmentsRenderer])
        self.pygments = Mimeview(self.env).renderers[0]
        self.req = Mock(base_path='', chrome={}, args={},
                        abs_href=Href('/'), href=Href('/'),
                        session={}, perm=None, authname=None, tz=None)
        self.context = web_context(self.req)
        pygments_html = open(os.path.join(os.path.split(__file__)[0],
                                       'pygments.html'))
        self.pygments_html = Stream(list(HTMLParser(pygments_html, encoding='utf-8')))

    def _expected(self, expected_id):
        return self.pygments_html.select(
            '//div[@id="%s"]/*|//div[@id="%s"]/text())' %
            (expected_id, expected_id))

    def _test(self, expected_id, result):
        expected = str(self._expected(expected_id))
        result = str(result)
        #print "\nE: " + repr(expected)
        #print "\nR: " + repr(result)
        expected, result = expected.splitlines(), result.splitlines()
        for exp, res in zip(expected, result):
            self.assertEqual(exp, res)
        self.assertEqual(len(expected), len(result))

    def test_python_hello(self):
        """
        Simple Python highlighting with Pygments (direct)
        """
        result = self.pygments.render(self.context, 'text/x-python', """
def hello():
        return "Hello World!"
""")
        self.assertTrue(result)
        self._test('python_hello', result)

    def test_python_hello_mimeview(self):
        """
        Simple Python highlighting with Pygments (through Mimeview.render)
        """
        result = Mimeview(self.env).render(self.context, 'text/x-python', """
def hello():
        return "Hello World!"
""")
        self.assertTrue(result)
        self._test('python_hello_mimeview', result)

    def test_newline_content(self):
        """
        The behavior of Pygments changed post-Pygments 0.11.1, and now
        contains all four newlines.  In Pygments 0.11.1 and prior, it only
        has three since stripnl defaults to True.

        See http://trac.edgewall.org/ticket/7705.
        """
        from pkg_resources import parse_version, get_distribution

        result = self.pygments.render(self.context, 'text/x-python', '\n\n\n\n')
        self.assertTrue(result)
        t = "".join([r[1] for r in result if r[0] is TEXT])

        if parse_version(pygments.__version__) > parse_version('0.11.1') \
           or pygments.__version__ == '0.11.1' and 'dev' in \
           get_distribution('Pygments').version:
            self.assertEqual("\n\n\n\n", t)
        else:
            self.assertEqual("\n\n\n", t)

    def test_empty_content(self):
        """
        A '\n' token is generated for an empty file, so we have to bypass
        pygments when rendering empty files.
        """
        result = self.pygments.render(self.context, 'text/x-python', '')
        self.assertIsNone(result)

    def test_extra_mimetypes(self):
        """
        The text/x-ini mimetype is normally not known by Trac, but
        Pygments supports it.
        """
        mimeview = Mimeview(self.env)
        self.assertEqual('text/x-ini; charset=utf-8',
                         mimeview.get_mimetype('file.ini'))
        self.assertEqual('text/x-ini; charset=utf-8',
                         mimeview.get_mimetype('file.cfg'))
        self.assertEqual('text/x-ini; charset=utf-8',
                         mimeview.get_mimetype('file.text/x-ini'))
Beispiel #47
0
    def process_request(self, req):
        req.perm.assert_permission('TICKET_VIEW')

        action = req.args.get('action', 'view')

        db = self.env.get_db_cnx()
        id = int(req.args.get('id'))

        ticket = Ticket(self.env, id, db=db)

        if req.method == 'POST':
            if not req.args.has_key('preview'):
                self._do_save(req, db, ticket)
            else:
                # Use user supplied values
                ticket.populate(req.args)
                self._validate_ticket(req, ticket)

                req.hdf['ticket.action'] = action
                req.hdf['ticket.ts'] = req.args.get('ts')
                req.hdf['ticket.reassign_owner'] = req.args.get('reassign_owner') \
                                                   or req.authname
                req.hdf['ticket.resolve_resolution'] = req.args.get('resolve_resolution')
                comment = req.args.get('comment')
                if comment:
                    req.hdf['ticket.comment'] = comment
                    # Wiki format a preview of comment
                    req.hdf['ticket.comment_preview'] = wiki_to_html(
                        comment, self.env, req, db)
        else:
            req.hdf['ticket.reassign_owner'] = req.authname
            # Store a timestamp in order to detect "mid air collisions"
            req.hdf['ticket.ts'] = ticket.time_changed

        self._insert_ticket_data(req, db, ticket,
                                 get_reporter_id(req, 'author'))

        mime = Mimeview(self.env)
        format = req.args.get('format')
        if format:
            mime.send_converted(req, 'trac.ticket.Ticket', ticket, format,
                                'ticket_%d' % ticket.id)

        # If the ticket is being shown in the context of a query, add
        # links to help navigate in the query result set
        if 'query_tickets' in req.session:
            tickets = req.session['query_tickets'].split()
            if str(id) in tickets:
                idx = tickets.index(str(ticket.id))
                if idx > 0:
                    add_link(req, 'first', req.href.ticket(tickets[0]),
                             u'Ticket #%s' % tickets[0])
                    add_link(req, 'prev', req.href.ticket(tickets[idx - 1]),
                             u'Ticket #%s' % tickets[idx - 1])
                if idx < len(tickets) - 1:
                    add_link(req, 'next', req.href.ticket(tickets[idx + 1]),
                             u'Ticket #%s' % tickets[idx + 1])
                    add_link(req, 'last', req.href.ticket(tickets[-1]),
                             u'Ticket #%s' % tickets[-1])
                add_link(req, 'up', req.session['query_href'])

        add_stylesheet(req, 'common/css/ticket.css')

        # Add registered converters
        for conversion in mime.get_supported_conversions('trac.ticket.Ticket'):
            conversion_href = req.href.ticket(ticket.id, format=conversion[0])
            add_link(req, 'alternate', conversion_href, conversion[1],
                     conversion[3])

        return 'ticket.cs', None
Beispiel #48
0
    def process_request(self, req):
        req.perm.require('WIKI_VIEW')

        action = req.args.get('action', 'view')
        version = req.args.get('version')
        root = self.config.get('docs', 'root', '')
        base = req.args.get('path')
        if base[-1] == '/':
            base = base[:-1]
        path = root + base

        title = base or 'Docs'
        if action != 'view':
            title += ' (%s)' % action
        data = {}
        data['title'] = title

        repos = self.env.get_repository(authname=req.authname)
        node = repos.get_node(path, None)

        if node.isdir:
            page = DirPage(self.env, node, root, base)
        else:
            page = FilePage(self.env, node, root, base)

        data['editable'] = not node.isdir

        if req.method == 'POST':

            if action == 'edit':
                if page.node.isdir:
                    raise TracError("Cannot edit a directory")
                latest_version = page.version
                if req.args.has_key('cancel'):
                    req.redirect(req.href.docs(page.base))
                elif int(version) != latest_version:
                    action = 'collision'
                    self._render_editor(req, page, data)
                elif req.args.has_key('preview'):
                    action = 'preview'
                    self._render_editor(req, page, data, preview=True)
                else:
                    self._do_save(req, page)

        elif action == 'edit':
            self._render_editor(req, page, data)

        else:
            req.perm.assert_permission('WIKI_VIEW')

            if node.isdir:
                data['entries'] = page.get_entries(req)
                if page.index is not None:
                    data['index'] = page.index.get_html(req)
                else:
                    mimeview = Mimeview(self.env)
                    text = []
                    text.append('=' * (len(page.name) + 6))
                    text.append('   %s' % page.name)
                    text.append('=' * (len(page.name) + 6))
                    text = '\n'.join(text)
                    mimetype = 'text/x-rst; charset=utf8'
                    result = mimeview.render(req, mimetype, text)
                    data['index'] = result

            else:
                mime_type, chunk = page.get_raw()

                # When possible, send with non-text mimetype
                # Perhaps we should embed images...? 
                if not mime_type.startswith('text') or \
                    mime_type.startswith('text/html'):
                    req.send_response(200)
                    req.send_header('Content-Type', mime_type)
                    req.end_headers()
                    req.write(chunk)
                    return

                format = req.args.get('format')
                if format:
                    Mimeview(self.env).send_converted(req, 'text/x-rst', chunk, format, page.name)

                for conversion in Mimeview(self.env).get_supported_conversions('text/x-rst'):
                    conversion_href = req.href.docs(page.base, format=conversion[0])
                    add_link(req, 'alternate', conversion_href, conversion[1],
                             conversion[3])

                # Render the content into HTML
                data['content'] = page.get_html(req)


        data['action'] = action
        data['current_href'] = req.href.docs(page.base)
        data['log_href'] = req.href.log(page.path)

        # Include trac wiki stylesheet
        add_stylesheet(req, 'common/css/wiki.css')

        # Include trac docs stylesheet
        add_stylesheet(req, 'docs/common.css')

        # Include docutils stylesheet
        add_stylesheet(req, 'docs/docutils.css')

        # Include google-code-prettify
        add_stylesheet(req, 'docs/prettify.css')
        add_script(req, 'docs/prettify.min.js')

        # Include context navigation links
        history = [('root', req.href.docs())]
        t = ''
        for s in base[1:].split('/'):
            if not s: continue
            t += '/' + s
            history.append((s, req.href.docs(t)))
        for h in reversed(history):
            add_ctxtnav(req, h[0], h[1])
        add_ctxtnav(req, 'Revision Log', req.href.log(path))

        return 'docs.html', data, None
Beispiel #49
0
    def process_request(self, req):
        action = req.args.get('action', 'view')
        pagename = req.args.get('page', self.START_PAGE)
        version = None
        if req.args.get('version'):  # Allow version to be empty
            version = req.args.getint('version')
        old_version = req.args.getint('old_version')

        if pagename.startswith('/') or pagename.endswith('/') or \
                '//' in pagename:
            pagename = re.sub(r'/{2,}', '/', pagename.strip('/'))
            req.redirect(req.href.wiki(pagename))
        if not validate_page_name(pagename):
            raise TracError(_("Invalid Wiki page name '%(name)s'",
                              name=pagename))

        page = WikiPage(self.env, pagename)
        versioned_page = WikiPage(self.env, pagename, version)

        req.perm(versioned_page.resource).require('WIKI_VIEW')

        if version and versioned_page.version != version:
            raise ResourceNotFound(
                _('No version "%(num)s" for Wiki page "%(name)s"',
                  num=version, name=page.name))

        add_stylesheet(req, 'common/css/wiki.css')

        if req.method == 'POST':
            if action == 'edit':
                if 'cancel' in req.args:
                    req.redirect(req.href.wiki(page.name))

                has_collision = version != page.version
                for a in ('preview', 'diff', 'merge'):
                    if a in req.args:
                        action = a
                        break
                versioned_page.text = req.args.get('text')
                valid = self._validate(req, versioned_page)
                if action == 'edit' and not has_collision and valid:
                    return self._do_save(req, versioned_page)
                else:
                    return self._render_editor(req, page, action,
                                               has_collision)
            elif action == 'edit_comment':
                self._do_edit_comment(req, versioned_page)
            elif action == 'delete':
                self._do_delete(req, versioned_page)
            elif action == 'rename':
                return self._do_rename(req, page)
            elif action == 'diff':
                style, options, diff_data = get_diff_options(req)
                contextall = diff_data['options']['contextall']
                req.redirect(req.href.wiki(versioned_page.name, action='diff',
                                           old_version=old_version,
                                           version=version,
                                           contextall=contextall or None))
            else:
                raise HTTPBadRequest(_("Invalid request arguments."))
        elif action == 'delete':
            return self._render_confirm_delete(req, page)
        elif action == 'rename':
            return self._render_confirm_rename(req, page)
        elif action == 'edit':
            return self._render_editor(req, page)
        elif action == 'edit_comment':
            return self._render_edit_comment(req, versioned_page)
        elif action == 'diff':
            return self._render_diff(req, versioned_page)
        elif action == 'history':
            return self._render_history(req, versioned_page)
        else:
            format = req.args.get('format')
            if format:
                Mimeview(self.env).send_converted(req, 'text/x-trac-wiki',
                                                  versioned_page.text,
                                                  format, versioned_page.name)
            return self._render_view(req, versioned_page)
Beispiel #50
0
class TicketConversionTestCase(unittest.TestCase):

    def setUp(self):
        self.env = EnvironmentStub()
        self.env.config.set('trac', 'templates_dir',
                            os.path.join(os.path.dirname(self.env.path),
                                         'templates'))
        self.ticket_module = TicketModule(self.env)
        self.mimeview = Mimeview(self.env)
        self.req = Mock(base_path='/trac.cgi', path_info='',
                        href=Href('/trac.cgi'), chrome={'logo': {}},
                        abs_href=Href('http://example.org/trac.cgi'),
                        environ={}, perm=PermissionCache(self.env, '-'),
                        authname='-', args={}, tz=None,
                        locale='', session=None, form_token=None)

    def tearDown(self):
        self.env.reset_db()

    def _create_a_ticket(self):
        # 1. Creating ticket
        ticket = Ticket(self.env)
        ticket['owner'] = ''
        ticket['reporter'] = 'santa'
        ticket['summary'] = 'Foo'
        ticket['description'] = 'Bar'
        ticket['foo'] = 'This is a custom field'
        ticket.insert()
        return ticket

    def _create_a_ticket_with_email(self):
        ticket = Ticket(self.env)
        ticket['owner'] = '*****@*****.**'
        ticket['reporter'] = '*****@*****.**'
        ticket['cc'] = 'cc1, [email protected]'
        ticket['summary'] = 'Foo'
        ticket['description'] = 'Bar'
        ticket.insert()
        return ticket

    def test_conversions(self):
        conversions = self.mimeview.get_supported_conversions(
            'trac.ticket.Ticket')
        expected = sorted([('csv', 'Comma-delimited Text', 'csv',
                           'trac.ticket.Ticket', 'text/csv', 8,
                           self.ticket_module),
                          ('tab', 'Tab-delimited Text', 'tsv',
                           'trac.ticket.Ticket', 'text/tab-separated-values', 8,
                           self.ticket_module),
                           ('rss', 'RSS Feed', 'xml',
                            'trac.ticket.Ticket', 'application/rss+xml', 8,
                            self.ticket_module)],
                          key=lambda i: i[-1], reverse=True)
        self.assertEqual(expected, conversions)

    def test_csv_conversion(self):
        ticket = self._create_a_ticket()
        csv = self.mimeview.convert_content(self.req, 'trac.ticket.Ticket',
                                            ticket, 'csv')
        self.assertEqual(('\xef\xbb\xbf'
                          'id,summary,reporter,owner,description,status,'
                          'keywords,cc\r\n1,Foo,santa,,Bar,,,\r\n',
                          'text/csv;charset=utf-8', 'csv'), csv)

    def test_csv_conversion_with_obfuscation(self):
        ticket = self._create_a_ticket_with_email()
        csv = self.mimeview.convert_content(self.req, 'trac.ticket.Ticket',
                                            ticket, 'csv')
        self.assertEqual(
            ('\xef\xbb\xbf'
             'id,summary,reporter,owner,description,status,keywords,cc\r\n'
             '1,Foo,santa@…,joe@…,Bar,,,cc1 cc2@…\r\n',
             'text/csv;charset=utf-8', 'csv'),
            csv)
        self.req.perm = MockPerm()
        csv = self.mimeview.convert_content(self.req, 'trac.ticket.Ticket',
                                            ticket, 'csv')
        self.assertEqual(
            ('\xef\xbb\xbf'
             'id,summary,reporter,owner,description,status,keywords,cc\r\n'
             '1,Foo,[email protected],[email protected],Bar,,,'
             'cc1 [email protected]\r\n',
             'text/csv;charset=utf-8', 'csv'),
            csv)

    def test_tab_conversion(self):
        ticket = self._create_a_ticket()
        csv = self.mimeview.convert_content(self.req, 'trac.ticket.Ticket',
                                            ticket, 'tab')
        self.assertEqual(('\xef\xbb\xbf'
                          'id\tsummary\treporter\towner\tdescription\tstatus\t'
                          'keywords\tcc\r\n1\tFoo\tsanta\t\tBar\t\t\t\r\n',
                          'text/tab-separated-values;charset=utf-8', 'tsv'),
                         csv)

    def test_tab_conversion_with_obfuscation(self):
        ticket = self._create_a_ticket_with_email()
        csv = self.mimeview.convert_content(self.req, 'trac.ticket.Ticket',
                                            ticket, 'tab')
        self.assertEqual(
            ('\xef\xbb\xbf'
             'id\tsummary\treporter\towner\tdescription\tstatus\tkeywords\t'
             'cc\r\n'
             '1\tFoo\tsanta@…\tjoe@…\tBar\t\t\tcc1 cc2@…\r\n',
             'text/tab-separated-values;charset=utf-8', 'tsv'),
            csv)
        self.req.perm = MockPerm()
        csv = self.mimeview.convert_content(self.req, 'trac.ticket.Ticket',
                                            ticket, 'tab')
        self.assertEqual(
            ('\xef\xbb\xbf'
             'id\tsummary\treporter\towner\tdescription\tstatus\tkeywords\t'
             'cc\r\n'
             '1\tFoo\[email protected]\[email protected]\tBar\t\t\t'
             'cc1 [email protected]\r\n',
             'text/tab-separated-values;charset=utf-8', 'tsv'),
            csv)

    def test_rss_conversion(self):
        ticket = self._create_a_ticket()
        content, mimetype, ext = self.mimeview.convert_content(
            self.req, 'trac.ticket.Ticket', ticket, 'rss')
        self.assertEqual(("""<?xml version="1.0"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
  <channel>
    <title>My Project: Ticket #1: Foo</title>
    <link>http://example.org/trac.cgi/ticket/1</link>
    <description>&lt;p&gt;
Bar
&lt;/p&gt;
</description>
    <language>en-us</language>
    <generator>Trac %s</generator>
 </channel>
</rss>""" % (TRAC_VERSION),
                          'application/rss+xml', 'xml'),
                         (content.replace('\r', ''), mimetype, ext))
    def _render_readme(self, req, stream, data):
        add_stylesheet(req, 'common/css/code.css')

        repos = data.get('repos') or self.env.get_repository()
        rev = req.args.get('rev', None)

        # Rendering all READMEs in a directory preview
        for entry in data['dir']['entries']:
            try:
                if not entry.isdir and entry.name.lower().startswith('readme'):
                    node = repos.get_node(entry.path, rev)
                    req.perm(data['context'].resource).require('FILE_VIEW')
                    mimeview = Mimeview(self.env)
                    content = node.get_content()
                    mimetype = node.content_type
                    divclass = 'searchable'
                    if entry.name.lower().endswith('.wiki'):
                        mimetype = 'text/x-trac-wiki'
                        divclass = 'searchable wiki'
                    elif entry.name.lower().endswith('.md'):
                        mimetype = 'text/x-markdown'
                        divclass = 'searchable markdown'
                    if not mimetype or mimetype == 'application/octet-stream':
                        mimetype = mimeview.get_mimetype(
                            node.name, content.read(4096)) or \
                            mimetype or 'text/plain'
                    del content
                    self.log.debug(
                        "ReadmeRenderer: rendering node %s@%s as %s",
                        node.name, rev, mimetype)
                    output = mimeview.preview_data(
                        data['context'],
                        node.get_content(),
                        node.get_content_length(),
                        mimetype,
                        node.created_path,
                        '',
                        annotations=[],
                        force_source=False)

                    if output:
                        if isinstance(output['rendered'], Stream):
                            content = output['rendered'].select('.')
                        else:
                            content = output['rendered']
                        insert = tag.div(
                            tag.h1(entry.name,
                                   tag.a(Markup(' &para;'),
                                         class_="anchor",
                                         href='#' + entry.name,
                                         title='Link to file'),
                                   id_=entry.name),
                            tag.div(content,
                                    class_=divclass,
                                    title=entry.name),
                            class_="readme",
                            style="padding-top: 1em;"
                        )
                        xpath = "//div[@id='content']/div[@id='help']"
                        stream |= Transformer(xpath).before(insert)
            except Exception, e:
                self.log.debug(to_unicode(e))
Beispiel #52
0
class PatchRendererTestCase(unittest.TestCase):

    def setUp(self):
        env = EnvironmentStub(enable=[Chrome, PatchRenderer])
        req = MockRequest(env)
        self.context = web_context(req)
        self.patch = Mimeview(env).renderers[0]
        html_file = os.path.join(os.path.dirname(__file__), 'patch.data')
        self.patch_html = {}
        testcase = []
        with open(html_file, 'rb') as f:
            for line in f.readlines():
                if line.startswith('#'):
                    self.patch_html[line[1:].strip()] = testcase = []
                else:
                    testcase.append(line.rstrip())

    def _expected(self, expected_id):
        return self.patch_html[expected_id]

    def _test(self, expected_id, result):
        expected = self._expected(expected_id)
        result = result.splitlines()
        self.maxDiff = None
        for exp, res in zip(expected, result):
            self.assertEqual(exp, res)
        self.assertEqual(len(expected), len(result))

    def test_simple(self):
        """
        Simple patch rendering
        """
        result = self.patch.render(self.context, None, """
--- README.orig 2006-10-27 14:42:04.062500000 +0200
+++ README      2006-10-27 14:42:28.125000000 +0200
@@ -1,5 +1,5 @@
 ----
-base
-base
-base
+be
+the base
+base modified
 .
""")
        self.assertTrue(result)
        self._test('simple', result)

    def test_no_newline_in_base(self):
        """
        Simple regression test for #4027 ("No newline at end of file")
        """
        result = self.patch.render(self.context, None, """
--- nonewline   2006-10-27 08:36:48.453125000 +0200
+++ newline     2006-10-27 08:36:57.187500000 +0200
@@ -1 +1 @@
-ONELINE
\ No newline at end of file
+ONELINE
""")
        self.assertTrue(result)
        self._test('no_newline_in_base', result)

    def test_no_newline_in_changed(self):
        """
        Another simple regression test for #4027 ("No newline at end of file")
        """
        result = self.patch.render(self.context, None, """
--- newline     2006-10-27 08:36:57.187500000 +0200
+++ nonewline   2006-10-27 08:36:48.453125000 +0200
@@ -1 +1 @@
-ONELINE
+ONELINE
\ No newline at end of file
""")
        self.assertTrue(result)
        self._test('no_newline_in_changed', result)
    def test_diff_to_hdf_expandtabs(self):
        """Regression test related to #4557"""
        changes = self.patch._diff_to_hdf(
            ['--- hello.c 1',
             '+++ hello.c 2',
             '@@ -1 +1 @@',
             '-aa\tb',
             '+aaxb'], 8)
        self.assertEqual('aa<del>&nbsp; &nbsp; &nbsp; </del>b',
                         str(changes[0]['diffs'][0][0]['base']['lines'][0]))
        self.assertEqual('aa<ins>x</ins>b',
                         str(changes[0]['diffs'][0][0]['changed']['lines'][0]))

    def test_diff_to_hdf_leading_ws(self):
        """Regression test related to #5795"""
        changes = self.patch._diff_to_hdf(
            ['--- hello.c 1',
             '+++ hello.c 2',
             '@@ -1 +1 @@',
             '-*a',
             '+ *a'], 8)
        self.assertEqual('<del></del>*a',
                         str(changes[0]['diffs'][0][0]['base']['lines'][0]))
        self.assertEqual('<ins>&nbsp;</ins>*a',
                         str(changes[0]['diffs'][0][0]['changed']['lines'][0]))

    def test_range_information_with_no_lines(self):
        result = self.patch.render(self.context, None, """
Index: filename.txt
===================================================================
--- filename.txt
+++ filename.txt
@@ -14,7 +14,7 @@
""")
        self.assertTrue(result)
        self._test('range_information_with_no_lines', result)
Beispiel #53
0
    def process_request(self, req):
        """ Process request for listing, creating and removing projects
        """

        files_core = FilesCoreComponent(self.env)
        timeline_notifier = FilesEventNotifier(self.env)
        node_factory, download_config = files_core.files_node_factory_and_config(req)
        if req.args.get('redirect') == 'downloads':
            req.perm.require('FILES_DOWNLOADS_VIEW')
            if download_config.downloads_dir == '':
                raise HTTPNotFound(_("The project doesn't have downloads directory."))
            req.redirect(req.href.files(download_config.downloads_dir))

        user_store = get_userstore()
        user = user_store.getUser(req.authname)

        env_name = download_config.env_name

        node = MappedFileNode.from_request_path_info(req.path_info, node_factory)
        open_in_mode_mode = ''
        filename = None
        if req.args.get('action') == 'open_in_mode':
            open_in_mode_mode = req.args.get('mode')
        if not node.exists():
            if node.is_download() and node.download().is_available():
                node.delete()
            raise HTTPNotFound(_("The file was not found!"))
        if req.method == 'POST' and not req.args.get('cancel'):
            # Each X_from_request or X_by_request method does permission check
            action = req.args.get('action')
            # need to delete a file?
            if action == 'delete_multiple' or action == 'delete':
                self.process_delete(action, node, node_factory, req, timeline_notifier)
            elif action == 'add_file':
                filename, open_in_mode_mode = self.process_add_file(node,
                    req, timeline_notifier, user)
            elif action == 'move_multiple' or action == 'rename':
                self.process_move(action, node, node_factory, req,
                    timeline_notifier, user)
            elif action == 'add_folder':
                try:
                    new_dir = node.create_dir_from_request(req, user.id, timeline_notifier)
                    if not new_dir:
                        add_warning(req, _("No folder name was given"))
                    else:
                        filename = new_dir.filename
                        open_in_mode_mode = 'show_mode'
                except TracError as e:
                    add_warning(req, _("Error when creating a new directory: ") + str(e))
            elif action == 'update':
                filename, open_in_mode_mode = self.process_update(node, node_factory, req,
                    timeline_notifier, user)

        if node.is_dir():
            if open_in_mode_mode:
                if not filename:
                    filename = req.args.get('target')
                return self.show_dir(req, node, node_factory, files_core, user_store,
                    target_filename=filename, current_mode=open_in_mode_mode)
            else:
                return self.show_dir(req, node, node_factory, files_core, user_store)
        elif node.is_file():
            mimeview = Mimeview(self.env)
            try:
                node.show_file(req, mimeview, timeline_notifier)
            except InvalidOperationError as e:
                pass
            else:
                add_warning(req, _("Error was received when displaying the file"))
            parent_node = node.get_parent_dir()
            # Error was obtained
            return self.show_dir(req, parent_node, node_factory, files_core, user_store)
        else:
            raise TracError(_('Invalid filesystem node was requested'))
Beispiel #54
0
 def test_get_supported_conversions(self):
     mimeview = Mimeview(self.env)
     conversions = mimeview.get_supported_conversions('text/x-sample')
     self.assertEqual(Converter0(self.env), conversions[0][-1])
     self.assertEqual(Converter1(self.env), conversions[1][-1])
     self.assertEqual(Converter2(self.env), conversions[2][-1])
Beispiel #55
0
class PygmentsRendererTestCase(unittest.TestCase):

    def setUp(self):
        self.env = EnvironmentStub(enable=[Chrome, PygmentsRenderer])
        self.pygments = Mimeview(self.env).renderers[0]
        self.req = Mock(base_path='', chrome={}, args={},
                        abs_href=Href('/'), href=Href('/'),
                        session={}, perm=None, authname=None, tz=None)
        self.context = web_context(self.req)
        pygments_html = open(os.path.join(os.path.split(__file__)[0],
                                       'pygments.html'))
        self.pygments_html = Stream(list(HTMLParser(pygments_html, encoding='utf-8')))

    def _expected(self, expected_id):
        return self.pygments_html.select(
            '//div[@id="%s"]/*|//div[@id="%s"]/text())' % 
            (expected_id, expected_id))

    def _test(self, expected_id, result):
        expected = str(self._expected(expected_id))
        result = str(result)
        #print "\nE: " + repr(expected)
        #print "\nR: " + repr(result)
        expected, result = expected.splitlines(), result.splitlines()
        for exp, res in zip(expected, result):
            self.assertEquals(exp, res)
        self.assertEquals(len(expected), len(result))

    def test_python_hello(self):
        """
        Simple Python highlighting with Pygments (direct)
        """
        result = self.pygments.render(self.context, 'text/x-python', """
def hello():
        return "Hello World!"
""")
        self.assertTrue(result)
        self._test('python_hello', result)

    def test_python_hello_mimeview(self):
        """
        Simple Python highlighting with Pygments (through Mimeview.render)
        """
        result = Mimeview(self.env).render(self.context, 'text/x-python', """
def hello():
        return "Hello World!"
""")
        self.assertTrue(result)
        self._test('python_hello_mimeview', result)

    def test_newline_content(self):
        """
        The behavior of Pygments changed post-Pygments 0.11.1, and now
        contains all four newlines.  In Pygments 0.11.1 and prior, it only
        has three since stripnl defaults to True.

        See http://trac.edgewall.org/ticket/7705.
        """
        from pkg_resources import parse_version, get_distribution

        result = self.pygments.render(self.context, 'text/x-python', '\n\n\n\n')
        self.assertTrue(result)
        t = "".join([r[1] for r in result if r[0] is TEXT])

        if parse_version(pygments.__version__) > parse_version('0.11.1') \
           or pygments.__version__ == '0.11.1' and 'dev' in \
           get_distribution('Pygments').version:
            self.assertEqual("\n\n\n\n", t)
        else:
            self.assertEqual("\n\n\n", t)

    def test_empty_content(self):
        """
        A '\n' token is generated for an empty file, so we have to bypass
        pygments when rendering empty files.
        """
        result = self.pygments.render(self.context, 'text/x-python', '')
        self.assertEqual(None, result)