Here is a patch that makes gnulib-tool.py use the standard Python program directory structure: - a single .py file in the parent directory, - any number of .py files in a subdirectory.
With this, no PYTHONPATH override is needed any more, and the import-related error markers in Eclipse are gone. Since this change has consequences on the Eclipse project configuration, I incorporated the instructions from <https://lists.gnu.org/archive/html/bug-gnulib/2024-03/msg00157.html>, with the necessary changes, into the HACKING file. Collin, feel free to document the way you install, configure, and customize PyCharm in the same file. Bruno
>From dbeb5f1f1a018b6a81f899092554ff0af8776ec3 Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Date: Mon, 1 Apr 2024 21:50:51 +0200 Subject: [PATCH 1/2] gnulib-tool.py: Use a standard Python program directory structure. * pygnulib/main.py (main_with_exception_handling): New function for existing code. * .gnulib-tool.py: New file. * pygnulib/constants.py: Update the computation of APP['root']. * gnulib-tool.py: Don't set PYTHONPATH. --- .gnulib-tool.py | 30 ++++++++++++++++++++++++++++++ ChangeLog | 9 +++++++++ gnulib-tool.py | 6 +----- pygnulib/constants.py | 4 ++-- pygnulib/main.py | 2 +- 5 files changed, 43 insertions(+), 8 deletions(-) create mode 100644 .gnulib-tool.py diff --git a/.gnulib-tool.py b/.gnulib-tool.py new file mode 100644 index 0000000000..3b2d6913f3 --- /dev/null +++ b/.gnulib-tool.py @@ -0,0 +1,30 @@ +# Copyright (C) 2024 Free Software Foundation, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +# + +# This file exists to satisfy the standard layout of a Python program: +# - a single .py file in the parent directory, +# - any number of .py files in a subdirectory. +# Explanation: https://stackoverflow.com/questions/16981921/relative-imports-in-python-3 +# Without this standard layout, we got +# - errors at runtime: +# from . import constants => ImportError: attempted relative import with no known parent package +# from pygnulib import constants => ModuleNotFoundError: No module named 'pygnulib' +# - error markers in Eclipse + PyDev. + +from pygnulib import main + +if __name__ == '__main__': + main.main_with_exception_handling() diff --git a/ChangeLog b/ChangeLog index ef529a5e4c..7a387b3300 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2024-04-01 Bruno Haible <br...@clisp.org> + + gnulib-tool.py: Use a standard Python program directory structure. + * pygnulib/main.py (main_with_exception_handling): New function for + existing code. + * .gnulib-tool.py: New file. + * pygnulib/constants.py: Update the computation of APP['root']. + * gnulib-tool.py: Don't set PYTHONPATH. + 2024-04-01 Bruno Haible <br...@clisp.org> gnulib-tool.py: Simplify imports. diff --git a/gnulib-tool.py b/gnulib-tool.py index f94c9c36a7..bb2837a3d5 100755 --- a/gnulib-tool.py +++ b/gnulib-tool.py @@ -144,8 +144,4 @@ else func_fatal_error "python3 not found; try setting GNULIB_TOOL_IMPL=sh" fi -# Setting the PYTHONPATH environment variable is needed to avoid an error: -# from . import constants => ImportError: attempted relative import with no known parent package -# from pygnulib import constants => ModuleNotFoundError: No module named 'pygnulib' -# Explanation: https://stackoverflow.com/questions/16981921/relative-imports-in-python-3 -exec env PYTHONPATH="$gnulib_dir" python3 "$gnulib_dir/pygnulib/main.py" "$@" +exec python3 "$gnulib_dir/.gnulib-tool.py" "$@" diff --git a/pygnulib/constants.py b/pygnulib/constants.py index a6ef32cb47..8f698fe01e 100644 --- a/pygnulib/constants.py +++ b/pygnulib/constants.py @@ -74,8 +74,8 @@ if ENCS['shell'] == None: ENCS['shell'] = 'UTF-8' # Set APP dictionary -APP['path'] = os.path.realpath(sys.argv[0]) # file name of <gnulib>/pygnulib/main.py -APP['root'] = os.path.dirname(os.path.dirname(APP['path'])) # file name of <gnulib> +APP['path'] = os.path.realpath(sys.argv[0]) # file name of <gnulib>/.gnulib-tool.py +APP['root'] = os.path.dirname(APP['path']) # file name of <gnulib> APP['name'] = os.path.join(APP['root'], 'gnulib-tool.py') # Set DIRS directory diff --git a/pygnulib/main.py b/pygnulib/main.py index 31bb434b3a..a57e5b04a3 100644 --- a/pygnulib/main.py +++ b/pygnulib/main.py @@ -1373,7 +1373,7 @@ def main() -> None: pass -if __name__ == '__main__': +def main_with_exception_handling() -> None: try: # Try to execute main() except GLError as error: -- 2.34.1
>From 382ba5c05473d4d8c450e1eef055f86b5b27fbba Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Date: Tue, 2 Apr 2024 00:21:54 +0200 Subject: [PATCH 2/2] gnulib-tool.py: Add developer documentation. * HACKING: New section "Debugging the Python implementation of gnulib-tool". --- ChangeLog | 6 ++++++ HACKING | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/ChangeLog b/ChangeLog index 7a387b3300..1668b7cfd8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2024-04-01 Bruno Haible <br...@clisp.org> + + gnulib-tool.py: Add developer documentation. + * HACKING: New section "Debugging the Python implementation of + gnulib-tool". + 2024-04-01 Bruno Haible <br...@clisp.org> gnulib-tool.py: Use a standard Python program directory structure. diff --git a/HACKING b/HACKING index a3c65213d2..119bac8c10 100644 --- a/HACKING +++ b/HACKING @@ -29,6 +29,7 @@ Using git Copyright-paperwork-exempt: Yes - use the 'git commit' option --author="Contributor Name <email@address>" + License Notices =============== @@ -43,12 +44,14 @@ use the license notices from etc/license-notices/ . This avoids gratuitous differences in wording, as well misunderstandings when a license notice would say "This program ...". + Test Suite ========== When adding a module, add a unit test module as well. This is our best chance to catch portability problems. + Warning Options =============== @@ -514,3 +517,55 @@ https://releases.llvm.org/16.0.0/tools/clang/docs/DiagnosticsReference.html : $ make Again, use your own judgement to determine whether to fix or ignore a specific warning. + + +Debugging the Python implementation of gnulib-tool +================================================== + +With Eclipse and PyDev as IDE +----------------------------- + +* Download and configuration: + - Eclipse IDE from https://www.eclipse.org/downloads/packages/ + (either the build for Java or for C/C++ should work fine; + either use the Eclipse Installer program at the top of the page, + or one of the individual download links below). + - PyDev from https://www.pydev.org/download.html + section "Install as Plugin". + (Don't use LiClipse, since the license costs money.) + - Follow https://www.pydev.org/manual_101_install.html, + replacing http://www.pydev.org/updates + with https://www.pydev.org/updates + - Once installed, restart the IDE. + - Window > Preferences > PyDev > Interpreters > Python Interpreter: + New > path: /usr/bin/python3 + +* Create a project: + Let GNULIB_DIR be my gnulib checkout. + - File > New > Project... > PyDev > PyDev Project. Call it 'gnulib-tool'. + Note that this is a project inside the Eclipse workspace, so far + unrelated to the GNULIB_DIR. + - Popup menu > New > Link to Existing Source + Name: gnulib + Path: <GNULIB_DIR> + +* Create a run configuration: + - Run > Run Configurations... > Python Run + Popup menu > New configuration + Name: gnulib-tool.py + Main > Project: gnulib-tool + Main > Main Module: ${workspace_loc:gnulib-tool/gnulib/.gnulib-tool.py} + Arguments > Program arguments: --help + - Test it: Run this configuration. + +* Create a debug configuration: + - Run > Debug Configurations... > gnulib-tool.py + Popup menu > Duplicate + - In the duplicate, set + Arguments > Working directory: /tmp/oath-toolkit/lib + Arguments > Program arguments: --add-import + +* Debug it: + - Open GLImport.py. + - On the left-hand border of this editor, do "Add breakpoint". + - Run > Debug Configurations... > pick the duplicate. Press Debug. -- 2.34.1