| 
29 | 29 | 
 
  | 
30 | 30 | def missing_exports(internal_obj, wrapped_obj) -> None:  | 
31 | 31 |     """  | 
 | 32 | +    Identify if any of the rust exposted structs or functions do not have wrappers.  | 
 | 33 | +
  | 
32 | 34 |     Special handling for:  | 
33 | 35 |     - Raw* classes: Internal implementation details that shouldn't be exposed  | 
34 | 36 |     - _global_ctx: Internal implementation detail  | 
35 | 37 |     - __self__, __class__: Python special attributes  | 
36 | 38 |     """  | 
37 |  | -    # Special case enums - just make sure they exist since dir()  | 
38 |  | -    # and other functions get overridden.  | 
 | 39 | +    # Special case enums - EnumType overrides a some of the internal functions,  | 
 | 40 | +    # so check all of the values exist and move on  | 
39 | 41 |     if isinstance(wrapped_obj, EnumType):  | 
 | 42 | +        expected_values = [v for v in dir(internal_obj) if not v.startswith("__")]  | 
 | 43 | +        for value in expected_values:  | 
 | 44 | +            assert value in dir(wrapped_obj)  | 
40 | 45 |         return  | 
41 | 46 | 
 
  | 
42 |  | -    # iterate through all the classes in datafusion._internal  | 
43 |  | -    for attr in dir(internal_obj):  | 
 | 47 | +    for internal_attr_name in dir(internal_obj):  | 
44 | 48 |         # Skip internal implementation details that shouldn't be exposed in public API  | 
45 |  | -        if attr in ["_global_ctx"] or attr.startswith("Raw"):  | 
 | 49 | +        if internal_attr_name in ["_global_ctx"]:  | 
46 | 50 |             continue  | 
47 | 51 | 
 
  | 
48 |  | -        assert attr in dir(wrapped_obj)  | 
 | 52 | +        wrapped_attr_name = (  | 
 | 53 | +            internal_attr_name[3:]  | 
 | 54 | +            if internal_attr_name.startswith("Raw")  | 
 | 55 | +            else internal_attr_name  | 
 | 56 | +        )  | 
 | 57 | +        assert wrapped_attr_name in dir(wrapped_obj)  | 
49 | 58 | 
 
  | 
50 |  | -        internal_attr = getattr(internal_obj, attr)  | 
51 |  | -        wrapped_attr = getattr(wrapped_obj, attr)  | 
 | 59 | +        internal_attr = getattr(internal_obj, internal_attr_name)  | 
 | 60 | +        wrapped_attr = getattr(wrapped_obj, wrapped_attr_name)  | 
52 | 61 | 
 
  | 
 | 62 | +        # There are some auto generated attributes that can be None, such as  | 
 | 63 | +        # __kwdefaults__ and __doc__. As long as these are None on the internal  | 
 | 64 | +        # object, it's okay to skip them. However if they do exist on the internal  | 
 | 65 | +        # object they must also exist on the wrapped object.  | 
53 | 66 |         if internal_attr is not None:  | 
54 | 67 |             if wrapped_attr is None:  | 
55 |  | -                print("Missing attribute: ", attr)  | 
 | 68 | +                print("Missing attribute: ", internal_attr_name)  | 
56 | 69 |                 assert False  | 
57 | 70 | 
 
  | 
58 |  | -        if attr in ["__self__", "__class__"]:  | 
 | 71 | +        if internal_attr_name in ["__self__", "__class__"]:  | 
59 | 72 |             continue  | 
60 | 73 | 
 
  | 
61 |  | -        # check if the class found in the internal module has a  | 
62 |  | -        # wrapper exposed in the public module, datafusion  | 
63 | 74 |         if isinstance(internal_attr, list):  | 
64 | 75 |             assert isinstance(wrapped_attr, list)  | 
 | 76 | + | 
 | 77 | +            # We have cases like __all__ that are a list and we want to be certain that  | 
 | 78 | +            # every value in the list in the internal object is also in the wrapper list  | 
65 | 79 |             for val in internal_attr:  | 
66 |  | -                # Skip Raw* classes as they are internal  | 
67 | 80 |                 if isinstance(val, str) and val.startswith("Raw"):  | 
68 |  | -                    print("Skipping Raw* class: ", val)  | 
69 |  | -                    continue  | 
70 |  | - | 
71 |  | -                assert val in wrapped_attr  | 
 | 81 | +                    assert val[3:] in wrapped_attr  | 
 | 82 | +                else:  | 
 | 83 | +                    assert val in wrapped_attr  | 
72 | 84 |         elif hasattr(internal_attr, "__dict__"):  | 
 | 85 | +            # Check all submodules recursively  | 
73 | 86 |             missing_exports(internal_attr, wrapped_attr)  | 
74 | 87 | 
 
  | 
75 | 88 | 
 
  | 
 | 
0 commit comments