Skip to content

gh-115421: List all test subdirs in Makefile by makesetup - #115511

Closed
sobolevn wants to merge 1 commit into
python:mainfrom
sobolevn:issue-115421
Closed

sobolevn wants to merge 1 commit into
python:mainfrom
sobolevn:issue-115421

Conversation

@sobolevn

@sobolevn sobolevn commented Feb 15, 2024 •

Copy link
Copy Markdown
Member

It produces:

TESTSUBDIRS=       test test/test_cppext test/test_pathlib test/test_inspect test/mathdata test/test_gdb test/test_tomllib test/test_tomllib/data test/test_tomllib/data/valid test/test_tomllib/data/valid/array test/test_tomllib/data/valid/multiline-basic-str test/test_tomllib/data/valid/dates-and-times test/test_tomllib/data/invalid test/test_tomllib/data/invalid/array test/test_tomllib/data/invalid/keys-and-vals test/test_tomllib/data/invalid/inline-table test/test_tomllib/data/invalid/multiline-basic-str test/test_tomllib/data/invalid/literal-str test/test_tomllib/data/invalid/dotted-keys test/test_tomllib/data/invalid/table test/test_tomllib/data/invalid/boolean test/test_tomllib/data/invalid/dates-and-times test/test_tomllib/data/invalid/multiline-literal-str test/test_tomllib/data/invalid/array-of-tables test/test_module test/test_pydoc test/crashers test/test_json test/test_ttk test/test_peg_generator test/test_tools test/audiodata test/typinganndata test/test_tkinter test/test_importlib test/test_importlib/extension test/test_importlib/partial test/test_importlib/resources test/test_importlib/resources/namespacedata01 test/test_importlib/resources/zipdata01 test/test_importlib/resources/data02 test/test_importlib/resources/data02/subdirectory test/test_importlib/resources/data02/subdirectory/subsubdir test/test_importlib/resources/data02/one test/test_importlib/resources/data02/two test/test_importlib/resources/data03 test/test_importlib/resources/data03/namespace test/test_importlib/resources/data03/namespace/portion2 test/test_importlib/resources/data03/namespace/portion1 test/test_importlib/resources/zipdata02 test/test_importlib/resources/data01 test/test_importlib/resources/data01/subdirectory test/test_importlib/source test/test_importlib/import_ test/test_importlib/namespace_pkgs test/test_importlib/namespace_pkgs/project1 test/test_importlib/namespace_pkgs/project1/parent test/test_importlib/namespace_pkgs/project1/parent/child test/test_importlib/namespace_pkgs/portion2 test/test_importlib/namespace_pkgs/portion2/foo test/test_importlib/namespace_pkgs/not_a_namespace_pkg test/test_importlib/namespace_pkgs/not_a_namespace_pkg/foo test/test_importlib/namespace_pkgs/project3 test/test_importlib/namespace_pkgs/project3/parent test/test_importlib/namespace_pkgs/project3/parent/child test/test_importlib/namespace_pkgs/project2 test/test_importlib/namespace_pkgs/project2/parent test/test_importlib/namespace_pkgs/project2/parent/child test/test_importlib/namespace_pkgs/module_and_namespace_package test/test_importlib/namespace_pkgs/module_and_namespace_package/a_test test/test_importlib/namespace_pkgs/both_portions test/test_importlib/namespace_pkgs/both_portions/foo test/test_importlib/namespace_pkgs/portion1 test/test_importlib/namespace_pkgs/portion1/foo test/test_importlib/frozen test/test_importlib/data test/test_importlib/builtin test/test_ctypes test/test_future_stmt test/dtracedata test/tracedmodules test/test_doctest test/tokenizedata test/test_zipfile test/test_zipfile/_path test/test_multiprocessing_spawn test/decimaltestdata test/xmltestdata test/xmltestdata/c14n-20 test/test_xml test/encoded_modules test/cjkencodings test/test_warnings test/test_warnings/data test/test_multiprocessing_forkserver test/regrtestdata test/regrtestdata/import_from_tests test/regrtestdata/import_from_tests/test_regrtest_b test/archivetestdata test/test_unittest test/test_unittest/testmock test/test_sqlite3 test/certdata test/certdata/capath test/test_import test/test_import/data test/test_import/data/package2 test/test_import/data/circular_imports test/test_import/data/circular_imports/subpkg test/test_import/data/circular_imports/subpkg2 test/test_import/data/circular_imports/subpkg2/parent test/test_import/data/unwritable test/test_import/data/package test/test_zoneinfo test/test_zoneinfo/data test/support test/support/interpreters test/support/_hypothesis_stubs test/tkinterdata test/test_interpreters test/test_dataclasses test/test_concurrent_futures test/test_multiprocessing_fork test/test_capi test/leakers test/wheeldata test/test_email test/test_email/data test/test_asyncio test/libregrtest test/data test/subprocessdata test/configdata 

And here's what is installed:

» tree -d temp/usr/local/lib/python3.13/test/
temp/usr/local/lib/python3.13/test/
├── __pycache__
├── archivetestdata
│   └── __pycache__
├── audiodata
├── certdata
│   ├── __pycache__
│   └── capath
├── cjkencodings
├── configdata
├── crashers
│   └── __pycache__
├── data
├── decimaltestdata
├── dtracedata
│   └── __pycache__
├── encoded_modules
│   └── __pycache__
├── leakers
│   └── __pycache__
├── libregrtest
│   └── __pycache__
├── mathdata
├── regrtestdata
│   └── import_from_tests
│       ├── __pycache__
│       └── test_regrtest_b
│           └── __pycache__
├── subprocessdata
│   └── __pycache__
├── support
│   ├── __pycache__
│   ├── _hypothesis_stubs
│   │   └── __pycache__
│   └── interpreters
│       └── __pycache__
├── test_asyncio
│   └── __pycache__
├── test_capi
│   └── __pycache__
├── test_concurrent_futures
│   └── __pycache__
├── test_cppext
│   └── __pycache__
├── test_ctypes
│   └── __pycache__
├── test_dataclasses
│   └── __pycache__
├── test_doctest
│   └── __pycache__
├── test_email
│   ├── __pycache__
│   └── data
├── test_future_stmt
│   └── __pycache__
├── test_gdb
│   └── __pycache__
├── test_import
│   ├── __pycache__
│   └── data
│       ├── __pycache__
│       ├── circular_imports
│       │   ├── __pycache__
│       │   ├── subpkg
│       │   │   └── __pycache__
│       │   └── subpkg2
│       │       ├── __pycache__
│       │       └── parent
│       │           └── __pycache__
│       ├── package
│       │   └── __pycache__
│       ├── package2
│       │   └── __pycache__
│       └── unwritable
│           └── __pycache__
├── test_importlib
│   ├── __pycache__
│   ├── builtin
│   │   └── __pycache__
│   ├── data
│   │   └── __pycache__
│   ├── extension
│   │   └── __pycache__
│   ├── frozen
│   │   └── __pycache__
│   ├── import_
│   │   └── __pycache__
│   ├── namespace_pkgs
│   │   ├── both_portions
│   │   │   └── foo
│   │   │       └── __pycache__
│   │   ├── module_and_namespace_package
│   │   │   ├── __pycache__
│   │   │   └── a_test
│   │   ├── not_a_namespace_pkg
│   │   │   └── foo
│   │   │       └── __pycache__
│   │   ├── portion1
│   │   │   └── foo
│   │   │       └── __pycache__
│   │   ├── portion2
│   │   │   └── foo
│   │   │       └── __pycache__
│   │   ├── project1
│   │   │   └── parent
│   │   │       └── child
│   │   │           └── __pycache__
│   │   ├── project2
│   │   │   └── parent
│   │   │       └── child
│   │   │           └── __pycache__
│   │   └── project3
│   │       └── parent
│   │           └── child
│   │               └── __pycache__
│   ├── partial
│   │   └── __pycache__
│   ├── resources
│   │   ├── __pycache__
│   │   ├── data01
│   │   │   ├── __pycache__
│   │   │   └── subdirectory
│   │   │       └── __pycache__
│   │   ├── data02
│   │   │   ├── __pycache__
│   │   │   ├── one
│   │   │   │   └── __pycache__
│   │   │   ├── subdirectory
│   │   │   │   └── subsubdir
│   │   │   └── two
│   │   │       └── __pycache__
│   │   ├── data03
│   │   │   ├── __pycache__
│   │   │   └── namespace
│   │   │       ├── portion1
│   │   │       │   └── __pycache__
│   │   │       └── portion2
│   │   │           └── __pycache__
│   │   ├── namespacedata01
│   │   ├── zipdata01
│   │   │   └── __pycache__
│   │   └── zipdata02
│   │       └── __pycache__
│   └── source
│       └── __pycache__
├── test_inspect
│   └── __pycache__
├── test_interpreters
│   └── __pycache__
├── test_json
│   └── __pycache__
├── test_module
│   └── __pycache__
├── test_multiprocessing_fork
│   └── __pycache__
├── test_multiprocessing_forkserver
│   └── __pycache__
├── test_multiprocessing_spawn
│   └── __pycache__
├── test_pathlib
│   └── __pycache__
├── test_peg_generator
│   └── __pycache__
├── test_pydoc
│   └── __pycache__
├── test_sqlite3
│   └── __pycache__
├── test_tkinter
│   └── __pycache__
├── test_tomllib
│   ├── __pycache__
│   └── data
│       ├── invalid
│       │   ├── array
│       │   ├── array-of-tables
│       │   ├── boolean
│       │   ├── dates-and-times
│       │   ├── dotted-keys
│       │   ├── inline-table
│       │   ├── keys-and-vals
│       │   ├── literal-str
│       │   ├── multiline-basic-str
│       │   ├── multiline-literal-str
│       │   └── table
│       └── valid
│           ├── array
│           ├── dates-and-times
│           └── multiline-basic-str
├── test_tools
│   └── __pycache__
├── test_ttk
│   └── __pycache__
├── test_unittest
│   ├── __pycache__
│   └── testmock
│       └── __pycache__
├── test_warnings
│   ├── __pycache__
│   └── data
│       └── __pycache__
├── test_xml
├── test_zipfile
│   ├── __pycache__
│   └── _path
│       └── __pycache__
├── test_zoneinfo
│   ├── __pycache__
│   └── data
│       └── __pycache__
├── tkinterdata
├── tokenizedata
│   └── __pycache__
├── tracedmodules
│   └── __pycache__
├── typinganndata
│   └── __pycache__
├── wheeldata
└── xmltestdata
    └── c14n-20

219 directories

Note that __pycache__ directories are created by compile job and they are not copied.

This is the first time I touch makesetup, so please, be very careful during the review :)

@Yhg1s Yhg1s left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure makesetup is the right place to do this. Its job is to generate the build rules for extension modules, and making it do more things means it's going to be harder to replace. Also, makesetup is run as part of configure, so if you create new directories (as part of development or as part of a build step) the resulting directory won't be installed.

Using find in makesetup is also a new requirement. find isn't as ubiquitous or standardised as bare sh, which makesetup has so far used.

How about instead of doing this in makesetup, changing the libinstall step in Makefile.pre.in to recurse into subdirectories when processing TESTSUBDIRS? It would require duplicating a bit of the logic to separate out the processing of LIBSUBDIRS from TESTSUBDIRS (we do not want to copy LIBSUBDIRS directories recursively, since they may contain test subdirs).

Comment thread Modules/makesetup
echo "s%_MODOBJS_%$OBJS%" >>$sedf
echo "s%_MODLIBS_%$LIBS%" >>$sedf
# We used to have some test modules not installed, see gh-115421
TESTSUBDIRS="$(cd Lib; find test -type d -not -path '*/__pycache__' | tr '\n' ' ')"

@Yhg1s Yhg1s Feb 15, 2024 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the first use of $() in this file, and I'm not sure about the portability of it (configure seems to have a fallback mechanism for $()). Given there's no nested backticks, probably safer to use those, like the rest of the file does.

-path '*/__pycache__' is usually written as -name __pycache__.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, your suggestion feels simplier! I will try to implement it soon, thanks for the idea!

@vstinner

Copy link
Copy Markdown
Member

Would it make sense to only copy directories which contain .py files? Maybe not.

The Windows installer doesn't care and copy Lib/test/*/ directories: I'm fine with this approach.

@sobolevn

Copy link
Copy Markdown
Member Author

Well, I don't quite like the solution that I working on :(

diff --git Makefile.pre.in Makefile.pre.in
index e37ae14326e..75e7ec6f68a 100644
--- Makefile.pre.in
+++ Makefile.pre.in
@@ -2239,8 +2239,8 @@ COMPILEALL_OPTS=-j0
 
 TEST_MODULES=@TEST_MODULES@
 
-.PHONY: libinstall
-libinstall:	all $(srcdir)/Modules/xxmodule.c
+.PHONY: commonlibinstall
+commonlibinstall: 
 	@for i in $(SCRIPTDIR) $(LIBDEST); \
 	do \
 		if test ! -d $(DESTDIR)$$i; then \
@@ -2249,12 +2249,49 @@ libinstall:	all $(srcdir)/Modules/xxmodule.c
 		else	true; \
 		fi; \
 	done
-	@if test "$(TEST_MODULES)" = yes; then \
-		subdirs="$(LIBSUBDIRS) $(TESTSUBDIRS)"; \
-	else \
-		subdirs="$(LIBSUBDIRS)"; \
-	fi; \
-	for d in $$subdirs; \
+
+.PHONY: testlibinstall
+testlibinstall: $(srcdir)/Lib/test/* $(srcdir)/Lib/test/**/*
+	if test "$(TEST_MODULES)" = yes; then \
+		for entry in $^; \
+		do \
+		    if test ! -d $$entry; then continue; else true; fi; \
+			if test `ls $$entry | wc -l` -lt 1; then continue; fi; \
+			case $$entry in \
+			**__pycache__**) \
+				continue; \
+			esac; \
+			libdest=$(LIBDEST)/$${entry#Lib/}; \
+			if test ! -d $(DESTDIR)$$libdest; then \
+				echo "Creating directory $$libdest"; \
+				$(INSTALL) -d -m $(DIRMODE) $(DESTDIR)$$libdest; \
+			else	true; \
+			fi; \
+			for sub in $$entry/*; \
+			do \
+				if test -d $$sub; then continue; fi; \
+				case $$i in \
+				*CVS) ;; \
+				*.py[co]) ;; \
+				*.orig) ;; \
+				*~) ;; \
+				*) \
+					dest=$(DESTDIR)$(LIBDEST)/$${sub#Lib/}; \
+					if test -x $$sub; then \
+						echo $(INSTALL_SCRIPT) $$sub $$dest; \
+						$(INSTALL_SCRIPT) $$sub $$dest; \
+					else \
+						echo $(INSTALL_DATA) $$sub $$dest; \
+						$(INSTALL_DATA) $$sub $$dest; \
+					fi; \
+				esac; \
+			done; \
+		done; \
+	fi
+
+.PHONY: libinstall
+libinstall:	all commonlibinstall testlibinstall $(srcdir)/Modules/xxmodule.c
+	for d in $(LIBSUBDIRS); \
 	do \
 		a=$(srcdir)/Lib/$$d; \
 		if test ! -d $$a; then continue; else true; fi; \
@@ -2275,12 +2312,7 @@ libinstall:	all $(srcdir)/Modules/xxmodule.c
 			echo $(INSTALL_DATA) $$i $(LIBDEST); \
 		fi; \
 	done
-	@if test "$(TEST_MODULES)" = yes; then \
-		subdirs="$(LIBSUBDIRS) $(TESTSUBDIRS)"; \
-	else \
-		subdirs="$(LIBSUBDIRS)"; \
-	fi; \
-	for d in $$subdirs; \
+	for d in $(LIBSUBDIRS); \
 	do \
 		a=$(srcdir)/Lib/$$d; \
 		if test ! -d $$a; then continue; else true; fi; \

This is the WIP, because it does not handle idellib.idle_test right now, most likely I will need a separate build target for it.

For my taste it is very complex, it repeats quite a lot of logic from libinstall.

Maybe we should test that all test folders are listed in Makefile during our CI?

@sobolevn

Copy link
Copy Markdown
Member Author

Alternative PR: #115813

@encukou

encukou commented Mar 7, 2024

Copy link
Copy Markdown
Member

The alternative is merged.

@encukou encukou closed this Mar 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants