diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 4e27f14..0000000 --- a/LICENSE +++ /dev/null @@ -1,48 +0,0 @@ -PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 --------------------------------------------- - -1. This LICENSE AGREEMENT is between the Python Software Foundation -("PSF"), and the Individual or Organization ("Licensee") accessing and -otherwise using this software ("Python") in source or binary form and -its associated documentation. - -2. Subject to the terms and conditions of this License Agreement, PSF -hereby grants Licensee a nonexclusive, royalty-free, world-wide license -to reproduce, analyze, test, perform and/or display publicly, prepare -derivative works, distribute, and otherwise use Python alone or in any -derivative version, provided, however, that PSF's License Agreement and -PSF's notice of copyright, i.e., "Copyright (c) 2001, 2002, 2003, 2004, -2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, -2017, 2018 Python Software Foundation; All Rights Reserved" are retained -in Python alone or in any derivative version prepared by Licensee. - -3. In the event Licensee prepares a derivative work that is based on -or incorporates Python or any part thereof, and wants to make -the derivative work available to others as provided herein, then -Licensee hereby agrees to include in any such work a brief summary of -the changes made to Python. - -4. PSF is making Python available to Licensee on an "AS IS" -basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR -IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND -DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS -FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT -INFRINGE ANY THIRD PARTY RIGHTS. - -5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON -FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS -A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, -OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -6. This License Agreement will automatically terminate upon a material -breach of its terms and conditions. - -7. Nothing in this License Agreement shall be deemed to create any -relationship of agency, partnership, or joint venture between PSF and -Licensee. This License Agreement does not grant permission to use PSF -trademarks or trade name in a trademark sense to endorse or promote -products or services of Licensee, or any third party. - -8. By copying, installing or otherwise using Python, Licensee -agrees to be bound by the terms and conditions of this License -Agreement. diff --git a/compileall2-0.7.2.tar.gz b/compileall2-0.7.2.tar.gz deleted file mode 100644 index 6889b52..0000000 --- a/compileall2-0.7.2.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:70e2f8499175a5689cb02fd1eeda3d4b67d68437cd3bb7af8d20b175f70e8aae -size 10975 diff --git a/compileall2-0.8.0.tar.gz b/compileall2-0.8.0.tar.gz new file mode 100644 index 0000000..4a40cf4 --- /dev/null +++ b/compileall2-0.8.0.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c976d99ea6af04482c87b434f8b10ce21fccc7e95a8e63792c0895677f6f48e3 +size 9499 diff --git a/python-compileall2.changes b/python-compileall2.changes index 1be47a7..8e58a98 100644 --- a/python-compileall2.changes +++ b/python-compileall2.changes @@ -1,8 +1,20 @@ +------------------------------------------------------------------- +Sat Apr 6 19:18:36 UTC 2024 - Dirk Müller + +- update to 0.8.0: + * bpo-36786: Run compileall in parallel during "make install" + * bpo-40692: Run more test_concurrent_futures tests (GH-20239) + * gh-105931: Fix surprising compileall stripdir behaviour + (GH-108671) + * GH-84559: Deprecate fork being the multiprocessing default. + * bpo-40447: accept all path-like objects in + * Fix missing space with help for -m compileall -o + ------------------------------------------------------------------- Sat Jan 7 17:08:43 UTC 2023 - Dirk Müller - update to 0.7.2: - * Improved tests + * Improved tests * switch to pyproject.toml ------------------------------------------------------------------- diff --git a/python-compileall2.spec b/python-compileall2.spec index f6c1058..49fd8bd 100644 --- a/python-compileall2.spec +++ b/python-compileall2.spec @@ -1,7 +1,7 @@ # # spec file for package python-compileall2 # -# Copyright (c) 2023 SUSE LLC +# Copyright (c) 2024 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -16,16 +16,14 @@ # -%{?!python_module:%define python_module() python-%{**} python3-%{**}} -%define skip_python2 1 +%{?sle15_python_module_pythons} Name: python-compileall2 -Version: 0.7.2 +Version: 0.8.0 Release: 0 Summary: Enhanced Python `compileall` module License: Python-2.0 URL: https://github.com/fedora-python/compileall2 Source: https://files.pythonhosted.org/packages/source/c/compileall2/compileall2-%{version}.tar.gz -Source1: https://raw.githubusercontent.com/fedora-python/compileall2/master/LICENSE Source2: https://raw.githubusercontent.com/fedora-python/compileall2/master/test_compileall2.py BuildRequires: %{python_module pip} BuildRequires: %{python_module pytest} @@ -41,7 +39,7 @@ Enhanced Python `compileall` module. %prep %setup -q -n compileall2-%{version} -cp %{SOURCE1} %{SOURCE2} . +cp -p %{SOURCE2} . %build export LANG=en_US.UTF-8 diff --git a/test_compileall2.py b/test_compileall2.py index 354a170..0ce8abb 100644 --- a/test_compileall2.py +++ b/test_compileall2.py @@ -1,5 +1,6 @@ import sys import compileall2 as compileall +import contextlib import importlib.util import test.test_importlib.util import marshal @@ -16,10 +17,14 @@ import functools import filecmp from unittest import mock, skipUnless +from concurrent.futures import ProcessPoolExecutor try: - from concurrent.futures import ProcessPoolExecutor + # compileall relies on ProcessPoolExecutor if ProcessPoolExecutor exists + # and it can function. + from concurrent.futures.process import _check_system_limits + _check_system_limits() _have_multiprocessing = True -except ImportError: +except NotImplementedError: _have_multiprocessing = False from test import support @@ -122,7 +127,7 @@ class CompileallTestsBase: self.directory = tempfile.mkdtemp() self.source_path = os.path.join(self.directory, '_test.py') self.bc_path = importlib.util.cache_from_source(self.source_path) - with open(self.source_path, 'w') as file: + with open(self.source_path, 'w', encoding="utf-8") as file: file.write('x = 123\n') self.source_path2 = os.path.join(self.directory, '_test2.py') self.bc_path2 = importlib.util.cache_from_source(self.source_path2) @@ -137,16 +142,34 @@ class CompileallTestsBase: def add_bad_source_file(self): self.bad_source_path = os.path.join(self.directory, '_test_bad.py') - with open(self.bad_source_path, 'w') as file: + with open(self.bad_source_path, 'w', encoding="utf-8") as file: file.write('x (\n') def timestamp_metadata(self): with open(self.bc_path, 'rb') as file: data = file.read(compileall.pyc_header_lenght) mtime = int(os.stat(self.source_path).st_mtime) - compare = struct.pack(*(compileall.pyc_header_format + (mtime,))) + compare = struct.pack(*(compileall.pyc_header_format + (mtime & 0xFFFF_FFFF,))) return data, compare + def test_year_2038_mtime_compilation(self): + # Test to make sure we can handle mtimes larger than what a 32-bit + # signed number can hold as part of bpo-34990 + try: + os.utime(self.source_path, (2**32 - 1, 2**32 - 1)) + except (OverflowError, OSError): + self.skipTest("filesystem doesn't support timestamps near 2**32") + self.assertTrue(compileall.compile_file(self.source_path)) + + def test_larger_than_32_bit_times(self): + # This is similar to the test above but we skip it if the OS doesn't + # support modification times larger than 32-bits. + try: + os.utime(self.source_path, (2**35, 2**35)) + except (OverflowError, OSError): + self.skipTest("filesystem doesn't support large timestamps") + self.assertTrue(compileall.compile_file(self.source_path)) + def recreation_check(self, metadata): """Check that compileall recreates bytecode when the new metadata is used.""" @@ -211,6 +234,20 @@ class CompileallTestsBase: quiet=2)) self.assertTrue(os.path.isfile(self.bc_path)) + def test_compile_file_pathlike_stripdir(self): + self.assertFalse(os.path.isfile(self.bc_path)) + self.assertTrue(compileall.compile_file(pathlib.Path(self.source_path), + stripdir=pathlib.Path('stripdir_path'), + quiet=2)) + self.assertTrue(os.path.isfile(self.bc_path)) + + def test_compile_file_pathlike_prependdir(self): + self.assertFalse(os.path.isfile(self.bc_path)) + self.assertTrue(compileall.compile_file(pathlib.Path(self.source_path), + prependdir=pathlib.Path('prependdir_path'), + quiet=2)) + self.assertTrue(os.path.isfile(self.bc_path)) + def test_compile_path(self): with test.test_importlib.util.import_state(path=[self.directory]): self.assertTrue(compileall.compile_path(quiet=2)) @@ -227,11 +264,19 @@ class CompileallTestsBase: data_file = os.path.join(data_dir, 'file') os.mkdir(data_dir) # touch data/file - with open(data_file, 'w'): + with open(data_file, 'wb'): pass compileall.compile_file(data_file) self.assertFalse(os.path.exists(os.path.join(data_dir, '__pycache__'))) + + def test_compile_file_encoding_fallback(self): + # Bug 44666 reported that compile_file failed when sys.stdout.encoding is None + self.add_bad_source_file() + with contextlib.redirect_stdout(io.StringIO()): + self.assertFalse(compileall.compile_file(self.bad_source_path)) + + def test_optimize(self): # make sure compiling with different optimization settings than the # interpreter's creates the correct file names @@ -256,6 +301,21 @@ class CompileallTestsBase: self.assertRegex(line, r'Listing ([^WindowsPath|PosixPath].*)') self.assertTrue(os.path.isfile(self.bc_path)) + def test_compile_dir_pathlike_stripdir(self): + self.assertFalse(os.path.isfile(self.bc_path)) + self.assertTrue(compileall.compile_dir(pathlib.Path(self.directory), + stripdir=pathlib.Path('stripdir_path'), + quiet=2)) + self.assertTrue(os.path.isfile(self.bc_path)) + + def test_compile_dir_pathlike_prependdir(self): + self.assertFalse(os.path.isfile(self.bc_path)) + self.assertTrue(compileall.compile_dir(pathlib.Path(self.directory), + prependdir=pathlib.Path('prependdir_path'), + quiet=2)) + self.assertTrue(os.path.isfile(self.bc_path)) + + @skipUnless(_have_multiprocessing, "requires multiprocessing") @mock.patch('concurrent.futures.ProcessPoolExecutor') def test_compile_pool_called(self, pool_mock): compileall.compile_dir(self.directory, quiet=True, workers=5) @@ -266,11 +326,13 @@ class CompileallTestsBase: "workers must be greater or equal to 0"): compileall.compile_dir(self.directory, workers=-1) + @skipUnless(_have_multiprocessing, "requires multiprocessing") @mock.patch('concurrent.futures.ProcessPoolExecutor') def test_compile_workers_cpu_count(self, pool_mock): compileall.compile_dir(self.directory, quiet=True, workers=0) self.assertEqual(pool_mock.call_args[1]['max_workers'], None) + @skipUnless(_have_multiprocessing, "requires multiprocessing") @mock.patch('concurrent.futures.ProcessPoolExecutor') @mock.patch('compileall2.compile_file') def test_compile_one_worker(self, compile_file_mock, pool_mock): @@ -361,6 +423,29 @@ class CompileallTestsBase: str(err, encoding=sys.getdefaultencoding()) ) + def test_strip_only_invalid(self): + fullpath = ["test", "build", "real", "path"] + path = os.path.join(self.directory, *fullpath) + os.makedirs(path) + script = script_helper.make_script(path, "test", "1 / 0") + bc = importlib.util.cache_from_source(script) + stripdir = os.path.join(self.directory, *(fullpath[:2] + ['fake'])) + compileall.compile_dir(path, quiet=True, stripdir=stripdir) + rc, out, err = script_helper.assert_python_failure(bc) + expected_not_in = os.path.join(self.directory, *fullpath[2:]) + self.assertIn( + path, + str(err, encoding=sys.getdefaultencoding()) + ) + self.assertNotIn( + expected_not_in, + str(err, encoding=sys.getdefaultencoding()) + ) + self.assertNotIn( + stripdir, + str(err, encoding=sys.getdefaultencoding()) + ) + def test_prepend_only(self): fullpath = ["test", "build", "real", "path"] path = os.path.join(self.directory, *fullpath) @@ -752,8 +837,7 @@ class CommandLineTestsBase: if not directory.is_dir(): directory.mkdir() directory_created = True - with path.open('w') as file: - file.write('# for test_compileall') + path.write_text('# for test_compileall', encoding="utf-8") except OSError: sys_path_writable = False break @@ -1037,7 +1121,7 @@ class CommandLineTestsBase: f2 = script_helper.make_script(self.pkgdir, 'f2', '') f3 = script_helper.make_script(self.pkgdir, 'f3', '') f4 = script_helper.make_script(self.pkgdir, 'f4', '') - with open(os.path.join(self.directory, 'l1'), 'w') as l1: + with open(os.path.join(self.directory, 'l1'), 'w', encoding="utf-8") as l1: l1.write(os.path.join(self.pkgdir, 'f1.py')+os.linesep) l1.write(os.path.join(self.pkgdir, 'f2.py')+os.linesep) self.assertRunOK('-i', os.path.join(self.directory, 'l1'), f4) @@ -1051,7 +1135,7 @@ class CommandLineTestsBase: f2 = script_helper.make_script(self.pkgdir, 'f2', '') f3 = script_helper.make_script(self.pkgdir, 'f3', '') f4 = script_helper.make_script(self.pkgdir, 'f4', '') - with open(os.path.join(self.directory, 'l1'), 'w') as l1: + with open(os.path.join(self.directory, 'l1'), 'w', encoding="utf-8") as l1: l1.write(os.path.join(self.pkgdir, 'f2.py')+os.linesep) self.assertRunOK('-i', os.path.join(self.directory, 'l1')) self.assertNotCompiled(f1) @@ -1121,7 +1205,7 @@ class CommandLineTestsBase: new=[sys.executable, self.directory, "-j0"]): compileall.main() self.assertTrue(compile_dir.called) - self.assertEqual(compile_dir.call_args[-1]['workers'], None) + self.assertEqual(compile_dir.call_args[-1]['workers'], 0) def test_strip_and_prepend(self): fullpath = ["test", "build", "real", "path"]