# Copyright 2013 Yahoo! Inc. All Rights Reserved # Copyright 2013 OpenStack Foundation # Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. ''' The code must executed within ./openstack-manuals/doc/training-manuals/sources/. The code will automagically create the 7 'core' openstack repositories and convert the rst docs to xml. ''' import os import re import sys def create_repo(directory): #clone remote to local repo root, ignore error if exist for x in directory: os.system("git clone https://git.openstack.org/openstack/" + x + ".git") def pull_repo_updates(directory): #pull remote repo updates for x in directory: os.chdir("./" + x) os.system("git pull origin master") os.chdir("../") def patternmatch(directory, docs_location, rstfile): #simple pattern matching source rst to output docbook5.0 xml good_file = {"addmethod.openstackapi", "architecture", "development.environment", "drivers", "threading", "unit_tests"} try: #open the file to convert infile = open(directory + docs_location + rstfile) except IOError: #if file is a directory then recurse print("patternmatch:in IOError:directory:" + directory + ", docs_location: " + docs_location + ", rstfile: " + rstfile) os.mkdir(os.path.expanduser("./openstack-manuals/doc/training-guide/sources/" + directory + rstfile)) walkdirectories(directory + docs_location, rstfile +"/") #docs_location and rstfile are both directories in this case return outfilenamepart = infile.name.split(".rst") outfilename = outfilenamepart[0].split("/") matchslash = re.search(r'(.*/.*/.*/.*)', directory) if matchslash: #if recursion match is good print("patternmatch:matchslash:directory:" + directory + ", docs_location: " + docs_location + ", rstfile: " + rstfile) try: if outfilenamepart[-1]: #TODO if not rst file, then copy image files return except: pass directory = directory.split("/") good_file_found = "false" for filename in good_file: #check for good file name, else skip to next file if filename == outfilename[-1]: good_file_found = "true" continue if good_file_found == "false": #jump out of called routine return outfile = open("./openstack-manuals/doc/training-guide/sources/" + directory[0] + "/" + docs_location + outfilename[-1] + ".xml", "w+") print(directory[0] + "/" + docs_location + outfilename[-1] + ".xml") else: print("patternmatch:not matchslash:directory:" + directory + ", docs_location: " + docs_location + ", rstfile: " + rstfile) try: if outfilenamepart[-1]: #TODO if not rst file, then copy image files #createfile(directory, docs_location, outfilename) return except: pass good_file_found = "false" for filename in good_file: #check for good file name, else skip to next file if filename == outfilename[-1]: good_file_found = "true" continue if good_file_found == "false": #jump out of called routine return outfile = open("./openstack-manuals/doc/training-guide/sources/" + directory + outfilename[-1] + ".xml", "w+") print(directory + outfilename[-1] + ".xml") #header of new xml file outfile.write("\n") outfile.write("
\n") outfile.write("" + outfilename[-1].title() + "\n") #start header xml_section_name = "header" outfile.write("
\n") outfile.write("" + xml_section_name.title() + "\n") outfile.write("\n") #always read two lines at a time, once pattern match on multiple char, previous line is section id and title prevline = "empty" startitemizedlist = 0 for line in infile: #match single line ahead for section titles match1 = re.search(r'(.*)(=======)(.*)', line) match2 = re.search(r'(.*)(-------)(.*)', line) match3 = re.search(r'(.*)(~~~~~~~)(.*)', line) match4 = re.search(r'(\s*)(\*\s)(.*)', prevline) match5 = re.search(r'(\s*)(\*\s)(.*)', line) #ignoring orderedlists for now #match6 = re.search(r'(\s*)([0-9]\.\s)(.*)', prevline) #match7 = re.search(r'(\s*)([0-9]\.\s)(.*)', line) if match1 or match2 or match3: #close previous para and section outfile.write("\n") outfile.write("
\n") #start new section and para xml_section_name = prevline.replace(" ", "-") xml_section_name = xml_section_name.replace("\'", "-") xml_section_name = xml_section_name.replace("`", "-") xml_section_name = xml_section_name.replace("\"", "-") xml_section_name = xml_section_name.replace(":", "-") xml_section_name = xml_section_name.replace(",", "-") xml_section_name = xml_section_name.replace("(", "-") xml_section_name = xml_section_name.replace(")", "-") outfile.write("
\n") outfile.write("" + xml_section_name.strip().title() + "\n") outfile.write("\n") elif not match4 and match5: #start itemizedlist startitemizedlist = 1 outfile.write("\n") listitem = match5.group(3).replace("<","[") listitem = listitem.replace(">","]") listitem = listitem.replace("&","-") outfile.write("" + listitem + "\n") elif match4 and match5: #continue itemizedlist listitem = match5.group(3).replace("<","[") listitem = listitem.replace(">","]") listitem = listitem.replace("&","-") outfile.write("" + listitem + "\n") elif match4 and not match5: #close itemizedlist startitemizedlist = 0 outfile.write("\n") elif prevline != "empty" and not prevline.isspace(): #no match, so inside section and para prevline = prevline.replace("<","[") prevline = prevline.replace(">","]") prevline = prevline.replace("&","-") outfile.write(prevline) #save previous line for pattern matching prevline = line #catch end of file, missing close itemized list if startitemizedlist == 1: outfile.write("\n") #close last para and section outfile.write("\n") outfile.write("
\n") outfile.write("
") def walkdirectories(projectdirectory, sourcedirectory): #print("walkdirectories: " + projectdirectory + sourcedirectory) print("walkdirectories:current directory is ") os.system("pwd") for rstfile in os.listdir(projectdirectory + sourcedirectory): #walk files in the directory if rstfile.startswith('.'): #ignore hidden files continue patternmatch(projectdirectory, sourcedirectory, rstfile) def convert_rst_docbook5(repository_hash): for item in repository_hash: print("convert_rst_docbook5:start convert rst: " + item + repository_hash[item]) os.system("rm -R ./openstack-manuals/doc/training-guide/sources/" + item) try: #use try for when the remove directory fails os.mkdir("./openstack-manuals/doc/training-guide/sources/" + item) except OSError: pass walkdirectories(item, repository_hash[item]) #os.chdir("../") print("convert_rst_docbook5:completed convert rst: " + item + repository_hash[item]) repository_hash = {'cinder/':"/doc/source/devref/"} ''' 'nova/':"/doc/source/devref/", 'glance/':"/doc/source/", 'neutron/':"/doc/source/devref/", 'swift/':"/doc/source/", 'keystone/':"doc/source/", 'horizon/':"/doc/source/"}''' os.chdir("../../../../")#root of repository directories in relation to ./training-guides/sources create_repo(repository_hash) pull_repo_updates(repository_hash) convert_rst_docbook5(repository_hash)