wip: still banging against weirdness w/ bson regexps

This commit is contained in:
Mike Dirolf 2009-01-07 19:52:58 -05:00
parent 3e6d3f3cbe
commit 6efb96a893
2 changed files with 55 additions and 3 deletions

38
bson.py
View File

@ -195,6 +195,24 @@ def _get_date(data):
def _get_null(data):
return (None, data)
_re_stack = []
def _get_regex(data):
(pattern, data) = _get_c_string(data)
print "out %r" % pattern
(bson_flags, data) = _get_c_string(data)
flags = 0
if bson_flags.find("i") > -1:
flags |= re.IGNORECASE
if bson_flags.find("m") > -1:
flags |= re.MULTILINE
print "out %r" % flags
res = re.compile(pattern, flags)
other = _re_stack.pop(0)
assert res.pattern == other.pattern, "%r %r" % (res.pattern, other.pattern)
assert res == other, "%r %r" % (res.pattern, other.pattern)
return (re.compile(pattern, flags), data)
_element_getter = {
"\x01": _get_number,
"\x02": _get_string,
@ -206,7 +224,7 @@ _element_getter = {
"\x08": _get_boolean,
"\x09": _get_date,
"\x0A": _get_null,
# "\x0B": _get_regex,
"\x0B": _get_regex,
# "\x0C": _get_ref,
# "\x0D": _get_code,
# "\x0E": _get_symbol,
@ -238,6 +256,7 @@ def _int_to_bson(int):
def _int_64_to_bson(int):
return struct.pack("<q", int)
_RE_TYPE = type(_valid_array_name)
def _value_to_bson(value):
if isinstance(value, types.FloatType):
return ("\x01", struct.pack("<d", value))
@ -261,9 +280,20 @@ def _value_to_bson(value):
return ("\x09", _int_64_to_bson(millis))
if isinstance(value, types.NoneType):
return ("\x0A", "")
if isinstance(value, _RE_TYPE):
_re_stack.append(value)
pattern = value.pattern
print "in %r" % pattern
print "in %r" % value.flags
flags = "g" # TODO should it be global by default?
if value.flags & re.IGNORECASE:
flags += "i"
if value.flags & re.MULTILINE:
flags += "m"
return ("\x0B", _make_c_string(pattern) + _make_c_string(flags))
if isinstance(value, types.IntType):
return ("\x10", _int_to_bson(value))
raise InvalidDocument("cannot convert value of type %s to bson" % value.__class__)
raise InvalidDocument("cannot convert value of type %s to bson" % type(value))
def _element_to_bson(key, value):
if not isinstance(key, types.StringTypes):
@ -388,6 +418,8 @@ class TestBSON(unittest.TestCase):
"\x0B\x00\x00\x00\x0A\x74\x65\x73\x74\x00\x00")
self.assertEqual(BSON.from_dict({"date": datetime.datetime(2007, 1, 7, 19, 30, 11)}),
"\x13\x00\x00\x00\x09\x64\x61\x74\x65\x00\x38\xBE\x1C\xFF\x0F\x01\x00\x00\x00")
# self.assertEqual(BSON.from_dict({"regex": re.compile("a*b", re.IGNORECASE)}),
# "\x13\x00\x00\x00\x0B\x72\x65\x67\x65\x78\x00\x61\x2A\x62\x00\x67\x69\x00\x00")
def test_from_then_to_dict(self):
def helper(dict):
@ -401,6 +433,8 @@ class TestBSON(unittest.TestCase):
helper({"an array": [1, True, 3.8, u"world"]})
helper({"an object": {"test": u"something"}})
# helper({"re": re.compile(u"", re.MULTILINE)})
def from_then_to_dict(dict):
return dict == (BSON.from_dict(dict)).to_dict()

View File

@ -2,6 +2,7 @@ import random
import sys
import traceback
import datetime
import re
gen_target = 100
examples = 5
@ -9,6 +10,9 @@ examples = 5
def lift(value):
return lambda: value
def choose_lifted(list):
return lambda: random.choice(list)
def choose(list):
return lambda: random.choice(list)()
@ -30,7 +34,7 @@ def gen_printable_char():
def gen_printable_string(gen_length):
return lambda: "".join(gen_list(gen_printable_char(), gen_length)())
def gen_char():
def gen_char(set=None):
return lambda: chr(random.randint(0, 255))
def gen_string(gen_length):
@ -63,6 +67,17 @@ def gen_dict(gen_key, gen_value, gen_length):
return result
return lambda: a_dict(gen_key, gen_value, gen_length())
def gen_regexp(gen_length):
pattern = lambda: u"".join(gen_list(choose_lifted(u"abc."), gen_length)())
def gen_flags():
flags = 0
if random.random() > 0.5:
flags = flags | re.IGNORECASE
if random.random() > 0.5:
flags = flags | re.MULTILINE
return flags
return lambda: re.compile(pattern(), gen_flags())
def gen_mongo_value(depth):
choices = [gen_unicode(gen_range(0, 50)),
gen_string(gen_range(0, 1000)),
@ -70,6 +85,7 @@ def gen_mongo_value(depth):
gen_float(),
gen_boolean(),
gen_datetime(),
gen_regexp(gen_range(0, 20)),
lift(None),]
if depth > 0:
choices.append(gen_mongo_list(depth))
@ -93,8 +109,10 @@ def check(predicate, generator):
case = generator()
try:
if not predicate(case):
print "FAIL"
counter_examples.append(repr(case))
except:
print "FAIL"
counter_examples.append("%r : %s" % (case, traceback.format_exc()))
return counter_examples