def _element_to_bson(key, value, check_keys, opts): """Encode a single key, value pair.""" if not isinstance(key, string_type): raise InvalidDocument("documents must have only string keys, " "key was %r" % (key, )) if check_keys: if key.startswith("$"): raise InvalidDocument("key %r must not start with '$'" % (key, )) if "." in key: raise InvalidDocument("key %r must not contain '.'" % (key, )) name = _make_name(key) return _name_value_to_bson(name, value, check_keys, opts)
def _make_name(string): """Make a 'C' string suitable for a BSON key.""" # Keys can only be text in python 3. if "\x00" in string: raise InvalidDocument("BSON keys / regex patterns must not " "contain a NUL character") return _utf_8_encode(string)[0] + b"\x00"
def _name_value_to_bson(name, value, check_keys, opts): """Encode a single name, value pair.""" # First see if the type is already cached. KeyError will only ever # happen once per subtype. try: return _ENCODERS[type(value)](name, value, check_keys, opts) except KeyError: pass # Second, fall back to trying _type_marker. This has to be done # before the loop below since users could subclass one of our # custom types that subclasses a python built-in (e.g. Binary) marker = getattr(value, "_type_marker", None) if isinstance(marker, int) and marker in _MARKERS: func = _MARKERS[marker] # Cache this type for faster subsequent lookup. _ENCODERS[type(value)] = func return func(name, value, check_keys, opts) # If all else fails test each base type. This will only happen once for # a subtype of a supported base type. for base in _ENCODERS: if isinstance(value, base): func = _ENCODERS[base] # Cache this type for faster subsequent lookup. _ENCODERS[type(value)] = func return func(name, value, check_keys, opts) raise InvalidDocument("cannot convert value of type %s to bson" % type(value))
def _make_c_string_check(string): """Make a 'C' string, checking for embedded NUL characters.""" if isinstance(string, bytes): if b"\x00" in string: raise InvalidDocument("BSON keys / regex patterns must not " "contain a NUL character") try: _utf_8_decode(string, None, True) return string + b"\x00" except UnicodeError: raise InvalidStringData("strings in documents must be valid " "UTF-8: %r" % string) else: if "\x00" in string: raise InvalidDocument("BSON keys / regex patterns must not " "contain a NUL character") return _utf_8_encode(string)[0] + b"\x00"