Extensions: quiet warnings from pylint

Some warnings remain which need further investigation.
This commit is contained in:
Campbell Barton
2024-06-14 15:12:19 +10:00
parent 7952f35292
commit 2dd339bff3
12 changed files with 143 additions and 110 deletions

View File

@@ -74,7 +74,8 @@ watch_check_ruff:
check_pylint:
@cd "$(BASE_DIR)" && \
pylint $(PY_FILES) \
--disable=C0111,C0301,C0302,C0103,C0415,R1702,R1705,R0902,R0903,R0913,E0611,E0401,I1101,R0801,C0209,W0511,W0718,W0719,C0413,R0911,R0912,R0914,R0915
--disable=C0103,C0111,C0201,C0301,C0302,C0415,R1702,R1705,R0902,R0903,R0913,E0611,E0401,I1101,R0801,C0209,W0511,W0718,W0719,C0413,R0911,R0912,R0914,R0915 \
--msg-template='{abspath}:{line}:{column}: {msg_id}: {msg} ({symbol})'
watch_check_pylint:
@cd "$(BASE_DIR)" && \
while true; do \

View File

@@ -16,6 +16,30 @@ bl_info = {
}
if "bpy" in locals():
# This doesn't need to be inline because sub-modules aren't important into the global name-space.
# The check for `bpy` ensures this is always assigned before use.
# pylint: disable-next=used-before-assignment
_local_module_reload()
import bpy
from bpy.props import (
BoolProperty,
EnumProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bpy.types import (
AddonPreferences,
)
# -----------------------------------------------------------------------------
# Local Module Reload
def _local_module_reload():
import importlib
from . import (
bl_extension_cli,
@@ -31,29 +55,6 @@ if "bpy" in locals():
importlib.reload(bl_extension_ops)
importlib.reload(bl_extension_ui)
importlib.reload(bl_extension_utils)
del (
bl_extension_cli,
bl_extension_local,
bl_extension_notify,
bl_extension_ops,
bl_extension_ui,
bl_extension_utils,
)
del importlib
import bpy
from bpy.props import (
BoolProperty,
EnumProperty,
IntProperty,
PointerProperty,
StringProperty,
)
from bpy.types import (
AddonPreferences,
)
class BlExtPreferences(AddonPreferences):
@@ -144,6 +145,7 @@ def repo_stats_calc_outdated_for_repo_directory(repo_directory):
if pkg_manifest_local is None:
return 0
# pylint: disable-next=using-constant-test
if False:
# TODO: support this, currently creating this data involves a conversion which isn't free.
# This can probably be done once and cached, but for now use another function that provides this.
@@ -384,6 +386,7 @@ def monkeypatch_extenions_repos_update_pre_impl():
def monkeypatch_extenions_repos_update_post_impl():
import os
# pylint: disable-next=redefined-outer-name
from . import bl_extension_ops
repo_cache_store = repo_cache_store_ensure()
@@ -463,8 +466,7 @@ def monkeypatch_install():
def monkeypatch_uninstall():
handlers = bpy.app.handlers._extension_repos_update_pre
fn_override = monkeypatch_extensions_repos_update_pre
for i in range(len(handlers)):
fn = handlers[i]
for i, fn in enumerate(handlers):
if fn is fn_override:
handlers[i] = fn_override._fn_orig
del fn_override._fn_orig
@@ -472,8 +474,7 @@ def monkeypatch_uninstall():
handlers = bpy.app.handlers._extension_repos_update_post
fn_override = monkeypatch_extenions_repos_update_post
for i in range(len(handlers)):
fn = handlers[i]
for i, fn in enumerate(handlers):
if fn is fn_override:
handlers[i] = fn_override._fn_orig
del fn_override._fn_orig

View File

@@ -16,8 +16,6 @@ import argparse
import os
import sys
from .bl_extension_utils import PkgManifest_Normalized
from typing import (
Any,
List,
@@ -26,6 +24,8 @@ from typing import (
Union,
)
from .bl_extension_utils import PkgManifest_Normalized
show_color = (
False if os.environ.get("NO_COLOR") else
sys.stdout.isatty()

View File

@@ -11,10 +11,10 @@ __all__ = (
"update_ui_text",
)
import os
import bpy
import sys
import os
import bpy
from bpy.app.translations import pgettext_rpt as rpt_

View File

@@ -370,7 +370,7 @@ def _preferences_ensure_disabled(*, repo_item, pkg_id_sequence, default_set):
# Needed for `startswith` check.
prefix_addon_modules = {prefix_base + pkg_id for pkg_id in modules_clear}
# Needed for `startswith` check (sub-modules).
prefix_addon_modules_base = tuple([module + "." for module in prefix_addon_modules])
prefix_addon_modules_base = tuple(module + "." for module in prefix_addon_modules)
# NOTE(@ideasman42): clearing the modules is not great practice,
# however we need to ensure this is fully un-loaded then reloaded.
@@ -657,6 +657,7 @@ def _extensions_wheel_filter_for_platform(wheels):
wheel_filename_split = wheel_filename[:-4].split("-")
# Skipping, should never happen as validation will fail,
# keep paranoid check although this might be removed in the future.
# pylint: disable-next=superfluous-parens
if not (5 <= len(wheel_filename_split) <= 6):
print("Error: wheel doesn't follow naming spec \"{:s}\"".format(wheel_filename))
continue
@@ -840,7 +841,7 @@ class CommandHandle:
handle.wm.modal_handler_add(op)
op._runtime_handle = handle
op.runtime_handle_set(handle)
return {'RUNNING_MODAL'}
def op_modal_step(self, op, context):
@@ -880,7 +881,7 @@ class CommandHandle:
if command_result.all_complete:
self.wm.event_timer_remove(self.modal_timer)
del op._runtime_handle
op.runtime_handle_clear()
context.workspace.status_text_set(None)
repo_status_text.running = False
@@ -1040,6 +1041,14 @@ class _ExtCmdMixIn:
self._runtime_handle.op_modal_cancel(self, context)
self.exec_command_finish(canceled)
def runtime_handle_set(self, runtime_handle):
assert isinstance(runtime_handle, CommandHandle)
# pylint: disable-next=attribute-defined-outside-init
self._runtime_handle = runtime_handle
def runtime_handle_clear(self):
del self._runtime_handle
class EXTENSIONS_OT_dummy_progress(Operator, _ExtCmdMixIn):
bl_idname = "extensions.dummy_progress"
@@ -1244,7 +1253,7 @@ class EXTENSIONS_OT_repo_refresh_all(Operator):
def _exceptions_as_report(self, repo_name, ex):
self.report({'WARNING'}, "{:s}: {:s}".format(repo_name, str(ex)))
def execute(self, context):
def execute(self, _context):
import addon_utils
repos_all = extension_repos_read()
@@ -1292,12 +1301,12 @@ class EXTENSIONS_OT_repo_add_from_drop(Operator):
return {'RUNNING_MODAL'}
def execute(self, context):
def execute(self, _context):
# Open an "Add Remote Repository" popup with the URL pre-filled.
bpy.ops.preferences.extension_repo_add('INVOKE_DEFAULT', type='REMOTE', remote_url=self.url)
return {'CANCELLED'}
def draw(self, context):
def draw(self, _context):
url = self.url
# Skip the URL prefix scheme, e.g. `https://` for less "noisy" outpout.
url_split = url.partition("://")
@@ -2045,7 +2054,7 @@ class EXTENSIONS_OT_package_install_files(Operator, _ExtCmdMixIn):
layout = self.layout
layout.operator_context = 'EXEC_DEFAULT'
pkg_id, pkg_type = self._drop_variables
_pkg_id, pkg_type = self._drop_variables
layout.label(text="Local Repository")
layout.prop(self, "repo", text="")
@@ -2720,7 +2729,7 @@ class EXTENSIONS_OT_userpref_show_online(Operator):
return False
return True
def execute(self, context):
def execute(self, _context):
bpy.ops.screen.userpref_show('INVOKE_DEFAULT', section='SYSTEM')
return {'FINISHED'}
@@ -2733,7 +2742,7 @@ class EXTENSIONS_OT_userpref_allow_online(Operator):
bl_options = {'INTERNAL'}
@classmethod
def poll(cls, context):
def poll(cls, _context):
if bpy.app.online_access_override:
if not bpy.app.online_access:
cls.poll_message_set("Blender was launched in offline-mode which cannot be changed at runtime")
@@ -2754,11 +2763,11 @@ class EXTENSIONS_OT_userpref_allow_online_popup(Operator):
bl_label = ""
bl_options = {'INTERNAL'}
def execute(self, context):
def execute(self, _context):
bpy.ops.screen.userpref_show('INVOKE_DEFAULT', section='SYSTEM')
return {'FINISHED'}
def invoke(self, context, event):
def invoke(self, context, _event):
wm = context.window_manager
if bpy.app.online_access_override:
# No Cancel/Confirm buttons.
@@ -2775,7 +2784,7 @@ class EXTENSIONS_OT_userpref_allow_online_popup(Operator):
)
return {'RUNNING_MODAL'}
def draw(self, context):
def draw(self, _context):
layout = self.layout
col = layout.column()
if bpy.app.online_access_override:
@@ -2800,11 +2809,11 @@ class EXTENSIONS_OT_package_enable_not_installed(Operator):
bl_label = "Enable Extension"
@classmethod
def poll(cls, context):
def poll(cls, _context):
cls.poll_message_set("Extension needs to be installed before it can be enabled")
return False
def execute(self, context):
def execute(self, _context):
# This operator only exists to be able to show disabled check-boxes for extensions
# while giving users a reasonable explanation on why is that.
return {'CANCELLED'}

View File

@@ -375,13 +375,14 @@ extensions_map_from_legacy_addons_url = None
# NOTE: this can be removed once upgrading from 4.1 is no longer relevant.
def extensions_map_from_legacy_addons_ensure():
import os
global extensions_map_from_legacy_addons
global extensions_map_from_legacy_addons_url
# pylint: disable-next=global-statement
global extensions_map_from_legacy_addons, extensions_map_from_legacy_addons_url
if extensions_map_from_legacy_addons is not None:
return
filepath = os.path.join(os.path.dirname(__file__), "extensions_map_from_legacy_addons.py")
with open(filepath, "rb") as fh:
# pylint: disable-next=eval-used
data = eval(compile(fh.read(), filepath, "eval"), {})
extensions_map_from_legacy_addons = data["extensions"]
extensions_map_from_legacy_addons_url = data["remote_url"]
@@ -610,7 +611,7 @@ def extensions_panel_draw_impl(
local_ex = None
continue
has_remote = (repos_all[repo_index].remote_url != "")
has_remote = repos_all[repo_index].remote_url != ""
if pkg_manifest_remote is None:
if has_remote:
# NOTE: it would be nice to detect when the repository ran sync and it failed.
@@ -658,12 +659,14 @@ def extensions_panel_draw_impl(
if is_installed:
# Currently we only need to know the module name once installed.
addon_module_name = "bl_ext.{:s}.{:s}".format(repos_all[repo_index].module, pkg_id)
# pylint: disable-next=possibly-used-before-assignment
is_enabled = addon_module_name in used_addon_module_name_map
else:
is_enabled = False
addon_module_name = None
elif is_theme:
# pylint: disable-next=possibly-used-before-assignment
is_enabled = (repo_index, pkg_id) == active_theme_info
addon_module_name = None
else:
@@ -868,6 +871,7 @@ def extensions_panel_draw_impl(
extension_tags=extension_tags,
enabled_only=enabled_only,
used_addon_module_name_map=used_addon_module_name_map,
# pylint: disable-next=possibly-used-before-assignment
addon_modules=addon_modules,
)
@@ -939,7 +943,7 @@ class USERPREF_PT_extensions_filter(Panel):
col = layout.column(heading="Show")
col.use_property_split = True
sub = col.column()
sub.active = (not wm.extension_updates_only)
sub.active = not wm.extension_updates_only
sub.prop(wm, "extension_show_legacy_addons", text="Legacy Add-ons")

View File

@@ -360,8 +360,8 @@ def repo_index_outdated(directory: str) -> bool:
def platform_from_this_system() -> str:
from .cli.blender_ext import platform_from_this_system
result = platform_from_this_system()
from .cli.blender_ext import platform_from_this_system as platform_from_this_system_impl
result = platform_from_this_system_impl()
assert isinstance(result, str)
return result
@@ -642,7 +642,7 @@ def pkg_make_obsolete_for_testing(local_dir: str, pkg_id: str) -> None:
with open(filepath, "r", encoding="utf-8") as fh:
data = fh.read()
def key_replace(match: re.Match[str]) -> str:
def key_replace(_match: re.Match[str]) -> str:
return "version = \"0.0.0\""
data = re.sub(r"^\s*version\s*=\s*\"[^\"]+\"", key_replace, data, flags=re.MULTILINE)
@@ -803,7 +803,7 @@ class CommandBatch:
request_exit: Optional[bool] = None
while True:
try:
# Request `request_exit` starts of as None, then it's a boolean.
# Request `request_exit` starts off as None, then it's a boolean.
json_messages = cmd.fn_iter.send(request_exit) # type: ignore
except StopIteration:
break
@@ -910,7 +910,7 @@ class CommandBatch:
# Check if all are complete.
assert complete_count == len([cmd for cmd in self._batch if cmd.status == CommandBatchItem.STATUS_COMPLETE])
all_complete = (complete_count == len(self._batch))
all_complete = complete_count == len(self._batch)
return CommandBatch_ExecNonBlockingResult(
messages=command_output,
all_complete=all_complete,
@@ -1054,75 +1054,80 @@ class PkgManifest_Normalized(NamedTuple):
# from breaking Blender's internal functionality.
try:
name = manifest_dict["name"]
tagline = manifest_dict["tagline"]
version = manifest_dict["version"]
type = manifest_dict["type"]
maintainer = manifest_dict["maintainer"]
license = manifest_dict["license"]
field_name = manifest_dict["name"]
field_tagline = manifest_dict["tagline"]
field_version = manifest_dict["version"]
field_type = manifest_dict["type"]
field_maintainer = manifest_dict["maintainer"]
field_license = manifest_dict["license"]
# Optional.
website = manifest_dict.get("website", "")
permissions: Union[List[str], Dict[str, str]] = manifest_dict.get("permissions", {})
tags = manifest_dict.get("tags", [])
wheels = manifest_dict.get("wheels", [])
field_website = manifest_dict.get("website", "")
field_permissions: Union[List[str], Dict[str, str]] = manifest_dict.get("permissions", {})
field_tags = manifest_dict.get("tags", [])
field_wheels = manifest_dict.get("wheels", [])
# Remote only (not found in TOML files).
archive_size = manifest_dict.get("archive_size", 0)
archive_url = manifest_dict.get("archive_url", "")
field_archive_size = manifest_dict.get("archive_size", 0)
field_archive_url = manifest_dict.get("archive_url", "")
except KeyError as ex:
error_fn(KeyError("{:s}: missing key {:s}".format(pkg_idname, str(ex))))
return None
# This is an old (now unsupported) format, convert into a dictionary.
if isinstance(permissions, list):
permissions = {key: "Undefined" for key in permissions}
if isinstance(field_permissions, list):
field_permissions = {key: "Undefined" for key in field_permissions}
try:
if not (isinstance(name, str) and name):
if not (isinstance(field_name, str) and field_name):
raise TypeError("{:s}: \"name\" must be a non-empty string".format(pkg_idname))
if not isinstance(tagline, str):
if not isinstance(field_tagline, str):
raise TypeError("{:s}: \"tagline\" must be a string".format(pkg_idname))
if not (isinstance(version, str) and version):
if not (isinstance(field_version, str) and field_version):
raise TypeError("{:s}: \"version\" must be a non-empty string".format(pkg_idname))
if not (isinstance(type, str) and type):
if not (isinstance(field_type, str) and field_type):
raise TypeError("{:s}: \"type\" must be a non-empty string".format(pkg_idname))
if not (isinstance(maintainer, str) and maintainer):
if not (isinstance(field_maintainer, str) and field_maintainer):
raise TypeError("{:s}: \"maintainer\" must be a non-empty string".format(pkg_idname))
if not (
isinstance(license, list) and
license and
(not any(1 for x in license if not isinstance(x, str)))
isinstance(field_license, list) and
field_license and
(not any(1 for x in field_license if not isinstance(x, str)))
):
raise TypeError("{:s}: \"license\" must be a non-empty list of strings".format(pkg_idname))
# Optional.
if not isinstance(website, str):
if not isinstance(field_website, str):
raise TypeError("{:s}: \"website\" must be a string".format(pkg_idname))
if not (
isinstance(permissions, dict) and
(not any(1 for k, v in permissions.items() if not (isinstance(k, str) and isinstance(v, str))))
isinstance(field_permissions, dict) and
(
not any(
1 for k, v in field_permissions.items()
if not (isinstance(k, str) and isinstance(v, str))
)
)
):
raise TypeError("{:s}: \"permissions\" must be a non-empty list of strings".format(pkg_idname))
if not (isinstance(tags, list) and (not any(1 for x in tags if not isinstance(x, str)))):
if not (isinstance(field_tags, list) and (not any(1 for x in field_tags if not isinstance(x, str)))):
raise TypeError("{:s}: \"tags\" must be a non-empty list of strings".format(pkg_idname))
if not (isinstance(wheels, list) and (not any(1 for x in wheels if not isinstance(x, str)))):
if not (isinstance(field_wheels, list) and (not any(1 for x in field_wheels if not isinstance(x, str)))):
raise TypeError("{:s}: \"wheels\" must be a non-empty list of strings".format(pkg_idname))
# Remote only.
if not isinstance(archive_size, int):
if not isinstance(field_archive_size, int):
raise TypeError("{:s}: \"archive_size\" must be an int".format(pkg_idname))
if not isinstance(archive_url, str):
if not isinstance(field_archive_url, str):
raise TypeError("{:s}: \"archive_url\" must a string".format(pkg_idname))
except TypeError as ex:
@@ -1130,23 +1135,23 @@ class PkgManifest_Normalized(NamedTuple):
return None
return PkgManifest_Normalized(
name=name,
tagline=tagline,
version=version,
type=type,
name=field_name,
tagline=field_tagline,
version=field_version,
type=field_type,
# Remove the maintainers email while it's not private, showing prominently
# could cause maintainers to get direct emails instead of issue tracking systems.
maintainer=maintainer.split("<", 1)[0].rstrip(),
license=license_info_to_text(license),
maintainer=field_maintainer.split("<", 1)[0].rstrip(),
license=license_info_to_text(field_license),
# Optional.
website=website,
permissions=permissions,
tags=tuple(tags),
wheels=tuple(wheels),
website=field_website,
permissions=field_permissions,
tags=tuple(field_tags),
wheels=tuple(field_wheels),
archive_size=archive_size,
archive_url=archive_url,
archive_size=field_archive_size,
archive_url=field_archive_url,
)
@@ -1160,7 +1165,7 @@ def repository_id_with_error_fn(
error_fn(ValueError("{:s}: \"id\" missing".format(repo_directory)))
return None
if not (isinstance(pkg_idname, str)):
if not isinstance(pkg_idname, str):
error_fn(ValueError("{:s}: \"id\" must be a string".format(repo_directory)))
return None
@@ -1178,8 +1183,8 @@ def repository_filter_skip(
filter_params: PkgManifest_FilterParams,
error_fn: Callable[[Exception], None],
) -> bool:
from .cli.blender_ext import repository_filter_skip
result = repository_filter_skip(
from .cli.blender_ext import repository_filter_skip as repository_filter_skip_impl
result = repository_filter_skip_impl(
item,
filter_blender_version=filter_params.blender_version,
filter_platform=filter_params.platform,
@@ -1772,7 +1777,6 @@ class RepoCacheStore:
*,
error_fn: Callable[[Exception], None],
ignore_missing: bool = False,
directory_subset: Optional[Set[str]] = None,
) -> Optional[Dict[str, PkgManifest_Normalized]]:
for repo_entry in self._repos:
if directory == repo_entry.directory:

View File

@@ -174,6 +174,7 @@ def message_progress(msg_fn: MessageFn, s: str, progress: int, progress_range: i
def force_exit_ok_enable() -> None:
# pylint: disable-next=global-statement
global FORCE_EXIT_OK
FORCE_EXIT_OK = True
# Without this, some errors are printed on exit.
@@ -479,6 +480,7 @@ def pkg_manifest_from_dict_and_validate_impl(
for key in PkgManifest._fields:
val = data.get(key, ...)
if val is ...:
# pylint: disable-next=no-member
val = PkgManifest._field_defaults.get(key, ...)
# `pkg_manifest_is_valid_or_error{_all}` will have caught this, assert all the same.
assert val is not ...
@@ -1209,6 +1211,7 @@ def pkg_manifest_validate_field_nop(
strict: bool,
) -> Optional[str]:
_ = strict, value
# pylint: disable-next=useless-return
return None
@@ -1432,6 +1435,7 @@ def pkg_manifest_validate_field_wheels(
return "wheel paths must end with \".whl\", found {!r}".format(wheel)
wheel_filename_split = wheel_filename.split("-")
# pylint: disable-next=superfluous-parens
if not (5 <= len(wheel_filename_split) <= 6):
return "wheel filename must follow the spec \"{:s}\", found {!r}".format(filename_spec, wheel_filename)
@@ -1534,9 +1538,11 @@ def pkg_manifest_is_valid_or_error_impl(
is_default_value = False
x_val = data.get(x_key, ...)
if x_val is ...:
# pylint: disable-next=no-member
x_val = PkgManifest._field_defaults.get(x_key, ...)
if from_repo:
if x_val is ...:
# pylint: disable-next=no-member
x_val = PkgManifest_Archive._field_defaults.get(x_key, ...)
if x_val is ...:
error_list.append("missing \"{:s}\"".format(x_key))
@@ -1861,7 +1867,7 @@ def pkg_manifest_detect_duplicates(pkg_idname: str, pkg_items: List[PkgManifest]
item_curr = version_ranges[i]
# Previous maximum is less than or equal to the current minimum, no overlap.
if not (item_prev[1] <= item_curr[0]):
if item_prev[1] > item_curr[0]:
duplicates_found.append("{:s} & {:s}".format(
version_range_as_str(*item_prev),
version_range_as_str(*item_curr),

View File

@@ -4,6 +4,7 @@
# This is a data file that is evaluated directly (not imported).
# NOTE: this can be removed once upgrading from 4.1 is no longer relevant.
# pylint: disable-next=pointless-statement
{
"remote_url": "https://extensions.blender.org/api/v1/extensions",
"extensions": {

View File

@@ -28,6 +28,7 @@ from typing import (
)
# For more useful output that isn't clipped.
# pylint: disable-next=protected-access
unittest.util._MAX_LENGTH = 10_000
IS_WIN32 = sys.platform == "win32"

View File

@@ -33,6 +33,7 @@ from typing import (
# For more useful output that isn't clipped.
# pylint: disable-next=protected-access
unittest.util._MAX_LENGTH = 10_000
PKG_MANIFEST_FILENAME_TOML = "blender_manifest.toml"
@@ -63,8 +64,9 @@ import python_wheel_generate # noqa: E402
# Don't import as module, instead load the class.
def execfile(filepath: str, *, name: str = "__main__") -> Dict[str, Any]:
global_namespace = {"__file__": filepath, "__name__": name}
with open(filepath, encoding="utf-8") as file_handle:
exec(compile(file_handle.read(), filepath, 'exec'), global_namespace)
with open(filepath, encoding="utf-8") as fh:
# pylint: disable-next=exec-used
exec(compile(fh.read(), filepath, 'exec'), global_namespace)
return global_namespace
@@ -556,7 +558,7 @@ class TestSimple(TestWithTempBlenderUser_MixIn, unittest.TestCase):
stdout = run_blender_extensions_no_errors(("install", ",".join(packages_to_install), "--enable"))
self.assertEqual(
tuple([line for line in stdout.split("\n") if line.startswith("STATUS ")]),
tuple(line for line in stdout.split("\n") if line.startswith("STATUS ")),
(
'''STATUS Installed "my_test_pkg"''',
'''STATUS Installed "my_test_pkg_a"''',
@@ -573,18 +575,21 @@ class TestSimple(TestWithTempBlenderUser_MixIn, unittest.TestCase):
(
'''import sys\n'''
'''try:\n'''
''' import {:s}\n'''
''' import {wheel_module_name:s}\n'''
''' found = True\n'''
'''except ModuleNotFoundError:\n'''
''' found = False\n'''
'''if found:\n'''
''' if {:s}.__version__ == "{:s}":\n'''
''' if {wheel_module_name:s}.__version__ == "{packages_wheel_version_max:s}":\n'''
''' sys.exit(64) # Success!\n'''
''' else:\n'''
''' sys.exit(32)\n'''
'''else:\n'''
''' sys.exit(16)\n'''
).format(wheel_module_name, wheel_module_name, packages_wheel_version_max),
).format(
wheel_module_name=wheel_module_name,
packages_wheel_version_max=packages_wheel_version_max,
),
))
self.assertEqual(returncode, 64)

View File

@@ -25,8 +25,9 @@ BASE_DIR = os.path.normpath(os.path.join(CURRENT_DIR, ".."))
# Don't import as module, instead load the class.
def execfile(filepath: str, *, name: str = "__main__") -> Dict[str, Any]:
global_namespace = {"__file__": filepath, "__name__": name}
with open(filepath, encoding="utf-8") as file_handle:
exec(compile(file_handle.read(), filepath, 'exec'), global_namespace)
with open(filepath, encoding="utf-8") as fh:
# pylint: disable-next=exec-used
exec(compile(fh.read(), filepath, 'exec'), global_namespace)
return global_namespace