Attachment 'name.py'

Download

   1 # -*- coding: utf8 -*-
   2 """
   3 Normalize page names
   4 
   5 See http://moinmoin.wikiwikiweb.de/MoinMoinBugs/CanCreateBadNames
   6 """
   7 
   8 import unittest
   9 
  10 class InvalidPageNameError(Exception): pass
  11 
  12 
  13 def normalizePageName(candidate):
  14     """ Normalize page name
  15     
  16     Normalaized page name contain only alpha numeric Unicode characters with 
  17     optional one space between words, and no empty path components.
  18     
  19     Leading, traling or multiple spaces in names are considered a user error
  20     and fixed quitely without any error mesages.
  21     
  22     Empty path components are ignored just like the shell does.
  23     
  24     @param candidate: Unicode string with candidate name
  25     @return: normalized name
  26     @rtype: Unicode string
  27     """
  28     # Validate input
  29     if candidate == '':
  30         raise InvalidPageNameError(candidate)
  31 
  32     # Split sub pages and normalize each component
  33     validComponents = []
  34     pages = candidate.split('/')
  35     for pageName in pages:    
  36         # Split words removing multiple white space between and around words
  37         pageWords = pageName.split()        
  38         # Ignore empty names in the path e.g. '/  /Name/' - > 'Name'
  39         if not pageWords:
  40             continue
  41             
  42         for word in pageWords:
  43             for character in word:
  44                 if not character.isalnum():
  45                     raise InvalidPageNameError(candidate)
  46                         
  47         # All words are valid, return valid name using one space between words
  48         pageName = ' '.join(pageWords)
  49         validComponents.append(pageName)
  50             
  51     # Join normalized components
  52     normalizedName = '/'.join(validComponents)
  53     
  54     # Do not allow empty names after normalization
  55     if normalizedName == '':
  56         raise InvalidPageNameError(candidate)
  57     return normalizedName
  58     
  59 
  60 class ValidNamesTestCase(unittest.TestCase):
  61 
  62     TESTS = (
  63         # name, normalized name
  64         # Remove empty components
  65         (u'/Page////Page//', u'Page/Page'),
  66         # Remove extra White Space
  67         (u' Page \t Name / SubPage ', u'Page Name/SubPage'),
  68         # German umlauts
  69         (u'Jürgen Hermann', u'Jürgen Hermann'),
  70         # Hebrew
  71         (u'\u05d0\u05d1 \u05d2', u'\u05d0\u05d1 \u05d2'),
  72         # Add more tests
  73     )
  74     
  75     def testNormalizePageName(self):
  76         """ wikiutil: normalize page names """
  77         for test, expected in self.TESTS:
  78             result = normalizePageName(test)
  79             self.failUnlessEqual(result, expected,
  80                 'expected "%(expected)s" but got "%(result)s"' % locals())
  81 
  82 
  83 class InvalidNamesTestCase(unittest.TestCase):    
  84     TESTS = (
  85         # Empty
  86         u'',
  87         # White Space only
  88         u'  \t\n  ', 
  89         # Special Unicode white space
  90         u' \u200f ',
  91         # Sub pages with empty pages or white space
  92         u'///', u' /   / /  / ', u'\u200f/ / '
  93         # Non alpha numeric
  94         u'.', u'-', u'|', u'%', u'&', u'?', u'@', u'!', u'$', u'*', u'(', u')', 
  95         u'<', u'>', u'\u202a',
  96         # Mix
  97         u'\u202a/ValidComponent',
  98         # Add more tests
  99     )
 100     
 101     def testInvalidPageNames(self):
 102         """ wikiutil: invalid page name raise exception """
 103         for test in self.TESTS:
 104             self.failUnlessRaises(InvalidPageNameError, normalizePageName, test)
 105 
 106 
 107 if __name__ == '__main__':
 108     suite = unittest.TestSuite()
 109     suite.addTest(unittest.makeSuite(ValidNamesTestCase))
 110     suite.addTest(unittest.makeSuite(InvalidNamesTestCase))
 111     unittest.TextTestRunner(verbosity=2).run(suite)
 112     

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.
  • [get | view] (2004-09-06 15:49:21, 3.5 KB) [[attachment:name.py]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.