diff options
author | Johan Dahlin <jdahlin@async.com.br> | 2008-10-30 17:12:51 +0000 |
---|---|---|
committer | Johan Dahlin <johan@src.gnome.org> | 2008-10-30 17:12:51 +0000 |
commit | 53d089628f98fca0ca7984a95902134a7d7c11b8 (patch) | |
tree | b410c743aed159768cb275a00cf4f36867c8b192 /giscanner | |
parent | 0fcde9ead2e60751268dde5300a7a3e4f13f5c58 (diff) | |
download | gobject-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.am | 1 | ||||
-rw-r--r-- | giscanner/cachestore.py | 87 | ||||
-rw-r--r-- | giscanner/girparser.py | 36 | ||||
-rw-r--r-- | giscanner/transformer.py | 18 |
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)): |