Skip to content
Snippets Groups Projects
Unverified Commit 7e19e417 authored by Erlend Egeberg Aasland's avatar Erlend Egeberg Aasland Committed by GitHub
Browse files

gh-95411: IDLE - Enable using the module browser with .pyw files (#95397)



Co-authored-by: default avatarTerry Jan Reedy <tjreedy@udel.edu>
parent d92b19e1
No related branches found
No related tags found
No related merge requests found
...@@ -3,6 +3,8 @@ What's New in IDLE 3.11.0 ...@@ -3,6 +3,8 @@ What's New in IDLE 3.11.0
Released on 2022-10-03 Released on 2022-10-03
========================= =========================
gh-95411: Enable using IDLE's module browser with .pyw files.
gh-89610: Add .pyi as a recognized extension for IDLE on macOS. This allows gh-89610: Add .pyi as a recognized extension for IDLE on macOS. This allows
opening stub files by double clicking on them in the Finder. opening stub files by double clicking on them in the Finder.
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
(or recheck on window popup) (or recheck on window popup)
- add popup menu with more options (e.g. doc strings, base classes, imports) - add popup menu with more options (e.g. doc strings, base classes, imports)
- add base classes to class browser tree - add base classes to class browser tree
- finish removing limitation to x.py files (ModuleBrowserTreeItem)
""" """
import os import os
...@@ -16,12 +15,22 @@ ...@@ -16,12 +15,22 @@
from idlelib.config import idleConf from idlelib.config import idleConf
from idlelib import pyshell from idlelib import pyshell
from idlelib.tree import TreeNode, TreeItem, ScrolledCanvas from idlelib.tree import TreeNode, TreeItem, ScrolledCanvas
from idlelib.util import py_extensions
from idlelib.window import ListedToplevel from idlelib.window import ListedToplevel
file_open = None # Method...Item and Class...Item use this. file_open = None # Method...Item and Class...Item use this.
# Normally pyshell.flist.open, but there is no pyshell.flist for htest. # Normally pyshell.flist.open, but there is no pyshell.flist for htest.
# The browser depends on pyclbr and importlib which do not support .pyi files.
browseable_extension_blocklist = ('.pyi',)
def is_browseable_extension(path):
_, ext = os.path.splitext(path)
ext = os.path.normcase(ext)
return ext in py_extensions and ext not in browseable_extension_blocklist
def transform_children(child_dict, modname=None): def transform_children(child_dict, modname=None):
"""Transform a child dictionary to an ordered sequence of objects. """Transform a child dictionary to an ordered sequence of objects.
...@@ -76,8 +85,8 @@ def __init__(self, master, path, *, _htest=False, _utest=False): ...@@ -76,8 +85,8 @@ def __init__(self, master, path, *, _htest=False, _utest=False):
Instance variables: Instance variables:
name: Module name. name: Module name.
file: Full path and module with .py extension. Used in file: Full path and module with supported extension.
creating ModuleBrowserTreeItem as the rootnode for Used in creating ModuleBrowserTreeItem as the rootnode for
the tree and subsequently in the children. the tree and subsequently in the children.
""" """
self.master = master self.master = master
...@@ -161,22 +170,22 @@ def GetSubList(self): ...@@ -161,22 +170,22 @@ def GetSubList(self):
def OnDoubleClick(self): def OnDoubleClick(self):
"Open a module in an editor window when double clicked." "Open a module in an editor window when double clicked."
if os.path.normcase(self.file[-3:]) != ".py": if not is_browseable_extension(self.file):
return return
if not os.path.exists(self.file): if not os.path.exists(self.file):
return return
file_open(self.file) file_open(self.file)
def IsExpandable(self): def IsExpandable(self):
"Return True if Python (.py) file." "Return True if Python file."
return os.path.normcase(self.file[-3:]) == ".py" return is_browseable_extension(self.file)
def listchildren(self): def listchildren(self):
"Return sequenced classes and functions in the module." "Return sequenced classes and functions in the module."
dir, base = os.path.split(self.file) if not is_browseable_extension(self.file):
name, ext = os.path.splitext(base)
if os.path.normcase(ext) != ".py":
return [] return []
dir, base = os.path.split(self.file)
name, _ = os.path.splitext(base)
try: try:
tree = pyclbr.readmodule_ex(name, [dir] + sys.path) tree = pyclbr.readmodule_ex(name, [dir] + sys.path)
except ImportError: except ImportError:
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import unittest import unittest
from unittest import mock from unittest import mock
from idlelib.idle_test.mock_idle import Func from idlelib.idle_test.mock_idle import Func
from idlelib.util import py_extensions
from collections import deque from collections import deque
import os.path import os.path
...@@ -57,6 +58,15 @@ def test_close(self): ...@@ -57,6 +58,15 @@ def test_close(self):
self.assertTrue(mb.node.destroy.called) self.assertTrue(mb.node.destroy.called)
del mb.top.destroy, mb.node.destroy del mb.top.destroy, mb.node.destroy
def test_is_browseable_extension(self):
path = "/path/to/file"
for ext in py_extensions:
with self.subTest(ext=ext):
filename = f'{path}{ext}'
actual = browser.is_browseable_extension(filename)
expected = ext not in browser.browseable_extension_blocklist
self.assertEqual(actual, expected)
# Nested tree same as in test_pyclbr.py except for supers on C0. C1. # Nested tree same as in test_pyclbr.py except for supers on C0. C1.
mb = pyclbr mb = pyclbr
......
Enable using IDLE's module browser with .pyw files.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment