mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +00:00 
			
		
		
		
	gh-102209: Sync with zipp 3.15 moving complexity tests into dedicated module (#102232)
Sync with jaraco/zipp@757a4e1a.
This commit is contained in:
		
							parent
							
								
									207e1c5cae
								
							
						
					
					
						commit
						a35fd38b57
					
				
					 7 changed files with 87 additions and 51 deletions
				
			
		|  | @ -1,30 +0,0 @@ | ||||||
| import contextlib |  | ||||||
| import time |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class DeadlineExceeded(Exception): |  | ||||||
|     pass |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class TimedContext(contextlib.ContextDecorator): |  | ||||||
|     """ |  | ||||||
|     A context that will raise DeadlineExceeded if the |  | ||||||
|     max duration is reached during the execution. |  | ||||||
| 
 |  | ||||||
|     >>> TimedContext(1)(time.sleep)(.1) |  | ||||||
|     >>> TimedContext(0)(time.sleep)(.1) |  | ||||||
|     Traceback (most recent call last): |  | ||||||
|     ... |  | ||||||
|     tests._context.DeadlineExceeded: (..., 0) |  | ||||||
|     """ |  | ||||||
| 
 |  | ||||||
|     def __init__(self, max_duration: int): |  | ||||||
|         self.max_duration = max_duration |  | ||||||
| 
 |  | ||||||
|     def __enter__(self): |  | ||||||
|         self.start = time.monotonic() |  | ||||||
| 
 |  | ||||||
|     def __exit__(self, *err): |  | ||||||
|         duration = time.monotonic() - self.start |  | ||||||
|         if duration > self.max_duration: |  | ||||||
|             raise DeadlineExceeded(duration, self.max_duration) |  | ||||||
|  | @ -1,8 +0,0 @@ | ||||||
| try: |  | ||||||
|     from func_timeout import func_set_timeout as set_timeout |  | ||||||
| except ImportError:  # pragma: no cover |  | ||||||
|     # provide a fallback that doesn't actually time out |  | ||||||
|     from ._context import TimedContext as set_timeout |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| __all__ = ['set_timeout'] |  | ||||||
|  | @ -1,4 +1,6 @@ | ||||||
| import itertools | import itertools | ||||||
|  | from collections import deque | ||||||
|  | from itertools import islice | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| # from jaraco.itertools 6.3.0 | # from jaraco.itertools 6.3.0 | ||||||
|  | @ -39,3 +41,39 @@ def always_iterable(obj, base_type=(str, bytes)): | ||||||
|         return iter(obj) |         return iter(obj) | ||||||
|     except TypeError: |     except TypeError: | ||||||
|         return iter((obj,)) |         return iter((obj,)) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # from more_itertools v9.0.0 | ||||||
|  | def consume(iterator, n=None): | ||||||
|  |     """Advance *iterable* by *n* steps. If *n* is ``None``, consume it | ||||||
|  |     entirely. | ||||||
|  |     Efficiently exhausts an iterator without returning values. Defaults to | ||||||
|  |     consuming the whole iterator, but an optional second argument may be | ||||||
|  |     provided to limit consumption. | ||||||
|  |         >>> i = (x for x in range(10)) | ||||||
|  |         >>> next(i) | ||||||
|  |         0 | ||||||
|  |         >>> consume(i, 3) | ||||||
|  |         >>> next(i) | ||||||
|  |         4 | ||||||
|  |         >>> consume(i) | ||||||
|  |         >>> next(i) | ||||||
|  |         Traceback (most recent call last): | ||||||
|  |           File "<stdin>", line 1, in <module> | ||||||
|  |         StopIteration | ||||||
|  |     If the iterator has fewer items remaining than the provided limit, the | ||||||
|  |     whole iterator will be consumed. | ||||||
|  |         >>> i = (x for x in range(3)) | ||||||
|  |         >>> consume(i, 5) | ||||||
|  |         >>> next(i) | ||||||
|  |         Traceback (most recent call last): | ||||||
|  |           File "<stdin>", line 1, in <module> | ||||||
|  |         StopIteration | ||||||
|  |     """ | ||||||
|  |     # Use functions that consume iterators at C speed. | ||||||
|  |     if n is None: | ||||||
|  |         # feed the entire iterator into a zero-length deque | ||||||
|  |         deque(iterator, maxlen=0) | ||||||
|  |     else: | ||||||
|  |         # advance to the empty slice starting at position n | ||||||
|  |         next(islice(iterator, n, n), None) | ||||||
|  |  | ||||||
							
								
								
									
										9
									
								
								Lib/test/test_zipfile/_support.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								Lib/test/test_zipfile/_support.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | ||||||
|  | import importlib | ||||||
|  | import unittest | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def import_or_skip(name): | ||||||
|  |     try: | ||||||
|  |         return importlib.import_module(name) | ||||||
|  |     except ImportError:  # pragma: no cover | ||||||
|  |         raise unittest.SkipTest(f'Unable to import {name}') | ||||||
							
								
								
									
										24
									
								
								Lib/test/test_zipfile/test_complexity.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								Lib/test/test_zipfile/test_complexity.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,24 @@ | ||||||
|  | import unittest | ||||||
|  | import string | ||||||
|  | import zipfile | ||||||
|  | 
 | ||||||
|  | from ._functools import compose | ||||||
|  | from ._itertools import consume | ||||||
|  | 
 | ||||||
|  | from ._support import import_or_skip | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | big_o = import_or_skip('big_o') | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class TestComplexity(unittest.TestCase): | ||||||
|  |     def test_implied_dirs_performance(self): | ||||||
|  |         best, others = big_o.big_o( | ||||||
|  |             compose(consume, zipfile.CompleteDirs._implied_dirs), | ||||||
|  |             lambda size: [ | ||||||
|  |                 '/'.join(string.ascii_lowercase + str(n)) for n in range(size) | ||||||
|  |             ], | ||||||
|  |             max_n=1000, | ||||||
|  |             min_n=1, | ||||||
|  |         ) | ||||||
|  |         assert best <= big_o.complexities.Linear | ||||||
|  | @ -3,7 +3,6 @@ | ||||||
| import contextlib | import contextlib | ||||||
| import pathlib | import pathlib | ||||||
| import pickle | import pickle | ||||||
| import string |  | ||||||
| import sys | import sys | ||||||
| import unittest | import unittest | ||||||
| import zipfile | import zipfile | ||||||
|  | @ -12,7 +11,6 @@ | ||||||
| from ._itertools import Counter | from ._itertools import Counter | ||||||
| 
 | 
 | ||||||
| from ._test_params import parameterize, Invoked | from ._test_params import parameterize, Invoked | ||||||
| from ._func_timeout_compat import set_timeout |  | ||||||
| 
 | 
 | ||||||
| from test.support.os_helper import temp_dir | from test.support.os_helper import temp_dir | ||||||
| 
 | 
 | ||||||
|  | @ -22,9 +20,6 @@ class itertools: | ||||||
|         Counter = Counter |         Counter = Counter | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| consume = tuple |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def add_dirs(zf): | def add_dirs(zf): | ||||||
|     """ |     """ | ||||||
|     Given a writable zip file zf, inject directory entries for |     Given a writable zip file zf, inject directory entries for | ||||||
|  | @ -330,12 +325,6 @@ def test_joinpath_constant_time(self): | ||||||
|         # Check the file iterated all items |         # Check the file iterated all items | ||||||
|         assert entries.count == self.HUGE_ZIPFILE_NUM_ENTRIES |         assert entries.count == self.HUGE_ZIPFILE_NUM_ENTRIES | ||||||
| 
 | 
 | ||||||
|     # timeout disabled due to #102209 |  | ||||||
|     # @set_timeout(3) |  | ||||||
|     def test_implied_dirs_performance(self): |  | ||||||
|         data = ['/'.join(string.ascii_lowercase + str(n)) for n in range(10000)] |  | ||||||
|         zipfile.CompleteDirs._implied_dirs(data) |  | ||||||
| 
 |  | ||||||
|     @pass_alpharep |     @pass_alpharep | ||||||
|     def test_read_does_not_close(self, alpharep): |     def test_read_does_not_close(self, alpharep): | ||||||
|         alpharep = self.zipfile_ondisk(alpharep) |         alpharep = self.zipfile_ondisk(alpharep) | ||||||
|  | @ -513,7 +502,7 @@ def test_pickle(self, alpharep, path_type, subpath): | ||||||
|         saved_1 = pickle.dumps(zipfile.Path(zipfile_ondisk, at=subpath)) |         saved_1 = pickle.dumps(zipfile.Path(zipfile_ondisk, at=subpath)) | ||||||
|         restored_1 = pickle.loads(saved_1) |         restored_1 = pickle.loads(saved_1) | ||||||
|         first, *rest = restored_1.iterdir() |         first, *rest = restored_1.iterdir() | ||||||
|         assert first.read_text().startswith('content of ') |         assert first.read_text(encoding='utf-8').startswith('content of ') | ||||||
| 
 | 
 | ||||||
|     @pass_alpharep |     @pass_alpharep | ||||||
|     def test_extract_orig_with_implied_dirs(self, alpharep): |     def test_extract_orig_with_implied_dirs(self, alpharep): | ||||||
|  | @ -525,3 +514,12 @@ def test_extract_orig_with_implied_dirs(self, alpharep): | ||||||
|         # wrap the zipfile for its side effect |         # wrap the zipfile for its side effect | ||||||
|         zipfile.Path(zf) |         zipfile.Path(zf) | ||||||
|         zf.extractall(source_path.parent) |         zf.extractall(source_path.parent) | ||||||
|  | 
 | ||||||
|  |     @pass_alpharep | ||||||
|  |     def test_getinfo_missing(self, alpharep): | ||||||
|  |         """ | ||||||
|  |         Validate behavior of getinfo on original zipfile after wrapping. | ||||||
|  |         """ | ||||||
|  |         zipfile.Path(alpharep) | ||||||
|  |         with self.assertRaises(KeyError): | ||||||
|  |             alpharep.getinfo('does-not-exist') | ||||||
|  |  | ||||||
|  | @ -86,6 +86,11 @@ class CompleteDirs(InitializedState, zipfile.ZipFile): | ||||||
|     """ |     """ | ||||||
|     A ZipFile subclass that ensures that implied directories |     A ZipFile subclass that ensures that implied directories | ||||||
|     are always included in the namelist. |     are always included in the namelist. | ||||||
|  | 
 | ||||||
|  |     >>> list(CompleteDirs._implied_dirs(['foo/bar.txt', 'foo/bar/baz.txt'])) | ||||||
|  |     ['foo/', 'foo/bar/'] | ||||||
|  |     >>> list(CompleteDirs._implied_dirs(['foo/bar.txt', 'foo/bar/baz.txt', 'foo/bar/'])) | ||||||
|  |     ['foo/'] | ||||||
|     """ |     """ | ||||||
| 
 | 
 | ||||||
|     @staticmethod |     @staticmethod | ||||||
|  | @ -215,7 +220,7 @@ class Path: | ||||||
| 
 | 
 | ||||||
|     Read text: |     Read text: | ||||||
| 
 | 
 | ||||||
|     >>> c.read_text() |     >>> c.read_text(encoding='utf-8') | ||||||
|     'content of c' |     'content of c' | ||||||
| 
 | 
 | ||||||
|     existence: |     existence: | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jason R. Coombs
						Jason R. Coombs