class Config:
- """The most basic gnulib configuration holder"""
+ """gnulib generic configuration"""
_TABLE_ = {
"gnulib" : "",
"root" : "",
def __getitem__(self, key):
if key not in Config._TABLE_:
- key = key.replace("_", "-")
+ key = key.replace("-", "_")
if key not in Config._TABLE_:
- raise KeyError("unsupported option: '%s'" % key)
+ raise KeyError("unsupported option: %r" % key)
return self.__dict__["_table_"][key]
if key not in Config._TABLE_:
key = key.replace("_", "-")
if key not in Config._TABLE_:
- raise KeyError("unsupported option: '%s'" % key)
+ raise KeyError("unsupported option: %r" % key)
+ key = key.replace("-", "_")
typeid = type(Config._TABLE_[key])
if key == "lgpl":
if value < 2.59:
raise NotImplementedError("pygnulib ")
elif not isinstance(value, typeid):
- raise TypeError("'%s' option must be of '%s' type" % (key, typeid))
+ raise TypeError("%r option must be of %r type" % (key, typeid))
tests = ["tests", "cxx-tests", "longrunning-tests", "privileged-tests", "unportable-tests"]
if key == "all-tests":
class CachedConfig(Config):
- """Cached configuration holder"""
+ """gnulib cached configuration"""
_AUTOCONF_ = {
"autoconf" : re.compile(".*AC_PREREQ\\(\\[(.*?)\\]\\)", re.S | re.M),
"aux-dir" : re.compile("^AC_CONFIG_AUX_DIR\\(\\[(.*?)\\]\\)$", re.S | re.M),
--- /dev/null
+#!/usr/bin/python
+# encoding: UTF-8
+
+
+import os
+
+
+from .config import Config
+from .module import FileModule
+
+
+class FileSystem:
+ """gnulib generic virtual file system"""
+ _SUBST_ = {
+ "build-aux" : "aux-dir",
+ "doc" : "doc-base",
+ "lib" : "source-base",
+ "m4" : "m4-base",
+ "tests" : "tests-base",
+ "tests=lib" : "tests-base",
+ "po" : "po-base",
+ }
+
+ def __init__(self, root, config):
+ if not isinstance(root, str):
+ raise TypeError("root must be of 'str' type")
+ if not isinstance(config, Config):
+ raise TypeError("config must be of 'Config' type")
+ if not os.path.exists(root):
+ raise FileNotFoundError(root)
+ if not os.path.isdir(root):
+ raise NotADirectoryError(root)
+ self._config_ = config
+ self._root_ = os.path.realpath(root)
+
+
+ def __getitem__(self, name):
+ """retrieve the canonical path of the specified file name"""
+ parts = []
+ replaced = False
+ if not isinstance(name, str):
+ raise TypeError("name must be of 'str' type")
+ path = os.path.normpath(name)
+ if os.path.isabs(path):
+ raise ValueError("name must be a relative path")
+ for part in path.split(os.path.sep):
+ if part == "..":
+ parts += [part]
+ continue
+ if not replaced:
+ for old, new in FileSystem._SUBST_.items():
+ if part == old:
+ part = self._config_[new]
+ replaced = True
+ parts += [part]
+ path = os.path.sep.join([self._root_] + parts)
+ if not os.path.exists(path):
+ raise FileNotFoundError(name)
+ return path
+
+
+
+class GitFileSystem(FileSystem):
+ """gnulib Git-based virtual file system"""
+ _EXCLUDE_ = {
+ "." : str.startswith,
+ "~" : str.endswith,
+ "-tests" : str.endswith,
+ "CVS" : str.startswith,
+ "ChangeLog" : str.__eq__,
+ "COPYING" : str.__eq__,
+ "README" : str.__eq__,
+ "TEMPLATE" : str.__eq__,
+ "TEMPLATE-TESTS" : str.__eq__,
+ "TEMPLATE-EXTENDED" : str.__eq__,
+ }
+
+
+ def __init__(self, root, config):
+ if not os.path.isdir(root):
+ raise FileNotFoundError(root)
+ if not os.path.isdir(os.path.join(root, ".git")):
+ raise TypeError("%r is not a gnulib repository")
+ super(GitFileSystem, self).__init__(root, config)
+
+
+ def module(self, name):
+ """instantiate gnulib module by its name"""
+ if name in GitFileSystem._EXCLUDE_:
+ raise KeyError("module does not exist")
+ path = os.path.join(self["modules"], name)
+ return FileModule(path, name=name)
+
+
+ def modules(self):
+ """iterate over all available modules"""
+ prefix = self["modules"]
+ for root, _, files in os.walk(prefix):
+ names = []
+ for name in files:
+ exclude = False
+ for key, method in GitFileSystem._EXCLUDE_.items():
+ if method(name, key):
+ exclude = True
+ break
+ if not exclude:
+ names += [name]
+ for name in names:
+ path = os.path.join(root, name)
+ name = path[len(prefix) + 1:]
+ yield FileModule(path, name=name)
# encoding: UTF-8
+import codecs
import os
import re
-import codecs
class Module:
+ """gnulib generic module"""
_PATTERN_ = re.compile("")
_TABLE_ = {
"description" : (0x00, str, None, "Description"),
return self.__dict__["_name_"]
+ @property
+ def dependencies(self):
+ pattern = re.compile("^([A-Za-z0-9_\\-\\+/]+)(?:\\s+(.+))*$", re.S)
+ for dep in self.__dict__["_table_"]["dependencies"]:
+ yield pattern.findall(dep)[0]
+
+
def __hash__(self):
return hash(str(self))
def __getitem__(self, key):
if key not in Module._TABLE_:
- raise ValueError("unsupported key: '%s'" % key)
+ raise ValueError("unsupported key: %r" % key)
return self.__dict__["_table_"][key]
def __setitem__(self, key, value):
if key not in Module._TABLE_:
- raise ValueError("unsupported key: '%s'" % key)
+ raise ValueError("unsupported key: %r" % key)
typeid = Module._TABLE_[key][1]
if not isinstance(value, typeid):
- raise TypeError("'%s' key expects '%s' type" % (key, typeid))
+ typename = typeid.__name__
+ raise TypeError("%r key must be of %r type" % (key, typename))
self.__dict__["_table_"][key] = value
def __eq__(self, value):
if isinstance(value, Module):
return (self.__dict__["_name_"] == value.__dict__["_name_"]) \
- and (self.__dict__["_table_"] == value.__dict__["_name_"])
+ and (self.__dict__["_table_"] == value.__dict__["_table_"])
return TypeError("cannot compare pygnulib.Module with %r type" % type(value))
def __ne__(self, value):
class FileModule(Module):
- """Read or modify existing gnulib module package"""
+ """gnulib module text file"""
def __init__(self, path, mode="r", name=None, **kwargs):
if name is None:
with codecs.open(path, "rb", "UTF-8") as stream:
data = stream.read()
for key, (_, typeid, pattern, _) in Module._TABLE_.items():
+ pattern = re.compile(pattern)
match = pattern.findall(data)
self[key] = [_ for _ in "".join(match).split("\n") if _.strip()] \
if typeid is list else \
("\n".join([_.strip() for _ in match]) if match else "")
+ self["dependencies"] = [_ for _ in self["dependencies"] if not _.startswith("#")]
self.__dict__["_stream_"] = None
elif mode == "w":
super(FileModule, self).__init__(name)
+++ /dev/null
-#!/usr/bin/python
-# encoding: UTF-8
-
-
-import os
-
-
-from .config import Config
-from .module import FileModule
-
-
-class Project:
- """gnulib project directory"""
- _SUBST_ = {
- "build-aux" : "aux-dir",
- "doc" : "doc-base",
- "lib" : "source-base",
- "m4" : "m4-base",
- "tests" : "tests-base",
- "tests=lib" : "tests-base",
- "po" : "po-base",
- }
-
- def __init__(self, root, **kwargs):
- if not isinstance(root, str):
- raise TypeError("root must be of 'str' type")
- if not os.path.exists(root):
- raise FileNotFoundError(root)
- if not os.path.isdir(root):
- raise NotADirectoryError(root)
- self._root_ = root
- self._config_ = Config(**kwargs)
-
-
- @property
- def root(self):
- return self._root_
-
-
- def path(self, name):
- parts = []
- replaced = False
- if not isinstance(name, str):
- raise TypeError("src must be of 'str' type")
- name = os.path.normpath(name)
- if os.path.isabs(name):
- raise ValueError("name must be a relative path")
- for part in name.split(os.path.sep):
- if part == "..":
- parts += [part]
- continue
- if not replaced:
- for old, new in Project._SUBST_.items():
- if part == old:
- part = self._config_[new]
- replaced = True
- parts += [part]
- return os.path.sep.join(parts)
-
-
- def exists(self, name):
- path = self.path(name)
- return os.path.exists(path)
-
-
- def stat(self, name):
- return os.stat(self.path(name))
-
-
-
-class GitRepository(Project):
- """gnulib Git repository"""
- _EXCLUDE_ = {
- "CVS",
- "ChangeLog",
- "COPYING",
- "README",
- "TEMPLATE",
- "TEMPLATE-EXTENDED",
- }
-
-
- def __init__(self, root, **kwargs):
- if not os.path.isdir(root):
- raise FileNotFoundError(root)
- if not os.path.isdir(os.path.join(root, ".git")):
- raise TypeError("%r is not a gnulib repository")
- super(GitRepository, self).__init__(root, **kwargs)
-
-
- def module(self, name):
- if name in GitRepository._EXCLUDE_:
- raise KeyError("module does not exist")
- path = os.path.join(self.root, "modules", name)
- return FileModule(path, name=name)
-
-
- def modules(self):
- for root, _, files in os.walk(os.path.join(self.root, "modules")):
- for name in [_ for _ in files if _ not in GitRepository._EXCLUDE_]:
- path = os.path.join(root, name)
- yield FileModule(path, name=name)