mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	bpo-22276: Change pathlib.Path.glob not to ignore trailing path separator (GH-10349)
Now pathlib.Path.glob() **only** matches directories when the pattern ends in a path separator. Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
This commit is contained in:
		
							parent
							
								
									0ef8d921f5
								
							
						
					
					
						commit
						ea2f5bcda1
					
				
					 5 changed files with 42 additions and 0 deletions
				
			
		|  | @ -815,6 +815,9 @@ call fails (for example because the path doesn't exist). | |||
| 
 | ||||
|    .. audit-event:: pathlib.Path.glob self,pattern pathlib.Path.glob | ||||
| 
 | ||||
|    .. versionchanged:: 3.11 | ||||
|       Return only directories if *pattern* ends with a pathname components | ||||
|       separator (:data:`~os.sep` or :data:`~os.altsep`). | ||||
| 
 | ||||
| .. method:: Path.group() | ||||
| 
 | ||||
|  | @ -1104,6 +1107,9 @@ call fails (for example because the path doesn't exist). | |||
| 
 | ||||
|    .. audit-event:: pathlib.Path.rglob self,pattern pathlib.Path.rglob | ||||
| 
 | ||||
|    .. versionchanged:: 3.11 | ||||
|       Return only directories if *pattern* ends with a pathname components | ||||
|       separator (:data:`~os.sep` or :data:`~os.altsep`). | ||||
| 
 | ||||
| .. method:: Path.rmdir() | ||||
| 
 | ||||
|  |  | |||
|  | @ -506,6 +506,15 @@ os | |||
|   instead of ``CryptGenRandom()`` which is deprecated. | ||||
|   (Contributed by Dong-hee Na in :issue:`44611`.) | ||||
| 
 | ||||
| 
 | ||||
| pathlib | ||||
| ------- | ||||
| 
 | ||||
| * :meth:`~pathlib.Path.glob` and :meth:`~pathlib.Path.rglob` return only | ||||
|   directories if *pattern* ends with a pathname components separator: | ||||
|   :data:`~os.sep` or :data:`~os.altsep`. | ||||
|   (Contributed by Eisuke Kawasima in :issue:`22276` and :issue:`33392`.) | ||||
| 
 | ||||
| re | ||||
| -- | ||||
| 
 | ||||
|  |  | |||
|  | @ -281,6 +281,8 @@ def make_uri(self, path): | |||
| def _make_selector(pattern_parts, flavour): | ||||
|     pat = pattern_parts[0] | ||||
|     child_parts = pattern_parts[1:] | ||||
|     if not pat: | ||||
|         return _TerminatingSelector() | ||||
|     if pat == '**': | ||||
|         cls = _RecursiveWildcardSelector | ||||
|     elif '**' in pat: | ||||
|  | @ -943,6 +945,8 @@ def glob(self, pattern): | |||
|         drv, root, pattern_parts = self._flavour.parse_parts((pattern,)) | ||||
|         if drv or root: | ||||
|             raise NotImplementedError("Non-relative patterns are unsupported") | ||||
|         if pattern[-1] in (self._flavour.sep, self._flavour.altsep): | ||||
|             pattern_parts.append('') | ||||
|         selector = _make_selector(tuple(pattern_parts), self._flavour) | ||||
|         for p in selector.select_from(self): | ||||
|             yield p | ||||
|  | @ -956,6 +960,8 @@ def rglob(self, pattern): | |||
|         drv, root, pattern_parts = self._flavour.parse_parts((pattern,)) | ||||
|         if drv or root: | ||||
|             raise NotImplementedError("Non-relative patterns are unsupported") | ||||
|         if pattern[-1] in (self._flavour.sep, self._flavour.altsep): | ||||
|             pattern_parts.append('') | ||||
|         selector = _make_selector(("**",) + tuple(pattern_parts), self._flavour) | ||||
|         for p in selector.select_from(self): | ||||
|             yield p | ||||
|  |  | |||
|  | @ -1662,6 +1662,11 @@ def _check(glob, expected): | |||
|         else: | ||||
|             _check(p.glob("*/fileB"), ['dirB/fileB', 'linkB/fileB']) | ||||
| 
 | ||||
|         if not os_helper.can_symlink(): | ||||
|             _check(p.glob("*/"), ["dirA", "dirB", "dirC", "dirE"]) | ||||
|         else: | ||||
|             _check(p.glob("*/"), ["dirA", "dirB", "dirC", "dirE", "linkB"]) | ||||
| 
 | ||||
|     def test_rglob_common(self): | ||||
|         def _check(glob, expected): | ||||
|             self.assertEqual(set(glob), { P(BASE, q) for q in expected }) | ||||
|  | @ -1679,6 +1684,16 @@ def _check(glob, expected): | |||
|                                         "linkB/fileB", "dirA/linkC/fileB"]) | ||||
|         _check(p.rglob("file*"), ["fileA", "dirB/fileB", | ||||
|                                   "dirC/fileC", "dirC/dirD/fileD"]) | ||||
|         if not os_helper.can_symlink(): | ||||
|             _check(p.rglob("*/"), [ | ||||
|                 "dirA", "dirB", "dirC", "dirC/dirD", "dirE", | ||||
|             ]) | ||||
|         else: | ||||
|             _check(p.rglob("*/"), [ | ||||
|                 "dirA", "dirA/linkC", "dirB", "dirB/linkD", "dirC", | ||||
|                 "dirC/dirD", "dirE", "linkB", | ||||
|             ]) | ||||
| 
 | ||||
|         p = P(BASE, "dirC") | ||||
|         _check(p.rglob("file*"), ["dirC/fileC", "dirC/dirD/fileD"]) | ||||
|         _check(p.rglob("*/*"), ["dirC/dirD/fileD"]) | ||||
|  | @ -2704,6 +2719,7 @@ def test_glob(self): | |||
|         P = self.cls | ||||
|         p = P(BASE) | ||||
|         self.assertEqual(set(p.glob("FILEa")), { P(BASE, "fileA") }) | ||||
|         self.assertEqual(set(p.glob("*a\\")), { P(BASE, "dirA") }) | ||||
|         self.assertEqual(set(p.glob("F*a")), { P(BASE, "fileA") }) | ||||
|         self.assertEqual(set(map(str, p.glob("FILEa"))), {f"{p}\\FILEa"}) | ||||
|         self.assertEqual(set(map(str, p.glob("F*a"))), {f"{p}\\fileA"}) | ||||
|  | @ -2712,6 +2728,7 @@ def test_rglob(self): | |||
|         P = self.cls | ||||
|         p = P(BASE, "dirC") | ||||
|         self.assertEqual(set(p.rglob("FILEd")), { P(BASE, "dirC/dirD/fileD") }) | ||||
|         self.assertEqual(set(p.rglob("*\\")), { P(BASE, "dirC/dirD") }) | ||||
|         self.assertEqual(set(map(str, p.rglob("FILEd"))), {f"{p}\\dirD\\FILEd"}) | ||||
| 
 | ||||
|     def test_expanduser(self): | ||||
|  |  | |||
|  | @ -0,0 +1,4 @@ | |||
| :class:`~pathlib.Path` methods :meth:`~pathlib.Path.glob` and :meth:`~pathlib.Path.rglob` return only | ||||
| directories if *pattern* ends with a pathname components separator | ||||
| (``/`` or :data:`~os.sep`). | ||||
| Patch by Eisuke Kawashima. | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Eisuke Kawashima
						Eisuke Kawashima