def _handle_builder(self, req): m = self.BUILDER_RE.match(req.path_info) try: builder = m.group(1) or None except Exception as e: builder = None master = BuildBotSystem(self.buildbot_url) if builder is None: data = {'names': master.getAllBuilders()} return 'bbw_allbuilders.html', data, 'text/html' else: class Foo: pass b = Foo() b.name = str(builder) b.current = 'CURRENT-TEXT' b.recent = [] b.slaves = [] data = {'builder': b} try: master = BuildBotSystem(self.buildbot_url) data = {'builder': master.getBuilder(builder)} except Exception as e: print('Error fetching builder stats', e) data['context'] = Context.from_request(req, ('buildbot', builder)) return 'bbw_builder.html', data, 'text/html'
def template_data(self, req, query, kwargs=None): db = self.env.get_read_db() tickets = query.execute(req, db) filtered_tickets = [ticket for ticket in tickets if 'TICKET_VIEW' in req.perm(Ticket(self.env, int(ticket['id'])).resource)] context = Context.from_request(req, 'query') return query.template_data(context, filtered_tickets, None, datetime.now(req.tz), req)
def _gather_option_data(self, req, section_name, option_name, section_default_values): option = None if (section_name, option_name) in Option.registry: # Allow wiki formatting in descriptions option = Option.registry[(section_name, option_name)] option_desc = format_to_oneliner(self.env, Context.from_request(req), option.__doc__) option_type = option.__class__.__name__.lower()[:-6] or 'text' else: option_desc = None option_type = 'text' # See "IniEditorBasicSecurityManager" for why we use a pipe char here. if ('%s|%s' % (section_name, option_name)) in self.password_options_set: option_type = 'password' if section_default_values: default_value = (self._convert_value( section_default_values.get(option_name), option) or '') else: default_value = '' return { 'default_value': default_value, 'desc': option_desc, 'type': option_type, 'option_info': option, 'access': self._check_option_access(section_name, option_name) }
def process_request(self, req): page_name = req.args.get('page_name', '') if page_name == '': page_name = 'index' # Add breadcrumb package_name, filename = self._get_package_and_filename(page_name) index_file = filename[:-len('.txt')] + '/index.txt' if not self._resource_exists(package_name, filename): # check if it is a folder, then match with index if self._resource_exists(package_name, index_file): filename = index_file else: error_msg = _('Page %(page_name)s not found', page_name=page_name) raise ResourceNotFound(error_msg) utf8_string = resource_string(package_name, filename) help_contents = utf8_string.decode('UTF-8') # add navigation bar self._set_prev_next(req) data = dict(context=Context.from_request(req), contents=help_contents, page_name=page_name) return ('agilo_help.html', data, 'text/html')
def _convert_query(self, req, query, sheet_query=True, sheet_history=False): # no paginator query.max = 0 query.has_more_pages = False query.offset = 0 # extract all fields except custom fields cols = ['id'] cols.extend(f['name'] for f in query.fields if not f.get('custom')) cols.extend(name for name in ('time', 'changetime') if name not in cols) query.cols = cols if hasattr(self.env, 'get_read_db'): db = self.env.get_read_db() else: db = self.env.get_db_cnx() tickets = query.execute(req, db) # add custom fields to avoid error to join many tables custom_fields = [f['name'] for f in query.fields if f.get('custom')] self._fill_custom_fields(tickets, custom_fields, db) context = Context.from_request(req, 'query', absurls=True) cols.extend([name for name in custom_fields if name not in cols]) data = query.template_data(context, tickets) book = Workbook(encoding='utf-8', style_compression=1) if sheet_query: self._create_sheet_query(req, context, data, book) if sheet_history: self._create_sheet_history(req, context, data, book) return get_workbook_content(book), 'application/vnd.ms-excel'
def pre_process_request(self, req, handler): if req.path_info.startswith('/wiki'): if req.method == 'POST' and req.args.get('action','view') == 'view': post_handler = None for poster in self.macro_posters: if not hasattr(poster, 'match_macro_post'): continue rv = poster.match_macro_post(req) if isinstance(rv, (str, unicode)): rv = rv in req.args.keys() if rv: post_handler = poster break if post_handler: post_handler.process_macro_post(req) else: # Silly stuff here self.log.debug('MacroPostModule: Unclaimed POST, scanning page %s', req.path_info[6:]) page = WikiPage(self.env, req.path_info[6:]) matches = self.macro_re.findall(page.text) + self.proc_re.findall(page.text) for name in matches: self.log.debug('MacroPostModule: Found macro "%s"', name) resource = Resource('wiki', name) context = Context.from_request(req, resource) wp = WikiProcessor(Formatter(self.env, context), name) if wp.macro_provider is None: self.log.debug('MacroPostModule: Invalid name!!! How did that happen') continue if hasattr(wp.macro_provider, 'process_macro_post') and \ not hasattr(wp.macro_provider, 'match_macro_post'): wp.macro_provider.process_macro_post(req) req.environ['REQUEST_METHOD'] = 'GET' # Revert back to a GET return handler
def expand_macro(self, formatter, name, content): # Example: [[ASA(42)]] args, kw = parse_args(content) args = [arg.strip() for arg in args] if not args or not args[0].isdigit(): raise TracError('Custom artifact id not specified') args, kw = parse_args(content) if not args or not args[0].isdigit(): raise TracError('Custom artifact id not specified') artifact_id = int(args[0]) dbp = DBPool(self.env, InstancePool()) try: dbp.load_artifact(id=artifact_id) except ValueError: return system_message("Custom Artifact not found", "No custom artifact was found for id '{0}'.".format(artifact_id)) artifact = dbp.pool.get_item(id=artifact_id) artifact_url = formatter.req.href.customartifacts('artifact/{0}'.format(artifact.get_id())) res = Core._get_resource(artifact) if not artifact in (Entity, Instance, None) and not type(artifact)==unicode else None spec_name, spec_url, values = _get_artifact_details(artifact, formatter.req) tpl='view_artifact_dialog.html' data = { 'context': Context.from_request(formatter.req, res), 'spec_name': spec_name, 'spec_url': spec_url, 'artifact': artifact, 'artifact_url': artifact_url, 'artifacts_values': values, } return Chrome(self.env).render_template(formatter.req, tpl, data, None, fragment=True)
def get_edit_artifact(request, dbp, obj, resource): require_permission(request.req, resource, dbp.env, operation="MODIFY") assert(isinstance(obj, Instance)) # otherwise, we're trying to edit something that is not an artifact aa_attributes = [name for name, val in obj.get_values()] attr_suggestions = [attr.name for attr in obj.get_attributes() if not attr.name in aa_attributes] values = [] for name,val in obj.get_values(): if type(val) is list: for v in val: values.append((str(uuid.uuid4()), name, v)) else: values.append((str(uuid.uuid4()), name, val)) # track access dbp.track_it("artifact", obj.get_id(), "edit", request.req.authname, str(datetime.now())) data = { 'context': Context.from_request(request.req, resource), 'spec_name': obj.__class__.get_name() if not obj.__class__ == Instance else "", 'artifact': obj, 'artifact_values': values, 'attr_suggestions' : attr_suggestions, 'default': obj.str_attr, 'url_path': request.req.href.customartifacts('artifact', obj.get_id()), } return 'edit_artifact_%s.html' % (request.get_format(),), data, None
def _do_ticket(self, req, template, data, content_type): if 'ticket' in data and 'linked_tickets' in data: ticket = data['ticket'] context = Context.from_request(req, ticket.resource) # Add name:#n links to link fields of Ticket instance when # flowing from storage to browser if req.method == 'GET': RemoteLinksProvider(self.env).augment_ticket(ticket) # Rerender link fields for field in data['fields']: if field['type'] == 'link': name = field['name'] field['rendered'] = format_to_oneliner(self.env, context, ticket[name]) # Add RemoteTicket objects for linked issues table, and pass list # of rejects that could not be retrieved linked_tickets, linked_rejects = self._remote_tickets(ticket, context) data['linked_tickets'].extend(linked_tickets) data['linked_rejects'].extend(linked_rejects) # Provide list of remote sites if newlinked form options are present if 'newlinked_options' in data: remote_sites = RemoteTicketSystem(self.env).get_remote_tracs() data['remote_sites'] = remote_sites return (template, data, content_type)
def render_macro(self, req, name, content): # Pull out the arguments source_obj = str(content) dest_format = "text/x-trac-wiki" 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> # 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 = (str( WikiTextRenderer(self.env).render(ctxt, "text/x-trac-wiki", str(out)))) return foo
def wiki_to_html(self, wikitext, req): self.env.log.debug('start function wiki_to_html') # pylint: disable-msg=E1101 # Remove some macros (TOC is better handled in ODT itself) for macro in self.remove_macros: wikitext = re.sub('\[\[%s(\([^)]*\))?\]\]' % macro, "", wikitext) # Now convert wiki to HTML out = StringIO() context = Context.from_request(req, absurls=True) Formatter(self.env, # pylint: disable-msg=E1101 context('wiki', self.page_name)).format(wikitext, out) html = Markup(out.getvalue()) html = html.encode("utf-8", 'replace') # Clean up the HTML html = re.sub('<span class="icon">.</span>', '', html) # Remove external link icon tidy_options = dict(output_xhtml=1, add_xml_decl=1, indent=1, tidy_mark=0, input_encoding='utf8', output_encoding='utf8', doctype='auto', wrap=0, char_encoding='utf8') html = tidy.parseString(html, **tidy_options) # Replace nbsp with entity: # http://www.mail-archive.com/[email protected]/msg03670.html html = str(html).replace(" ", " ") # Tidy creates newlines after <pre> (by indenting) html = re.sub('<pre([^>]*)>\n', '<pre\\1>', html) return html
def process_request(self, req): # Allow all POST requests (with a valid __FORM_TOKEN, ensuring that # the client has at least some permission). Additionally, allow GET # requests from TRAC_ADMIN for testing purposes. if req.method != 'POST': req.perm.require('TRAC_ADMIN') # @todo: Embed "tips" within the rendered output for the editor # (recognize TracLinks, table-stuff, macros, processors) # @todo: Save the content in server-side user-specific field for recovery realm = req.args.get('realm', 'wiki') id = req.args.get('id') version = req.args.get('version') if version is not None: try: version = int(version) except ValueError: version = None text = req.args.get('text', '') flavor = req.args.get('flavor') options = {} if 'escape_newlines' in req.args: options['escape_newlines'] = bool(int(req.args['escape_newlines'] or 0)) if 'shorten' in req.args: options['shorten'] = bool(int(req.args['shorten'] or 0)) resource = Resource(realm, id=id, version=version) context = Context.from_request(req, resource) rendered = format_to(self.env, flavor, context, text, **options) req.send(rendered.encode('utf-8'))
def process_request(self, req): # Allow all POST requests (with a valid __FORM_TOKEN, ensuring that # the client has at least some permission). Additionally, allow GET # requests from TRAC_ADMIN for testing purposes. if req.method != 'POST': req.perm.require('TRAC_ADMIN') realm = req.args.get('realm', 'wiki') id = req.args.get('id') version = req.args.get('version') if version is not None: try: version = int(version) except ValueError: version = None text = req.args.get('text', '') flavor = req.args.get('flavor') options = {} if 'escape_newlines' in req.args: options['escape_newlines'] = bool( int(req.args['escape_newlines'] or 0)) if 'shorten' in req.args: options['shorten'] = bool(int(req.args['shorten'] or 0)) resource = Resource(realm, id=id, version=version) context = Context.from_request(req, resource) rendered = format_to(self.env, flavor, context, text, **options) req.send(rendered.encode('utf-8'))
def _create_html_body(self, chrome, req, ticket, cnum, link): tktmod = TicketModule(self.env) attmod = AttachmentModule(self.env) data = tktmod._prepare_data(req, ticket) tktmod._insert_ticket_data(req, ticket, data, req.authname, {}) data['ticket']['link'] = link changes = data.get('changes') if cnum is None: changes = [] else: changes = [ change for change in (changes or []) if change.get('cnum') == cnum ] data['changes'] = changes context = Context.from_request(req, ticket.resource, absurls=True) data.update({ 'can_append': False, 'show_editor': False, 'start_time': ticket['changetime'], 'context': context, 'alist': attmod.attachment_data(context), 'styles': self._get_styles(chrome), 'link': tag.a(link, href=link), 'tag_': tag_, }) rendered = chrome.render_template(req, 'htmlnotification_ticket.html', data, fragment=True) return unicode(rendered)
def get_new_spec(request, dbp, obj, resource): require_permission(request.req, resource, dbp.env, operation="CREATE") from model import Entity if obj is Entity: # instantiating Entity (i.e., creating a spec) pass elif obj is Instance or isinstance( obj, Entity): # instantiating an existing spec return get_new_artifact(request, dbp, obj, resource) else: raise Exception( "Trying to instantiate something that can't be instantiated '%s'" % (obj, )) # track access dbp.track_it("spec", "", "new", request.req.authname, str(datetime.now())) data = { 'context': Context.from_request(request.req, resource), 'types': ['Text', 'Number'], # , 'Adaptive Artifact' 'multiplicities': ['1', '0..*', '1..*'], 'url_path': request.req.href.customartifacts('spec', obj.get_name()), } return 'edit_spec_page.html', data, None
def process_request(self, req): # Allow all POST requests (with a valid __FORM_TOKEN, ensuring that # the client has at least some permission). Additionally, allow GET # requests from TRAC_ADMIN for testing purposes. if req.method != 'POST': req.perm.require('TRAC_ADMIN') realm = req.args.get('realm', 'wiki') id = req.args.get('id') version = req.args.get('version') if version is not None: try: version = int(version) except ValueError: version = None text = req.args.get('text', '') flavor = req.args.get('flavor') options = {} if 'escape_newlines' in req.args: options['escape_newlines'] = bool(int(req.args['escape_newlines'] or 0)) if 'shorten' in req.args: options['shorten'] = bool(int(req.args['shorten'] or 0)) resource = Resource(realm, id=id, version=version) context = Context.from_request(req, resource) rendered = format_to(self.env, flavor, context, text, **options) req.send(rendered.encode('utf-8'))
def get_list_pages(request, dbp, obj, resource): require_permission(request.req, resource, dbp.env) artifact_id = request.req.args.get('artifact', None) if artifact_id is None: raise Exception("No artifact was specified.") dbp.load_artifact(artifact_id) artifact = dbp.pool.get_item(artifact_id) results = [] for pagename, page_version_id, ref_count in dbp.get_wiki_page_ref_counts( artifact): page = WikiPage(dbp.env, pagename) results.append({ 'href': get_resource_url(dbp.env, page.resource, request.req.href), 'title': pagename, 'date': user_time(request.req, format_datetime, page.time), 'author': page.author, 'excerpt': shorten_result(page.text) }) data = { 'context': Context.from_request(request.req, resource), 'artifact': artifact, 'results': results, } return 'list_pages.html', data, None
def get_list_pages(request, dbp, obj, resource): require_permission(request.req, resource, dbp.env) artifact_id = request.req.args.get('artifact', None) if artifact_id is None: raise Exception("No artifact was specified.") dbp.load_artifact(artifact_id) artifact = dbp.pool.get_item(artifact_id) results = [] for pagename, page_version_id, ref_count in dbp.get_wiki_page_ref_counts(artifact): page = WikiPage(dbp.env, pagename) results.append( {'href': get_resource_url(dbp.env, page.resource, request.req.href), 'title': pagename, 'date': user_time(request.req, format_datetime, page.time), 'author': page.author, 'excerpt': shorten_result(page.text)} ) data = { 'context': Context.from_request(request.req, resource), 'artifact': artifact, 'results': results, } return 'list_pages.html', data, None
def setup_widget(self, widgetns): r"""(Insert | update) the IWidgetProvider in the global namespace. @param widgetns widget name. @throws RuntimeError if a widget with requested name cannot be found. """ globs = self.globalns globs['ctx'] = Context.from_request(globs['req']) globs['auth_ctx'] = Context.from_request(globs['auth_req']) for wp in self.dbsys.providers : if widgetns in set(wp.get_widgets()) : globs['widget'] = wp break else : raise InvalidIdentifier('Cannot load widget provider for %s' % widgetns)
def render(self, req): """Render the data.""" context = Context.from_request(req) mimeview = Mimeview(self.env) return mimeview.render(context, self.mimetype, self.data, annotations=['lineno'])
def setUp(self): """ Set up the testing environment. """ self.env = EnvironmentStub(enable=[CodeExample]) self.req = Mock(base_path='', chrome={}, args={}, abs_href=Href('/'), href=Href('/'), session={}, perm=[], authname=None, tz=None, locale='utf-8') self.context = Context.from_request(self.req)
def format_to_html(req, env, text): req = Mock(href=Href('/'), abs_href=Href('http://www.example.com/'), authname='anonymous', perm=MockPerm(), args={}) context = Context.from_request(req) return trac.wiki.formatter.format_to_html(env, context, text)
def _get_welcome_page(self, req): rendered_page = None wiki_welcome = WikiPage(self.env, 'WelcomePage') if wiki_welcome: context = Context.from_request(req, wiki_welcome.resource) wiki_renderer = WikiTextRenderer(self.env) rendered_page = wiki_renderer.render(context, 'text/x-trac-wiki', wiki_welcome.text) return rendered_page
def process_request(self, req): """ Process request for listing, creating and removing projects """ add_script(req, 'multiproject/js/summary.js') data = {} if req.authname == 'anonymous': req.perm.require('PROJECT_VIEW') if not ('PROJECT_VIEW' in req.perm or 'PROJECT_PRIVATE_VIEW' in req.perm): return 'no_access.html', data, None # Load project from db project = Project.get(self.env) if req.args.get('action') == 'timeline_events': return self.get_summary_timeline_events(req, project.created) # TODO: Move project timeline implementation into macro # Get recent timeline events # TODO: Move project downloads implementation into macro # Get list of featured downloads downloads = [] if self.env.is_component_enabled('tracdownloads.api.DownloadsApi'): api = None # In case of import error we don't have it, so don't return any downloads try: from tracdownloads.api import DownloadsApi api = DownloadsApi(self.env) except ImportError: self.log.warning( "Unable to import DownloadsApi, but it's enabled.") if api: downloads = api.get_summary_items() # Load wiki:SummaryPage and show it as a main page summary_content = None summary_wiki = WikiPage(self.env, 'SummaryPage') if summary_wiki: context = Context.from_request(req, summary_wiki.resource) wiki_renderer = WikiTextRenderer(self.env) summary_content = wiki_renderer.render(context, 'text/x-trac-wiki', summary_wiki.text) data = { '_project_': project, # project object of a project we are in 'downloads': downloads, # list of featured downloads 'wiki_summary': summary_content, # Rendered content of the SummaryPage 'is_summary': True, 'env': self.env, } return 'summary.html', data, None
def render_admin_panel(self, req, cat, page, path_info): """ Returns the admin view and handles the form actions """ req.perm.require('TRAC_ADMIN') project = Project.get(self.env) if req.method == 'POST': myprojects_url = conf.url_home_path + "/myprojects" conf.log.exception("Redirect URL: %s" % myprojects_url) thisurl = Href(req.base_path)(req.path_info) context = Context.from_request(req) # Handle project remove if 'remove' in req.args: # Don't allow removing home if project.env_name == conf.sys_home_project_name: add_warning(req, 'Cannot remove home project') return req.redirect(thisurl) # Archive the project before removal archive = ProjectArchive() archived = archive.archive(project) if not archived: add_warning(req, 'Could not archive project "%s". Will not remove the project' % project.project_name) return req.redirect(thisurl) # Notify listeners. The project object still exists, but database does not for listener in self.project_change_listeners: listener.project_archived(project) # Do the actual project removal projects = Projects() if projects.remove_project(project): # Notify listeners. The project object still exists, but database does not for listener in self.project_change_listeners: listener.project_deleted(project) # NOTE: We no longer have project tables/session etc available req.redirect(myprojects_url) else: add_warning(req, 'Could not remove project "%s". Try again later' % project.project_name) return req.redirect(thisurl) add_script(req, 'multiproject/js/jquery-ui.js') add_script(req, 'multiproject/js/multiproject.js') add_script(req, 'multiproject/js/admin_system.js') add_stylesheet(req, 'multiproject/css/jquery-ui.css') # NOTE: Trac automatically puts 'project' dict in chrome thus it cannot be used data = {'multiproject': { 'project':project, 'home_url':conf.url_home_path }} return 'admin_system.html', data
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(Context.from_request(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 setup_widget(self, widgetns): r"""(Insert | update) the IWidgetProvider in the global namespace. @param widgetns widget name. @throws RuntimeError if a widget with requested name cannot be found. """ globs = self.globalns globs['ctx'] = Context.from_request(globs['req']) globs['auth_ctx'] = Context.from_request(globs['auth_req']) for wp in self.dbsys.providers: if widgetns in set(wp.get_widgets()): globs['widget'] = wp break else: raise InvalidIdentifier('Cannot load widget provider for %s' % widgetns)
def process_request(self, req): req.perm.require('BROWSER_VIEW') presel = req.args.get('preselected') if presel and (presel + '/').startswith(req.href.browser() + '/'): req.redirect(presel) path = req.args.get('path', '/') rev = req.args.get('rev', '') if rev in ('', 'HEAD'): rev = None order = req.args.get('order', 'name').lower() desc = req.args.has_key('desc') xhr = req.get_header('X-Requested-With') == 'XMLHttpRequest' rm = RepositoryManager(self.env) all_repositories = rm.get_all_repositories() reponame, repos, path = rm.get_repository_by_path(path) # Repository index show_index = not reponame and path == '/' if show_index: if repos and (as_bool(all_repositories[''].get('hidden')) or not repos.can_view(req.perm)): repos = None if not repos and reponame: raise ResourceNotFound( _("Repository '%(repo)s' not found", repo=reponame)) if reponame and reponame != repos.reponame: # Redirect alias qs = req.query_string req.redirect( req.href.browser(repos.reponame or None, path) + (qs and '?' + qs or '')) reponame = repos and repos.reponame or None # Find node for the requested path/rev context = Context.from_request(req) node = None display_rev = lambda rev: rev if repos: try: if rev: rev = repos.normalize_rev(rev) # If `rev` is `None`, we'll try to reuse `None` consistently, # as a special shortcut to the latest revision. rev_or_latest = rev or repos.youngest_rev node = get_existing_node(req, repos, path, rev_or_latest) except NoSuchChangeset, e: raise ResourceNotFound(e.message, _('Invalid changeset number')) context = context( repos.resource.child('source', path, version=rev_or_latest)) display_rev = repos.display_rev
def process_request(self, req): """ Process request for listing, creating and removing projects """ add_script(req, 'multiproject/js/summary.js') data = {} if req.authname == 'anonymous': req.perm.require('PROJECT_VIEW') if not ('PROJECT_VIEW' in req.perm or 'PROJECT_PRIVATE_VIEW' in req.perm): return 'no_access.html', data, None # Load project from db project = Project.get(self.env) if req.args.get('action') == 'timeline_events': return self.get_summary_timeline_events(req, project.created) # TODO: Move project timeline implementation into macro # Get recent timeline events # TODO: Move project downloads implementation into macro # Get list of featured downloads downloads = [] if self.env.is_component_enabled('tracdownloads.api.DownloadsApi'): api = None # In case of import error we don't have it, so don't return any downloads try: from tracdownloads.api import DownloadsApi api = DownloadsApi(self.env) except ImportError: self.log.warning("Unable to import DownloadsApi, but it's enabled.") if api: downloads = api.get_summary_items() # Load wiki:SummaryPage and show it as a main page summary_content = None summary_wiki = WikiPage(self.env, 'SummaryPage') if summary_wiki: context = Context.from_request(req, summary_wiki.resource) wiki_renderer = WikiTextRenderer(self.env) summary_content = wiki_renderer.render(context, 'text/x-trac-wiki', summary_wiki.text) data = { '_project_': project, # project object of a project we are in 'downloads': downloads, # list of featured downloads 'wiki_summary': summary_content, # Rendered content of the SummaryPage 'is_summary': True, 'env': self.env, } return 'summary.html', data, None
def _export_ticket(self, req, ticket, writer, field_names): cols = [unicode(ticket.id)] for name in field_names: value = ticket[name] or '' if name in ('cc', 'reporter'): context = Context.from_request(req, ticket.resource) value = Chrome(self.env).format_emails(context, value, ' ') cols.append(unicode(value).encode('utf-8')) writer.writerow(cols)
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 = Context.from_request(self.req) pygments_html = open(os.path.join(os.path.split(__file__)[0], 'pygments.html')) self.pygments_html = Stream(list(HTMLParser(pygments_html)))
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)))
def process_request(self, req): req.perm.require('BROWSER_VIEW') presel = req.args.get('preselected') if presel and (presel + '/').startswith(req.href.browser() + '/'): req.redirect(presel) path = req.args.get('path', '/') rev = req.args.get('rev', '') if rev in ('', 'HEAD'): rev = None order = req.args.get('order', 'name').lower() desc = req.args.has_key('desc') xhr = req.get_header('X-Requested-With') == 'XMLHttpRequest' rm = RepositoryManager(self.env) all_repositories = rm.get_all_repositories() reponame, repos, path = rm.get_repository_by_path(path) # Repository index show_index = not reponame and path == '/' if show_index: if repos and (as_bool(all_repositories[''].get('hidden')) or not repos.can_view(req.perm)): repos = None if not repos and reponame: raise ResourceNotFound(_("Repository '%(repo)s' not found", repo=reponame)) if reponame and reponame != repos.reponame: # Redirect alias qs = req.query_string req.redirect(req.href.browser(repos.reponame or None, path) + (qs and '?' + qs or '')) reponame = repos and repos.reponame or None # Find node for the requested path/rev context = Context.from_request(req) node = None display_rev = lambda rev: rev if repos: try: if rev: rev = repos.normalize_rev(rev) # If `rev` is `None`, we'll try to reuse `None` consistently, # as a special shortcut to the latest revision. rev_or_latest = rev or repos.youngest_rev node = get_existing_node(req, repos, path, rev_or_latest) except NoSuchChangeset, e: raise ResourceNotFound(e.message, _('Invalid changeset number')) context = context(repos.resource.child('source', path, version=rev_or_latest)) display_rev = repos.display_rev
def process_request(self, req): req.perm.assert_permission('TICKET_VIEW') if 'id' in req.args.keys(): try: ticket = int(req.args.get('id')) except ValueError: raise TracError('Need integer ticket id.') sql = ("SELECT 1 FROM ticket WHERE id=%s" % ticket) db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute(sql) row = cursor.fetchone() if not row: raise TracError( 'Cannot build dependency graph for non-existent ticket %d.' % ticket) depth = -1 for key in req.args.keys(): if key == 'depth': depth = req.args[key] options = '%s,%s' % (ticket, depth) add_ctxtnav(req, 'Back to Ticket #%s' % ticket, req.href.ticket(ticket)) title = 'Ticket #%s Dependency Graph' % ticket headline = 'Dependency Graph for Ticket #%s' % ticket else: constraints = {} for key in req.args.keys(): if isinstance(req.args[key], (list, tuple)): constraints[key] = '|'.join(req.args[key]) else: constraints[key] = req.args[key] options = 'query:' + '&'.join(key + '=' + constraints[key] for key in constraints) title = 'Ticket query Dependency Graph' headline = 'Dependency Graph for Query' add_ctxtnav(req, 'Back to query', req.href('query', **req.args)) data = {} context = Context.from_request(req, '') formatter = Formatter(self.env, context) graph = DepGraphMacro(self.env).expand_macro(formatter, 'DepGraph', options) data['title'] = title data['headline'] = headline data['depgraph'] = Markup(graph) return 'depgraph.html', data, None
class IncludeMacro(WikiMacroBase): """A macro to include other resources in wiki pages. More documentation to follow. """ implements(IPermissionRequestor) # Default output formats for sources that need them. default_formats = { 'wiki': 'text/x-trac-wiki', } # IWikiMacroProvider methods def expand_macro(self, formatter, name, content): args = [x.strip() for x in content.split(',')] if len(args) == 1: args.append(None) elif len(args) != 2: return system_message('Invalid arguments "%s"' % content) # Pull out the arguments. source, dest_format = args try: source_format, source_obj = source.split(':', 1) except ValueError: # If no : is present, assume its a wiki page. source_format, source_obj = 'wiki', source # Apply a default format if needed. if dest_format is None: dest_format = self.default_formats.get(source_format) out = ctxt = None if source_format in ('http', 'https', 'ftp'): # Since I can't really do recursion checking, and because this # could be a source of abuse allow selectively blocking it. # RFE: Allow blacklist/whitelist patterns for URLS. <NPK> # RFE: Track page edits and prevent unauthorized users from ever # entering an URL include. <NPK> if 'INCLUDE_URL' not in formatter.perm: self.log.info( "IncludeMacro: Blocking attempt by %s to include URL %s " "on page %s", formatter.req.authname, source, formatter.req.path_info) return '' try: urlf = urllib2.urlopen(source) out = urlf.read() except urllib2.URLError, e: return system_message("Error while retrieving file", str(e)) except TracError, e: return system_message("Error while previewing", str(e)) ctxt = Context.from_request(formatter.req)
def post_process_request(self, req, template, data, content_type): if template == 'report_view.html' and req.args.get('id'): format = req.args.get('format') if format == 'xls': resource = Resource('report', req.args['id']) data['context'] = Context.from_request(req, resource, absurls=True) self._convert_report(req, data) elif not format: self._add_alternate_links(req) return template, data, content_type
def process_request(self, req): # Create request context. context = Context.from_request(req) context.realm = 'discussion-core' if req.args.has_key('forum'): context.resource = Resource('discussion', 'forum/%s' % (req.args['forum'], )) if req.args.has_key('topic'): context.resource = Resource('discussion', 'topic/%s' % (req.args['topic'], )) if req.args.has_key('message'): context.resource = Resource('discussion', 'message/%s' % (req.args['message'], )) # Redirect to content converter if requested. if req.args.has_key('format'): if req.args.has_key('topic'): Mimeview(self.env).send_converted(req, 'tracdiscussion.topic', context.resource, req.args.get('format'), filename=None) elif req.args.has_key('forum'): Mimeview(self.env).send_converted(req, 'tracdiscussion.forum', context.resource, req.args.get('format'), filename=None) # Process request and return content. api = self.env[DiscussionApi] template, data = api.process_discussion(context) if context.redirect_url: # Redirect if needed. href = req.href(context.redirect_url[0]) + context.redirect_url[1] self.log.debug(_("Redirecting to %s") % (href)) req.redirect(req.href('discussion', 'redirect', redirect_url=href)) else: # Add links to other formats. if context.forum or context.topic or context.message: for conversion in Mimeview(self.env).get_supported_conversions( 'tracdiscussion.topic'): format, name, extension, in_mimetype, out_mimetype, \ quality, component = conversion conversion_href = get_resource_url(self.env, context.resource, context.req.href, format=format) add_link(context.req, 'alternate', conversion_href, name, out_mimetype, format) # Return template and its data. return template, data, None
def process_request(self, req): req.perm.assert_permission('TICKET_VIEW') if 'id' in req.args.keys(): try: ticket = int(req.args.get('id')) except ValueError: raise TracError('Need integer ticket id.') sql = ("SELECT 1 FROM ticket WHERE id=%s" %ticket) db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute(sql) row = cursor.fetchone() if not row: raise TracError('Cannot build dependency graph for non-existent ticket %d.' % ticket) depth = -1 for key in req.args.keys(): if key == 'depth': depth = req.args[key] options = '%s,%s' %(ticket, depth) add_ctxtnav(req, 'Back to Ticket #%s'%ticket, req.href.ticket(ticket)) title = 'Ticket #%s Dependency Graph' %ticket headline = 'Dependency Graph for Ticket #%s' %ticket else: constraints = {} for key in req.args.keys(): if isinstance(req.args[key], (list, tuple)): constraints[key] = '|'.join(req.args[key]) else: constraints[key] = req.args[key] options = 'query:' + '&'.join(key + '=' + constraints[key] for key in constraints) title = 'Ticket query Dependency Graph' headline = 'Dependency Graph for Query' add_ctxtnav(req, 'Back to query', req.href('query', **req.args)) data = {} context = Context.from_request(req, '') formatter = Formatter(self.env, context) graph = DepGraphMacro(self.env).expand_macro(formatter, 'DepGraph', options) data['title'] = title data['headline'] = headline data['depgraph'] = Markup(graph) return 'depgraph.html', data, None
def post_process_request(self, req, template, data, content_type): if template == 'report_view.html' and req.args.get('id'): format = req.args.getfirst('format') if format in ('xlsx', 'xls'): resource = Resource('report', req.args['id']) data['context'] = Context.from_request(req, resource, absurls=True) self._convert_report(format, req, data) elif not format: self._add_alternate_links(req) return template, data, content_type
def process_request(self, req): ''' Create a resource realm for the test item ''' EventModel = EventData(self.env, None) context = Context.from_request(req) context.realm = 'pm' ''' Render Content ''' director = self._parse_url_request(req) data = {} add_stylesheet(req, 'ht/css/pm.css') add_stylesheet(req, 'ht/css/fullcalendar.css') add_stylesheet(req, 'ht/css/jquery-ui-1.8.16.sqa.css') add_javascript(req, 'ht/js/fullcalendar.js') add_javascript(req, 'ht/js/jquery-ui-1.8.16.custom.min.js') add_javascript(req, 'ht/js/jquery.flot.js') add_javascript(req, 'ht/js/jquery.flot.pie.js') add_javascript(req, 'ht/js/pm.js') #self.log.debug("--> Got this request: %s and %s" % (req, req.args)) if (req.args.has_key('areq')): ''' Process AJAX request ''' #self.log.debug("Processing AJAX Request %s" %(req.args['areq']) ) if (req.args['areq'] == 'pm_cal_req'): ''' ''' json_data = EventModel.getEventData(req) #self.log.debug("JSON CONTENT - %s" %(json_data) ) ''' BYPASS Trac template processing Return RAW data feeds... no template ''' #self.log.debug("Length of Json String ----> %s" %(len(json_data)) ) req.send_header('content-length', len(json_data) ) req.write(json_data) return return 'pm/main.html', data, None
def get_view_spec(request, dbp, obj, resource): require_permission(request.req, resource, dbp.env) # track access dbp.track_it("spec", obj.get_id(), "view", request.req.authname, str(datetime.now())) data = { 'context': Context.from_request(request.req, resource), 'spec': obj, 'artifacts_url': request.req.href.customartifacts(spec=obj.get_name()), } return 'view_spec_page.html', data, None
def process_request(self, req): req.perm.require('PRODUCT_VIEW') # Initially this will render static widgets. With time it will be # more and more dynamic and flexible. if self.env[QueryModule] is not None: add_ctxtnav(req, _('Custom Query'), req.href.query()) if self.env[ReportModule] is not None: add_ctxtnav(req, _('Reports'), req.href.report()) context = Context.from_request(req) template, layout_data = self.expand_layout_data(context, 'bootstrap_grid', self.DASHBOARD_SCHEMA if isinstance(self.env, ProductEnvironment) else self.DASHBOARD_GLOBAL_SCHEMA ) widgets = self.expand_widget_data(context, layout_data) return template, { 'context': Context.from_request(req), 'layout': layout_data, 'widgets': widgets, 'title': _(self.mainnav_label), 'default': {'height': self.default_widget_height or None} }, None
def filter_stream(self, req, method, filename, stream, data): if filename == 'ticket.html': ticket = data.get('ticket') if ticket and ticket.exists: context = Context.from_request(req, ticket.resource) self.changesets = TicketChangesetsFormatter(self.env, context, ticket.id) exists = self.changesets.exists() if exists or not self.hide_when_none: filter = Transformer('//div[@id="attachments"]') return stream | filter.after(self._render(req, ticket, exists)) return stream
def expand_layout_data(self, req, layout_name, schema, embed=False): """Determine the template needed to render a specific layout and the data needed to place the widgets at expected location. """ layout = DashboardSystem(self.env).resolve_layout(layout_name) ctx = Context.from_request(req) template = layout.expand_layout(layout_name, ctx, { 'schema' : schema, 'embed' : embed })['template'] return template, schema
def setUp(self): self.env = EnvironmentStub(enable=[AutoWikify]) self.req = Mock( authname='anonymous', perm=MockPerm(), tz=None, args={}, href=Href('/'), abs_href=Href('http://www.example.com/')) self.autowikify = AutoWikify(self.env) for name in (u'autowikify', u'あいうName', u'Nameあいう', u'かきくけこ'): page = WikiPage(self.env, name) page.text = name page.save('admin', '', '::1') self.context = Context.from_request(self.req, WikiPage(self.env, name))
def get_list_search_by_filter(request, dbp, obj, resource): require_permission(request.req, resource, dbp.env) dbp.load_artifacts_of(Instance.get_name()) artifacts_with_no_spec = dbp.pool.get_instances_of(Instance.get_name(), direct_instances_only=True) # track access dbp.track_it("pick_artifact", "", "view", request.req.authname, str(datetime.now())) data = { 'context': Context.from_request(request.req, resource), 'url_path': '', } return 'index_dialog.html', data, None
def get_list_spec(request, dbp, obj, resource): require_permission(request.req, resource, dbp.env) dbp.load_artifacts_of(obj.get_name()) artifacts = dbp.pool.get_instances_of(obj.get_name()) data = { 'context': Context.from_request(request.req, resource), 'action': 'list', 'list_title': obj.get_name() + "s", 'spec': obj, 'artifacts': artifacts, } return 'list_spec_artifacts_page.html', data, None
def _export_rss(self, req, resource): # Create request context. context = Context.from_request(req) context.realm = 'discussion-core' context.resource = resource # Process request and get template and template data. api = self.env[DiscussionApi] template, data = api.process_discussion(context) # Render template and return RSS feed. output = Chrome(self.env).render_template(req, template, data, 'application/rss+xml') return output, 'application/rss+xml'
def _render_view(self, req, db, version): db = self.env.get_db_cnx() sql = "SELECT name FROM milestone " \ "INNER JOIN milestone_version ON (name = milestone) " \ "WHERE version = %s " \ "ORDER BY due" cursor = db.cursor() cursor.execute(sql, (version.name,)) milestones = [] tickets = [] milestone_stats = [] for row in cursor: milestone = Milestone(self.env, row[0]) milestones.append(milestone) mtickets = get_tickets_for_milestone(self.env, db, milestone.name, 'owner') mtickets = apply_ticket_permissions(self.env, req, mtickets) tickets += mtickets stat = get_ticket_stats(self.milestone_stats_provider, mtickets) milestone_stats.append(milestone_stats_data(self.env, req, stat, milestone.name)) stats = get_ticket_stats(self.version_stats_provider, tickets) interval_hrefs = version_interval_hrefs(self.env, req, stats, [milestone.name for milestone in milestones]) version.resource = Resource('version', version.name) context = Context.from_request(req, version.resource) version.is_released = version.time and version.time.date() < date.today() version.stats = stats version.interval_hrefs = interval_hrefs version.stats_href = [] # Not implemented yet, see th:#10349 data = { 'context': context, 'version': version, 'attachments': AttachmentModule(self.env).attachment_data(context), 'milestones': milestones, 'milestone_stats': milestone_stats, 'show_milestone_description': self.show_milestone_description # Not implemented yet } add_stylesheet(req, 'extendedversion/css/version.css') add_script(req, 'common/js/folding.js') add_ctxtnav(req, _("Back to Versions"), req.href.versions()) return 'version_view.html', data, None
def get_list_search_no_spec(request, dbp, obj, resource): require_permission(request.req, resource, dbp.env) dbp.load_artifacts_of(Instance.get_name()) artifacts_with_no_spec = dbp.pool.get_instances_of( Instance.get_name(), direct_instances_only=True) data = { 'context': Context.from_request(request.req, resource), 'action': 'list', 'list_title': 'Artifacts without a spec', 'spec': Instance, 'artifacts': artifacts_with_no_spec, } return 'list_spec_artifacts_page.html', data, None