+list

---------- Forwarded message ----------
From: Guido Trotter <[email protected]>
Date: Wed, Jul 31, 2013 at 1:09 PM
Subject: Re: [PATCH master 02/12] Add predicates to test Python types in opcodes
To: "Jose A. Lopes" <[email protected]>


On Wed, Jul 31, 2013 at 12:54 PM, Jose A. Lopes <[email protected]> wrote:
> From: "Jose A. Lopes" <[email protected]>
>
> Add helper functions to test Python types, which are used by opcode
> parameters and return values.
>
> Signed-off-by: Jose A. Lopes <[email protected]>
> ---
>  lib/ht.py | 229 
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 228 insertions(+), 1 deletion(-)
>
> diff --git a/lib/ht.py b/lib/ht.py
> index a452239..d5719c0 100644
> --- a/lib/ht.py
> +++ b/lib/ht.py
> @@ -23,10 +23,12 @@
>
>  import re
>  import operator
> +import ipaddr
>
>  from ganeti import compat
>  from ganeti import utils
>  from ganeti import constants
> +from ganeti import objects
>
>
>  _PAREN_RE = re.compile("^[a-zA-Z0-9_-]+$")
> @@ -359,6 +361,16 @@ TMaybeDict = TMaybe(TDict)
>  #: Maybe a list (list or None)
>  TMaybeList = TMaybe(TList)
>
> +
> +#: a positive number (value > 0)
> +def TNonNegative(val_type):
> +  return WithDesc("GreaterThanZero")(TAnd(val_type, lambda v: v > 0))
> +
> +
> +#: a non-negative number (value >= 0)
> +def TPositive(val_type):
> +  return WithDesc("EqualOrGreaterThanZero")(TAnd(val_type, lambda v: v >= 0))
> +

Are these two inverted? :)
Also should they be PositiveNumber, NonNegativeNumber?


>  #: a non-negative integer (value >= 0)
>  TNonNegativeInt = \
>    TAnd(TInt, WithDesc("EqualOrGreaterThanZero")(lambda v: v >= 0))
> @@ -383,7 +395,7 @@ TJobId = WithDesc("JobId")(TOr(TNonNegativeInt,
>                                 TRegex(re.compile("^%s$" %
>                                                   
> constants.JOB_ID_TEMPLATE))))
>
> -#: Number
> +TDouble = TFloat
>  TNumber = TOr(TInt, TFloat)
>
>  #: Relative job ID
> @@ -415,6 +427,24 @@ def TListOf(my_type):
>  TMaybeListOf = lambda item_type: TMaybe(TListOf(item_type))
>
>
> +def TTupleOf(*val_types):
> +  """Checks if a given value is a list with the proper size and its
> +     elements match the given types.
> +
> +  """
> +  desc = WithDesc("Tuple of %s" % (Parens(val_types), ))
> +  return desc(TAnd(TIsLength(len(val_types)), TItems(val_types)))
> +
> +
> +def TSet(val_type):
> +  """Checks if a given value is a list with all elements of the same
> +     type and eliminates duplicated elements.
> +
> +  """
> +  desc = WithDesc("Set of %s" % (Parens(val_type), ))
> +  return desc(lambda st: TListOf(val_type)(list(set(st))))
> +
> +

TSetOf if the others are TDictOf, TTupleOf, etc...

>  def TDictOf(key_type, val_type):
>    """Checks a dict type for the type of its key/values.
>
> @@ -497,3 +527,200 @@ def TItems(items):
>
>    return desc(lambda value: compat.all(check(i)
>                                         for (check, i) in zip(items, value)))
> +
> +
> +TAllocPolicy = TElemOf(constants.VALID_ALLOC_POLICIES)
> +TCVErrorCode = TElemOf(constants.CV_ALL_ECODES_STRINGS)
> +TQueryResultCode = TElemOf(constants.RS_ALL)
> +TExportTarget = TOr(TNonEmptyString, TList)
> +TExportMode = TElemOf(constants.EXPORT_MODES)
> +
> +
> +# FIXME: check haskell code "mkDiskIndex"

Can you explain this FIXME better?

> +TDiskIndex = TNonNegativeInt
> +TReplaceDisksMode = TElemOf(constants.REPLACE_MODES)
> +TDiskTemplate = TElemOf(constants.DISK_TEMPLATES)
> +TNodeEvacMode = TElemOf(constants.IALLOCATOR_NEVAC_MODES)
> +TIAllocatorTestDir = TElemOf(constants.VALID_IALLOCATOR_DIRECTIONS)
> +TIAllocatorMode = TElemOf(constants.VALID_IALLOCATOR_MODES)
> +
> +
> +def TSetParamsMods(fn):
> +  """Generates a check for modification lists.
> +
> +  """
> +  # Old format
> +  # TODO: Remove in version 2.8 including support in LUInstanceSetParams

Are we committing code to 2.10 with a TODO to remove in 2.8?
Should we at least update the TODO ?

> +  old_mod_item_fn = \
> +    TAnd(TIsLength(2),
> +         TItems([TOr(TElemOf(constants.DDMS_VALUES), TNonNegativeInt), fn]))
> +
> +  # New format, supporting adding/removing disks/NICs at arbitrary indices
> +  mod_item_fn = \
> +      TAnd(TIsLength(3), TItems([
> +        TElemOf(constants.DDMS_VALUES_WITH_MODIFY),
> +        Comment("Device index, can be negative, e.g. -1 for last disk")
> +                 (TOr(TInt, TString)),
> +        fn,
> +        ]))
> +
> +  return TOr(Comment("Recommended")(TListOf(mod_item_fn)),
> +             Comment("Deprecated")(TListOf(old_mod_item_fn)))
> +
> +
> +TINicParams = \
> +    Comment("NIC parameters")(TDictOf(TElemOf(constants.INIC_PARAMS),
> +                                      TMaybeString))
> +
> +TIDiskParams = \
> +    Comment("Disk parameters")(TDictOf(TElemOf(constants.IDISK_PARAMS),
> +                                       TOr(TNonEmptyString, TInt)))
> +
> +THypervisor = TElemOf(constants.HYPER_TYPES)
> +TMigrationMode = TElemOf(constants.HT_MIGRATION_MODES)
> +TNICMode = TElemOf(constants.NIC_VALID_MODES)
> +TInstCreateMode = TElemOf(constants.INSTANCE_CREATE_MODES)
> +TRebootType = TElemOf(constants.REBOOT_TYPES)
> +TFileDriver = TElemOf(constants.FILE_DRIVER)
> +TOobCommand = TElemOf(constants.OOB_COMMANDS)
> +TQueryTypeOp = TElemOf(constants.QR_VIA_OP)
> +
> +TDiskParams = \
> +    Comment("Disk parameters")(TDictOf(TNonEmptyString,
> +                                       TOr(TNonEmptyString, TInt)))
> +
> +TDiskChanges = \
> +    TAnd(TIsLength(2),
> +         TItems([Comment("Disk index")(TNonNegativeInt),
> +                 Comment("Parameters")(TDiskParams)]))
> +
> +TRecreateDisksInfo = TOr(TListOf(TNonNegativeInt), TListOf(TDiskChanges))
> +
> +
> +def TStorageType(val):
> +  """Builds a function that checks if a given value is a valid storage
> +  type.
> +
> +  """
> +  return (val in constants.STORAGE_TYPES)
> +
> +
> +TTagKind = TElemOf(constants.VALID_TAG_TYPES)
> +TDdmSimple = TElemOf(constants.DDMS_VALUES)
> +TVerifyOptionalChecks = TElemOf(constants.VERIFY_OPTIONAL_CHECKS)
> +
> +
> +@WithDesc("IPv4 network")
> +def _CheckCIDRNetNotation(value):
> +  """Ensure a given CIDR notation type is valid.
> +
> +  """
> +  try:
> +    ipaddr.IPv4Network(value)
> +  except ipaddr.AddressValueError:
> +    return False
> +  return True
> +
> +
> +@WithDesc("IPv4 address")
> +def _CheckCIDRAddrNotation(value):
> +  """Ensure a given CIDR notation type is valid.
> +
> +  """
> +  try:
> +    ipaddr.IPv4Address(value)
> +  except ipaddr.AddressValueError:
> +    return False
> +  return True
> +
> +
> +@WithDesc("IPv6 address")
> +def _CheckCIDR6AddrNotation(value):
> +  """Ensure a given CIDR notation type is valid.
> +
> +  """
> +  try:
> +    ipaddr.IPv6Address(value)
> +  except ipaddr.AddressValueError:
> +    return False
> +  return True
> +
> +
> +@WithDesc("IPv6 network")
> +def _CheckCIDR6NetNotation(value):
> +  """Ensure a given CIDR notation type is valid.
> +
> +  """
> +  try:
> +    ipaddr.IPv6Network(value)
> +  except ipaddr.AddressValueError:
> +    return False
> +  return True
> +
> +
> +TIPv4Address = TAnd(TString, _CheckCIDRAddrNotation)
> +TIPv6Address = TAnd(TString, _CheckCIDR6AddrNotation)
> +TIPv4Network = TAnd(TString, _CheckCIDRNetNotation)
> +TIPv6Network = TAnd(TString, _CheckCIDR6NetNotation)
> +
> +
> +def TObject(val_type):
> +  return TDictOf(TAny, val_type)
> +
> +
> +def TObjectCheck(obj, fields_types):
> +  """Helper to generate type checks for objects.
> +
> +  @param obj: The object to generate type checks
> +  @param fields_types: The fields and their types as a dict
> +  @return: A ht type check function
> +
> +  """
> +  assert set(obj.GetAllSlots()) == set(fields_types.keys()), \
> +    "%s != %s" % (set(obj.GetAllSlots()), set(fields_types.keys()))
> +  return TStrictDict(True, True, fields_types)
> +
> +
> +TQueryFieldDef = \
> +    TObjectCheck(objects.QueryFieldDefinition, {
> +        "name": TNonEmptyString,
> +        "title": TNonEmptyString,
> +        "kind": TElemOf(constants.QFT_ALL),
> +        "doc": TNonEmptyString
> +    })
> +
> +TQueryRow = \
> +    TListOf(TAnd(TIsLength(2),
> +                 TItems([TElemOf(constants.RS_ALL), TAny])))
> +
> +TQueryResult = TListOf(TQueryRow)
> +
> +TQueryResponse = \
> +    TObjectCheck(objects.QueryResponse, {
> +        "fields": TListOf(TQueryFieldDef),
> +        "data": TQueryResult
> +    })
> +
> +TQueryFieldsResponse = \
> +    TObjectCheck(objects.QueryFieldsResponse, {
> +        "fields": TListOf(TQueryFieldDef)
> +    })
> +
> +TJobIdListItem = \
> +    TAnd(TIsLength(2),
> +         TItems([Comment("success")(TBool),
> +                 Comment("Job ID if successful, error message"
> +                         " otherwise")(TOr(TString, TJobId))]))
> +
> +TJobIdList = TListOf(TJobIdListItem)
> +
> +TJobIdListOnly = TStrictDict(True, True, {
> +  constants.JOB_IDS_KEY: Comment("List of submitted jobs")(TJobIdList)
> +  })
> +
> +TInstanceMultiAllocResponse = \
> +    TStrictDict(True, True, {
> +      constants.JOB_IDS_KEY: Comment("List of submitted jobs")(TJobIdList),
> +      ALLOCATABLE_KEY: TListOf(TNonEmptyString),
> +      FAILED_KEY: TListOf(TNonEmptyString)
> +    })

Thanks,

Guido


-- 
Guido Trotter
Ganeti Engineering
Google Germany GmbH
Dienerstr. 12, 80331, München

Registergericht und -nummer: Hamburg, HRB 86891
Sitz der Gesellschaft: Hamburg
Geschäftsführer: Graham Law, Christine Elizabeth Flores
Steuernummer: 48/725/00206
Umsatzsteueridentifikationsnummer: DE813741370

Reply via email to