; 8c@sh dZddd!ZdkZdklZlZlZdklZhdd<d d<d d<d defd?YZ"d@fdAYZ#dBe"fdCYZ$dDe#e$fdEYZ%dFe$fdGYZ&dHe$fdIYZ'dJe$fdKYZ(dLe$fdMYZ)dNe$fdOYZ*dPe$fdQYZ+dRe$fdSYZ,dTe$fdUYZ-dVe$fdWYZ.dXe$fdYYZ/dZe$fd[YZ0d\e$fd]YZ1d^e$fd_YZ2d`e$fdaYZ3dbe$fdcYZ4dde$fdeYZ5dfe$fdgYZ6dhe$fdiYZ7dje$fdkYZ8dle$fdmYZ9dne$fdoYZ:dpe$fdqYZ;dre$fdsYZ<dte%fduYZ=dve%fdwYZ>dxe%fdyYZ?dze%fd{YZ@d|e%fd}YZAd~e%fdYZBde%fdYZCdeCfdYZDde#e"fdYZEde"fdYZFde$fdYZGdeGfdYZHde#e"fdYZIde$fdYZJde"fdYZKde%fdYZLdeLfdYZMde"fdYZNdeNfdYZOde%fdYZPde%fdYZQde"fdYZRde"fdYZSde%fdYZTde#e"fdYZUde#e"fdYZVde%fdYZWde#e"fdYZXde"fdYZYde#e"fdYZZdeZfdYZ[de%fdYZ\de#e"fdYZ]de$fdYZ^de$fdYZ_de$fdYZ`de%fdYZadeafdYZbdeafdYZcde%fdYZdde#e"fdYZede%fdYZfde%fdYZgde%fdYZhdehfdYZide"fdYZjde"fdYZkde$fdYZlde#elfdYZmde#e"fdYZnde%fdYZode%fdYZpdepfdYZqdepfdYZrdepfdYZsdepfdYZtdetfdYZude$fdYZvdZwgdZxgdZygdZzgdZ{gdZ|gdZ}de#e"fdYZ~dZdZeieidZdZdZgdZgdZdZddZdZdZdZdZdZdZdZdS(s&HTML40 -- generate HTML conformant to the 4.0 standard. See: http://www.w3.org/TR/REC-html40/ All HTML 4.0 elements are implemented except for a few which are deprecated. All attributes should be implemented. HTML is generally case-insensitive, whereas Python is not. All elements have been coded in UPPER CASE, with attributes in lower case. General usage: e = ELEMENT(*content, **attr) i.e., the positional arguments become the content of the element, and the keyword arguments set element attributes. All attributes MUST be specified with keyword arguments, and the content MUST be a series of positional arguments; if you use content="spam", it will set this as the attribute content, not as the element content. Multiple content arguments are simply joined with no separator. Example: >>> t = TABLE(TR(TH('SPAM'), TH('EGGS')), TR(TD('foo','bar', colspan=2)) ) >>> print t
SPAM EGGS
foobar
As with HTMLgen and other HTML generators, you can print the object and it makes one monster string and writes that to stdout. Unlike HTMLgen, these objects all have a writeto(fp=stdout, indent=0, perlevel=2) method. This method may save memory, and it might be faster possibly (many fewer string joins), plus you get progressive output. If you want to alter the indentation on the string output, try: >> print t.__str__(indent=5, perlevel=6)
SPAM EGGS
foobar
The output from either method (__str__ or writeto) SHOULD be the lexically equivalent, regardless of indentation; not all elements are made pretty, only those which are insensitive to the addition of whitespace before or after the start/end tags. If you don't like the indenting, use writeto(perlevel=0) (or __str__(perlevel=0)). Element attributes can be set through the normal Python dictionary operations on the object (they are not Python attributes). Note: There are a few HTML attributes with a dash in them. In these cases, substitute an underscore and the output will be corrected. HTML 4.0 also defines a class attribute, which conflicts with Python's class statement; use klass instead. The new LABEL element has a for attribute which also conflicts; use label_for instead. >>> print META(http_equiv='refresh',content='60;/index2.html') The output order of attributes is indeterminate (based on hash order), but this is of no particular importance. The extent of attribute checking is limited to checking that the attribute is legal for that element; the values themselves are not checked, but must be convertible to a string. The content items must be convertible to strings and/or have a writeto() method. Some elements may have a few attributes they shouldn't, particularly those which use intrinsic events. Valid attributes are defined for each element with dictionaries, with the keys being the attributes. If the value is false, it's a boolean; otherwise the value is printed. Subclassing: If all you need to do is have some defaults, override the defaults dictionary. You will also need to set name to the correct element name. Example: >>> class Refresh(META): defaults = {'http_equiv': 'refresh'}; name = 'META' ... >>> print Refresh(content='10; /index2.html') Weirdness with Netscape 4.x: It recognizes a border attribute for the FRAMESET element, though it is not defined in the HTML 4.0 spec. It seems to recognize the frameborder attribute for FRAME, but border only changes from a 3D shaded border to a flat, unresizable grey border. Because of this, there is a border attribute defined for FRAMESET. Similarly, HTML 4.0 does not define a border attribute for INPUT (for use with type="image"), but one has been added anyway. Historical notes: My first experience with an HTML generator was with the one which comes with "Internet Programming with Python" by Aaron Watters, Guido van Rossum, and James C. Ahlstrom. I hate to dis it, but the thing really drove me nuts after awhile. Horrible to debug anything, but maybe my understanding of it was incomplete. I then discovered HTMLgen by Robin Friedrich: http://starship.skyport.net/crew/friedrich/HTMLgen/html/main.html It worked much better, for me at least, good enough for a major project. There were, however, some frustrations: Subclassing could sometimes be difficult (in fairness, I think that was by design), and there were some missing features I wanted. Plus the thing's huge, as Python modules go. These are relatively minor gripes, and if you don't like this module, definitely use HTMLgen. Mainly I did this because the methodology to do it just sorta dawned on me. The result is, I think, some pretty clean code. Really, there's hardly any actual code at all. Hey, and when was the last time saw a subclass inherit from only one parent class with only a pass statement and no attributes defined? There's 27 of them here. There's almost no logic to it at all; it's pretty much all driven by dictionaries. Yes, there are a number of features missing which are present in HTMLgen, namely the document classes. All the high-level abstractions are going in another module or two. s$Revision: 1.8 $i iN(slowersjoinsreplace(sstdoutsidisklasssstylestitleslangsdirsonloadsonunloadsonclicks ondblclicks onmousedowns onmouseups onmouseovers onmousemoves onmouseoutsonfocussonblurs onkeypresss onkeydownsonkeyupsonsubmitsonresetsonselectsonchangesaltsshapescoordsshrefstargetstabindexs accesskeysheightswidthsbordersalignshspacesvspacescharscharoffsvalignssizescolorsfaceshreflangstypesrelsrevsframesrules(sMarkupsComment(sXMLPIsDOCTYPEs_HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"s\HTML PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN" "http://www.w3.org/TR/REC-HTML/frameset.dtd"sElementcBstZhZhdd<dd<dd<dds<%s>scCsZ|ii|do'd|ii||t||fp||o|pdSdS(Nis%s="%s"s(sselfsattlistsgetsksattr_translationssstr(sselfsk((sA/mnt/gmirror/ports/textproc/py-HyperText/work/HyperText/HTML40.pys str_attributescCs<|i}|o|i|i|fp|i|iSdS(N(sselfsstr_attribute_listsasstart_tag_stringsnamesstart_tag_no_attr_string(sselfsa((sA/mnt/gmirror/ports/textproc/py-HyperText/work/HyperText/HTML40.pys start_tags cCs#|io|i|ipdSdS(Ns(sselfs content_modelsend_tag_stringsname(sself((sA/mnt/gmirror/ports/textproc/py-HyperText/work/HyperText/HTML40.pysend_tags( s__name__s __module__sdefaultssattr_translationss__init__supdates __setitem__sstart_tag_stringsstart_tag_no_attr_stringsend_tag_strings str_attributes start_tagsend_tag(((sA/mnt/gmirror/ports/textproc/py-HyperText/work/HyperText/HTML40.pysElements*    sPrettyTagsMixIncBs)tZedddZdddZRS(NiicCsdd|}|i||ixU|iD]J}t|do!t |d||||q/|it |q/W|i|i dS(Ns s swriteto( sindentsmyindentsfpswritesselfs start_tagscontentscshasattrsgetattrsperlevelsstrsend_tag(sselfsfpsindentsperlevelscsmyindent((sA/mnt/gmirror/ports/textproc/py-HyperText/work/HyperText/HTML40.pyswritetos !cCs|odpdd|}||ig}xU|iD]J}y'|it |i |||fWq8|it |q8Xq8W|i|i t |dSdS(Ns ss (sperlevelsindentsmyindentsselfs start_tagssscontentscsappendsapplys__str__sstrsend_tagsjoin(sselfsindentsperlevelscsmyindentss((sA/mnt/gmirror/ports/textproc/py-HyperText/work/HyperText/HTML40.pys__str__s '(s__name__s __module__sstdoutswritetos__str__(((sA/mnt/gmirror/ports/textproc/py-HyperText/work/HyperText/HTML40.pysPrettyTagsMixIns s CommonElementcBstZeZRS(N(s__name__s __module__sattrssattlist(((sA/mnt/gmirror/ports/textproc/py-HyperText/work/HyperText/HTML40.pys CommonElementss PCElementcBstZRS(N(s__name__s __module__(((sA/mnt/gmirror/ports/textproc/py-HyperText/work/HyperText/HTML40.pys PCElementssAcBsdtZhdd<dds(sselfsstr_attribute_listsaslevel(sselfsa((sA/mnt/gmirror/ports/textproc/py-HyperText/work/HyperText/HTML40.pys start_tags cCs |io d|ipdSdS(Ns s(sselfs content_modelslevel(sself((sA/mnt/gmirror/ports/textproc/py-HyperText/work/HyperText/HTML40.pysend_tags(s__name__s __module__sattlistsupdatesattrss__init__s start_tagsend_tag(((sA/mnt/gmirror/ports/textproc/py-HyperText/work/HyperText/HTML40.pysHeading~s    sHEADcBs$tZhdds>(sreplacesrss(sssr((sA/mnt/gmirror/ports/textproc/py-HyperText/work/HyperText/HTML40.pys quote_bodyWss_,.-cCs{g}xa|D]Y}|tjo|i|q |djo|idq |idt|q Wt|dSdS(Ns s+s%%%02xs(slssscssafesappendsordsjoin(ssscsl((sA/mnt/gmirror/ports/textproc/py-HyperText/work/HyperText/HTML40.pys url_encode\s  cOst|d}g}x=|iD]/\}}|idt |t |fq"Wt|d}|ot||gdp|SdS(Ns/s%s=%ss&s?( sjoinsargssurl_pathsaskwargssitemssksvsappends url_encodesurl_vals(sargsskwargssasvsksurl_valssurl_path((sA/mnt/gmirror/ports/textproc/py-HyperText/work/HyperText/HTML40.pysURLds 'cKslg}x[|D]S\}}tt|f|}||d<||jod|d