[gtk-doc] Converted gtkdoc-rebase from Perl to Python.



commit d1198e59daf6cb5e450206c4016ad422a93c015e
Author: Jussi Pakkanen <jpakkane gmail com>
Date:   Tue Mar 21 17:34:42 2017 -0400

    Converted gtkdoc-rebase from Perl to Python.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=780512

 gtkdoc-rebase.in      |  527 ++++++++++++++++++++-----------------------------
 tests/Makefile.am     |    4 +-
 tests/gtkdoc-rebase.t |   30 ---
 tests/tools.sh.in     |    4 +-
 4 files changed, 214 insertions(+), 351 deletions(-)
---
diff --git a/gtkdoc-rebase.in b/gtkdoc-rebase.in
old mode 100644
new mode 100755
index b1d7f8b..9fa80af
--- a/gtkdoc-rebase.in
+++ b/gtkdoc-rebase.in
@@ -1,5 +1,5 @@
-#!@PERL@ -w
-# -*- cperl -*-
+#!@PYTHON@
+# -*- python -*-
 #
 # gtk-doc - GTK DocBook documentation generator.
 # Copyright (C) 1998  Damon Chaplin
@@ -26,25 +26,11 @@
 # Description : Rebases URI references in installed HTML documentation.
 #############################################################################
 
-use strict;
-use bytes;
-use Getopt::Long qw(:config gnu_getopt);
-use Cwd qw(realpath);
+from __future__ import print_function
 
-push @INC, '@PACKAGE_DATA_DIR@';
-require "gtkdoc-common.pl";
+import os, sys, argparse, subprocess, re
 
-# Options
-
-my $HTML_DIR;
-my @OTHER_DIRS;
-my $DEST_DIR;
-my $PRINT_VERSION;
-my $PRINT_HELP;
-my $AGGRESSIVE;
-my $ONLINE;
-my $RELATIVE;
-my $VERBOSE;
+other_dirs = []
 
 # Maps.
 # These two point to the last seen URI of given type for a package:
@@ -52,325 +38,232 @@ my $VERBOSE;
 # LocalMap: package => local URI
 # This maps all seen URIs of a package to fix broken links in the process:
 # RevMap: URI => package
-my (%OnlineMap, %LocalMap, %RevMap);
+OnLineMap = {}
+LocalMap = {}
+RevMap = {}
 # Remember what mangling we did.
-my %Mapped;
-
-
-Run() unless caller; # Run program unless loaded as a module
-
-
-sub Run {
-    my %optctl = ('html-dir' => \$HTML_DIR,
-            'other-dir' => \@OTHER_DIRS,
-            'dest-dir' => \$DEST_DIR,
-            'online' => \$ONLINE,
-            'relative' => \$RELATIVE,
-            'aggressive' => \$AGGRESSIVE,
-            'verbose' => \$VERBOSE,
-            'version' => \$PRINT_VERSION,
-            'help' => \$PRINT_HELP);
-    GetOptions(\%optctl, 'html-dir=s', 'other-dir=s@', 'dest-dir:s',
-             'online', 'relative', 'aggressive', 'verbose',
-             'version', 'help');
-
-    if ($PRINT_VERSION) {
-        print "@VERSION@\n";
-        exit 0;
-    }
-
-    if ($PRINT_HELP) {
-        print <<EOF;
-gtkdoc-rebase version @VERSION@ - rewrite the base url of html files
-
---html-dir=HTML_DIR     The directory which contains the installed HTML
---other-dir=OTHER_DIR   Directories to recursively scan for indices (index.sgml)
-                        May be used more than once for multiple directories
---online                Prefer cross-references to online documents
---relative              Prefer relative cross-references
---aggressive            Rebase links to all files that are under a directory
-                        matching a package name.
---dest-dir=ROOT_DIR     Staging area virtual root, this prefix will be removed
-                        from HTML_DIR fore relative link calculation.
---verbose               Be verbose
---version               Print the version of this program
---help                  Print this help
-EOF
-        exit 0;
-    }
-
-    if (!$HTML_DIR) {
-        die "No HTML directory (--html-dir) given.\n";
-    }
-
-    my $dir;
+Mapped = {}
+
+
+parser = argparse.ArgumentParser()
+
+parser.add_argument('--version', action='version', version='@VERSION@')
+parser.add_argument('--html-dir', dest='html_dir', default='')
+parser.add_argument('--other-dir', dest='other_dir', default=[], action='append')
+parser.add_argument('--dest-dir', dest='dest_dir', default='')
+parser.add_argument('--aggressive', action='store_true', default=False)
+parser.add_argument('--verbose', action='store_true', default=False)
+group = parser.add_mutually_exclusive_group()
+group.add_argument('--online', action='store_true', default=False)
+group.add_argument('--relative', action='store_true', default=False)
+
+def log(options, *msg):
+    if options.verbose:
+        print(*msg)
+
+def Run():
+    options = parser.parse_args()
+
+    if (options.html_dir == ''):
+        sys.exit("No HTML directory (--html-dir) given.")
 
     # We scan the directory containing GLib and any directories in GNOME2_PATH
     # first, but these will be overriden by any later scans.
-    if (defined ($ENV{"GNOME2_PATH"})) {
-        foreach $dir (split(/:/, $ENV{"GNOME2_PATH"})) {
-            $dir = $dir . "/share/gtk-doc/html";
-            if ($dir && -d $dir) {
-                print "Prepending GNOME2_PATH directory: $dir\n" if $VERBOSE;
-                unshift @OTHER_DIRS, $dir;
-            }
-        }
-    }
-
-    $dir = `@PKG_CONFIG@ --variable=prefix glib-2.0`;
-    $dir =~ s/^\s*(\S*)\s*$/$1/;
-    $dir = $dir . "/share/gtk-doc/html";
-    print "Prepending GLib directory $dir\n" if $VERBOSE;
-    unshift @OTHER_DIRS, $dir;
+    if "GNOME2_PATH" in os.environ:
+        for dir in os.environ["GNOME2_PATH"].split(':'):
+            dir = os.path.join(dir, "/share/gtk-doc/html")
+            if os.path.isdir(dir):
+                log(options, "Prepending GNOME2_PATH directory:", dir)
+                other_dirs = [dir] + other_dirs
+
+    dir = subprocess.check_call(['@PKG_CONFIG@', '--variable=prefix', 'glib-2.0'], universal_newlines=True)
+    dir = dir.strip()
+    dir = os.path.join(dir, "/share/gtk-doc/html")
+    log(options, "Prepending GLib directory", dir)
+    other_dirs = [dir] + other_dirs
 
     # Check all other dirs, but skip already scanned dirs ord subdirs of those
-    if ($DEST_DIR) {
-        $DEST_DIR =~ s#/?$#/#;
-    }
-    $HTML_DIR =~ s#/?$#/#;
 
-    foreach $dir (@OTHER_DIRS) {
-        &ScanDirectory($dir, $HTML_DIR);
-    }
+    for dir in other_dirs:
+        ScanDirectory(dir, options);
 
-    if ($RELATIVE) {
-        &RelativizeLocalMap($HTML_DIR);
-    }
+    if options.relative:
+        RelativizeLocalMap(options.html_dir);
 
-    &RebaseReferences($HTML_DIR);
-    &PrintWhatWeHaveDone();
-}
+    RebaseReferences(options.html_dir)
+    PrintWhatWeHaveDone()
 
 
-sub ScanDirectory {
-    my ($dir, $self) = @_;
+def ScanDirectory(dir, options):
     # This array holds any subdirectories found.
-    my (@subdirs) = ();
-
-    print "Scanning documentation directory $dir\n" if $VERBOSE;
-
-    if ("$dir/" eq $self) {
-        print "Excluding self\n" if $VERBOSE;
-        return;
-    }
-    if (not opendir(HTMLDIR, $dir)) {
-        print "Cannot open $dir: $!\n";
-        return;
-    }
-
-    my $file;
-    my $onlinedir;
-    my $have_index = 0;
-    foreach $file (readdir(HTMLDIR)) {
-        if ($file eq '.' or $file eq '..') {
-            next;
-        }
-        elsif (-d "$dir/$file") {
-            push @subdirs, $file;
-            next;
-        }
-        if ($file =~ m/\.devhelp2$/) {
-            print "Reading index from $file\n" if $VERBOSE;
-            my $o = &ReadDevhelp($dir, $file);
-            # Prefer this location over possibly stale index.sgml
-            if ($o) {
-                $onlinedir = $o;
-            }
-            $have_index = 1;
-        }
-        if (!$onlinedir and ($file eq "index.sgml")) {
-            print "Reading index from index.sgml\n" if $VERBOSE;
-            $onlinedir = &ReadIndex($dir, $file);
-            $have_index = 1;
-        }
-        elsif (($file eq "index.sgml.gz") && ! (-e "$dir/index.sgml")) {
-            # debian/ubuntu started to compress this as index.sgml.gz :/
-            print <<EOF;
-Please fix https://bugs.launchpad.net/ubuntu/+source/gtk-doc/+bug/77138 . For now run:
-gunzip $dir/$file
-EOF
-        }
-        elsif (($file =~ m/\.devhelp2.gz$/) && ! (-e "$dir/$1.devhelp2")) {
-            # debian/ubuntu started to compress this as *devhelp2.gz :/
-            print <<EOF;
-Please fix https://bugs.launchpad.net/ubuntu/+source/gtk-doc/+bug/1466210 . For now run:
-gunzip $dir/$file
-EOF
-        }
-        # we could consider supporting: use IO::Zlib;
-    }
-    closedir (HTMLDIR);
-    if ($have_index) {
-        &AddMap($dir, $onlinedir);
-    }
+    subdirs = []
+    onlinedir = None
+
+    log(options, "Scanning documentation directory " + dir)
+
+    if dir == options.html_dir:
+        log(options, "Excluding self")
+        return
+
+    have_index = False
+    with os.scandir(options.html_dir) as d:
+        for file in d:
+            if file.is_dir():
+                subdirs.push_back(file.name)
+                continue
+
+            if file.name.endswit('.devhelp2'):
+                log(options, "Reading index from " + file.name)
+                o = ReadDevhelp(dir, file.name);
+                # Prefer this location over possibly stale index.sgml
+                if o is not None:
+                    onlinedir = o
+                have_index = True
+
+            if onlinedir and file.name == "index.sgml":
+                log(options, "Reading index from index.sgml")
+                onlinedir = ReadIndex(dir, file.name);
+                have_index = True
+            elif file.name == "index.sgml.gz" and not os.path.exists(os.path.join(dir, 'index.sgml')):
+                # debian/ubuntu started to compress this as index.sgml.gz :/
+                print(''' Please fix https://bugs.launchpad.net/ubuntu/+source/gtk-doc/+bug/77138 . For now 
run:
+gunzip %s/%s
+''' % (dir, file.name))
+            elif file.name.endswith('.devhelp2.gz') and not os.path.exists(os.path.join(dir, e.fname, 
'devhelp2')):
+                # debian/ubuntu started to compress this as *devhelp2.gz :/
+                print('''Please fix https://bugs.launchpad.net/ubuntu/+source/gtk-doc/+bug/1466210 . For now 
run:
+gunzip %d/%s
+''' % (dir, file.name))
+
+            # we could consider supporting: gzip module
+    if have_index:
+        AddMap(dir, onlinedir);
 
     # Now recursively scan the subdirectories.
-    my $d;
-    foreach my $subdir (@subdirs) {
-        &ScanDirectory("$dir/$subdir", $self);
-    }
-}
+    for subdir in subdirs:
+        ScanDirectory(os.path.join(dir, subdir), options);
 
 
-sub ReadDevhelp {
-    my ($dir, $file) = @_;
-    my $onlinedir;
+def ReadDevhelp(dir, file):
+    onlinedir = None
 
-    open(INDEXFILE, "$dir/$file") || die "Can't open $dir/$file: $!";
-    while (<INDEXFILE>) {
+    for line in open(os.path.join(dir, file)):
         # online must come before chapter/functions
-        last if m/<(chapters|functions)/;
-        if (m/ online="([^"]*)"/) {
-            $onlinedir = $1;
+        if '<chapters' in line or '<functions' in line:
+            break
+        match = re.search(r'  online="([^"]*)"/')
+        if match:
             # Remove trailing non-directory component.
-            $onlinedir =~ s#(.*/).*#$1#;
-        }
-    }
-    close (INDEXFILE);
-    return $onlinedir;
-}
+            onlinedir = re.sub(r'(.*/).*', r'\1', match.groups(1))
+    return onlinedir
 
 
-sub ReadIndex {
-    my ($dir, $file) = @_;
-    my $onlinedir;
+def ReadIndex(dir, file):
+    onlinedir = None
 
-    open(INDEXFILE, "$dir/$file") || die "Can't open $dir/$file: $!";
-    while (<INDEXFILE>) {
+    for line in open(os.path.join(dir, file)):
         # ONLINE must come before any ANCHORs
-        last if m/^<ANCHOR/;
-        if (m/^<ONLINE\s+href\s*=\s*"([^"]+)"\s*>/) {
-            $onlinedir = $1;
+        if '<ANCHOR' in line:
+            break
+        match = re.match(r'''^<ONLINE\s+href\s*=\s*"([^"]+)"\s*>''', line)
+        if match:
             # Remove trailing non-directory component.
-            $onlinedir =~ s#(.*/).*#$1#;
-        }
-    }
-    close (INDEXFILE);
-    return $onlinedir;
-}
-
-
-sub AddMap {
-    my ($dir, $onlinedir) = @_;
-    my $package;
-
-    $dir =~ s#/?$#/#;
-    ($package = $dir) =~ s#.*/([^/]+)/#$1#;
-    if ($DEST_DIR and substr($dir, 0, length $DEST_DIR) eq $DEST_DIR) {
-        $dir = substr($dir, -1 + length $DEST_DIR);
-    }
-    if ($onlinedir) {
-        print "On-line location of $package: $onlinedir\n" if $VERBOSE;
-        $OnlineMap{ $package } = $onlinedir;
-        $RevMap{ $onlinedir } = $package;
-    } else {
-        print "No On-line location for $package found\n" if $VERBOSE;
-    }
-    print "Local location of $package: $dir\n" if $VERBOSE;
-    $LocalMap{ $package } = $dir;
-    $RevMap{ $dir } = $package;
-}
-
-
-sub RelativizeLocalMap {
-    my ($self) = @_;
-    my $prefix;
-    my $dir;
-
-    $self = realpath $self;
-    $self =~ s#/?$#/#;
-    ($prefix = $self) =~ s#[^/]+/$##;
-    foreach my $package (keys %LocalMap) {
-        $dir = $LocalMap{ $package };
-        if (substr($dir, 0, length $prefix) eq $prefix) {
-            $dir = "../" . substr($dir, length $prefix);
-            $LocalMap{ $package } = $dir;
-            print "Relativizing local location of $package to $dir\n" if $VERBOSE;
-        }
-    }
-}
-
-
-sub RebaseReferences {
-    my ($dir) = @_;
-
-    opendir(HTMLDIR, $dir) || die "Can't open HTML directory $dir: $!";
-    foreach my $file (readdir(HTMLDIR)) {
-        if ($file =~ m/\.html?$/) {
-            &RebaseFile("$dir$file");
-        }
-    }
-    closedir (HTMLDIR);
-}
-
-
-sub RebaseFile {
-    my ($file) = @_;
-    print "Fixing file: $file\n" if $VERBOSE;
-
-    open(HTMLFILE, $file) || die "Can't open $file: $!";
-    local $/;
-    undef $/;
-    my $text = <HTMLFILE>;
-    close(HTMLFILE);
-
-    $text =~ s#(<a(?:\s+\w+=(?:"[^"]*"|'[^']*'))*\s+href=")([^"]*)(")#$1 . &RebaseLink($2) .$3#gse;
-
-    open(NEWFILE, ">$file.new") || die "Can't open $file: $!";
-    print NEWFILE $text;
-    close(NEWFILE);
-
-    unlink($file) || die "Can't delete $file: $!";
-    rename("$file.new", $file) || die "Can't rename $file.new: $!";
-}
-
-
-sub RebaseLink {
-    my ($href) = @_;
-    my ($dir, $origdir, $file, $package);
-
-    if ($href =~ m#^(.*/)([^/]*)$#) {
-        $dir = $origdir = $1;
-        $file = $2;
-        if ($RevMap{ $dir }) {
-            $package = $RevMap{ $dir };
-        }
-        elsif ($dir =~ m#^\.\./([^/]+)/#) {
-            $package = $1
-        }
-        elsif ($AGGRESSIVE) {
-            $dir =~ m#([^/]+)/$#;
-            $package = $1;
-        }
-
-        if ($package) {
-            if ($ONLINE && $OnlineMap{ $package }) {
-              $dir = $OnlineMap{ $package };
-            }
-            elsif ($LocalMap{ $package }) {
-              $dir = $LocalMap{ $package };
-            }
-            $href = $dir . $file;
-        } else {
-          @TRACE@("Can't determine package for '$href'");
-        }
-        if ($dir ne $origdir) {
-            if ($Mapped{ $origdir }) {
-              $Mapped{ $origdir }->[1]++;
-            }
-            else {
-              $Mapped{ $origdir } = [ $dir, 1 ];
-            }
-        }
-    }
-    return $href;
-}
-
-
-sub PrintWhatWeHaveDone {
-    my ($origdir, $info);
-    foreach $origdir (sort keys %Mapped) {
-        $info = $Mapped{$origdir};
-        print "$origdir -> ", $info->[0], " (", $info->[1], ")\n";
-    }
-}
+            onlinedir = re.sub(r'''(.*/).*''', r'\1', match.groups(1))
+    return onlinedir
+
+
+def AddMap(dir, onlinerdir, options):
+    package = None
+
+    package = os.path.split(dir)[1]
+    if options.dest_dir != '' and dir.startswith(options.dest_dir):
+        dir = dir[len(options.dest_dir)-1:]
+
+    if onlinedir:
+        log(options, "On-line location of %s." % onlinedir)
+        OnlineMap[package] = onlinedir;
+        RevMap[onlinedir] = package;
+    else:
+        log(options, "No On-line location for %s found" % package)
+
+    log(options,  "Local location of $package: " + dir)
+    LocalMap[package] = dir;
+    RevMap[dir] = package;
+
+
+def RelativizeLocalMap(dirname, options):
+    prefix = None
+    dir = None
+
+    dirname = os.path.realpath(dirname)
+    prefix = os.path.split(dir)
+    for package, dir in LocalMap.items():
+        if dir.startswith(prefix):
+            dir = os.path.join("..", dir[len(prefix):])
+            LocalMap[package] = dir
+            log(options, "Relativizing local location of $package to " + dir)
+
+def RebaseReferences(dirname, options):
+    for ifile in os.listdir(ifile):
+        if ifile.endswith('.html'):
+            RebaseFile(os.path.join(dirname, ifile), options)
+
+
+def RebaseFile(filename, options):
+    log(options, "Fixing file: " + filename)
+    regex = re.compile(r'''(<a(?:\s+\w+=(?:"[^"]*"|'[^']*'))*\s+href=")([^"]*)(")''')
+
+    def repl_func(match):
+        return match.group(1) + RebaseLink(match.group(2)) + match.group(3)
+
+    contents = open(filename).read()
+    processed = re.sub(regex, repl_func, contents, flags=re.MULTILINE)
+    newfilename = filename + '.new'
+    open(newfilename, 'w').write(processed)
+    os.unlink(filename)
+    os.rename(newfilename, filename)
+
+
+def RebaseLink(href, options):
+    match = re.fullmatch(r'(.*/)([^/]*)', href)
+    package = None
+    origdir = 'INVALID'
+
+    if match:
+        dir = origdir = match.group(1)
+        file = match.group(2)
+        if dir in RevMap:
+            package = RevMap[dir]
+        else:
+            match = re.match(r'\.\./([^/]+)', href)
+            if match is not None:
+                package = match.groups(1)
+            elif options.aggressive:
+                match = re.search(r'''([^/]+)/$''', href)
+                package = match.groups(1);
+
+        if package:
+            if options.online and package in OnlineMap:
+              dir = OnlineMap[package]
+            elif package in LocalMap:
+              dir = LocalMap[package]
+            href = os.path.join(dir, file)
+        else:
+          log(options, "Can't determine package for '%s'" % href);
+
+        if dir != origdir:
+            if origdir in Mapped:
+                Mapped[origdir][1] += 1
+            else:
+                Mapped[origdir] = [dir, 1]
+    return href
+
+
+def PrintWhatWeHaveDone():
+    for origdir in sorted(Mapped.keys()):
+        info = Mapped[origdir]
+        print(origdir, "->", info[0], "(%s)" % info[1])
+
+if __name__== '__main__':
+        Run()
+
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 83c5c4e..d9d289a 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -5,7 +5,7 @@ SUBDIRS = gobject bugs annotations fail empty program .
 if BUILD_TESTS
 
 TESTS = \
-  gtkdoc-common.t gtkdoc-fixxref.t gtkdoc-mkdb.t gtkdoc-rebase.t gtkdoc-scan.t \
+  gtkdoc-common.t gtkdoc-fixxref.t gtkdoc-mkdb.t gtkdoc-scan.t \
   tools.sh gobject.sh bugs.sh annotations.sh fail.sh empty.sh sanity.sh \
   program.sh
 TESTS_ENVIRONMENT = \
@@ -21,7 +21,7 @@ endif
 
 EXTRA_DIST = gtkdoctest.sh tools.sh sanity.sh \
        gobject.sh bugs.sh annotations.sh fail.sh empty.sh \
-       gtkdoc-common.t gtkdoc-fixxref.t gtkdoc-mkdb.t gtkdoc-rebase.t gtkdoc-scan.t
+       gtkdoc-common.t gtkdoc-fixxref.t gtkdoc-mkdb.t gtkdoc-scan.t
 
 
 # run any given test by running make <test>.check
diff --git a/tests/tools.sh.in b/tests/tools.sh.in
index ab9e5cf..9661421 100644
--- a/tests/tools.sh.in
+++ b/tests/tools.sh.in
@@ -10,7 +10,7 @@ echo "Running suite(s): gtk-doc-$suite";
 # we can use which here as we override the path in TEST_ENVIRONMENT
 
 # test perl scripts
-for file in gtkdoc-check gtkdoc-fixxref gtkdoc-mkdb gtkdoc-rebase gtkdoc-scan gtkdoc-scangobj ; do
+for file in gtkdoc-check gtkdoc-fixxref gtkdoc-mkdb gtkdoc-scan gtkdoc-scangobj ; do
   @PERL@ -cwT `which $file`
   if test $? = 1 ; then failed=`expr $failed + 1`; fi
   tested=`expr $tested + 1`
@@ -34,7 +34,7 @@ done
 
 
 # test python scripts
-for file in gtkdoc-depscan gtkdoc-mkhtml gtkdoc-mkman gtkdoc-mkpdf; do
+for file in gtkdoc-depscan gtkdoc-mkhtml gtkdoc-mkman gtkdoc-mkpdf gtkdoc-rebase; do
     fullfile=`which $file`
     @PYTHON@ -m py_compile $fullfile
     if test $? != 0 ; then failed=`expr $failed + 1`; fi


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]