diff options
Diffstat (limited to 'cobbler/Cheetah/Tools/MondoReportDoc.txt')
-rw-r--r-- | cobbler/Cheetah/Tools/MondoReportDoc.txt | 391 |
1 files changed, 391 insertions, 0 deletions
diff --git a/cobbler/Cheetah/Tools/MondoReportDoc.txt b/cobbler/Cheetah/Tools/MondoReportDoc.txt new file mode 100644 index 0000000..29a026d --- /dev/null +++ b/cobbler/Cheetah/Tools/MondoReportDoc.txt @@ -0,0 +1,391 @@ +MondoReport Documentation +Version 0.01 alpha 24-Nov-2001. iron@mso.oz.net or mso@oz.net. +Copyright (c) 2001 Mike Orr. License: same as Python or Cheetah. + +* * * * * +STATUS: previous/next batches and query string are not implemented yet. +Sorting not designed yet. Considering "click on this column header to sort by +this field" and multiple ascending/descending sort fields for a future version. + +Tested with Python 2.2b1. May work with Python 2.1 or 2.0. + +* * * * * +OVERVIEW + +MondoReport -- provide information about a list that is useful in generating +any kind of report. The module consists of one main public class, and some +generic functions you may find useful in other programs. This file contains an +overview, syntax reference and examples. The module is designed both for +standalone use and for integration with the Cheetah template system +(http://www.cheetahtemplate.org/), so the examples are in both Python and +Cheetah. The main uses of MondoReport are: + +(A) to iterate through a list. In this sense MR is a for-loop enhancer, +providing information that would be verbose to calculate otherwise. + +(B) to separate a list into equal-size "pages" (or "batches"--the two terms are +interchangeable) and only display the current page, plus limited information +about the previous and next pages. + +(C) to extract summary statistics about a certain column ("field") in the list. + +* * * * * +MAIN PUBLIC CLASS + +To create a MondoReport instance, supply a list to operate on. + + mr = MondoReport(origList) + +The list may be a list of anything, but if you use the 'field' argument in any +of the methods below, the elements must be instances or dictionaries. + +MondoReport assumes it's operating on an unchanging list. Do not modify the +list or any of its elements until you are completely finished with the +ModoReport object and its sub-objects. Otherwise, you may get an exception or +incorrect results. + +MondoReport instances have three methods: + + .page(size, start, overlap=0, orphan=0 + sort=None, reverse=False) => list of (r, a, b). + +'size' is an integer >= 1. 'start', 'overlap' and 'orphan' are integers >= 0. +The list returned contains one triple for each record in the current page. 'r' +is the original record. 'a' is a BatchRecord instance for the current record +in relation to all records in the origList. 'b' is a BatchRecord instance for +the current record in relation to all the records in that batch/page. (There +is a .batch method that's identical to .page.) + +The other options aren't implemented yet, but 'overlap' duplicates this many +records on adjacent batches. 'orphan' moves this many records or fewer, if +they are on a page alone, onto the neighboring page. 'sort' (string) specifies +a field to sort the records by. It may be suffixed by ":desc" to sort in +descending order. 'reverse' (boolean) reverses the sort order. If both +":desc" and 'reverse' are specified, they will cancel each other out. This +sorting/reversal happens on a copy of the origList, and all objects returned +by this method use the sorted list, except when resorting the next time. +To do more complicated sorting, such as a hierarchy of columns, do it to the +original list before creating the ModoReport object. + + .all(sort=None, reverse=False) => list of (r, a). + +Same, but the current page spans the entire origList. + + .summary() => Summary instance. + +Summary statistics for the entire origList. + +In Python, use .page or .all in a for loop: + + from Cheetah.Tools.MondoReport import MondoReport + mr = MondoReport(myList) + for r, a, b in mr.page(20, 40): + # Do something with r, a and b. The current page is the third page, + # with twenty records corresponding to origList[40:60]. + if not myList: + # Warn the user there are no records in the list. + +It works the same way in Cheetah, just convert to Cheetah syntax. This example +assumes the template doubles as a Webware servlet, so we use the servlet's +'$request' method to look up the CGI parameter 'start'. The default value is 0 +for the first page. + + #from Cheetah.Tools.MondoReport import MondoReport + #set $mr = $MondoReport($bigList) + #set $start = $request.field("start", 0) + #for $o, $a, $b in $mr.page(20, $start) + ... do something with $o, $a and $b ... + #end for + #unless $bigList + This is displayed if the original list has no elements. + It's equivalent to the "else" part Zope DTML's <dtml-in>. + #end unless + +* * * * * +USING 'r' RECORDS + +Use 'r' just as you would the original element. For instance: + + print r.attribute # If r is an instance. + print r['key'] # If r is a dictionary. + print r # If r is numeric or a string. + +In Cheetah, you can take advantage of Universal Dotted Notation and autocalling: + + $r.name ## 'name' may be an attribute or key of 'r'. If 'r' and/or + ## 'name' is a function or method, it will be called without + ## arguments. + $r.attribute + $r['key'] + $r + $r().attribute()['key']() + +If origList is a list of name/value pairs (2-tuples or 2-lists), you may +prefer to do this: + + for (key, value), a, b in mr.page(20, 40): + print key, "=>", value + + #for ($key, $value), $a, $b in $mr.page(20, $start) + $key => $value + #end for + +* * * * * +STATISTICS METHODS AND FIELD VALUES + +Certain methods below have an optional argument 'field'. If specified, +MondoReport will look up that field in each affected record and use its value +in the calculation. MondoReport uses Cheetah's NameMapper if available, +otherwise it uses a minimal NameMapper substitute that looks for an attribute +or dictionary key called "field". You'll get an exception if any record is a +type without attributes or keys, or if one or more records is missing that +attribute/key. + +If 'field' is None, MondoReport will use the entire record in its +calculation. This makes sense mainly if the records are a numeric type. + +All statistics methods filter out None values from their calculations, and +reduce the number of records accordingly. Most filter out non-numeric fields +(or records). Some raise NegativeError if a numeric field (or record) is +negative. + + +* * * * * +BatchRecord METHODS + +The 'a' and 'b' objects of MondoReport.page() and MondoReport.all() provide +these methods. + + .index() + +The current subscript. For 'a', this is the true subscript into origList. +For 'b', this is relative to the current page, so the first record will be 0. +Hint: In Cheetah, use autocalling to skip the parentheses: '$b.index'. + + .number() + +The record's position starting from 1. This is always '.index() + 1'. + + .Letter() + +The letter ("A", "B", "C") corresponding to .number(). Undefined if .number() +> 26. The current implementation just adds the offset to 'a' and returns +whatever character it happens to be. + +To make a less dumb implementation (e.g., "Z, AA, BB" or "Z, A1, B1"): +1) Subclass BatchRecord and override the .Letter method. +2) Subclass MondoReport and set the class variable .BatchRecordClass to your +new improved class. + + .letter() + +Same but lower case. + + .Roman() + +The Roman numeral corresponding to .number(). + + .roman() + +Same but lower case. + + .even() + +True if .number() is even. + + .odd() + +True if .number() is odd. + + .even_i() + +True if .index() is even. + + .odd_i() + +True if .index() is odd. + + .length() + +For 'a', number of records in origList. For 'b', number of records on this +page. + + .item() + +The record itself. You don't need this in the normal case since it's the same +as 'r', but it's useful for previous/next batches. + + .size() + +The 'size' argument used when this BatchRecord was created. +'a.size() == b.size()'. + + .first() + +True if this is the first record. + + .last() + +True if this is the last record. + + .firstValue(field=None) + +True if there is no previous record, or if the previous field/record has a +different value. Used for to print section headers. For instance, if you +are printing addresses by country, this will be true at the first occurrance +of each country. Or for indexes, you can have a non-printing field showing +which letter of the alphablet this entry starts with, and then print a "B" +header before printing the first record starting with "B". + + .lastValue(field=None) + +True if this is the last record containing the current value in the +field/record. + + .percentOfTotal(field=None, suffix="%", default="N/A", decimals=2) + +Returns the percent that the current field/record is of all fields/records. +If 'suffix' is None, returns a number; otherwise it returns a string with +'suffix' suffixed. If the current value is non-numeric, returns 'default' +instead (without 'suffix'). 'decimals' tells the number of decimal places to +return; if 0, there will be no decimal point. + + .prev() + +Returns a PrevNextBatch instance for the previous page. If there is no +previous page, returns None. [Not implemented yet.] + + .next() + +Returns a PrevNextBatch instance for the next page. If there is no next page, +returns None. [Not implemented yet.] + + .prevPages() + +Returns a list of PrevNextPage instances for every previous page, or [] if no +previous pages. [Not implemented yet.] + + .nextPages() + +Returns a list of PrevNextPage instances for every next page, or [] if no next +pages. [Not implemented yet.] + + .query(start=None, label=None, attribName="start", attribs=[]) + +[Not implemented yet.] + +With no arguments, returns the HTML query string with start value removed (so +you can append a new start value in your hyperlink). The query string is taken +from the 'QUERY_STRING' environmental variable, or "" if missing. (This is +Webware compatible.) + +With 'start' (an integer >= 0), returns the query string with an updated start +value, normally for the next or previous batch. + +With 'label' (a string), returns a complete HTML hyperlink: +'<A HREF="?new_query_string">label</A>'. You'll get a TypeError if you specify +'label' but not 'start'. + +With 'attribName' (a string), uses this attribute name rather than "start". +Useful if you have another CGI parameter "start" that's used for something +else. + +With 'attribs' (a dictionary), adds these attributes to the hyperlink. +For instance, 'attribs={"target": "_blank"}'. Ignored unless 'label' is +specified too. + +This method assumes the start parameter is a GET variable, not a POST variable. + + .summary() + +Returns a Summary instance. 'a.summary()' refers to all records in the +origList, so it's the same as MondoReport.summary(). 'b.summary()' refers only +to the records on the current page. [Not implemented yet.] + +* * * * * +PrevNextPage INSTANCES + +[Not implemented yet.] + +PrevNextPage instances have the following methods: + + .start() + +The index (true index of origList) that that page starts at. You may also use +'.start().index()', '.start().number()', etc. Also +'.start().item(field=None)'. (Oh, so *that*'s what .item is for!) + + .end() + +The index (true index of origList) that that page ends at. You may also use +'.end().index()', '.end().number()', etc. Also +'.end().item(field=None)'. + + .length() + +Number of records on that page. + + .query(label=None, attribName="start", attribs={}, before="", after="") + +[Not implemented yet.] + +Similar to 'a.query()' and 'b.query()', but automatically calculates the start +value for the appropriate page. + +For fancy HTML formatting, 'before' is prepended to the returned text and +'after' is appended. (There was an argument 'else_' for if there is no such +batch, but it was removed because you can't even get to this method at all in +that case.) + +* * * * * * +SUMMARY STATISTICS + +These methods are supported by the Summary instances returned by +MondoReport.Summary(): + + .sum(field=None) + +Sum of all numeric values in a field, or sum of all records. + + .total(field=None) + +Same. + + .count(field=None) + +Number of fields/records with non-None values. + + .min(field=None) + +Minimum value in that field/record. Ignores None values. + + .max(field=None) + +Maximum value in that field/record. Ignores None values. + + .mean(field=None) + +The mean (=average) of all numeric values in that field/record. + + .average(field=None) + +Same. + + .median(field=None) + +The median of all numeric values in that field/record. This is done by sorting +the values and taking the middle value. + + .variance(field=None), .variance_n(field=None) + .standardDeviation(field=None), .standardDeviation_n(field=None) + +[Not implemented yet.] + + +* * * * * +To run the regression tests (requires unittest.py, which is standard with +Python 2.2), run MondoReportTest.py from the command line. The regression test +double as usage examples. + + +# vim: shiftwidth=4 tabstop=4 expandtab textwidth=79 |