Orb/python/orb/filerenamer.py
changeset 2 932c358ece3e
child 4 468f4c8d3d5b
equal deleted inserted replaced
1:82f11024044a 2:932c358ece3e
       
     1 # Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved.
       
     2 # This component and the accompanying materials are made available under the terms of the License 
       
     3 # "Eclipse Public License v1.0" which accompanies this distribution, 
       
     4 # and is available at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     5 #
       
     6 # Initial Contributors:
       
     7 # Nokia Corporation - initial contribution.
       
     8 #
       
     9 # Contributors:
       
    10 # System Documentation Tools
       
    11 # Description:
       
    12 #
       
    13 import os.path
       
    14 import sys
       
    15 import unittest
       
    16 import xml
       
    17 import stat
       
    18 import logging
       
    19 from cStringIO import StringIO
       
    20 from xml.etree import ElementTree as etree
       
    21 from lib import scan, main, XmlParser, StubXmlParser
       
    22 from optparse import OptionParser
       
    23 
       
    24 __version__ = '0.1'
       
    25 
       
    26 
       
    27 UNSAFE_CHARS = ("\n", "\t", ":", "?", ",", "=", ".", "\\", "/", "[", "]", "|", "<", ">", "+", ";", '"', "-")
       
    28 
       
    29 
       
    30 class FileRenamer(object):
       
    31     """
       
    32     Given an xml file this class returns a MODE compatable filename
       
    33 
       
    34     >>> fr = FileRenamer(xmlparser=StubXmlParser())
       
    35     >>> fr.rename(r"c:\\temp\\xml\\class_c_active_scheduler.xml")
       
    36     'class_c_active_scheduler=GUID-BED8A733-2ED7-31AD-A911-C1F4707C67F=1=en=.reference'
       
    37     """
       
    38     def __init__(self, xmlparser=XmlParser(), publishing_target="mode"):
       
    39         self.parser = xmlparser
       
    40         self.publishing_target = publishing_target
       
    41     
       
    42     def _escape(self, filename):
       
    43         for char in UNSAFE_CHARS:
       
    44             filename = filename.replace(char, "")            
       
    45         filename = filename.encode('unicode-escape', 'ignore')
       
    46         filename = filename.replace(" ", "-")
       
    47         return filename        
       
    48     
       
    49     def rename(self, xmlfile):
       
    50         """
       
    51         Return DITA MODE compliant filename.
       
    52         Format of resultant filenames is:
       
    53             title=identifier=version=language=resolution.extension    
       
    54         Examples:
       
    55             Test-Document=GUID-1234=1=en=.reference
       
    56         """
       
    57         id = self.parser.parse(xmlfile)
       
    58         filename = os.path.basename(xmlfile)
       
    59         filename, ext = os.path.splitext(filename)
       
    60         if self.publishing_target == "mode":
       
    61             filename = self._escape(filename) 
       
    62             newfilename = "=".join((filename, id, '1', 'en', ''))
       
    63             ext = ext if ext == ".ditamap" else ".reference"
       
    64         elif self.publishing_target == "ditaot":
       
    65             newfilename = id
       
    66             ext = ext = ext if ext == ".ditamap" else ".xml"
       
    67         return newfilename + ext
       
    68 
       
    69 
       
    70 def rename(indir, publishing_target):
       
    71     fr = FileRenamer(publishing_target=publishing_target)
       
    72     for filepath in scan(indir):
       
    73         newfilename = os.path.join(os.path.dirname(filepath), fr.rename(filepath))
       
    74         try:
       
    75             os.chmod(filepath, stat.S_IWRITE)
       
    76         except Exception, e:
       
    77             logging.error('Unable to make file \"%s\" writable, error was: %s' % (filepath, e))
       
    78             continue
       
    79         else:
       
    80             logging.debug("Renaming %s to %s" % (filepath, newfilename))
       
    81             try:
       
    82                 os.rename(filepath, newfilename)
       
    83             except Exception, e:
       
    84                 logging.error('Unable to rename file \"%s\" to \"%s\", error was: %s' % (filepath, newfilename, e))
       
    85 
       
    86 def main():        
       
    87     usage = "usage: %prog <Path to the XML content> <publishing_target>\n"
       
    88     parser = OptionParser(usage, version='%prog ' + __version__)
       
    89     parser.add_option("-p", dest="publishing_target", type="choice", choices=["mode", "ditaot"], default="mode", 
       
    90                           help="Publishing Target: mode|ditaot, [default: %default]")
       
    91     parser.add_option("-l", "--loglevel", type="int", default=30, help="Log Level (debug=10, info=20, warning=30, [error=40], critical=50)")
       
    92     (options, args) = parser.parse_args()
       
    93     if len(args) < 1:
       
    94         parser.print_help()
       
    95         parser.error("Please supply the path to the XML content")
       
    96         
       
    97     if options.loglevel:
       
    98         logging.basicConfig(level=options.loglevel)
       
    99     
       
   100     rename(args[0],options.publishing_target)
       
   101 
       
   102 if __name__ == '__main__':
       
   103     sys.exit(main())
       
   104 
       
   105 ######################################
       
   106 # Test code
       
   107 ######################################
       
   108 
       
   109 class TestFileRenamer(unittest.TestCase):
       
   110     def test_i_can_return_a_files_new_mode_name(self):
       
   111         fr = FileRenamer(xmlparser=StubXmlParser(),publishing_target="mode")
       
   112         newfile = fr.rename("hello.xml")
       
   113         self.assertTrue(newfile == "hello=GUID-BED8A733-2ED7-31AD-A911-C1F4707C67F=1=en=.reference")
       
   114 
       
   115     def test_i_can_return_a_ditamaps_new_mode_name(self,publishing_target="mode"):
       
   116         fr = FileRenamer(xmlparser=StubXmlParser())
       
   117         newfile = fr.rename("hello.ditamap")
       
   118         self.assertTrue(newfile == "hello=GUID-BED8A733-2ED7-31AD-A911-C1F4707C67F=1=en=.ditamap")
       
   119 
       
   120 
       
   121     def test_i_can_return_a_files_new_name_if_passed_an_absolute_path(self):
       
   122         fr = FileRenamer(xmlparser=StubXmlParser())
       
   123         newfile = fr.rename("c:\\temp\\xml\\hello.xml")
       
   124         self.assertTrue(newfile == "hello=GUID-BED8A733-2ED7-31AD-A911-C1F4707C67F=1=en=.reference")
       
   125         
       
   126     def test_i_can_remove_incompatable_characters_from_a_filename(self):
       
   127         fr = FileRenamer(xmlparser=StubXmlParser())
       
   128         newfile = fr.rename("hello:?,=..xml")
       
   129         self.assertTrue(newfile , "hello=GUID-BED8A733-2ED7-31AD-A911-C1F4707C67F=1=en=.reference")        
       
   130 
       
   131     def test_i_can_return_a_files_new_ditaot_name(self):
       
   132         fr = FileRenamer(xmlparser=StubXmlParser(),publishing_target="ditaot")
       
   133         newfile = fr.rename("hello.xml")
       
   134         self.assertEquals(newfile, "GUID-BED8A733-2ED7-31AD-A911-C1F4707C67F.xml")
       
   135 
       
   136     def test_i_can_return_a_ditamaps_new_ditaot_name(self):
       
   137         fr = FileRenamer(xmlparser=StubXmlParser(),publishing_target="ditaot")
       
   138         newfile = fr.rename("hello.ditamap")
       
   139         self.assertEquals(newfile, "GUID-BED8A733-2ED7-31AD-A911-C1F4707C67F.ditamap")