@@ -1687,11 +1687,89 @@ mp_obj_t __attribute__((noinline, )) mp_import_from(mp_obj_t module, qstr name)
16871687 #endif
16881688}
16891689
1690+ #define IMPORT_ALL_DEBUGGING 0
1691+
1692+ #if IMPORT_ALL_DEBUGGING
1693+
1694+ #define IMPORT_ALL_DEBUG_PRINT_OBJECT (object ) mp_obj_print(object, PRINT_REPR);
1695+ #define IMPORT_ALL_DEBUG_PRINTF (fmt , ...) mp_printf(MP_PYTHON_PRINTER, fmt,##__VA_ARGS__)
1696+
1697+ #else
1698+
1699+ #define IMPORT_ALL_DEBUG_PRINT_OBJECT (object ) ;
1700+ #define IMPORT_ALL_DEBUG_PRINTF (fmt , ...) ;
1701+
1702+ #endif
1703+
16901704void mp_import_all (mp_obj_t module ) {
16911705 DEBUG_printf ("import all %p\n" , module );
16921706
1693- // TODO: Support __all__
16941707 mp_map_t * map = & mp_obj_module_get_globals (module )-> map ;
1708+
1709+ // check for __all__
1710+ mp_obj_t all_str = MP_OBJ_NEW_QSTR (MP_QSTR___all__ );
1711+ IMPORT_ALL_DEBUG_PRINTF ("allstr = %s\n" , mp_obj_str_get_str (all_str ));
1712+
1713+ qstr module_qname = MP_QSTR_empty ;
1714+ if (IMPORT_ALL_DEBUGGING ) {
1715+ mp_map_elem_t * elem = mp_map_lookup (map , MP_OBJ_NEW_QSTR (MP_QSTR___name__ ), MP_MAP_LOOKUP );
1716+ if (elem != NULL ) {
1717+ module_qname = mp_obj_str_get_qstr (elem -> value );
1718+ }
1719+ }
1720+
1721+ mp_map_elem_t * all_elem = mp_map_lookup (map , all_str , MP_MAP_LOOKUP );
1722+ if (all_elem != 0 && all_elem -> value != MP_OBJ_NULL ) {
1723+ // we have __all__ defined, so we only import those symbols
1724+
1725+ mp_obj_t all_obj = all_elem -> value ;
1726+ IMPORT_ALL_DEBUG_PRINTF ("processing import %q with __all__ * allstr = " , module_qname );
1727+ IMPORT_ALL_DEBUG_PRINT_OBJECT (all_obj );
1728+ IMPORT_ALL_DEBUG_PRINTF ("\n" );
1729+
1730+ // TODO: How should errors be handled?
1731+ // Maybe we should also check in the import logic, not
1732+ // just here? Otherwise we end up with a module that works fine
1733+ // with `import Module` but fails with `from Module import *`.
1734+ // And since ``from Module import *` actually imports the module
1735+ // _before_ calling mp_import_all, you can't simply fix the file
1736+ // and try again (assuming `supervisor.autoreload` is disabled).
1737+ // OTOH, CPython appears to behave them same way, so...
1738+ //
1739+ // would be nice to add the module name to the error message
1740+ #define IMPORT_ALL_KEY_FAILED (errType , message ) \
1741+ IMPORT_ALL_DEBUG_PRINTF("CANT_IMPORT_KEY: %s\n", \
1742+ mp_obj_str_get_str(all_key)); \
1743+ /* continue; */ \
1744+ mp_raise_msg_varg (& mp_type_ ##errType ##Error , \
1745+ MP_ERROR_TEXT ("%S '%s' in module %q" ), \
1746+ MP_ERROR_TEXT (message ), \
1747+ mp_obj_str_get_str (all_key ), \
1748+ module_qname \
1749+ ); \
1750+
1751+ mp_int_t all_len = mp_obj_get_int (mp_obj_len (all_obj ));
1752+ for (mp_int_t j = 0 ; j < all_len ; j ++ ) {
1753+ // get each key from __all__
1754+ mp_obj_t all_key = mp_obj_subscr (all_obj , MP_OBJ_NEW_SMALL_INT (j ), MP_OBJ_SENTINEL );
1755+ if (!mp_obj_is_str (all_key )) {
1756+ IMPORT_ALL_KEY_FAILED (Type , "__all__ item must be str" );
1757+ }
1758+ IMPORT_ALL_DEBUG_PRINTF (" symbol: %s\n" , mp_obj_str_get_str (all_key ));
1759+
1760+ // find the matching instance in the module
1761+ mp_map_elem_t * all_value = mp_map_lookup (map , all_key , MP_MAP_LOOKUP );
1762+ if (all_value == NULL ) {
1763+ IMPORT_ALL_KEY_FAILED (Attribute , "missing __all__ attribute" );
1764+ }
1765+ qstr qname = mp_obj_str_get_qstr (all_key );
1766+ mp_store_name (qname , all_value -> value );
1767+ }
1768+ return ;
1769+ }
1770+
1771+ // no __all__ defined, so we import everything
1772+ IMPORT_ALL_DEBUG_PRINTF ("processing from %q import * without __all__" , module_qname );
16951773 for (size_t i = 0 ; i < map -> alloc ; i ++ ) {
16961774 if (mp_map_slot_is_filled (map , i )) {
16971775 // Entry in module global scope may be generated programmatically
0 commit comments