Commit 09dc9a02 authored by Iustin Pop's avatar Iustin Pop
Browse files

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: default avatarIustin Pop <iustin@google.com>
Reviewed-by: default avatarMichael Hanselmann <hansmi@google.com>
parent 3d371913
#!/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__":
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment