Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
elifarley committed Dec 20, 2024
1 parent 03a0c92 commit ff3aeb2
Showing 1 changed file with 50 additions and 24 deletions.
74 changes: 50 additions & 24 deletions tests.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
from unittest.mock import patch, mock_open
from pathlib import Path
from tempfile import TemporaryDirectory
from shutil import which
from subprocess import run


from gitignore_parser import parse_gitignore

from unittest import TestCase, main, SkipTest
from unittest import TestCase, main, SkipTest, skipUnless


class Test(TestCase):
def test_simple(self):
matches = _parse_gitignore_string(
matches = self._parse_gitignore_string(
'__pycache__/\n'
'*.py[cod]',
fake_base_dir='/home/michael'
Expand All @@ -18,9 +21,10 @@ def test_simple(self):
self.assertTrue(matches('/home/michael/main.pyc'))
self.assertTrue(matches('/home/michael/dir/main.pyc'))
self.assertTrue(matches('/home/michael/__pycache__'))
self.assertTrue(matches('/home/michael/__pycache__/'))

def test_incomplete_filename(self):
matches = _parse_gitignore_string('o.py', fake_base_dir='/home/michael')
matches = self._parse_gitignore_string('o.py', fake_base_dir='/home/michael')
self.assertTrue(matches('/home/michael/o.py'))
self.assertFalse(matches('/home/michael/foo.py'))
self.assertFalse(matches('/home/michael/o.pyc'))
Expand All @@ -29,7 +33,7 @@ def test_incomplete_filename(self):
self.assertFalse(matches('/home/michael/dir/o.pyc'))

def test_wildcard(self):
matches = _parse_gitignore_string(
matches = self._parse_gitignore_string(
'hello.*',
fake_base_dir='/home/michael'
)
Expand All @@ -41,7 +45,7 @@ def test_wildcard(self):
self.assertFalse(matches('/home/michael/helloX'))

def test_anchored_wildcard(self):
matches = _parse_gitignore_string(
matches = self._parse_gitignore_string(
'/hello.*',
fake_base_dir='/home/michael'
)
Expand All @@ -50,7 +54,7 @@ def test_anchored_wildcard(self):
self.assertFalse(matches('/home/michael/a/hello.java'))

def test_trailingspaces(self):
matches = _parse_gitignore_string(
matches = self._parse_gitignore_string(
'ignoretrailingspace \n'
'notignoredspace\\ \n'
'partiallyignoredspace\\ \n'
Expand All @@ -73,7 +77,7 @@ def test_trailingspaces(self):
self.assertFalse(matches('/home/michael/notignoredmultiplespace'))

def test_comment(self):
matches = _parse_gitignore_string(
matches = self._parse_gitignore_string(
'somematch\n'
'#realcomment\n'
'othermatch\n'
Expand All @@ -86,21 +90,21 @@ def test_comment(self):
self.assertTrue(matches('/home/michael/#imnocomment'))

def test_ignore_directory(self):
matches = _parse_gitignore_string('.venv/', fake_base_dir='/home/michael')
matches = self.parse_gitignore_string('.venv/', fake_base_dir='/home/michael')
self.assertTrue(matches('/home/michael/.venv'))
self.assertTrue(matches('/home/michael/.venv/folder'))
self.assertTrue(matches('/home/michael/.venv/file.txt'))
self.assertFalse(matches('/home/michael/.venv_other_folder'))
self.assertFalse(matches('/home/michael/.venv_no_folder.py'))

def test_ignore_directory_asterisk(self):
matches = _parse_gitignore_string('.venv/*', fake_base_dir='/home/michael')
matches = self._parse_gitignore_string('.venv/*', fake_base_dir='/home/michael')
self.assertFalse(matches('/home/michael/.venv'))
self.assertTrue(matches('/home/michael/.venv/folder'))
self.assertTrue(matches('/home/michael/.venv/file.txt'))

def test_negation(self):
matches = _parse_gitignore_string(
matches = self._parse_gitignore_string(
'''
*.ignore
!keep.ignore
Expand All @@ -112,20 +116,20 @@ def test_negation(self):
self.assertTrue(matches('/home/michael/waste.ignore'))

def test_literal_exclamation_mark(self):
matches = _parse_gitignore_string('\\!ignore_me!', fake_base_dir='/home/michael')
matches = self._parse_gitignore_string('\\!ignore_me!', fake_base_dir='/home/michael')
self.assertTrue(matches('/home/michael/!ignore_me!'))
self.assertFalse(matches('/home/michael/ignore_me!'))
self.assertFalse(matches('/home/michael/ignore_me'))

def test_double_asterisks(self):
matches = _parse_gitignore_string('foo/**/Bar', fake_base_dir='/home/michael')
matches = self._parse_gitignore_string('foo/**/Bar', fake_base_dir='/home/michael')
self.assertTrue(matches('/home/michael/foo/hello/Bar'))
self.assertTrue(matches('/home/michael/foo/world/Bar'))
self.assertTrue(matches('/home/michael/foo/Bar'))
self.assertFalse(matches('/home/michael/foo/BarBar'))

def test_double_asterisk_without_slashes_handled_like_single_asterisk(self):
matches = _parse_gitignore_string('a/b**c/d', fake_base_dir='/home/michael')
matches = self._parse_gitignore_string('a/b**c/d', fake_base_dir='/home/michael')
self.assertTrue(matches('/home/michael/a/bc/d'))
self.assertTrue(matches('/home/michael/a/bXc/d'))
self.assertTrue(matches('/home/michael/a/bbc/d'))
Expand All @@ -136,15 +140,15 @@ def test_double_asterisk_without_slashes_handled_like_single_asterisk(self):
self.assertFalse(matches('/home/michael/a/bb/XX/cc/d'))

def test_more_asterisks_handled_like_single_asterisk(self):
matches = _parse_gitignore_string('***a/b', fake_base_dir='/home/michael')
matches = self._parse_gitignore_string('***a/b', fake_base_dir='/home/michael')
self.assertTrue(matches('/home/michael/XYZa/b'))
self.assertFalse(matches('/home/michael/foo/a/b'))
matches = _parse_gitignore_string('a/b***', fake_base_dir='/home/michael')
matches = self._parse_gitignore_string('a/b***', fake_base_dir='/home/michael')
self.assertTrue(matches('/home/michael/a/bXYZ'))
self.assertFalse(matches('/home/michael/a/b/foo'))

def test_directory_only_negation(self):
matches = _parse_gitignore_string('''
matches = self._parse_gitignore_string('''
data/**
!data/**/
!.gitkeep
Expand All @@ -160,18 +164,18 @@ def test_directory_only_negation(self):
self.assertTrue(matches('/home/michael/data/02_processed/processed_file.csv'))

def test_single_asterisk(self):
matches = _parse_gitignore_string('*', fake_base_dir='/home/michael')
matches = self._parse_gitignore_string('*', fake_base_dir='/home/michael')
self.assertTrue(matches('/home/michael/file.txt'))
self.assertTrue(matches('/home/michael/directory'))
self.assertTrue(matches('/home/michael/directory-trailing/'))

def test_supports_path_type_argument(self):
matches = _parse_gitignore_string('file1\n!file2', fake_base_dir='/home/michael')
matches = self._parse_gitignore_string('file1\n!file2', fake_base_dir='/home/michael')
self.assertTrue(matches(Path('/home/michael/file1')))
self.assertFalse(matches(Path('/home/michael/file2')))

def test_slash_in_range_does_not_match_dirs(self):
matches = _parse_gitignore_string('abc[X-Z/]def', fake_base_dir='/home/michael')
matches = self._parse_gitignore_string('abc[X-Z/]def', fake_base_dir='/home/michael')
self.assertFalse(matches('/home/michael/abcdef'))
self.assertTrue(matches('/home/michael/abcXdef'))
self.assertTrue(matches('/home/michael/abcYdef'))
Expand All @@ -190,7 +194,7 @@ def test_symlink_to_another_directory(self):
with TemporaryDirectory() as project_dir, TemporaryDirectory() as another_dir:
project_dir = Path(project_dir).resolve()
another_dir = Path(another_dir).resolve()
matches = _parse_gitignore_string('link', fake_base_dir=project_dir)
matches = self._parse_gitignore_string('link', fake_base_dir=project_dir)

# Create a symlink to another directory.
link = project_dir / 'link'
Expand All @@ -207,10 +211,32 @@ def test_symlink_to_another_directory(self):
# files.
self.assertTrue(matches(link))

def _parse_gitignore_string(data: str, fake_base_dir: str = None):
with patch('builtins.open', mock_open(read_data=data)):
success = parse_gitignore(f'{fake_base_dir}/.gitignore', fake_base_dir)
return success
def _parse_gitignore_string(self, data: str, fake_base_dir: str|None = None):
with patch('builtins.open', mock_open(read_data=data)):
success = parse_gitignore(f'{fake_base_dir}/.gitignore', fake_base_dir)
return success

@skipUnless(which("git"), "Git not installed")
class TestAgainstGit(Test):
"""Testcase running tests against `git check-ignore`.
This is not to test if git is right, this is to validate that all
tests from the Test class are valid according to git.
"""
def setUp(self):
self.tmpdir = tempfile.TemporaryDirectory()
run(["git", "init"], cwd=self.tmpdir.name)

def tearDown(self):
self.tmpdir.cleanup()

def _parse_gitignore_string(self, data: str, fake_base_dir: Optional[str] = None):
(Path(self.tmpdir.name) / ".gitignore").write_text(data, encoding="UTF-8")

def matcher(path):
path = str(path).replace(fake_base_dir + "/", "")
return run(["git", "check-ignore", path], cwd=self.tmpdir.name, check=False).returncode == 0

return matcher

if __name__ == '__main__':
main()
Expand Down

0 comments on commit ff3aeb2

Please sign in to comment.