X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=python%2Fovs%2Fdb%2Ftypes.py;h=fc9fc0a231d8a463a48f5c2d3b3d18d038e6d05d;hb=746cb7604e734c6e220c7a68218d8df50e692a56;hp=72ab41077be60a3a64a91b78d73090ffb797f28f;hpb=5c3a4660c0ab317f904446bef8cf1bcce439d754;p=sliver-openvswitch.git diff --git a/python/ovs/db/types.py b/python/ovs/db/types.py index 72ab41077..fc9fc0a23 100644 --- a/python/ovs/db/types.py +++ b/python/ovs/db/types.py @@ -1,4 +1,4 @@ -# Copyright (c) 2009, 2010, 2011 Nicira Networks +# Copyright (c) 2009, 2010, 2011, 2012 Nicira Networks # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -13,16 +13,19 @@ # limitations under the License. import sys +import uuid from ovs.db import error import ovs.db.parser import ovs.db.data import ovs.ovsuuid + class AtomicType(object): - def __init__(self, name, default): + def __init__(self, name, default, python_types): self.name = name self.default = default + self.python_types = python_types @staticmethod def from_string(s): @@ -51,16 +54,17 @@ class AtomicType(object): def default_atom(self): return ovs.db.data.Atom(self, self.default) -VoidType = AtomicType("void", None) -IntegerType = AtomicType("integer", 0) -RealType = AtomicType("real", 0.0) -BooleanType = AtomicType("boolean", False) -StringType = AtomicType("string", "") -UuidType = AtomicType("uuid", ovs.ovsuuid.zero()) +VoidType = AtomicType("void", None, ()) +IntegerType = AtomicType("integer", 0, (int, long)) +RealType = AtomicType("real", 0.0, (int, long, float)) +BooleanType = AtomicType("boolean", False, (bool,)) +StringType = AtomicType("string", "", (str, unicode)) +UuidType = AtomicType("uuid", ovs.ovsuuid.zero(), (uuid.UUID,)) ATOMIC_TYPES = [VoidType, IntegerType, RealType, BooleanType, StringType, UuidType] + def escapeCString(src): dst = "" for c in src: @@ -87,10 +91,13 @@ def escapeCString(src): dst += c return dst + def commafy(x): """Returns integer x formatted in decimal with thousands set off by commas.""" return _commafy("%d" % x) + + def _commafy(s): if s.startswith('-'): return '-' + _commafy(s[1:]) @@ -99,12 +106,14 @@ def _commafy(s): else: return _commafy(s[:-3]) + ',' + _commafy(s[-3:]) + def returnUnchanged(x): return x + class BaseType(object): def __init__(self, type_, enum=None, min=None, max=None, - min_length = 0, max_length=sys.maxint, ref_table=None): + min_length=0, max_length=sys.maxint, ref_table_name=None): assert isinstance(type_, AtomicType) self.type = type_ self.enum = enum @@ -112,11 +121,12 @@ class BaseType(object): self.max = max self.min_length = min_length self.max_length = max_length - self.ref_table = ref_table - if ref_table: + self.ref_table_name = ref_table_name + if ref_table_name: self.ref_type = 'strong' else: self.ref_type = None + self.ref_table = None def default(self): return ovs.db.data.Atom.default(self.type) @@ -128,7 +138,7 @@ class BaseType(object): self.min == other.min and self.max == other.max and self.min_length == other.min_length and self.max_length == other.max_length and - self.ref_table == other.ref_table) + self.ref_table_name == other.ref_table_name) def __ne__(self, other): if not isinstance(other, BaseType): @@ -142,7 +152,7 @@ class BaseType(object): if value is None: value = default else: - max_value = 2**32 - 1 + max_value = 2 ** 32 - 1 if not (0 <= value <= max_value): raise error.Error("%s out of valid range 0 to %d" % (name, max_value), value) @@ -160,16 +170,19 @@ class BaseType(object): enum = parser.get_optional("enum", []) if enum is not None: - base.enum = ovs.db.data.Datum.from_json(BaseType.get_enum_type(base.type), enum) + base.enum = ovs.db.data.Datum.from_json( + BaseType.get_enum_type(base.type), enum) elif base.type == IntegerType: base.min = parser.get_optional("minInteger", [int, long]) base.max = parser.get_optional("maxInteger", [int, long]) - if base.min is not None and base.max is not None and base.min > base.max: + if (base.min is not None and base.max is not None + and base.min > base.max): raise error.Error("minInteger exceeds maxInteger", json) elif base.type == RealType: base.min = parser.get_optional("minReal", [int, long, float]) base.max = parser.get_optional("maxReal", [int, long, float]) - if base.min is not None and base.max is not None and base.min > base.max: + if (base.min is not None and base.max is not None + and base.min > base.max): raise error.Error("minReal exceeds maxReal", json) elif base.type == StringType: base.min_length = BaseType.__parse_uint(parser, "minLength", 0) @@ -178,8 +191,8 @@ class BaseType(object): if base.min_length > base.max_length: raise error.Error("minLength exceeds maxLength", json) elif base.type == UuidType: - base.ref_table = parser.get_optional("refTable", ['id']) - if base.ref_table: + base.ref_table_name = parser.get_optional("refTable", ['id']) + if base.ref_table_name: base.ref_type = parser.get_optional("refType", [str, unicode], "strong") if base.ref_type not in ['strong', 'weak']: @@ -214,15 +227,17 @@ class BaseType(object): if self.max_length != sys.maxint: json['maxLength'] = self.max_length elif self.type == UuidType: - if self.ref_table: - json['refTable'] = self.ref_table + if self.ref_table_name: + json['refTable'] = self.ref_table_name if self.ref_type != 'strong': json['refType'] = self.ref_type return json def copy(self): - return BaseType(self.type, self.enum.copy(), self.min, self.max, - self.min_length, self.max_length, self.ref_table) + base = BaseType(self.type, self.enum.copy(), self.min, self.max, + self.min_length, self.max_length, self.ref_table_name) + base.ref_table = self.ref_table + return base def is_valid(self): if self.type in (VoidType, BooleanType, UuidType): @@ -235,9 +250,10 @@ class BaseType(object): return False def has_constraints(self): - return (self.enum is not None or self.min is not None or self.max is not None or + return (self.enum is not None or self.min is not None or + self.max is not None or self.min_length != 0 or self.max_length != sys.maxint or - self.ref_table is not None) + self.ref_table_name is not None) def without_constraints(self): return BaseType(self.type) @@ -247,9 +263,9 @@ class BaseType(object): """Returns the type of the 'enum' member for a BaseType whose 'type' is 'atomic_type'.""" return Type(BaseType(atomic_type), None, 1, sys.maxint) - + def is_ref(self): - return self.type == UuidType and self.ref_table is not None + return self.type == UuidType and self.ref_table_name is not None def is_strong_ref(self): return self.is_ref() and self.ref_type == 'strong' @@ -258,55 +274,64 @@ class BaseType(object): return self.is_ref() and self.ref_type == 'weak' def toEnglish(self, escapeLiteral=returnUnchanged): - if self.type == UuidType and self.ref_table: - s = escapeLiteral(self.ref_table) + if self.type == UuidType and self.ref_table_name: + s = escapeLiteral(self.ref_table_name) if self.ref_type == 'weak': s = "weak reference to " + s return s else: return self.type.to_string() - def constraintsToEnglish(self, escapeLiteral=returnUnchanged): + def constraintsToEnglish(self, escapeLiteral=returnUnchanged, + escapeNumber=returnUnchanged): if self.enum: literals = [value.toEnglish(escapeLiteral) for value in self.enum.values] if len(literals) == 2: - return 'either %s or %s' % (literals[0], literals[1]) + english = 'either %s or %s' % (literals[0], literals[1]) else: - return 'one of %s, %s, or %s' % (literals[0], - ', '.join(literals[1:-1]), - literals[-1]) + english = 'one of %s, %s, or %s' % (literals[0], + ', '.join(literals[1:-1]), + literals[-1]) elif self.min is not None and self.max is not None: if self.type == IntegerType: - return 'in range %s to %s' % (commafy(self.min), - commafy(self.max)) + english = 'in range %s to %s' % ( + escapeNumber(commafy(self.min)), + escapeNumber(commafy(self.max))) else: - return 'in range %g to %g' % (self.min, self.max) + english = 'in range %s to %s' % ( + escapeNumber("%g" % self.min), + escapeNumber("%g" % self.max)) elif self.min is not None: if self.type == IntegerType: - return 'at least %s' % commafy(self.min) + english = 'at least %s' % escapeNumber(commafy(self.min)) else: - return 'at least %g' % self.min + english = 'at least %s' % escapeNumber("%g" % self.min) elif self.max is not None: if self.type == IntegerType: - return 'at most %s' % commafy(self.max) + english = 'at most %s' % escapeNumber(commafy(self.max)) else: - return 'at most %g' % self.max + english = 'at most %s' % escapeNumber("%g" % self.max) elif self.min_length != 0 and self.max_length != sys.maxint: if self.min_length == self.max_length: - return 'exactly %d characters long' % (self.min_length) + english = ('exactly %s characters long' + % commafy(self.min_length)) else: - return 'between %d and %d characters long' % (self.min_length, self.max_length) + english = ('between %s and %s characters long' + % (commafy(self.min_length), + commafy(self.max_length))) elif self.min_length != 0: - return 'at least %d characters long' % self.min_length + return 'at least %s characters long' % commafy(self.min_length) elif self.max_length != sys.maxint: - return 'at most %d characters long' % self.max_length + english = 'at most %s characters long' % commafy(self.max_length) else: - return '' + english = '' + + return english def toCType(self, prefix): - if self.ref_table: - return "struct %s%s *" % (prefix, self.ref_table.lower()) + if self.ref_table_name: + return "struct %s%s *" % (prefix, self.ref_table_name.lower()) else: return {IntegerType: 'int64_t ', RealType: 'double ', @@ -319,7 +344,7 @@ class BaseType(object): def copyCValue(self, dst, src): args = {'dst': dst, 'src': src} - if self.ref_table: + if self.ref_table_name: return ("%(dst)s = %(src)s->header_.uuid;") % args elif self.type == StringType: return "%(dst)s = xstrdup(%(src)s);" % args @@ -327,7 +352,7 @@ class BaseType(object): return "%(dst)s = %(src)s;" % args def initCDefault(self, var, is_optional): - if self.ref_table: + if self.ref_table_name: return "%s = NULL;" % var elif self.type == StringType and not is_optional: return '%s = "";' % var @@ -338,7 +363,7 @@ class BaseType(object): BooleanType: '%s = false;', StringType: '%s = NULL;'}[self.type] return pattern % var - + def cInitBaseType(self, indent, var): stmts = [] stmts.append('ovsdb_base_type_init(&%s, %s);' % ( @@ -349,9 +374,11 @@ class BaseType(object): stmts += self.enum.cInitDatum("%s.enum_" % var) if self.type == IntegerType: if self.min is not None: - stmts.append('%s.u.integer.min = INT64_C(%d);' % (var, self.min)) + stmts.append('%s.u.integer.min = INT64_C(%d);' + % (var, self.min)) if self.max is not None: - stmts.append('%s.u.integer.max = INT64_C(%d);' % (var, self.max)) + stmts.append('%s.u.integer.max = INT64_C(%d);' + % (var, self.max)) elif self.type == RealType: if self.min is not None: stmts.append('%s.u.real.min = %d;' % (var, self.min)) @@ -359,15 +386,20 @@ class BaseType(object): stmts.append('%s.u.real.max = %d;' % (var, self.max)) elif self.type == StringType: if self.min_length is not None: - stmts.append('%s.u.string.minLen = %d;' % (var, self.min_length)) + stmts.append('%s.u.string.minLen = %d;' + % (var, self.min_length)) if self.max_length != sys.maxint: - stmts.append('%s.u.string.maxLen = %d;' % (var, self.max_length)) + stmts.append('%s.u.string.maxLen = %d;' + % (var, self.max_length)) elif self.type == UuidType: - if self.ref_table is not None: - stmts.append('%s.u.uuid.refTableName = "%s";' % (var, escapeCString(self.ref_table))) - stmts.append('%s.u.uuid.refType = OVSDB_REF_%s;' % (var, self.ref_type.upper())) + if self.ref_table_name is not None: + stmts.append('%s.u.uuid.refTableName = "%s";' + % (var, escapeCString(self.ref_table_name))) + stmts.append('%s.u.uuid.refType = OVSDB_REF_%s;' + % (var, self.ref_type.upper())) return '\n'.join([indent + stmt for stmt in stmts]) + class Type(object): DEFAULT_MIN = 1 DEFAULT_MAX = 1 @@ -420,7 +452,7 @@ class Type(object): def is_optional_pointer(self): return (self.is_optional() and not self.value - and (self.key.type == StringType or self.key.ref_table)) + and (self.key.type == StringType or self.key.ref_table_name)) @staticmethod def __n_from_json(json, default): @@ -430,7 +462,7 @@ class Type(object): return json else: raise error.Error("bad min or max value", json) - + @staticmethod def from_json(json): if type(json) in [str, unicode]: @@ -491,13 +523,14 @@ class Type(object): else: if self.n_max == sys.maxint: if self.n_min: - quantity = "%d or more " % self.n_min + quantity = "%s or more " % commafy(self.n_min) else: quantity = "" elif self.n_min: - quantity = "%d to %d " % (self.n_min, self.n_max) + quantity = "%s to %s " % (commafy(self.n_min), + commafy(self.n_max)) else: - quantity = "up to %d " % self.n_max + quantity = "up to %s " % commafy(self.n_max) if self.value: return "map of %s%s-%s pairs" % (quantity, keyName, valueName) @@ -508,9 +541,11 @@ class Type(object): plural = keyName + "s" return "set of %s%s" % (quantity, plural) - def constraintsToEnglish(self, escapeLiteral=returnUnchanged): + def constraintsToEnglish(self, escapeLiteral=returnUnchanged, + escapeNumber=returnUnchanged): constraints = [] - keyConstraints = self.key.constraintsToEnglish(escapeLiteral) + keyConstraints = self.key.constraintsToEnglish(escapeLiteral, + escapeNumber) if keyConstraints: if self.value: constraints.append('key %s' % keyConstraints) @@ -518,12 +553,13 @@ class Type(object): constraints.append(keyConstraints) if self.value: - valueConstraints = self.value.constraintsToEnglish(escapeLiteral) + valueConstraints = self.value.constraintsToEnglish(escapeLiteral, + escapeNumber) if valueConstraints: constraints.append('value %s' % valueConstraints) return ', '.join(constraints) - + def cDeclComment(self): if self.n_min == 1 and self.n_max == 1 and self.key.type == StringType: return "\t/* Always nonnull. */" @@ -544,4 +580,3 @@ class Type(object): n_max = self.n_max initMax = "%s%s.n_max = %s;" % (indent, var, n_max) return "\n".join((initKey, initValue, initMin, initMax)) -