def _ensure_proper_types(struct, encoding, force_types):
if force_types is None:<EOL><INDENT>return struct<EOL><DEDENT>res = None<EOL>if isinstance(struct, (dict, collections.OrderedDict)):<EOL><INDENT>res = type(struct)()<EOL>for k, v in struct.items():<EOL><INDENT>res[_ensure_proper_types(k, encoding, force_types)] =_ensure_proper_types(v, encoding, force_types)<EOL><DEDENT><DEDENT>elif isinstance(struct, list):<EOL><INDENT>res = []<EOL>for i in struct:<EOL><INDENT>res.append(_ensure_proper_types(i, encoding, force_types))<EOL><DEDENT><DEDENT>elif isinstance(struct, six.binary_type):<EOL><INDENT>res = struct.decode(encoding)<EOL><DEDENT>elif isinstance(struct, (six.text_type, type(None), type(True), six.integer_types, float)):<EOL><INDENT>res = struct<EOL><DEDENT>elif isinstance(struct, datetime.datetime):<EOL><INDENT>res = struct<EOL><DEDENT>else:<EOL><INDENT>raise AnyMarkupError('<STR_LIT>'.<EOL>format(type(struct)))<EOL><DEDENT>if force_types and isinstance(res, six.text_type):<EOL><INDENT>res = _recognize_basic_types(res)<EOL><DEDENT>elif not (force_types or<EOL>isinstance(res, (dict, collections.OrderedDict, list, six.text_type))):<EOL><INDENT>res = six.text_type(res)<EOL><DEDENT>return res<EOL>
A convenience function that recursively makes sure the given structure
    contains proper types according to value of `force_types`.

    Args:
        struct: a structure to check and fix
        encoding: encoding to use on found bytestrings
        force_types:
            if `True`, integers, floats, booleans and none/null
                are recognized and returned as proper types instead of strings;
            if `False`, everything is converted to strings
            if `None`, unmodified `struct` is returned
    Returns:
        a fully decoded copy of given structure