def parseargs(request, args, defpagename, defyear, defmonth, defoffset, defoffset2, defheight6, defanniversary, deftemplate): """ parse macro arguments """ args = wikiutil.parse_quoted_separated(args, name_value=False) args += [None] * 8 # fill up with None to trigger defaults parmpagename, parmyear, parmmonth, parmoffset, parmoffset2, parmheight6, parmanniversary, parmtemplate = args[:8] parmpagename = wikiutil.get_unicode(request, parmpagename, 'pagename', defpagename) parmyear = wikiutil.get_int(request, parmyear, 'year', defyear) parmmonth = wikiutil.get_int(request, parmmonth, 'month', defmonth) parmoffset = wikiutil.get_int(request, parmoffset, 'offset', defoffset) parmoffset2 = wikiutil.get_int(request, parmoffset2, 'offset2', defoffset2) parmheight6 = wikiutil.get_bool(request, parmheight6, 'height6', defheight6) parmanniversary = wikiutil.get_bool(request, parmanniversary, 'anniversary', defanniversary) parmtemplate = wikiutil.get_unicode(request, parmtemplate, 'template', deftemplate) # multiple pagenames separated by "*" - split into list of pagenames parmpagename = re.split(r'\*', parmpagename) return parmpagename, parmyear, parmmonth, parmoffset, parmoffset2, parmheight6, parmanniversary, parmtemplate
def testLimited(self): tests = [ # regular and quoting tests (u'd = 4,c=3,b=2,a= 1 ', ([], {u'd': u'4', u'c': u'3,b=2,a= 1'}, [])), (u'a,b,c,d', ([u'a', u'b,c,d'], {}, [])), (u'a=b,b,c,d', ([], {u'a': u'b'}, [u'b,c,d'])), ] for args, expected in tests: result = wikiutil.parse_quoted_separated(args, seplimit=1) assert expected == result for val in result[0]: assert val is None or isinstance(val, unicode) for val in result[1].keys(): assert val is None or isinstance(val, unicode) for val in result[1].values(): assert val is None or isinstance(val, unicode) for val in result[2]: assert val is None or isinstance(val, unicode)
def testNoNameValue(self): abcd = [u'a', u'b', u'c', u'd'] tests = [ # regular and quoting tests (u'd = 4,c=3,b=2,a= 1 ', [u'd = 4', u'c=3', u'b=2', u'a= 1']), (u'a,b,c,d', abcd), (u' a , b , c , d ', abcd), (u' a ', [u'a']), (u'" a "', [u' a ']), (u'a,b,c,d, "a,b,c,d"', abcd + [u'a,b,c,d']), (u'quote " :), b', [u'quote " :)', u'b']), (u'"quote "" :)", b', [u'quote " :)', u'b']), (u'"unended quote', [u'"unended quote']), (u'"', [u'"']), (u'd=d,e="a,b,c,d"', [u'd=d', u'e="a', u'b', u'c', u'd"']), ] for args, expected in tests: result = wikiutil.parse_quoted_separated(args, name_value=False) assert expected == result for val in result: assert val is None or isinstance(val, unicode)
def parseargs(request, args, defpagename, defyear, defmonth, defoffset, defoffset2, defheight6, defanniversary, deftemplate): """ parse macro arguments """ args = wikiutil.parse_quoted_separated(args, name_value=False) args += [None] * 8 # fill up with None to trigger defaults parmpagename, parmyear, parmmonth, parmoffset, parmoffset2, parmheight6, parmanniversary, parmtemplate = args[: 8] parmpagename = wikiutil.get_unicode(request, parmpagename, 'pagename', defpagename) parmyear = wikiutil.get_int(request, parmyear, 'year', defyear) parmmonth = wikiutil.get_int(request, parmmonth, 'month', defmonth) parmoffset = wikiutil.get_int(request, parmoffset, 'offset', defoffset) parmoffset2 = wikiutil.get_int(request, parmoffset2, 'offset2', defoffset2) parmheight6 = wikiutil.get_bool(request, parmheight6, 'height6', defheight6) parmanniversary = wikiutil.get_bool(request, parmanniversary, 'anniversary', defanniversary) parmtemplate = wikiutil.get_unicode(request, parmtemplate, 'template', deftemplate) # multiple pagenames separated by "*" - split into list of pagenames parmpagename = re.split(r'\*', parmpagename) return parmpagename, parmyear, parmmonth, parmoffset, parmoffset2, parmheight6, parmanniversary, parmtemplate
def _check(a, e): r = wikiutil.parse_quoted_separated(a) assert r == e
def testMacroArgs(self): abcd = [u'a', u'b', u'c', u'd'] abcd_dict = {u'a': u'1', u'b': u'2', u'c': u'3', u'd': u'4'} tests = [ # regular and quoting tests (u'd = 4,c=3,b=2,a= 1 ', ([], abcd_dict, [])), (u'a,b,c,d', (abcd, {}, [])), (u' a , b , c , d ', (abcd, {}, [])), (u' a ', ([u'a'], {}, [])), (u'" a "', ([u' a '], {}, [])), (u'a,b,c,d, "a,b,c,d"', (abcd+[u'a,b,c,d'], {}, [])), (u'quote " :), b', ([u'quote " :)', u'b'], {}, [])), (u'"quote "" :)", b', ([u'quote " :)', u'b'], {}, [])), (u'=7', ([], {u'': u'7'}, [])), (u',,', ([None, None, None], {}, [])), (u',"",', ([None, u'', None], {}, [])), (u',"", ""', ([None, u'', u''], {}, [])), (u' "" ,"", ""', ([u'', u'', u''], {}, [])), # some name=value test (u'd = 4,c=3,b=2,a= 1 ', ([], abcd_dict, [])), (u'd=d,e="a,b,c,d"', ([], {u'd': u'd', u'e': u'a,b,c,d'}, [])), (u'd = d,e = "a,b,c,d"', ([], {u'd': u'd', u'e': u'a,b,c,d'}, [])), (u'd = d, e = "a,b,c,d"', ([], {u'd': u'd', u'e': u'a,b,c,d'}, [])), (u'd = , e = "a,b,c,d"', ([], {u'd': None, u'e': u'a,b,c,d'}, [])), (u'd = "", e = "a,b,c,d"', ([], {u'd': u'', u'e': u'a,b,c,d'}, [])), (u'd = "", e = ', ([], {u'd': u'', u'e': None}, [])), (u'd=""', ([], {u'd': u''}, [])), (u'd = "", e = ""', ([], {u'd': u'', u'e': u''}, [])), # no, None as key isn't accepted (u' = "", e = ""', ([], {u'': u'', u'e': u''}, [])), # can quote both name and value: (u'd = d," e "= "a,b,c,d"', ([], {u'd': u'd', u' e ': u'a,b,c,d'}, [])), # trailing args (u'1,2,a=b,3,4', ([u'1', u'2'], {u'a': u'b'}, [u'3', u'4'])), # can quote quotes: (u'd = """d"', ([], {u'd': u'"d'}, [])), (u'd = """d"""', ([], {u'd': u'"d"'}, [])), (u'd = "d"" ", e=7', ([], {u'd': u'd" ', u'e': u'7'}, [])), (u'd = "d""", e=8', ([], {u'd': u'd"', u'e': u'8'}, [])), ] for args, expected in tests: result = wikiutil.parse_quoted_separated(args) assert expected == result for val in result[0]: assert val is None or isinstance(val, unicode) for val in result[1].keys(): assert val is None or isinstance(val, unicode) for val in result[1].values(): assert val is None or isinstance(val, unicode) for val in result[2]: assert val is None or isinstance(val, unicode)
def execute(macro, args): """ Execute the 'macro' with the given 'args': an optional list of selected category names (categories whose pages are to be shown). """ request = macro.request fmt = macro.formatter page = fmt.page # Interpret the arguments. try: selected_category_names = args and wikiutil.parse_quoted_separated(args, name_value=False) or [] except AttributeError: selected_category_names = args.split(",") selected_category_names = [arg for arg in selected_category_names if arg] # Get the categories. categories = getCategoryMapping(getCategories(request), request) # Generate a menu with the categories, together with expanded submenus for # the categories employed by the current page, the category represented by # the current page, or for those categories specified in the macro # arguments. output = [] output.append(fmt.bullet_list(on=1, attr={"class" : "category-menu"})) for category in categories: category_name, category_pagename = category # Work out whether the current page belongs to this category. page_is_category = page.page_name == category_pagename category_membership_regexp = re.compile(category_membership_regexp_str % category_pagename) page_is_in_category = category_membership_regexp.search(page.get_raw_body()) # Generate the submenu where appropriate. if selected_category_names and category_name in selected_category_names or \ not selected_category_names and (page_is_category or page_is_in_category): if page_is_category: output.append(fmt.listitem(on=1, attr={"class" : "selected current"})) output.append(fmt.text(category_name)) else: output.append(fmt.listitem(on=1, attr={"class" : "selected"})) output.append(fmt.pagelink(on=1, pagename=category_pagename)) output.append(fmt.text(category_name)) output.append(fmt.pagelink(on=0, pagename=category_pagename)) output.append(fmt.bullet_list(on=1, attr={"class" : "category-submenu"})) # Get the pages and page names in the category. pages_in_category = getPages(category_pagename, request) # Visit each page in the category. last_parts = [] for page_in_category in pages_in_category: pagename = page_in_category.page_name # Get a real page, not a result page. real_page_in_category = Page(request, pagename) # Get a pretty version of the page name. pretty_pagename = getPrettyPageName(real_page_in_category) if page.page_name == pagename: output.append(fmt.listitem(on=1, attr={"class" : "selected"})) else: output.append(fmt.listitem(on=1)) # Abbreviate long hierarchical names. parts = pretty_pagename.split(u" ?") common = 0 for last, current in map(None, last_parts, parts): if last == current: common += 1 else: break # Use the arrows to indicate subpages. prefix = u" ?" * common suffix = u" ?".join(parts[common:]) output.append(fmt.text(prefix)) # Link to the page using the pretty name. output.append(linkToPage(request, real_page_in_category, suffix)) output.append(fmt.listitem(on=0)) last_parts = parts output.append(fmt.bullet_list(on=0)) output.append(fmt.listitem(on=0)) # Otherwise generate a simple link. else: output.append(fmt.listitem(on=1)) output.append(fmt.pagelink(on=1, pagename=category_pagename)) output.append(fmt.text(category_name)) output.append(fmt.pagelink(on=0, pagename=category_pagename)) output.append(fmt.listitem(on=0)) output.append(fmt.bullet_list(on=0)) return ''.join(output)
def execute(macro, args): """ Execute the 'macro' with the given 'args': an optional list of selected category names (categories whose pages are to be shown), together with optional named arguments of the following forms: start=YYYY-MM shows event details starting from the specified month start=current-N shows event details relative to the current month end=YYYY-MM shows event details ending at the specified month end=current+N shows event details relative to the current month mode=calendar shows a calendar view of events mode=list shows a list of events by month mode=table shows a table of events names=daily shows the name of an event on every day of that event names=weekly shows the name of an event once per week calendar=NAME uses the given NAME to provide request parameters which can be used to control the calendar view template=PAGE uses the given PAGE as the default template for new events (or the default template from the configuration if not specified) parent=PAGE uses the given PAGE as the parent of any new event page """ request = macro.request fmt = macro.formatter page = fmt.page _ = request.getText # Interpret the arguments. try: parsed_args = args and wikiutil.parse_quoted_separated(args, name_value=False) or [] except AttributeError: parsed_args = args.split(",") parsed_args = [arg for arg in parsed_args if arg] # Get special arguments. category_names = [] raw_calendar_start = None raw_calendar_end = None calendar_start = None calendar_end = None mode = None name_usage = "weekly" calendar_name = None template_name = getattr(request.cfg, "event_aggregator_new_event_template", "EventTemplate") parent_name = None for arg in parsed_args: if arg.startswith("start="): raw_calendar_start = arg[6:] elif arg.startswith("end="): raw_calendar_end = arg[4:] elif arg.startswith("mode="): mode = arg[5:] elif arg.startswith("names="): name_usage = arg[6:] elif arg.startswith("calendar="): calendar_name = arg[9:] elif arg.startswith("template="): template_name = arg[9:] elif arg.startswith("parent="): parent_name = arg[7:] else: category_names.append(arg) original_calendar_start = calendar_start = EventAggregatorSupport.getParameterMonth(raw_calendar_start) original_calendar_end = calendar_end = EventAggregatorSupport.getParameterMonth(raw_calendar_end) # Find request parameters to override settings. calendar_start = EventAggregatorSupport.getFormMonth(request, calendar_name, "start") or calendar_start calendar_end = EventAggregatorSupport.getFormMonth(request, calendar_name, "end") or calendar_end mode = EventAggregatorSupport.getQualifiedParameter(request, calendar_name, "mode", mode or "calendar") # Get the events. events, shown_events, all_shown_events, earliest, latest = \ EventAggregatorSupport.getEvents(request, category_names, calendar_start, calendar_end) # Get a concrete period of time. first, last = EventAggregatorSupport.getConcretePeriod(calendar_start, calendar_end, earliest, latest) # Define a view of the calendar, retaining useful navigational information. view = View(page, calendar_name, raw_calendar_start, raw_calendar_end, original_calendar_start, original_calendar_end, calendar_start, calendar_end, first, last, category_names, template_name, parent_name, mode, name_usage) # Make a calendar. output = [] # Output download controls. output.append(fmt.div(on=1, css_class="event-controls")) output.append(view.writeDownloadControls()) output.append(fmt.div(on=0)) # Output a table. if mode == "table": # Start of table view output. output.append(fmt.table(on=1, attrs={"tableclass" : "event-table"})) output.append(fmt.table_row(on=1)) output.append(fmt.table_cell(on=1, attrs={"class" : "event-table-heading"})) output.append(fmt.text(_("Event dates"))) output.append(fmt.table_cell(on=0)) output.append(fmt.table_cell(on=1, attrs={"class" : "event-table-heading"})) output.append(fmt.text(_("Event location"))) output.append(fmt.table_cell(on=0)) output.append(fmt.table_cell(on=1, attrs={"class" : "event-table-heading"})) output.append(fmt.text(_("Event details"))) output.append(fmt.table_cell(on=0)) output.append(fmt.table_row(on=0)) # Get the events in order. ordered_events = EventAggregatorSupport.getOrderedEvents(all_shown_events) # Show the events in order. for event in ordered_events: event_page = event.getPage() event_summary = event.getSummary(parent_name) event_details = event.getDetails() # Prepare CSS classes with category-related styling. css_classes = ["event-table-details"] for topic in event_details.get("topics") or event_details.get("categories") or []: # Filter the category text to avoid illegal characters. css_classes.append("event-table-category-%s" % "".join(filter(lambda c: c.isalnum(), topic))) attrs = {"class" : " ".join(css_classes)} output.append(fmt.table_row(on=1)) # Start and end dates. output.append(fmt.table_cell(on=1, attrs=attrs)) output.append(fmt.span(on=1)) output.append(fmt.text(str(event_details["start"]))) output.append(fmt.span(on=0)) if event_details["start"] != event_details["end"]: output.append(fmt.text(" - ")) output.append(fmt.span(on=1)) output.append(fmt.text(str(event_details["end"]))) output.append(fmt.span(on=0)) output.append(fmt.table_cell(on=0)) # Location. output.append(fmt.table_cell(on=1, attrs=attrs)) if event_details.has_key("location"): output.append(fmt.text(event_details["location"])) output.append(fmt.table_cell(on=0)) # Link to the page using the summary. output.append(fmt.table_cell(on=1, attrs=attrs)) output.append(event_page.linkToPage(request, event_summary)) output.append(fmt.table_cell(on=0)) output.append(fmt.table_row(on=0)) # End of table view output. output.append(fmt.table(on=0)) # Output a list or calendar. elif mode in ("list", "calendar"): # Output top-level information. # Start of list view output. if mode == "list": output.append(fmt.bullet_list(on=1, attr={"class" : "event-listings"})) # Visit all months in the requested range, or across known events. for month in first.months_until(last): # Either output a calendar view... if mode == "calendar": # Output a month. output.append(fmt.table(on=1, attrs={"tableclass" : "event-month"})) output.append(fmt.table_row(on=1)) output.append(fmt.table_cell(on=1, attrs={"class" : "event-month-heading", "colspan" : "21"})) # Either write a month heading or produce links for navigable # calendars. output.append(view.writeMonthHeading(month)) output.append(fmt.table_cell(on=0)) output.append(fmt.table_row(on=0)) # Weekday headings. output.append(fmt.table_row(on=1)) for weekday in range(0, 7): output.append(fmt.table_cell(on=1, attrs={"class" : "event-weekday-heading", "colspan" : "3"})) output.append(fmt.text(_(EventAggregatorSupport.getDayLabel(weekday)))) output.append(fmt.table_cell(on=0)) output.append(fmt.table_row(on=0)) # Process the days of the month. start_weekday, number_of_days = month.month_properties() # The start weekday is the weekday of day number 1. # Find the first day of the week, counting from below zero, if # necessary, in order to land on the first day of the month as # day number 1. first_day = 1 - start_weekday while first_day <= number_of_days: # Find events in this week and determine how to mark them on the # calendar. week_start = month.as_date(max(first_day, 1)) week_end = month.as_date(min(first_day + 6, number_of_days)) full_coverage, week_slots = EventAggregatorSupport.getCoverage( week_start, week_end, shown_events.get(month, [])) # Output a week, starting with the day numbers. output.append(view.writeDayNumbers(first_day, number_of_days, month, full_coverage)) # Either generate empty days... if not week_slots: output.append(view.writeEmptyWeek(first_day, number_of_days)) # Or generate each set of scheduled events... else: output.append(view.writeWeekSlots(first_day, number_of_days, month, week_end, week_slots)) # Process the next week... first_day += 7 # End of month. output.append(fmt.table(on=0)) # Or output a summary view... elif mode == "list": # Output a list. output.append(fmt.listitem(on=1, attr={"class" : "event-listings-month"})) output.append(fmt.div(on=1, attr={"class" : "event-listings-month-heading"})) # Either write a month heading or produce links for navigable # calendars. output.append(view.writeMonthHeading(month)) output.append(fmt.div(on=0)) output.append(fmt.bullet_list(on=1, attr={"class" : "event-month-listings"})) # Get the events in order. ordered_events = EventAggregatorSupport.getOrderedEvents(shown_events.get(month, [])) # Show the events in order. for event in ordered_events: event_page = event.getPage() event_details = event.getDetails() event_summary = event.getSummary(parent_name) output.append(fmt.listitem(on=1, attr={"class" : "event-listing"})) # Link to the page using the summary. output.append(fmt.paragraph(on=1)) output.append(event_page.linkToPage(request, event_summary)) output.append(fmt.paragraph(on=0)) # Start and end dates. output.append(fmt.paragraph(on=1)) output.append(fmt.span(on=1)) output.append(fmt.text(str(event_details["start"]))) output.append(fmt.span(on=0)) output.append(fmt.text(" - ")) output.append(fmt.span(on=1)) output.append(fmt.text(str(event_details["end"]))) output.append(fmt.span(on=0)) output.append(fmt.paragraph(on=0)) # Location. if event_details.has_key("location"): output.append(fmt.paragraph(on=1)) output.append(fmt.text(event_details["location"])) output.append(fmt.paragraph(on=1)) # Topics. if event_details.has_key("topics") or event_details.has_key("categories"): output.append(fmt.bullet_list(on=1, attr={"class" : "event-topics"})) for topic in event_details.get("topics") or event_details.get("categories") or []: output.append(fmt.listitem(on=1)) output.append(fmt.text(topic)) output.append(fmt.listitem(on=0)) output.append(fmt.bullet_list(on=0)) output.append(fmt.listitem(on=0)) output.append(fmt.bullet_list(on=0)) # Output top-level information. # End of list view output. if mode == "list": output.append(fmt.bullet_list(on=0)) # Output view controls. output.append(fmt.div(on=1, css_class="event-controls")) output.append(view.writeViewControls()) output.append(fmt.div(on=0)) return ''.join(output)
def execute(macro, args): """ Execute the 'macro' with the given 'args': an optional list of selected category names (categories whose pages are to be shown), together with optional named arguments of the following forms: start=YYYY-MM shows event details starting from the specified month start=YYYY-MM-DD shows event details starting from the specified day start=current-N shows event details relative to the current month (or relative to the current day in "day" mode) end=YYYY-MM shows event details ending at the specified month end=YYYY-MM-DD shows event details ending on the specified day end=current+N shows event details relative to the current month (or relative to the current day in "day" mode) mode=calendar shows a calendar view of events mode=day shows a calendar day view of events mode=list shows a list of events by month mode=table shows a table of events mode=map shows a map of events calendar=NAME uses the given NAME to provide request parameters which can be used to control the calendar view template=PAGE uses the given PAGE as the default template for new events (or the default template from the configuration if not specified) parent=PAGE uses the given PAGE as the parent of any new event page Calendar view options: names=daily shows the name of an event on every day of that event names=weekly shows the name of an event once per week Map view options: map=NAME uses the given NAME as the map image, where an entry for the map must be found in the EventMaps page (or another page specified in the configuration by the 'event_aggregator_maps_page' setting) along with an attached map image """ request = macro.request fmt = macro.formatter page = fmt.page # Interpret the arguments. try: parsed_args = args and wikiutil.parse_quoted_separated(args, name_value=False) or [] except AttributeError: parsed_args = args.split(",") parsed_args = [arg for arg in parsed_args if arg] # Get special arguments. category_names = [] remote_sources = [] search_pattern = None raw_calendar_start = None raw_calendar_end = None calendar_start = None calendar_end = None raw_mode = None mode = None name_usage = "weekly" calendar_name = None template_name = getattr(request.cfg, "event_aggregator_new_event_template", "EventTemplate") parent_name = None map_name = None for arg in parsed_args: if arg.startswith("start="): raw_calendar_start = arg[6:] elif arg.startswith("end="): raw_calendar_end = arg[4:] elif arg.startswith("mode="): raw_mode = arg[5:] elif arg.startswith("names="): name_usage = arg[6:] elif arg.startswith("calendar="): calendar_name = arg[9:] elif arg.startswith("template="): template_name = arg[9:] elif arg.startswith("parent="): parent_name = arg[7:] elif arg.startswith("map="): map_name = arg[4:] elif arg.startswith("source="): remote_sources.append(arg[7:]) elif arg.startswith("search="): search_pattern = arg[7:] else: category_names.append(arg) # Find request parameters to override settings. mode = getQualifiedParameter(request, calendar_name, "mode", raw_mode or "calendar") # Different modes require different levels of precision by default. raw_resolution = raw_mode == "day" and "date" or "month" resolution = getQualifiedParameter(request, calendar_name, "resolution", mode == "day" and "date" or "month") resolution = mode == "calendar" and "month" or resolution # Determine the limits of the calendar. get_date, get_form_date = get_date_functions(raw_resolution) original_calendar_start = calendar_start = get_date(raw_calendar_start) original_calendar_end = calendar_end = get_date(raw_calendar_end) wider_calendar_start = getFormMonth(request, calendar_name, "wider-start") wider_calendar_end = getFormMonth(request, calendar_name, "wider-end") get_date, get_form_date = get_date_functions(resolution) calendar_start = get_form_date(request, calendar_name, "start") or calendar_start calendar_end = get_form_date(request, calendar_name, "end") or calendar_end # Get the events according to the resolution of the calendar. all_shown_events, first, last = getEventsUsingParameters( category_names, search_pattern, remote_sources, calendar_start, calendar_end, resolution, request) # Define a view of the calendar, retaining useful navigational information. view = View(page, calendar_name, raw_calendar_start, raw_calendar_end, original_calendar_start, original_calendar_end, calendar_start, calendar_end, wider_calendar_start, wider_calendar_end, first, last, category_names, remote_sources, search_pattern, template_name, parent_name, mode, raw_resolution, resolution, name_usage, map_name) return view.render(all_shown_events)