Changeset 163

Show
Ignore:
Timestamp:
03/22/06 11:42:42 (3 years ago)
Author:
tim
Message:

ran reindent and raised file exceptions in flatteners

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/pyramid/build.py

    r155 r163  
    3131    DATADIR = os.path.abspath(data) 
    3232    OUTPUTDIR = os.path.abspath(out) 
    33      
     33 
    3434    # check to see if the output directory exists 
    3535    if not os.path.exists(OUTPUTDIR): 
     
    4242        if not os.path.isdir(OUTPUTDIR): 
    4343            raise Error, 'OUTPUTDIR is not a directory' 
    44          
     44 
    4545    # Check that the output dir is not in a subversion folder 
    4646    if os.path.exists(os.path.join(OUTPUTDIR,'.svn')): 
    4747        raise Error, 'the OUTPUTDIR contains .svn folders, halting operation for safety' 
    48      
     48 
    4949    # dangerous remove directory contents function 
    5050    if partialbuild is False and rebuilddirs is None: 
    5151        utils.recursiveRemoveDirectoryContents(OUTPUTDIR) 
    52      
     52 
    5353    # copy in any resources needed 
    5454    for resourcedir in resourcedirs: 
     
    5959    os.chdir(DATADIR) 
    6060    basedir = path(DATADIR) 
    61      
     61 
    6262    # initialise a context 
    6363    ctx = Context() 
     
    7070    # set constants 
    7171    ctx.constants = constants 
    72      
     72 
    7373    for root, dirs, files in os.walk('.'): 
    74      
     74 
    7575        # get the path directory 
    7676        ctx.path = path(root).abspath() 
    7777        ctx.relpath = path(basedir).relpathto(root) 
    7878        ctx.relpathparent = path(basedir).relpathto(ctx.path.parent) 
    79          
     79 
    8080        # ignore svn folders 
    8181        try: 
     
    8383        except: 
    8484            pass 
    85          
     85 
    8686        # if the target directory is not available, create it 
    8787        if not os.path.isdir(os.path.join(OUTPUTDIR,root)): 
     
    9393                srcfile = os.path.join(ctx.path,f) 
    9494                targetfile = os.path.join(OUTPUTDIR,root,f) 
    95                 shutil.copy(srcfile,targetfile)             
    96      
     95                shutil.copy(srcfile,targetfile) 
     96 
    9797        # create the html from the index.yml fragment 
    9898        if root != '.': 
     
    102102        cachepath = outroot/'.cache.dump' 
    103103        cachepathparent = outroot.parent /'.cache.dump' 
    104          
    105          
     104 
     105 
    106106        # check to see if the current directory is in the rebuild dirs list 
    107107        matchesRebuildDir = False 
     
    111111                    matchesRebuildDir = True 
    112112                    break 
    113          
     113 
    114114        # check for nobuild 
    115115        nobuild = path(root) / 'NOBUILD' 
     
    117117            utils.copytree(root,os.path.join(OUTPUTDIR,root),nocopylist=['.svn']) 
    118118            continue 
    119          
    120          
     119 
     120 
    121121        if os.path.exists( cachepath ) and partialbuild: 
    122122            ctx = pickle.load(open(cachepath)) 
     
    127127            if matchesRebuildDir: 
    128128                ctx.data = pickle.load(open(cachepathparent)).data 
    129                  
     129 
    130130            if matchesRebuildDir or rebuilddirs is None: 
    131131                if ctx.verbose > 0: 
     
    133133 
    134134                ctx.partialbuild = False 
    135                  
     135 
    136136                try: 
    137137                    html = flat.flatten( [DOCTYPE,flatten(Y.fragmentConstructor(os.path.join(root,'index.yml')),ctx)] ) 
     
    143143 
    144144                    sys.exit() 
    145                      
     145 
    146146                file(os.path.join(OUTPUTDIR,root,'index.html'),'w').write(html) 
    147147                if createcache: 
     
    150150                if ctx.verbose > 1: 
    151151                    print '.. %s Rebuilt from Cached Data' % str(ctx.relpath) 
    152                  
    153                  
     152 
     153 
    154154def main(options,args): 
    155155    if options.resources: 
     
    157157    else: 
    158158        resourcedirs = [] 
    159      
     159 
    160160    if options.rebuilddirs: 
    161161        rebuilddirs = options.rebuilddirs.strip().split(',') 
    162162    else: 
    163         rebuilddirs = None     
     163        rebuilddirs = None 
    164164 
    165165    if options.constants: 
     
    173173                constants[key]=value 
    174174    else: 
    175         constants = None   
    176          
     175        constants = None 
     176 
    177177 
    178178    build(options.data,options.out,verbose=options.verbose,resourcedirs=resourcedirs,rebuilddirs=rebuilddirs,constants=constants,update=options.update,createcache=options.createcache) 
     
    184184    parser.add_option("-o", "--out", dest="out", help="directory in which to save output (will be emptied)", metavar="OUT") 
    185185    parser.add_option("-r", "--resources", dest="resources", help="comma separated list of resource directories to copy", metavar="RESOURCES") 
    186     parser.add_option("-v", "--verbose", action="store_const", dest="verbose", default=0, const=1, help="print status messages to stdout")     
    187     parser.add_option("-V", "--veryverbose", action="store_const", dest="verbose", default=0, const=2, help="print all data to stdout")     
    188     parser.add_option("-W", "--veryveryverbose", action="store_const", dest="verbose", default=0, const=3, help="print all data to stdout")     
     186    parser.add_option("-v", "--verbose", action="store_const", dest="verbose", default=0, const=1, help="print status messages to stdout") 
     187    parser.add_option("-V", "--veryverbose", action="store_const", dest="verbose", default=0, const=2, help="print all data to stdout") 
     188    parser.add_option("-W", "--veryveryverbose", action="store_const", dest="verbose", default=0, const=3, help="print all data to stdout") 
    189189    parser.add_option("-R", "--rebuilddirs",dest="rebuilddirs",help="only rebuild below these comma separated directories",metavar="REBUILDDIRS") 
    190190    parser.add_option("-C", "--createcache",action="store_true",dest="createcache",default=False,help="recreate the cache files",metavar="CREATECACHE") 
    191191    parser.add_option("-c", "--constants", dest="constants", help="pass in the names constants (e.g. PDO=/root/pdo,PSF=/psf", metavar="CONSTANTS") 
    192     parser.add_option("-U", "--update", action="store_true", dest="update", default=False, help="NOT WORKING DO NOT USE try to build only those pages that have changed")     
     192    parser.add_option("-U", "--update", action="store_true", dest="update", default=False, help="NOT WORKING DO NOT USE try to build only those pages that have changed") 
    193193    (options, args) = parser.parse_args() 
    194194    main(options,args) 
  • trunk/pyramid/core.py

    r149 r163  
    1313        self.verbose = node.get('verbose',False) 
    1414        self.root = path(node.get('root','')) 
    15          
     15 
    1616    def __eq__(self,other): 
    1717        return self.data == other.data 
    18      
     18 
    1919    def __ne__(self,other): 
    2020        return self.data != self.data 
  • trunk/pyramid/dictutils.py

    r96 r163  
    44 
    55def merge(a,b,dir=None,partialbuild=False): 
    6      
     6 
    77    if isinstance(a,Y.sectionnav) and isinstance(b,Y.sectionnav) and dir is not None: 
    88        # special case. If b is the same as a, it has been inhereited - sectionnav's 
     
    1515        else: 
    1616            mergetrees.merge(a,b,dir) 
    17      
     17 
    1818    elif isinstance(b,dict) and isinstance(a,dict): 
    1919        for bkey in b.keys(): 
     
    2727 
    2828class stackdict(dict): 
    29      
     29 
    3030    parent = None 
    31      
     31 
    3232    def __init__(self, parent=None): 
    3333        if parent is not None: 
    3434            self.parent = parent 
    3535            merge(self,parent) 
    36          
     36 
    3737    def popStack(self): 
    3838        return self.parent 
     
    4040# Test code: 
    4141if __name__ == "__main__": 
    42      
     42 
    4343    def keyval(text): 
    4444        ''' Factory to convert a string into key:val pair (split on last space) 
     
    4646        t = text.split(' ') 
    4747        return { ''.join(t[:-1]) : t[-1] } 
    48          
     48 
    4949    x = ''' 
    5050a: 1 
     
    5959b: 
    6060  x: 15 
    61   z:  
     61  z: 
    6262    p: 98 
    6363    q: 99 
    6464c: 3P0 
    6565    ''' 
    66      
     66 
    6767 
    6868    xd = syck.load(x,Loader=Y.Loader, implicit_typing=false) 
    6969    yd = syck.load(y,Loader=Y.Loader, implicit_typing=false) 
    70      
     70 
    7171    z = merge(xd,yd) 
    72      
     72 
    7373    print z 
    74      
     74 
    7575    print '-------------------' 
    76      
     76 
    7777    d = stackdict() 
    7878    d['a'] = 1 
    7979    d['b'] = {'x':1,'y':2 } 
    8080    print d 
    81      
     81 
    8282    d = stackdict(d) 
    8383    d['a'] = 2 
    8484    print d 
    85      
     85 
    8686    d = stackdict(d) 
    8787    d['b'] = {'x':2,'y': {'p':4 } } 
    8888    d['c'] = 100 
    8989    print d 
    90      
     90 
    9191    while 1: 
    9292        d = d.popStack() 
    9393        if d is None: 
    9494            break 
    95         print d     
     95        print d 
  • trunk/pyramid/flatteners.py

    r148 r163  
    2121    print '--- = Page ---------------' 
    2222    pprint(data) 
    23      
     23 
    2424# 
    2525# Flatteners adaption for different item types 
     
    4949    def flatten(self, ctx, dir): 
    5050        for value in self.original: 
    51             value = flatten(value, ctx, dir)    
     51            value = flatten(value, ctx, dir) 
    5252        return self.original 
    5353 
     
    5555    def flatten(self, ctx, dir): 
    5656        return T.xml(restParser.html_fragment(self.original)) 
    57      
     57 
    5858class RestFileFlattener(components.Adapter): 
    59     def flatten(self, ctx, dir):     
     59    def flatten(self, ctx, dir): 
    6060        try: 
    6161            restfile = os.path.join(dir,self.original) 
    6262            fp = open(restfile) 
    6363        except IOError: 
    64             print 'IOError whilst trying to open "restfile" %s'%(restfile)   
     64            print 'IOError whilst trying to open "restfile" %s'%(restfile) 
     65            raise 
    6566 
    6667        try: 
     
    7778            fp = open(htmlfile) 
    7879        except IOError: 
    79             print 'IOError whilst trying to open "htmlfile" %s'%(htmlfile)         
    80          
     80            print 'IOError whilst trying to open "htmlfile" %s'%(htmlfile) 
     81            raise 
     82 
    8183        return T.xml(fp.read()) 
    8284 
     
    8789    if filename[0] != '/' and filename[0:4] != 'http': 
    8890        filename = os.path.join(dir,filename) 
    89     return filename     
     91    return filename 
    9092 
    9193def getFilePointer(ctx,dir,filename): 
     
    9698    except IOError: 
    9799        print 'IOError whilst trying to open "htfile" %s'%(filename) 
     100        raise 
    98101    return fp 
    99102 
     
    101104    def flatten(self, ctx, dir): 
    102105        return T.xml(self.original) 
    103      
     106 
    104107class HtFileFlattener(components.Adapter): 
    105108    def flatten(self, ctx, dir): 
     
    137140            contents = '<strong>MoinMoin parse failed for %s - a wiki instance needs to be installed and the wikiconfig.py directory needs to be on the $PYTHONPATH</strong>'%url 
    138141        return T.xml(contents) 
    139          
     142 
    140143class AHrefFlattener(components.Adapter): 
    141144    def flatten(self, ctx, dir): 
     
    145148    def flatten(self, ctx, dir): 
    146149        return '/%s' % str(self.original) 
    147      
     150 
    148151class BreadcrumbFlattener(components.Adapter): 
    149152    def flatten(self, ctx, dir): 
     
    162165                    hook = item['children'] 
    163166                    break 
    164                      
     167 
    165168        return flatten(breadcrumb,ctx) 
    166169 
     
    182185def acquireTemplate(ctx,template): 
    183186    """ recursively ascends the data directory looking for an appropriate template 
    184     """  
     187    """ 
    185188    searchpath = ctx.path 
    186189    #overkill checking for search path infinite recursion 
     
    190193            break 
    191194        except IOError: 
    192             searchpath = searchpath.parent    
    193     return searchpath / template     
    194      
     195            searchpath = searchpath.parent 
     196    return searchpath / template 
     197 
    195198class FragmentFileFlattener(components.Adapter): 
    196199    ''' This is the core flattener that renders fragment types (which are template/data packets) 
     
    204207        if ctx.verbose > 1: 
    205208            print '=== Current Fragment ( %s )' % name 
    206          
     209 
    207210 
    208211        # get the parent data for the current file 
     
    236239            template = acquireTemplate(ctx,self.original.template) 
    237240            flattenedData = flatten( self.original.globals, ctx, dir ) 
    238             return T.xml(fragmentGenerate(dir,template,flattenedData))     
     241            return T.xml(fragmentGenerate(dir,template,flattenedData)) 
    239242        else: 
    240243            # Get the canonical directory and filename for this file 
    241244            dir,name = os.path.split(os.path.join(dir,self.original.file)) 
    242      
     245 
    243246            if ctx.verbose > 1: 
    244247                print '=== Current Fragment ( %s )' % name 
    245              
     248 
    246249            # get the parent data for the current file 
    247250            parentdata = getParentData(self,ctx,dir,name) 
     
    249252            # inherit data from parent and merge the result with any 'local' data 
    250253            mergedData = inheritAndMergeLocals(self,ctx,dir,name,self.original,parentdata) 
    251      
     254 
    252255            # Flatten the resultant data ready for use in the template 
    253256            flattenedMergedData = flatten( mergedData, ctx, dir ) 
    254      
     257 
    255258            if ctx.verbose > 2: 
    256259                logPageData(mergedData) 
    257      
     260 
    258261            # Search for the template in this directory and above 
    259262            template = acquireTemplate(ctx,self.original.template) 
     
    262265def getFragmentData(self,ctx,dir,name,parentdata): 
    263266    ''' Get the fragment data and assign it to self.original, preserving the filename 
    264     '''  
     267    ''' 
    265268    # Try to get the data out of the current ctx first (if it is there, it 
    266269    # must have come from the cache so return it 
     
    280283    ''' get the parents data for this .yml fie (or set it as an empty fragment if not available) 
    281284        this currently only looks 'up' one directory 
    282     '''  
     285    ''' 
    283286    parentpath = str(ctx.relpathparent) 
    284287    parentdata = copy.deepcopy(ctx.data.get(parentpath,{}).get(name,Y.fragment({}))) 
  • trunk/pyramid/mergetrees.py

    r50 r163  
    66    # create a pointer to the parent tree and initialise found 
    77    hook = ptree 
    8      
     8 
    99    if path: 
    1010        pathsegments = path.split('/') 
    1111    else: 
    1212        return 
    13          
     13 
    1414    # iterate on segments in the current path 
    1515    for depth,segment in enumerate( pathsegments ): 
     
    2626        # set the pointer to the found item's child list 
    2727        hook = found.get('children',[]) 
    28      
     28 
    2929    # (**a**) now we've got a pointer to the appropriate node, make each href 
    3030    # attribue in the child tree into an absolute path by adding the path to it 
    31     makePathsAbsolute(ctree,path)         
     31    makePathsAbsolute(ctree,path) 
    3232    addBreadcrumbData(ctree,found['data']) 
    33      
     33 
    3434    # add the child tree to the found node and make the found node selected 
    3535    found['children'] = ctree 
    3636    found['selected'] = 'selected' 
    37      
    38      
     37 
     38 
    3939def findChildenForKey(treelist,key): 
    4040    for item in treelist: 
     
    4242        if str(href) == key or ( isinstance(href,Y.rhref) and '/%s'%str(href) == key ) : 
    4343            return item 
    44              
     44 
    4545    return None 
    4646 
     
    5050        if isinstance(item['data']['href'],Y.rhref): 
    5151            item['data']['href'] = '/%s/%s' % (path,item['data']['href']) 
    52      
     52 
    5353def addBreadcrumbData(children,parentdata): 
    5454    for item in children: 
    5555        item['data']['breadcrumb'] = copy.deepcopy(parentdata.get('breadcrumb',[]) ) 
    5656        item['data']['breadcrumb'].append( Y.url( '%s %s' % (item['data']['label'],item['data']['href']) ) ) 
    57   
  • trunk/pyramid/mkpydir.py

    r133 r163  
    11import os 
    22from optparse import OptionParser 
    3 import shutil  
     3import shutil 
    44 
    55index_yml = """--- !fragment 
     
    4343    cyml.close() 
    4444 
    45      
     45 
    4646def mkpydir(directive,prefix,path,outputdir,copy,title): 
    4747    OUTPUTDIR = os.path.abspath(outputdir) 
    4848    if os.path.isdir(outputdir) is not True: 
    4949        os.mkdir(OUTPUTDIR) 
    50      
     50 
    5151    if directive == 'htfile': 
    52          
     52 
    5353        if copy is True: 
    5454            htfile = 'content.ht' 
     
    8484    chtml.write(content_html) 
    8585    chtml.close() 
    86      
     86 
    8787def main(options,args): 
    8888    if os.path.isdir(options.outputdir) and options.replace is True: 
    8989        shutil.rmtree(options.outputdir) 
    90          
     90 
    9191    mkpydir(options.type,options.dir,options.path,options.outputdir,options.copy,options.title) 
    9292 
     
    115115    parser.add_option("-c", "--copy", action="store_true", help="copy the htfile into the directory",dest="copy", metavar="COPY",default=True) 
    116116    (options, args) = parser.parse_args() 
    117     # further checking of options  
     117    # further checking of options 
    118118    if options.copy is not False: 
    119119        options.copy=True 
  • trunk/pyramid/page.py

    r147 r163  
    4343    def render_tree(self,ctx,data): 
    4444        ''' custom renderer for a tree like data structure (ie with data and children keys) 
    45         '''  
     45        ''' 
    4646        pgen = getPatterns(ctx.tag) 
    47          
     47 
    4848        html = [] 
    4949        if data: 
     
    5252                for key in item['data'].keys(): 
    5353                    ptag.fillSlots(key,item['data'][key]) 
    54                  
     54 
    5555                selected = item.get('selected','') 
    5656                ptag.fillSlots('selected',selected) 
     
    7676            except ValueError: 
    7777                raise 'invalid slice values' 
    78                  
     78 
    7979            tag = context.tag 
    8080            headers = tag.allPatterns('header') 
     
    8282            divider = tag.patternGenerator('divider', default=tags.invisible) 
    8383            content = [(pattern(data=element), divider(data=element)) for element in data[int(start):int(end)]] 
    84              
     84 
    8585            if not content: 
    8686                content = tag.allPatterns('empty') 
     
    8989                content[-1] = content[-1][0] 
    9090            footers = tag.allPatterns('footer') 
    91          
     91 
    9292            return tag.clear()[ headers, content, footers ] 
    9393        return render 
     
    102102        except IndexError: 
    103103            raise FragmentError, 'An error has occured whilst building the breadcrumb trail. This usually occurs when a content template has a breadcrumb trail renderer but the parent nav.yml does not include a reference to the current templates directory. Use -V to find out more information about which page cause this error.' 
    104              
     104 
    105105        return tag 
    106      
     106 
    107107    def generate(self): 
    108108        ''' render the fragment 
  • trunk/pyramid/path.py

    r96 r163  
    323323        d.files('*.pyc'). 
    324324        """ 
    325          
     325 
    326326        return [p for p in self.listdir(pattern) if p.isfile()] 
    327327 
     
    805805        def startfile(self): 
    806806            os.startfile(self) 
    807  
  • trunk/pyramid/restParser.py

    r114 r163  
    6868    except: 
    6969        input_string = input_string.decode('iso-8859-1') 
    70          
     70 
    7171    parts = html_parts( 
    7272        input_string=input_string, source_path=source_path, 
  • trunk/pyramid/utils.py

    r143 r163  
    33 
    44class Stack: 
    5      
     5 
    66    def __init__(self, indent, pointer): 
    77        self.indent = indent 
     
    99        self.indentStack = [] 
    1010        self.pointerStack = [] 
    11      
     11 
    1212    def push(self,indent): 
    1313        self.indentStack.append(self.indent) 
     
    1919        self.indent = self.indentStack.pop() 
    2020        self.pointer = self.pointerStack.pop() 
    21          
     21 
    2222    def prevIndent(self): 
    2323        return self.indentStack[-1] 
    2424 
    2525def parseIndentedList(text, factory): 
    26      
     26 
    2727    lines = text.split('\n') 
    2828    data = {'children':[]} 
     
    3131    while lines[0].strip() == '': 
    3232        lines = lines[1:] 
    33          
     33 
    3434    # this should be the first non-empty line 
    3535    trimline, newindent = stripAndCountIndent(lines[0]) 
     
    4242        if newindent > stack.indent: 
    4343            stack.push(newindent) 
    44              
     44 
    4545        if newindent < stack.indent: 
    4646            while newindent < stack.indent: 
     
    5050 
    5151        stack.pointer.append( {'data':factory(trimline), 'children':[] } ) 
    52          
     52 
    5353    return data['children'] 
    54          
     54 
    5555def stripAndCountIndent(line): 
    5656    lstripline = line.lstrip() 
    5757    return lstripline, len(line)-len(lstripline) 
    58      
     58 
    5959def recursiveRemoveDirectoryContents(dir): 
    6060    for root, dirs, files in os.walk(dir, topdown=False): 
     
    6767    segments = [] 
    6868    head = path 
    69     while 1:  
     69    while 1: 
    7070        head, tail = os.path.split(head) 
    7171        segments.append(tail) 
     
    8787        more... /downloads 
    8888''' 
    89      
    90      
     89 
     90 
    9191    def f(text): 
    9292        t = text.split(' ') 
    9393        return {'href': t[-1], 'label': t[:-1]} 
    94      
     94 
    9595    print 'text' 
    9696    print text 
    9797    tree = parseIndentedList(text, f) 
    98      
     98 
    9999    print "indented list" 
    100100    from pprint import pprint 
    101101    pprint(tree) 
    102      
     102 
    103103    # recreate indented list from data 
    104104    def printnode(item, indent=0): 
     
    107107        for child in item['children']: 
    108108            printnode(child, indent+4) 
    109              
     109 
    110110    printnode(tree, indent=-4) 
    111      
     111 
    112112 
    113113 
  • trunk/pyramid/yamlRegistry.py

    r124 r163  
    4242 
    4343class fragmentFile: 
    44     ''' A file fragment which points at another yaml file   
     44    ''' A file fragment which points at another yaml file 
    4545    ''' 
    4646    def __init__(self, node): 
    4747        self.file = node 
    48          
     48 
    4949    def __repr__(self): 
    5050        s = StringIO() 
     
    5454            pprint({'file':self.file},s) 
    5555        return s.getvalue() 
    56      
     56 
    5757    def __eq__(self,other): 
    5858        return self.file == other.file 
    59      
     59 
    6060    def __ne__(self,other): 
    6161        return self.file != other.file 
    62      
     62 
    6363def fragmentConstructor(node): 
    6464    try: 
     
    6767    except AttributeError: 
    6868        return fragmentFile(node) 
    69      
     69 
    7070 
    7171class rest(str): 
     
    7373    ''' 
    7474    pass 
    75          
     75 
    7676class restfile(str): 
    7777    ''' a rest file for converting to html 
     
    105105        self.file = node['file'] 
    106106        self.key = node.get('key',None) 
    107          
     107 
    108108    def __repr__(self): 
    109109        return '<htfiledata: file=%s, key=%s>'%(self.file,self.key) 
    110          
     110 
    111111    def __eq__(self,other): 
    112112        return self.file == other.file and self.key == other.key 
     
    142142    ''' 
    143143    return utils.parseIndentedList(node,url) 
    144      
     144 
    145145class sectionnav(list): 
    146146    ''' section navigation (inherited) 
     
    178178def pathconstruct(pathstring): 
    179179    return path(pathstring) 
    180          
     180 
    181181 
    182182def context(node): 
     
    193193            year = int(year) 
    194194        cls.__constructs[(tld,year,name)] = func 
    195          
     195 
    196196    register_construct = classmethod(register_construct) 
    197197 
     
    212212                if construct is not None: 
    213213                    return construct(node.value) 
    214         return syck.Loader.construct(self, node)     
    215      
     214        return syck.Loader.construct(self, node) 
     215 
    216216# Set up type registry 
    217217_typeRegistry = { 
     
    235235for vartype, factory in _typeRegistry.items(): 
    236236    Loader.register_construct(factory, vartype[2],tld=vartype[0],year=vartype[1]) 
    237      
    238      
    239