Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-pathspec for openSUSE:Factory 
checked in at 2022-12-05 18:00:30
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pathspec (Old)
 and      /work/SRC/openSUSE:Factory/.python-pathspec.new.1835 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-pathspec"

Mon Dec  5 18:00:30 2022 rev:11 rq:1039910 version:0.10.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pathspec/python-pathspec.changes  
2022-09-16 13:32:15.201251758 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-pathspec.new.1835/python-pathspec.changes    
    2022-12-05 18:00:32.688367130 +0100
@@ -1,0 +2,14 @@
+Sat Dec  3 19:55:41 UTC 2022 - Yogalakshmi Arunachalam <[email protected]>
+
+- Update to version 0.10.2: 
+  Bug fixes:
+  * Fix failing tests on Windows.
+  * Type hint on root parameter on 
pathspec.pathspec.PathSpec.match_tree_entries().
+  * Type hint on root parameter on 
pathspec.pathspec.PathSpec.match_tree_files().
+  * Type hint on root parameter on pathspec.util.iter_tree_entries().
+  * Type hint on root parameter on pathspec.util.iter_tree_files().
+  * Issue #64: IndexError with my .gitignore file when trying to build a 
Python package.
+  Improvements:
+  * Issue #58: CI: add GitHub Actions test workflow.
+
+-------------------------------------------------------------------

Old:
----
  pathspec-0.10.1.tar.gz

New:
----
  pathspec-0.10.2.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-pathspec.spec ++++++
--- /var/tmp/diff_new_pack.8BKngD/_old  2022-12-05 18:00:33.080369265 +0100
+++ /var/tmp/diff_new_pack.8BKngD/_new  2022-12-05 18:00:33.084369286 +0100
@@ -18,7 +18,7 @@
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-pathspec
-Version:        0.10.1
+Version:        0.10.2
 Release:        0
 Summary:        Utility library for gitignore style pattern matching of file 
paths
 License:        MPL-2.0

++++++ pathspec-0.10.1.tar.gz -> pathspec-0.10.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pathspec-0.10.1/CHANGES.rst 
new/pathspec-0.10.2/CHANGES.rst
--- old/pathspec-0.10.1/CHANGES.rst     2022-09-02 14:58:52.000000000 +0200
+++ new/pathspec-0.10.2/CHANGES.rst     2022-11-13 04:31:41.000000000 +0100
@@ -3,6 +3,27 @@
 ==============
 
 
+0.10.2 (2022-11-12)
+-------------------
+
+Bug fixes:
+
+- Fix failing tests on Windows.
+- Type hint on *root* parameter on 
`pathspec.pathspec.PathSpec.match_tree_entries()`.
+- Type hint on *root* parameter on 
`pathspec.pathspec.PathSpec.match_tree_files()`.
+- Type hint on *root* parameter on `pathspec.util.iter_tree_entries()`.
+- Type hint on *root* parameter on `pathspec.util.iter_tree_files()`.
+- `Issue #64`_: IndexError with my .gitignore file when trying to build a 
Python package.
+
+Improvements:
+
+- `Issue #58`_: CI: add GitHub Actions test workflow.
+
+
+.. _`Issue #58`: https://github.com/cpburnz/python-pathspec/pull/58
+.. _`Issue #64`: https://github.com/cpburnz/python-pathspec/issues/64
+
+
 0.10.1 (2022-09-02)
 -------------------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pathspec-0.10.1/PKG-INFO new/pathspec-0.10.2/PKG-INFO
--- old/pathspec-0.10.1/PKG-INFO        2022-09-02 14:59:57.875713800 +0200
+++ new/pathspec-0.10.2/PKG-INFO        2022-11-13 04:34:39.965963100 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: pathspec
-Version: 0.10.1
+Version: 0.10.2
 Summary: Utility library for gitignore style pattern matching of file paths.
 Home-page: https://github.com/cpburnz/python-pathspec
 Author: Caleb P. Burns
@@ -202,6 +202,27 @@
 ==============
 
 
+0.10.2 (2022-11-12)
+-------------------
+
+Bug fixes:
+
+- Fix failing tests on Windows.
+- Type hint on *root* parameter on 
`pathspec.pathspec.PathSpec.match_tree_entries()`.
+- Type hint on *root* parameter on 
`pathspec.pathspec.PathSpec.match_tree_files()`.
+- Type hint on *root* parameter on `pathspec.util.iter_tree_entries()`.
+- Type hint on *root* parameter on `pathspec.util.iter_tree_files()`.
+- `Issue #64`_: IndexError with my .gitignore file when trying to build a 
Python package.
+
+Improvements:
+
+- `Issue #58`_: CI: add GitHub Actions test workflow.
+
+
+.. _`Issue #58`: https://github.com/cpburnz/python-pathspec/pull/58
+.. _`Issue #64`: https://github.com/cpburnz/python-pathspec/issues/64
+
+
 0.10.1 (2022-09-02)
 -------------------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pathspec-0.10.1/README-dist.rst 
new/pathspec-0.10.2/README-dist.rst
--- old/pathspec-0.10.1/README-dist.rst 2022-09-02 14:59:55.000000000 +0200
+++ new/pathspec-0.10.2/README-dist.rst 2022-11-13 04:34:37.000000000 +0100
@@ -172,6 +172,27 @@
 ==============
 
 
+0.10.2 (2022-11-12)
+-------------------
+
+Bug fixes:
+
+- Fix failing tests on Windows.
+- Type hint on *root* parameter on 
`pathspec.pathspec.PathSpec.match_tree_entries()`.
+- Type hint on *root* parameter on 
`pathspec.pathspec.PathSpec.match_tree_files()`.
+- Type hint on *root* parameter on `pathspec.util.iter_tree_entries()`.
+- Type hint on *root* parameter on `pathspec.util.iter_tree_files()`.
+- `Issue #64`_: IndexError with my .gitignore file when trying to build a 
Python package.
+
+Improvements:
+
+- `Issue #58`_: CI: add GitHub Actions test workflow.
+
+
+.. _`Issue #58`: https://github.com/cpburnz/python-pathspec/pull/58
+.. _`Issue #64`: https://github.com/cpburnz/python-pathspec/issues/64
+
+
 0.10.1 (2022-09-02)
 -------------------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pathspec-0.10.1/pathspec/_meta.py 
new/pathspec-0.10.2/pathspec/_meta.py
--- old/pathspec-0.10.1/pathspec/_meta.py       2022-09-02 14:57:05.000000000 
+0200
+++ new/pathspec-0.10.2/pathspec/_meta.py       2022-11-13 04:33:03.000000000 
+0100
@@ -46,6 +46,7 @@
        "jack1142 <https://github.com/jack1142>",
        "mgorny <https://github.com/mgorny>",
        "bzakdd <https://github.com/bzakdd>",
+       "haimat <https://github.com/haimat>",
 ]
 __license__ = "MPL 2.0"
-__version__ = "0.10.1"
+__version__ = "0.10.2"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pathspec-0.10.1/pathspec/gitignore.py 
new/pathspec-0.10.2/pathspec/gitignore.py
--- old/pathspec-0.10.1/pathspec/gitignore.py   2022-08-31 04:30:13.000000000 
+0200
+++ new/pathspec-0.10.2/pathspec/gitignore.py   2022-11-12 17:34:39.000000000 
+0100
@@ -16,7 +16,9 @@
 from .pattern import (
        Pattern)
 from .patterns.gitwildmatch import (
-       GitWildMatchPattern)
+       GitWildMatchPattern,
+       GitWildMatchPatternError,
+       _DIR_MARK)
 from .util import (
        _is_iterable)
 
@@ -101,7 +103,17 @@
                                        # Pattern matched.
 
                                        # Check for directory marker.
-                                       dir_mark = match.match.group('ps_d')
+                                       try:
+                                               dir_mark = 
match.match.group(_DIR_MARK)
+                                       except IndexError as e:
+                                               # NOTICE: The exact content of 
this error message is subject
+                                               # to change.
+                                               raise GitWildMatchPatternError((
+                                                       f"Invalid git pattern: 
directory marker regex group is missing. "
+                                                       f"Debug: file={file!r} 
regex={pattern.regex!r} "
+                                                       f"group={_DIR_MARK!r} 
match={match.match!r}."
+                                               )) from e
+
                                        if dir_mark:
                                                # Pattern matched by a 
directory pattern.
                                                priority = 1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pathspec-0.10.1/pathspec/pathspec.py 
new/pathspec-0.10.2/pathspec/pathspec.py
--- old/pathspec-0.10.1/pathspec/pathspec.py    2022-08-31 04:30:13.000000000 
+0200
+++ new/pathspec-0.10.2/pathspec/pathspec.py    2022-09-08 02:08:58.000000000 
+0200
@@ -206,7 +206,7 @@
 
        def match_tree_entries(
                self,
-               root: str,
+               root: Union[str, PathLike],
                on_error: Optional[Callable] = None,
                follow_links: Optional[bool] = None,
        ) -> Iterator[TreeEntry]:
@@ -233,7 +233,7 @@
 
        def match_tree_files(
                self,
-               root: str,
+               root: Union[str, PathLike],
                on_error: Optional[Callable] = None,
                follow_links: Optional[bool] = None,
        ) -> Iterator[str]:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pathspec-0.10.1/pathspec/patterns/gitwildmatch.py 
new/pathspec-0.10.2/pathspec/patterns/gitwildmatch.py
--- old/pathspec-0.10.1/pathspec/patterns/gitwildmatch.py       2022-09-02 
14:41:48.000000000 +0200
+++ new/pathspec-0.10.2/pathspec/patterns/gitwildmatch.py       2022-11-12 
17:34:39.000000000 +0100
@@ -19,6 +19,12 @@
 The encoding to use when parsing a byte string pattern.
 """
 
+_DIR_MARK = 'ps_d'
+"""
+The regex group name for the directory marker. This is only used by
+:class:`GitIgnoreSpec`.
+"""
+
 
 class GitWildMatchPatternError(ValueError):
        """
@@ -112,7 +118,7 @@
                                # EDGE CASE: The '**/' pattern should match 
everything except
                                # individual files in the root directory. This 
case cannot be
                                # adequately handled through normalization. Use 
the override.
-                               override_regex = '^.+(?P<ps_d>/).*$'
+                               override_regex = f'^.+(?P<{_DIR_MARK}>/).*$'
 
                        if not pattern_segs[0]:
                                # A pattern beginning with a slash ('/') will 
only match paths
@@ -160,7 +166,7 @@
                                                if i == 0 and i == end:
                                                        # A pattern consisting 
solely of double-asterisks ('**')
                                                        # will match every path.
-                                                       output.append('.+')
+                                                       
output.append(f'[^/]+(?:(?P<{_DIR_MARK}>/).*)?')
                                                elif i == 0:
                                                        # A normalized pattern 
beginning with double-asterisks
                                                        # ('**') will match any 
leading path segments.
@@ -169,7 +175,7 @@
                                                elif i == end:
                                                        # A normalized pattern 
ending with double-asterisks ('**')
                                                        # will match any 
trailing path segments.
-                                                       
output.append('(?P<ps_d>/).*')
+                                                       
output.append(f'(?P<{_DIR_MARK}>/).*')
                                                else:
                                                        # A pattern with inner 
double-asterisks ('**') will match
                                                        # multiple (or zero) 
inner path segments.
@@ -187,7 +193,7 @@
                                                        # A pattern ending 
without a slash ('/') will match a file
                                                        # or a directory (with 
paths underneath it). E.g., "foo"
                                                        # matches "foo", 
"foo/bar", "foo/bar/baz", etc.
-                                                       
output.append('(?:(?P<ps_d>/).*)?')
+                                                       
output.append(f'(?:(?P<{_DIR_MARK}>/).*)?')
 
                                                need_slash = True
 
@@ -205,7 +211,7 @@
                                                        # A pattern ending 
without a slash ('/') will match a file
                                                        # or a directory (with 
paths underneath it). E.g., "foo"
                                                        # matches "foo", 
"foo/bar", "foo/bar/baz", etc.
-                                                       
output.append('(?:(?P<ps_d>/).*)?')
+                                                       
output.append(f'(?:(?P<{_DIR_MARK}>/).*)?')
 
                                                need_slash = True
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pathspec-0.10.1/pathspec/util.py 
new/pathspec-0.10.2/pathspec/util.py
--- old/pathspec-0.10.1/pathspec/util.py        2022-08-31 04:30:13.000000000 
+0200
+++ new/pathspec-0.10.2/pathspec/util.py        2022-09-08 02:01:52.000000000 
+0200
@@ -122,14 +122,15 @@
 
 
 def iter_tree_entries(
-       root: str,
+       root: Union[str, PathLike],
        on_error: Optional[Callable] = None,
        follow_links: Optional[bool] = None,
 ) -> Iterator['TreeEntry']:
        """
        Walks the specified directory for all files and directories.
 
-       *root* (:class:`str`) is the root directory to search.
+       *root* (:class:`str` or :class:`os.PathLike`) is the root directory to
+       search.
 
        *on_error* (:class:`~collections.abc.Callable` or :data:`None`)
        optionally is the error handler for file-system exceptions. It will be
@@ -237,14 +238,15 @@
 
 
 def iter_tree_files(
-       root: str,
+       root: Union[str, PathLike],
        on_error: Optional[Callable] = None,
        follow_links: Optional[bool] = None,
 ) -> Iterator[str]:
        """
        Walks the specified directory for all files.
 
-       *root* (:class:`str`) is the root directory to search for files.
+       *root* (:class:`str` or :class:`os.PathLike`) is the root directory to
+       search for files.
 
        *on_error* (:class:`~collections.abc.Callable` or :data:`None`)
        optionally is the error handler for file-system exceptions. It will be
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pathspec-0.10.1/pathspec.egg-info/PKG-INFO 
new/pathspec-0.10.2/pathspec.egg-info/PKG-INFO
--- old/pathspec-0.10.1/pathspec.egg-info/PKG-INFO      2022-09-02 
14:59:57.000000000 +0200
+++ new/pathspec-0.10.2/pathspec.egg-info/PKG-INFO      2022-11-13 
04:34:39.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: pathspec
-Version: 0.10.1
+Version: 0.10.2
 Summary: Utility library for gitignore style pattern matching of file paths.
 Home-page: https://github.com/cpburnz/python-pathspec
 Author: Caleb P. Burns
@@ -202,6 +202,27 @@
 ==============
 
 
+0.10.2 (2022-11-12)
+-------------------
+
+Bug fixes:
+
+- Fix failing tests on Windows.
+- Type hint on *root* parameter on 
`pathspec.pathspec.PathSpec.match_tree_entries()`.
+- Type hint on *root* parameter on 
`pathspec.pathspec.PathSpec.match_tree_files()`.
+- Type hint on *root* parameter on `pathspec.util.iter_tree_entries()`.
+- Type hint on *root* parameter on `pathspec.util.iter_tree_files()`.
+- `Issue #64`_: IndexError with my .gitignore file when trying to build a 
Python package.
+
+Improvements:
+
+- `Issue #58`_: CI: add GitHub Actions test workflow.
+
+
+.. _`Issue #58`: https://github.com/cpburnz/python-pathspec/pull/58
+.. _`Issue #64`: https://github.com/cpburnz/python-pathspec/issues/64
+
+
 0.10.1 (2022-09-02)
 -------------------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pathspec-0.10.1/pathspec.egg-info/SOURCES.txt 
new/pathspec-0.10.2/pathspec.egg-info/SOURCES.txt
--- old/pathspec-0.10.1/pathspec.egg-info/SOURCES.txt   2022-09-02 
14:59:57.000000000 +0200
+++ new/pathspec-0.10.2/pathspec.egg-info/SOURCES.txt   2022-11-13 
04:34:39.000000000 +0100
@@ -30,4 +30,5 @@
 tests/test_gitignore.py
 tests/test_gitwildmatch.py
 tests/test_pathspec.py
-tests/test_util.py
\ No newline at end of file
+tests/test_util.py
+tests/util.py
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pathspec-0.10.1/tests/test_gitignore.py 
new/pathspec-0.10.2/tests/test_gitignore.py
--- old/pathspec-0.10.1/tests/test_gitignore.py 2022-09-02 14:45:43.000000000 
+0200
+++ new/pathspec-0.10.2/tests/test_gitignore.py 2022-11-12 17:34:39.000000000 
+0100
@@ -311,3 +311,50 @@
                        'anydir/file.txt',
                        'product_dir/file.txt',
                })
+
+       def test_05_issue_39(self):
+               """
+               Test excluding files in a directory.
+               """
+               spec = GitIgnoreSpec.from_lines([
+                       '*.log',
+                       '!important/*.log',
+                       'trace.*',
+               ])
+               files = {
+                       'a.log',
+                       'b.txt',
+                       'important/d.log',
+                       'important/e.txt',
+                       'trace.c',
+               }
+               ignores = set(spec.match_files(files))
+               self.assertEqual(ignores, {
+                       'a.log',
+                       'trace.c',
+               })
+               self.assertEqual(files - ignores, {
+                       'b.txt',
+                       'important/d.log',
+                       'important/e.txt',
+               })
+
+       def test_06_issue_64(self):
+               """
+               Test using a double asterisk pattern.
+               """
+               spec = GitIgnoreSpec.from_lines([
+                       "**",
+               ])
+               files = {
+                       'x',
+                       'y.py',
+                       'A/x',
+                       'A/y.py',
+                       'A/B/x',
+                       'A/B/y.py',
+                       'A/B/C/x',
+                       'A/B/C/y.py',
+               }
+               ignores = set(spec.match_files(files))
+               self.assertEqual(ignores, files)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pathspec-0.10.1/tests/test_gitwildmatch.py 
new/pathspec-0.10.2/tests/test_gitwildmatch.py
--- old/pathspec-0.10.1/tests/test_gitwildmatch.py      2022-09-02 
14:33:13.000000000 +0200
+++ new/pathspec-0.10.2/tests/test_gitwildmatch.py      2022-11-12 
17:34:39.000000000 +0100
@@ -9,17 +9,18 @@
 from pathspec.patterns.gitwildmatch import (
        GitWildMatchPattern,
        GitWildMatchPatternError,
-       _BYTES_ENCODING)
+       _BYTES_ENCODING,
+       _DIR_MARK)
 from pathspec.util import (
        lookup_pattern)
 
 
-RE_DIR = "(?P<ps_d>/)"
+RE_DIR = f"(?P<{_DIR_MARK}>/)"
 """
 This regular expression matches the directory marker.
 """
 
-RE_SUB = "(?:(?P<ps_d>/).*)?"
+RE_SUB = f"(?:{RE_DIR}.*)?"
 """
 This regular expression matches an optional sub-path.
 """
@@ -257,7 +258,29 @@
                """
                regex, include = GitWildMatchPattern.pattern_to_regex('**')
                self.assertTrue(include)
-               self.assertEqual(regex, '^.+$')
+               self.assertEqual(regex, f'^[^/]+{RE_SUB}$')
+               pattern = GitWildMatchPattern(re.compile(regex), include)
+               results = set(filter(pattern.match_file, [
+                       'x',
+                       'y.py',
+                       'A/x',
+                       'A/y.py',
+                       'A/B/x',
+                       'A/B/y.py',
+                       'A/B/C/x',
+                       'A/B/C/y.py',
+               ]))
+
+               self.assertEqual(results, {
+                       'x',
+                       'y.py',
+                       'A/x',
+                       'A/y.py',
+                       'A/B/x',
+                       'A/B/y.py',
+                       'A/B/C/x',
+                       'A/B/C/y.py',
+               })
 
        def test_03_parent_double_asterisk(self):
                """
@@ -291,7 +314,7 @@
                """
                regex, include = GitWildMatchPattern.pattern_to_regex('**')
                self.assertTrue(include)
-               self.assertEqual(regex, '^.+$')
+               self.assertEqual(regex, f'^[^/]+{RE_SUB}$')
 
                equivalent_regex, include = 
GitWildMatchPattern.pattern_to_regex('**/**')
                self.assertTrue(include)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pathspec-0.10.1/tests/test_pathspec.py 
new/pathspec-0.10.2/tests/test_pathspec.py
--- old/pathspec-0.10.1/tests/test_pathspec.py  2022-09-02 14:45:17.000000000 
+0200
+++ new/pathspec-0.10.2/tests/test_pathspec.py  2022-09-08 02:20:27.000000000 
+0200
@@ -4,6 +4,7 @@
 
 import os
 import os.path
+import pathlib
 import shutil
 import tempfile
 import unittest
@@ -14,6 +15,10 @@
        PathSpec)
 from pathspec.util import (
        iter_tree_entries)
+from tests.util import (
+       make_dirs,
+       make_files,
+       ospath)
 
 
 class PathSpecTest(unittest.TestCase):
@@ -25,36 +30,19 @@
                """
                Create the specified directories.
                """
-               for dir in dirs:
-                       os.mkdir(os.path.join(self.temp_dir, self.ospath(dir)))
+               make_dirs(self.temp_dir, dirs)
 
        def make_files(self, files: Iterable[str]) -> None:
                """
                Create the specified files.
                """
-               for file in files:
-                       self.mkfile(os.path.join(self.temp_dir, 
self.ospath(file)))
-
-       @staticmethod
-       def mkfile(file: str) -> None:
-               """
-               Creates an empty file.
-               """
-               with open(file, 'wb'):
-                       pass
-
-       @staticmethod
-       def ospath(path: str) -> str:
-               """
-               Convert the POSIX path to a native OS path.
-               """
-               return os.path.join(*path.split('/'))
+               return make_files(self.temp_dir, files)
 
        def setUp(self) -> None:
                """
                Called before each test.
                """
-               self.temp_dir = tempfile.mkdtemp()
+               self.temp_dir = pathlib.Path(tempfile.mkdtemp())
 
        def tearDown(self) -> None:
                """
@@ -311,12 +299,12 @@
                        __entry.path
                        for __entry in spec.match_entries(entries)
                }
-               self.assertEqual(results, {
+               self.assertEqual(results, set(map(ospath, [
                        'X/a.txt',
                        'X/Z/c.txt',
                        'Y/a.txt',
                        'Y/Z/c.txt',
-               })
+               ])))
 
        def test_05_match_file(self):
                """
@@ -390,12 +378,12 @@
                        __entry.path
                        for __entry in spec.match_tree_entries(self.temp_dir)
                }
-               self.assertEqual(results, {
+               self.assertEqual(results, set(map(ospath, [
                        'X/a.txt',
                        'X/Z/c.txt',
                        'Y/a.txt',
                        'Y/Z/c.txt',
-               })
+               ])))
 
        def test_05_match_tree_files(self):
                """
@@ -420,12 +408,12 @@
                        'Y/Z/c.txt',
                ])
                results = set(spec.match_tree_files(self.temp_dir))
-               self.assertEqual(results, {
+               self.assertEqual(results, set(map(ospath, [
                        'X/a.txt',
                        'X/Z/c.txt',
                        'Y/a.txt',
                        'Y/Z/c.txt',
-               })
+               ])))
 
        def test_06_issue_41_a(self):
                """
@@ -537,3 +525,30 @@
                self.assertEqual(results, {
                        'anydir/file.txt',
                })
+
+       def test_08_issue_39(self):
+               """
+               Test excluding files in a directory.
+               """
+               spec = PathSpec.from_lines('gitwildmatch', [
+                       '*.log',
+                       '!important/*.log',
+                       'trace.*',
+               ])
+               files = {
+                       'a.log',
+                       'b.txt',
+                       'important/d.log',
+                       'important/e.txt',
+                       'trace.c',
+               }
+               ignores = set(spec.match_files(files))
+               self.assertEqual(ignores, {
+                       'a.log',
+                       'trace.c',
+               })
+               self.assertEqual(files - ignores, {
+                       'b.txt',
+                       'important/d.log',
+                       'important/e.txt',
+               })
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pathspec-0.10.1/tests/test_util.py 
new/pathspec-0.10.2/tests/test_util.py
--- old/pathspec-0.10.1/tests/test_util.py      2022-08-19 04:51:32.000000000 
+0200
+++ new/pathspec-0.10.2/tests/test_util.py      2022-09-08 02:58:17.000000000 
+0200
@@ -23,6 +23,12 @@
        iter_tree_files,
        match_file,
        normalize_file)
+from tests.util import (
+       make_dirs,
+       make_files,
+       make_links,
+       mkfile,
+       ospath)
 
 
 class MatchFileTest(unittest.TestCase):
@@ -65,39 +71,19 @@
                """
                Create the specified directories.
                """
-               for dir in dirs:
-                       os.mkdir(os.path.join(self.temp_dir, self.ospath(dir)))
+               make_dirs(self.temp_dir, dirs)
 
        def make_files(self, files: Iterable[str]) -> None:
                """
                Create the specified files.
                """
-               for file in files:
-                       self.mkfile(os.path.join(self.temp_dir, 
self.ospath(file)))
+               make_files(self.temp_dir, files)
 
        def make_links(self, links: Iterable[Tuple[str, str]]) -> None:
                """
                Create the specified links.
                """
-               for link, node in links:
-                       src = os.path.join(self.temp_dir, self.ospath(node))
-                       dest = os.path.join(self.temp_dir, self.ospath(link))
-                       os.symlink(src, dest)
-
-       @staticmethod
-       def mkfile(file: str) -> None:
-               """
-               Creates an empty file.
-               """
-               with open(file, 'wb'):
-                       pass
-
-       @staticmethod
-       def ospath(path: str) -> str:
-               """
-               Convert the POSIX path to a native OS path.
-               """
-               return os.path.join(*path.split('/'))
+               make_links(self.temp_dir, links)
 
        def require_realpath(self) -> None:
                """
@@ -118,7 +104,7 @@
                """
                Called before each test.
                """
-               self.temp_dir = tempfile.mkdtemp()
+               self.temp_dir = pathlib.Path(tempfile.mkdtemp())
 
        def tearDown(self) -> None:
                """
@@ -144,7 +130,7 @@
                        'Dir/Inner/f',
                ])
                results = set(iter_tree_files(self.temp_dir))
-               self.assertEqual(results, set(map(self.ospath, [
+               self.assertEqual(results, set(map(ospath, [
                        'a',
                        'b',
                        'Dir/c',
@@ -161,16 +147,16 @@
                # 3.2+.
                no_symlink = None
                try:
-                       file = os.path.join(self.temp_dir, 'file')
-                       link = os.path.join(self.temp_dir, 'link')
-                       self.mkfile(file)
+                       file = self.temp_dir / 'file'
+                       link = self.temp_dir / 'link'
+                       mkfile(file)
 
                        try:
                                os.symlink(file, link)
                        except (AttributeError, NotImplementedError, OSError):
                                no_symlink = True
-                               raise
-                       no_symlink = False
+                       else:
+                               no_symlink = False
 
                finally:
                        self.__class__.no_symlink = no_symlink
@@ -185,18 +171,17 @@
                broken_realpath = None
                try:
                        self.require_symlink()
-                       file = os.path.join(self.temp_dir, 'file')
-                       link = os.path.join(self.temp_dir, 'link')
-                       self.mkfile(file)
+                       file = self.temp_dir / 'file'
+                       link = self.temp_dir / 'link'
+                       mkfile(file)
                        os.symlink(file, link)
 
                        try:
                                self.assertEqual(os.path.realpath(file), 
os.path.realpath(link))
                        except AssertionError:
                                broken_realpath = True
-                               raise
-
-                       broken_realpath = False
+                       else:
+                               broken_realpath = False
 
                finally:
                        self.__class__.broken_realpath = broken_realpath
@@ -223,7 +208,7 @@
                        ('DirX', 'Dir'),
                ])
                results = set(iter_tree_files(self.temp_dir))
-               self.assertEqual(results, set(map(self.ospath, [
+               self.assertEqual(results, set(map(ospath, [
                        'a',
                        'ax',
                        'b',
@@ -260,7 +245,7 @@
                        ('Dir/Fx', 'Dir/Target'),
                ])
                results = set(iter_tree_files(self.temp_dir))
-               self.assertEqual(results, set(map(self.ospath, [
+               self.assertEqual(results, set(map(ospath, [
                        'Ax/Ex/file',
                        'Ax/Fx/file',
                        'Ax/Target/file',
@@ -293,7 +278,7 @@
                        set(iter_tree_files(self.temp_dir))
 
                self.assertEqual(context.exception.first_path, 'Dir')
-               self.assertEqual(context.exception.second_path, 
self.ospath('Dir/Self'))
+               self.assertEqual(context.exception.second_path, 
ospath('Dir/Self'))
 
        def test_2_5_recursive_circular_links(self):
                """
@@ -321,9 +306,9 @@
 
                self.assertIn(context.exception.first_path, ('A', 'B', 'C'))
                self.assertEqual(context.exception.second_path, {
-                       'A': self.ospath('A/Bx/Cx/Ax'),
-                       'B': self.ospath('B/Cx/Ax/Bx'),
-                       'C': self.ospath('C/Ax/Bx/Cx'),
+                       'A': ospath('A/Bx/Cx/Ax'),
+                       'B': ospath('B/Cx/Ax/Bx'),
+                       'C': ospath('C/Ax/Bx/Cx'),
                }[context.exception.first_path])
 
        def test_2_6_detect_broken_links(self):
@@ -375,7 +360,7 @@
                        ('DirX', 'Dir'),
                ])
                results = set(iter_tree_files(self.temp_dir, 
follow_links=False))
-               self.assertEqual(results, set(map(self.ospath, [
+               self.assertEqual(results, set(map(ospath, [
                        'A',
                        'Ax',
                        'B',
@@ -405,7 +390,7 @@
                        'Dir/Inner/f',
                ])
                results = {entry.path for entry in 
iter_tree_entries(self.temp_dir)}
-               self.assertEqual(results, set(map(self.ospath, [
+               self.assertEqual(results, set(map(ospath, [
                        'a',
                        'b',
                        'Dir',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pathspec-0.10.1/tests/util.py 
new/pathspec-0.10.2/tests/util.py
--- old/pathspec-0.10.1/tests/util.py   1970-01-01 01:00:00.000000000 +0100
+++ new/pathspec-0.10.2/tests/util.py   2022-09-08 01:10:25.000000000 +0200
@@ -0,0 +1,75 @@
+"""
+This module provides utility functions shared by tests.
+"""
+
+import os
+import os.path
+import pathlib
+
+from typing import (
+       Iterable,
+       Tuple)
+
+
+def make_dirs(temp_dir: pathlib.Path, dirs: Iterable[str]) -> None:
+       """
+       Create the specified directories.
+
+       *temp_dir* (:class:`pathlib.Path`) is the temporary directory to use.
+
+       *dirs* (:class:`Iterable` of :class:`str`) is the POSIX directory
+       paths (relative to *temp_dir*) to create.
+       """
+       for dir in dirs:
+               os.mkdir(temp_dir / ospath(dir))
+
+
+def make_files(temp_dir: pathlib.Path, files: Iterable[str]) -> None:
+       """
+       Create the specified files.
+
+       *temp_dir* (:class:`pathlib.Path`) is the temporary directory to use.
+
+       *files* (:class:`Iterable` of :class:`str`) is the POSIX file paths
+       (relative to *temp_dir*) to create.
+       """
+       for file in files:
+               mkfile(temp_dir / ospath(file))
+
+
+def make_links(temp_dir: pathlib.Path, links: Iterable[Tuple[str, str]]) -> 
None:
+       """
+       Create the specified links.
+
+       *temp_dir* (:class:`pathlib.Path`) is the temporary directory to use.
+
+       *links* (:class:`Iterable` of :class:`tuple`) contains the POSIX links
+       to create relative to *temp_dir*. Each link (:class:`tuple`) contains
+       the destination link path (:class:`str`) and source node path
+       (:class:`str`).
+       """
+       for link, node in links:
+               src = temp_dir / ospath(node)
+               dest = temp_dir / ospath(link)
+               os.symlink(src, dest)
+
+
+def mkfile(file: pathlib.Path) -> None:
+       """
+       Creates an empty file.
+
+       *file* (:class:`pathlib.Path`) is the native file path to create.
+       """
+       with open(file, 'wb'):
+               pass
+
+
+def ospath(path: str) -> str:
+       """
+       Convert the POSIX path to a native OS path.
+
+       *path* (:class:`str`) is the POSIX path.
+
+       Returns the native path (:class:`str`).
+       """
+       return os.path.join(*path.split('/'))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pathspec-0.10.1/tox.ini new/pathspec-0.10.2/tox.ini
--- old/pathspec-0.10.1/tox.ini 2022-08-13 04:06:31.000000000 +0200
+++ new/pathspec-0.10.2/tox.ini 2022-09-08 00:17:34.000000000 +0200
@@ -3,4 +3,4 @@
 isolated_build = True
 
 [testenv]
-commands = python -m unittest
+commands = python -m unittest {posargs}

Reply via email to