Revision 8620f50e

b/lib/ht.py
25 25

  
26 26
from ganeti import compat
27 27
from ganeti import utils
28
from ganeti import constants
28 29

  
29 30

  
30 31
_PAREN_RE = re.compile("^[a-zA-Z0-9_-]+$")
......
118 119

  
119 120

  
120 121
# Some basic types
122
@WithDesc("Anything")
123
def TAny(_):
124
  """Accepts any value.
125

  
126
  """
127
  return True
128

  
129

  
121 130
@WithDesc("NotNone")
122 131
def TNotNone(val):
123 132
  """Checks if the given value is not None.
......
245 254
                  (Parens(fn), Parens(test)))(lambda val: test(fn(val)))
246 255

  
247 256

  
257
def TRegex(pobj):
258
  """Checks whether a string matches a specific regular expression.
259

  
260
  @param pobj: Compiled regular expression as returned by C{re.compile}
261

  
262
  """
263
  desc = WithDesc("String matching regex \"%s\"" %
264
                  pobj.pattern.encode("string_escape"))
265

  
266
  return desc(TAnd(TString, pobj.match))
267

  
268

  
248 269
# Type aliases
249 270

  
250 271
#: a non-empty string
......
271 292
TPositiveFloat = \
272 293
  TAnd(TFloat, WithDesc("EqualGreaterZero")(lambda v: v >= 0.0))
273 294

  
295
#: Job ID
296
TJobId = TOr(TPositiveInt,
297
             TRegex(re.compile("^%s$" % constants.JOB_ID_TEMPLATE)))
298

  
274 299

  
275 300
def TListOf(my_type):
276 301
  """Checks if a given value is a list with all elements of the same type.
......
340 365
  return desc(TAnd(TDict,
341 366
                   compat.partial(_TStrictDictCheck, require_all, exclusive,
342 367
                                  items)))
368

  
369

  
370
def TItems(items):
371
  """Checks individual items of a container.
372

  
373
  If the verified value and the list of expected items differ in length, this
374
  check considers only as many items as are contained in the shorter list. Use
375
  L{TIsLength} to enforce a certain length.
376

  
377
  @type items: list
378
  @param items: List of checks
379

  
380
  """
381
  assert items, "Need items"
382

  
383
  text = ["Item", "item"]
384
  desc = WithDesc(utils.CommaJoin("%s %s is %s" %
385
                                  (text[int(idx > 0)], idx, Parens(check))
386
                                  for (idx, check) in enumerate(items)))
387

  
388
  return desc(lambda value: compat.all(check(i)
389
                                       for (check, i) in zip(items, value)))
b/test/ganeti.ht_unittest.py
230 230
    self.assertTrue(fn({"other": 11}))
231 231
    self.assertTrue(fn({"other": object()}))
232 232

  
233
  def testJobId(self):
234
    for i in [0, 1, 4395, 2347625220]:
235
      self.assertTrue(ht.TJobId(i))
236
      self.assertTrue(ht.TJobId(str(i)))
237
      self.assertFalse(ht.TJobId(-(i + 1)))
238

  
239
    for i in ["", "-", ".", ",", "a", "99j", "job-123", "\t", " 83 ",
240
              None, [], {}, object()]:
241
      self.assertFalse(ht.TJobId(i))
242

  
243
  def testItems(self):
244
    self.assertRaises(AssertionError, ht.TItems, [])
245

  
246
    fn = ht.TItems([ht.TString])
247
    self.assertFalse(fn([0]))
248
    self.assertFalse(fn([None]))
249
    self.assertTrue(fn(["Hello"]))
250
    self.assertTrue(fn(["Hello", "World"]))
251
    self.assertTrue(fn(["Hello", 0, 1, 2, "anything"]))
252

  
253
    fn = ht.TItems([ht.TAny, ht.TInt, ht.TAny])
254
    self.assertTrue(fn(["Hello", 0, []]))
255
    self.assertTrue(fn(["Hello", 893782]))
256
    self.assertTrue(fn([{}, -938210858947, None]))
257
    self.assertFalse(fn(["Hello", []]))
258

  
233 259

  
234 260
if __name__ == "__main__":
235 261
  testutils.GanetiTestProgram()

Also available in: Unified diff