Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

py/runtime.c: Add support for using __all__ in star import.#17331

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
yoctopuce wants to merge1 commit intomicropython:master
base:master
Choose a base branch
Loading
fromyoctopuce:MICROPY_ENABLE_MODULE_ALL
Open
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletionspy/mpconfig.h
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -603,6 +603,11 @@
#define MICROPY_ENABLE_EXTERNAL_IMPORT (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES)
#endif

// Whether to enable parsing __all__ when importing all public symbols from modules
#ifndef MICROPY_ENABLE_MODULE_IMPORT_ALL
#define MICROPY_ENABLE_MODULE_IMPORT_ALL (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_BASIC_FEATURES)
#endif

// Whether to use the POSIX reader for importing files
#ifndef MICROPY_READER_POSIX
#define MICROPY_READER_POSIX (0)
Expand Down
35 changes: 34 additions & 1 deletionpy/runtime.c
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -1247,6 +1247,19 @@ void mp_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest) {
mp_raise_msg_varg(&mp_type_AttributeError,
MP_ERROR_TEXT("type object '%q' has no attribute '%q'"),
((mp_obj_type_t *)MP_OBJ_TO_PTR(base))->name, attr);
#if MICROPY_ENABLE_MODULE_IMPORT_ALL && MICROPY_ERROR_REPORTING >= MICROPY_ERROR_REPORTING_DETAILED
} else if (mp_obj_is_type(base, &mp_type_module)) {
// report errors in __all__ as done by CPython
mp_obj_t dest_name[2];
qstr module_name = MP_QSTR_;
mp_load_method_maybe(base, MP_QSTR___name__, dest_name);
if (mp_obj_is_qstr(dest_name[0])) {
module_name = mp_obj_str_get_qstr(dest_name[0]);
}
mp_raise_msg_varg(&mp_type_AttributeError,
MP_ERROR_TEXT("module '%q' has no attribute '%q'"),
module_name, attr);
#endif
} else {
mp_raise_msg_varg(&mp_type_AttributeError,
MP_ERROR_TEXT("'%s' object has no attribute '%q'"),
Expand DownExpand Up@@ -1593,8 +1606,28 @@ mp_obj_t mp_import_from(mp_obj_t module, qstr name) {
void mp_import_all(mp_obj_t module) {
DEBUG_printf("import all %p\n", module);

// TODO: Support __all__
mp_map_t *map = &mp_obj_module_get_globals(module)->map;

#if MICROPY_ENABLE_MODULE_IMPORT_ALL
mp_map_elem_t *elem = mp_map_lookup(map, MP_OBJ_NEW_QSTR(MP_QSTR___all__), MP_MAP_LOOKUP);
if (elem != NULL) {
// When __all__ is defined, we must explicitly load all specified
// symbols, possibly invoking the module __getattr__ function
size_t len;
mp_obj_t *items;
mp_obj_get_array(elem->value, &len, &items);
for (size_t i = 0; i < len; i++) {
qstr qname = mp_obj_str_get_qstr(items[i]);
mp_obj_t dest[2];
mp_load_method(module, qname, dest);
mp_store_name(qname, dest[0]);
}
return;
}
#endif

// By default, the set of public names includes all names found in the module's
// namespace which do not begin with an underscore character ('_')
for (size_t i = 0; i < map->alloc; i++) {
if (mp_map_slot_is_filled(map, i)) {
// Entry in module global scope may be generated programmatically
Expand Down
10 changes: 0 additions & 10 deletionstests/cpydiff/core_import_all.py
View file
Open in desktop

This file was deleted.

1 change: 0 additions & 1 deletiontests/cpydiff/modules3/__init__.py
View file
Open in desktop

This file was deleted.

2 changes: 0 additions & 2 deletionstests/cpydiff/modules3/foo.py
View file
Open in desktop

This file was deleted.

59 changes: 59 additions & 0 deletionstests/import/import_star.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
# test `from package import *` conventions, including __all__ support
#
# This test requires MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_BASIC_FEATURES

try:
next(iter([]), 42)
except TypeError:
# 2-argument version of next() not supported
# we are probably not at MICROPY_CONFIG_ROM_LEVEL_BASIC_FEATURES
print('SKIP')
raise SystemExit

# 1. test default visibility
from pkgstar_default import *

print('visibleFun' in globals())
print('VisibleClass' in globals())
print('_hiddenFun' in globals())
print('_HiddenClass' in globals())
print(visibleFun())

# 2. test explicit visibility as defined by __all__ (as an array)
from pkgstar_all_array import *

print('publicFun' in globals())
print('PublicClass' in globals())
print('unlistedFun' in globals())
print('UnlistedClass' in globals())
print('_privateFun' in globals())
print('_PrivateClass' in globals())
print(publicFun())
# test dynamic import as used in asyncio
print('dynamicFun' in globals())
print(dynamicFun())

# 3. test explicit visibility as defined by __all__ (as an tuple)
from pkgstar_all_tuple import *

print('publicFun2' in globals())
print('PublicClass2' in globals())
print('unlistedFun2' in globals())
print('UnlistedClass2' in globals())
print(publicFun2())

# 4. test reporting of missing entries in __all__
try:
from pkgstar_all_miss import *

print("missed detection of incorrect __all__ definition")
except AttributeError as er:
print("AttributeError triggered for bad __all__ definition")

# 5. test reporting of invalid __all__ definition
try:
from pkgstar_all_inval import *

print("missed detection of incorrect __all__ definition")
except TypeError as er:
print("TypeError triggered for bad __all__ definition")
49 changes: 49 additions & 0 deletionstests/import/pkgstar_all_array/__init__.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
__all__ = ['publicFun', 'PublicClass', 'dynamicFun']


# Definitions below should always be imported by a star import
def publicFun():
return 1


class PublicClass:
def __init__(self):
self._val = 1


# If __all__ support is enabled, definitions below
# should not be imported by a star import
def unlistedFun():
return 0


class UnlistedClass:
def __init__(self):
self._val = 0


# Definitions below should be not be imported by a star import
# (they start with an underscore, and are not listed in __all__)
def _privateFun():
return -1


class _PrivateClass:
def __init__(self):
self._val = -1


# Test lazy loaded function, as used by extmod/asyncio:
# Works with a star import only if __all__ support is enabled
_attrs = {
"dynamicFun": "funcs",
}


def __getattr__(attr):
mod = _attrs.get(attr, None)
if mod is None:
raise AttributeError(attr)
value = getattr(__import__(mod, globals(), locals(), True, 1), attr)
globals()[attr] = value
return value
2 changes: 2 additions & 0 deletionstests/import/pkgstar_all_array/funcs.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
def dynamicFun():
return 777
1 change: 1 addition & 0 deletionstests/import/pkgstar_all_inval/__init__.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
__all__ = 42
8 changes: 8 additions & 0 deletionstests/import/pkgstar_all_miss/__init__.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
__all__ = ('existingFun', 'missingFun')


def existingFun():
return None


# missingFun is not defined, should raise an error on import
22 changes: 22 additions & 0 deletionstests/import/pkgstar_all_tuple/__init__.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
__all__ = ('publicFun2', 'PublicClass2')


# Definitions below should always be imported by a star import
def publicFun2():
return 2


class PublicClass2:
def __init__(self):
self._val = 2


# If __all__ support is enabled, definitions below
# should not be imported by a star import
def unlistedFun2():
return 0


class UnlistedClass2:
def __init__(self):
self._val = 0
20 changes: 20 additions & 0 deletionstests/import/pkgstar_default/__init__.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
# When __all__ is undefined, star import should only
# show objects that do not start with an underscore


def visibleFun():
return 42


class VisibleClass:
def __init__(self):
self._val = 42


def _hiddenFun():
return -1


class _HiddenClass:
def __init__(self):
self._val = -1
Loading

[8]ページ先頭

©2009-2025 Movatter.jp