From 09dc9a027f1fec89cd94dc324a5bdf3f3c5215f8 Mon Sep 17 00:00:00 2001 From: Iustin Pop <iustin@google.com> Date: Thu, 3 May 2012 23:11:30 -0700 Subject: [PATCH] Implement support for multi-module export This add support for exporting constants from multiple modules (as opposed to hard-coding constants), and also makes the output more readable by skipping things we know for sure we don't want to convert (as opposed to things we would like to but don't know _how_ to convert). Additionally, we export the constants from the luxi module too. Signed-off-by: Iustin Pop <iustin@google.com> Reviewed-by: Michael Hanselmann <hansmi@google.com> --- autotools/convert-constants | 66 ++++++++++++++++++++++++------------- 1 file changed, 44 insertions(+), 22 deletions(-) diff --git a/autotools/convert-constants b/autotools/convert-constants index ae367749a..cfac4121d 100755 --- a/autotools/convert-constants +++ b/autotools/convert-constants @@ -1,7 +1,7 @@ #!/usr/bin/python # -# Copyright (C) 2011 Google Inc. +# Copyright (C) 2011, 2012 Google Inc. # # 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 @@ -23,13 +23,18 @@ """ import re +import types -from ganeti import constants from ganeti import compat +from ganeti import constants +from ganeti import luxi #: Constant name regex CONSTANT_RE = re.compile("^[A-Z][A-Z0-9_-]+$") +#: Private name regex +PRIVATE_RE = re.compile("^__.+__$") + #: The type of regex objects RE_TYPE = type(CONSTANT_RE) @@ -79,40 +84,54 @@ def HaskellTypeVal(value): return None -def ConvertVariable(name, value): +def ConvertVariable(prefix, name, value): """Converts a given variable to Haskell code. + @param prefix: a prefix for the Haskell name (useful for module + identification) @param name: the Python name @param value: the value @return: a list of Haskell code lines """ lines = [] - hs_name = NameRules(name) + if prefix: + pfx_name = prefix + "_" + fqn = prefix + "." + name + else: + pfx_name = "" + fqn = name + hs_name = NameRules(pfx_name + name) hs_typeval = HaskellTypeVal(value) - if not CONSTANT_RE.match(name): - lines.append("-- Skipped %s, not constant" % name) + if (isinstance(value, types.ModuleType) or callable(value) or + PRIVATE_RE.match(name)): + # no sense in marking these, as we don't _want_ to convert them; the + # message in the next if block is for datatypes we don't _know_ + # (yet) how to convert + pass + elif not CONSTANT_RE.match(name): + lines.append("-- Skipped %s %s, not constant" % (fqn, type(value))) elif hs_typeval is not None: # this is a simple value (hs_type, hs_val) = hs_typeval - lines.append("-- | Converted from Python constant %s" % name) + lines.append("-- | Converted from Python constant %s" % fqn) lines.append("%s :: %s" % (hs_name, hs_type)) lines.append("%s = %s" % (hs_name, hs_val)) elif isinstance(value, dict): if value: - lines.append("-- Following lines come from dictionary %s" % name) + lines.append("-- Following lines come from dictionary %s" % fqn) for k in sorted(value.keys()): - lines.extend(ConvertVariable(DictKeyName(name, k), value[k])) + lines.extend(ConvertVariable(prefix, DictKeyName(name, k), value[k])) elif isinstance(value, tuple): tvs = [HaskellTypeVal(elem) for elem in value] if compat.all(e is not None for e in tvs): ttypes = ", ".join(e[0] for e in tvs) tvals = ", ".join(e[1] for e in tvs) - lines.append("-- | Converted from Python tuple %s" % name) + lines.append("-- | Converted from Python tuple %s" % fqn) lines.append("%s :: (%s)" % (hs_name, ttypes)) lines.append("%s = (%s)" % (hs_name, tvals)) else: - lines.append("-- Skipped tuple %s, cannot convert all elements" % name) + lines.append("-- Skipped tuple %s, cannot convert all elements" % fqn) elif isinstance(value, (list, set, frozenset)): # Lists and frozensets are handled the same in Haskell: as lists, # since lists are immutable and we don't need for constants the @@ -126,42 +145,45 @@ def ConvertVariable(name, value): ttypes, tvals = zip(*tvs) uniq_types = set(ttypes) if len(uniq_types) == 1: - lines.append("-- | Converted from Python list or set %s" % name) + lines.append("-- | Converted from Python list or set %s" % fqn) lines.append("%s :: [%s]" % (hs_name, uniq_types.pop())) lines.append("%s = [%s]" % (hs_name, ", ".join(tvals))) else: - lines.append("-- | Skipped list/set %s, is not homogeneous" % name) + lines.append("-- | Skipped list/set %s, is not homogeneous" % fqn) else: - lines.append("-- | Skipped list/set %s, cannot convert all elems" % name) + lines.append("-- | Skipped list/set %s, cannot convert all elems" % fqn) elif isinstance(value, RE_TYPE): tvs = HaskellTypeVal(value.pattern) assert tvs is not None - lines.append("-- | Converted from Python RE object %s" % name) + lines.append("-- | Converted from Python RE object %s" % fqn) lines.append("%s :: %s" % (hs_name, tvs[0])) lines.append("%s = %s" % (hs_name, tvs[1])) else: - lines.append("-- Skipped %s, %s not handled" % (name, type(value))) + lines.append("-- Skipped %s, %s not handled" % (fqn, type(value))) return lines -def Convert(): +def Convert(module, prefix): """Converts the constants to Haskell. """ lines = [""] - all_names = dir(constants) + all_names = dir(module) for name in all_names: - value = getattr(constants, name) - lines.extend(ConvertVariable(name, value)) - lines.append("") + value = getattr(module, name) + new_lines = ConvertVariable(prefix, name, value) + if new_lines: + lines.extend(new_lines) + lines.append("") return "\n".join(lines) def main(): - print Convert() + print Convert(constants, "") + print Convert(luxi, "luxi") if __name__ == "__main__": -- GitLab