Skip to content

Instantly share code, notes, and snippets.

@phillipberndt
Last active December 25, 2015 02:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save phillipberndt/6901085 to your computer and use it in GitHub Desktop.
Save phillipberndt/6901085 to your computer and use it in GitHub Desktop.
Script to determine the exact versions of the GTK libraries required for pqiv. See https://github.com/phillipberndt/pqiv/issues/13
#!/usr/bin/env python
# encoding: utf-8
#
# Find minimal required versions of the gtk/gdk/gdk_pixbuf/glib/cairo libs
# for pqiv
#
import re
import sys
import urllib
docs = {
"g": "https://developer.gnome.org/glib/stable/api-index-full.html",
"gtk": "https://developer.gnome.org/gtk3/stable/api-index-full.html",
"gdk": "https://developer.gnome.org/gdk/stable/api-index-full.html",
"gdk_pixbuf": "https://developer.gnome.org/gdk-pixbuf/stable/api-index-full.html",
"cairo": "http://cairographics.org/manual/index-all.html",
"g_io": "https://developer.gnome.org/gio/stable/api-index-full.html",
"poppler": "http://people.freedesktop.org/~ajohnson/docs/poppler-glib/api-index-full.html",
}
# For these functions, there is downwards compatibility code included
exclude = [
"cairo_surface_create_similar_image",
"g_get_real_time",
"g_memory_input_stream_new_from_bytes",
"g_thread_new",
"gdk_device_manager_get_client_pointer",
"gdk_device_warp",
"gdk_display_get_device_manager",
"gdk_pixbuf_animation_new_from_stream",
"gdk_screen_get_rgba_visual",
"gdk_screen_get_system_visual",
"gtk_settings_get_default",
"gtk_widget_set_visual",
"poppler_document_new_from_stream",
]
url_cache = {}
def get(url):
if url not in url_cache:
print "\033[sLoading " + url,
sys.stdout.flush()
url_cache[url] = urllib.urlopen(url).read()
print "\033[u\033[K\x08",
sys.stdout.flush()
return url_cache[url]
def find_minimal_version(function):
for library in docs.keys():
details_page = re.search('<a[^>]+href="([^"]+)"[^>]*>' + re.escape(function), get(docs[library]))
if not details_page:
continue
details_page = details_page.group(1)
url = docs[library][:docs[library].rfind("/")] + "/" + details_page[:details_page.find("#")]
details_page_data = get(url)
fn_begin = re.search("<h3>%s(\s|\xc2\xa0)" % re.escape(function), details_page_data)
if not fn_begin:
raise Exception("Did not find documentation")
fn_begin = fn_begin.start()
details_page_data = details_page_data[fn_begin+1:]
next_h3 = details_page_data.find("<h3>")
next_since = details_page_data.find('class="since"')
if next_since > 0 and (next_h3 > next_since or next_h3 < 0):
since = re.search('<p\s+class="since">Since\s+([^<]+)', details_page_data).group(1)
else:
raise Exception("No version information")
return (library, float(since))
raise Exception("Did not find command")
if __name__ == '__main__':
code = open("pqiv.c").read()
calls = set(re.findall("(?!<\w)((poppler|g_io|g|cairo|gtk|gdk_pixbuf|gdk)_\w+)\s*\(", code))
minimal_versions = {}
minimal_version_reasons = {}
for call in calls:
if call[0] in exclude:
continue
print "[\033[32m%50s\033[0m] " % call[0],
sys.stdout.flush()
try:
library, version = find_minimal_version(call[0])
except KeyboardInterrupt:
sys.exit(1)
except:
print "\033[31m" + str(sys.exc_info()[1]) + "\033[0m"
else:
if library not in minimal_versions or version > minimal_versions[library]:
minimal_versions[library] = version
minimal_version_reasons[library] = [ call[0] ]
elif str(version) == str(minimal_versions[library]):
minimal_version_reasons[library] += [ call[0] ]
print "\033[32m" + str(version) + "\033[0m (found in " + library + ")"
sys.stdout.flush()
print
print "Minimal versions required:"
print
for library, version in minimal_versions.items():
print " * %s >= %s" % (library, str(version))
print " because of: " + ", ".join(minimal_version_reasons[library])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment