summaryrefslogtreecommitdiff
path: root/giscanner
diff options
context:
space:
mode:
authorJohan Dahlin <jdahlin@async.com.br>2008-10-30 17:12:51 +0000
committerJohan Dahlin <johan@src.gnome.org>2008-10-30 17:12:51 +0000
commit53d089628f98fca0ca7984a95902134a7d7c11b8 (patch)
treeb410c743aed159768cb275a00cf4f36867c8b192 /giscanner
parent0fcde9ead2e60751268dde5300a7a3e4f13f5c58 (diff)
downloadgobject-introspection-53d089628f98fca0ca7984a95902134a7d7c11b8.tar.gz
Remove arguments from the constructor, move them to separate accessors.
2008-10-30 Johan Dahlin <jdahlin@async.com.br> * giscanner/girparser.py: Remove arguments from the constructor, move them to separate accessors. Add a new parse_tree method which takes an element tree instance. * tools/g-ir-scanner: Update callsite for this * giscanner/Makefile.am: * giscanner/cachestore.py: * giscanner/transformer.py: Cache the include parsing. Saves ~25% time when creating vte (which includes everything up to gtk+). svn path=/trunk/; revision=842
Diffstat (limited to 'giscanner')
-rw-r--r--giscanner/Makefile.am1
-rw-r--r--giscanner/cachestore.py87
-rw-r--r--giscanner/girparser.py36
-rw-r--r--giscanner/transformer.py18
4 files changed, 120 insertions, 22 deletions
diff --git a/giscanner/Makefile.am b/giscanner/Makefile.am
index a7e3ad5c..b21b17de 100644
--- a/giscanner/Makefile.am
+++ b/giscanner/Makefile.am
@@ -36,6 +36,7 @@ pkgpyexec_LTLIBRARIES = _giscanner.la
pkgpyexec_PYTHON = \
__init__.py \
ast.py \
+ cachestore.py \
cgobject.py \
config.py \
girparser.py \
diff --git a/giscanner/cachestore.py b/giscanner/cachestore.py
new file mode 100644
index 00000000..ddbbc059
--- /dev/null
+++ b/giscanner/cachestore.py
@@ -0,0 +1,87 @@
+# -*- Mode: Python -*-
+# GObject-Introspection - a framework for introspecting GObject libraries
+# Copyright (C) 2008 Johan Dahlin
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+
+import cPickle
+import hashlib
+import os
+import errno
+
+
+def _get_cachedir():
+ cachedir = os.path.join(os.environ['HOME'], '.cache')
+ if not os.path.exists(cachedir):
+ os.mkdir(cachedir, 0755)
+
+ scannerdir = os.path.join(cachedir, 'g-ir-scanner')
+ if not os.path.exists(scannerdir):
+ os.mkdir(scannerdir, 0755)
+ # If it exists and is a file, don't cache at all
+ elif not os.path.isdir(scannerdir):
+ return None
+ return scannerdir
+
+
+class CacheStore(object):
+
+ def __init__(self):
+ try:
+ self._directory = _get_cachedir()
+ except OSError, e:
+ if e.errno != errno.EPERM:
+ raise
+ self._directory = None
+
+ def _get_filename(self, filename):
+ # If we couldn't create the directory we're probably
+ # on a read only home directory where we just disable
+ # the cache all together.
+ if self._directory is None:
+ return
+ hexdigest = hashlib.sha1(filename).hexdigest()
+ return os.path.join(self._directory, hexdigest)
+
+ def _cache_is_valid(self, store_filename, filename):
+ return (os.stat(store_filename).st_mtime >=
+ os.stat(filename).st_mtime)
+
+ def store(self, filename, data):
+ store_filename = self._get_filename(filename)
+ if store_filename is None:
+ return
+ if (os.path.exists(store_filename) and
+ self._cache_is_valid(store_filename, filename)):
+ return None
+ fd = open(store_filename, 'w')
+ cPickle.dump(data, fd)
+
+ def load(self, filename):
+ store_filename = self._get_filename(filename)
+ if store_filename is None:
+ return
+ try:
+ fd = open(store_filename)
+ except IOError, e:
+ if e.errno == errno.ENOENT:
+ return None
+ raise
+ if not self._cache_is_valid(store_filename, filename):
+ return None
+ data = cPickle.load(fd)
+ return data
diff --git a/giscanner/girparser.py b/giscanner/girparser.py
index 689b635b..8b255a43 100644
--- a/giscanner/girparser.py
+++ b/giscanner/girparser.py
@@ -46,26 +46,23 @@ def _cns(tag):
class GIRParser(object):
- def __init__(self, filename,
- initial_parse=True,
- include_parsing=False):
+ def __init__(self):
+ self._include_parsing = False
+ self._shared_libraries = []
self._includes = set()
self._namespace = None
- self._shared_libraries = []
- self._include_parsing = include_parsing
- self._tree = parse(filename)
-
- if initial_parse:
- self.parse()
# Public API
- def parse(self):
- self._includes.clear()
- del self._namespace
- del self._shared_libraries[:]
+ def parse(self, filename):
+ tree = parse(filename)
+ self.parse_tree(tree)
- self._parse_api(self._tree.getroot())
+ def parse_tree(self, tree):
+ self._includes.clear()
+ self._namespace = None
+ self._shared_libraries = []
+ self._parse_api(tree.getroot())
def get_namespace(self):
return self._namespace
@@ -77,7 +74,10 @@ class GIRParser(object):
return self._includes
def get_doc(self):
- return self._tree
+ return parse(self._filename)
+
+ def set_include_parsing(self, include_parsing):
+ self._include_parsing = include_parsing
# Private
@@ -159,8 +159,8 @@ class GIRParser(object):
obj.fields.append(self._parse_function_common(callback, Callback))
for field in node.findall(_corens('field')):
obj.fields.append(self._parse_field(field))
- for property in node.findall(_corens('property')):
- obj.properties.append(self._parse_property(property))
+ for prop in node.findall(_corens('property')):
+ obj.properties.append(self._parse_property(prop))
for signal in node.findall(_glibns('signal')):
obj.signals.append(self._parse_function_common(signal, Function))
@@ -237,7 +237,7 @@ class GIRParser(object):
node.attrib.get(_cns('type')))
else:
union = Union(node.attrib['name'],
- node.attrib.get(_cns('type')))
+ node.attrib.get(_cns('type')))
self._add_node(union)
if self._include_parsing:
diff --git a/giscanner/transformer.py b/giscanner/transformer.py
index 2595477c..2e3e899b 100644
--- a/giscanner/transformer.py
+++ b/giscanner/transformer.py
@@ -65,7 +65,9 @@ class Names(object):
class Transformer(object):
- def __init__(self, generator, namespace_name, namespace_version):
+ def __init__(self, cachestore, generator,
+ namespace_name, namespace_version):
+ self._cachestore = cachestore
self.generator = generator
self._namespace = Namespace(namespace_name, namespace_version)
self._names = Names()
@@ -123,11 +125,19 @@ class Transformer(object):
% (girname, searchdirs))
def _parse_include(self, filename):
- parser = GIRParser(filename, include_parsing=True)
+ parser = self._cachestore.load(filename)
+ if parser is None:
+ parser = GIRParser()
+ parser.set_include_parsing(True)
+ parser.parse(filename)
+ self._cachestore.store(filename, parser)
+
for include in parser.get_includes():
self.register_include(include)
- nsname = parser.get_namespace().name
- for node in parser.get_namespace().nodes:
+
+ namespace = parser.get_namespace()
+ nsname = namespace.name
+ for node in namespace.nodes:
if isinstance(node, Alias):
self._names.aliases[node.name] = (nsname, node)
elif isinstance(node, (GLibBoxed, Interface, Class)):