Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ jobs:
run: tox -e pep8
- name: Check covering
run: tox -e cover
- name: Run unit tests
run: tox -e unit
- name: Test with tox
run: tox

Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ doc/build
.coverage
build/
.venv/
*/__pycache__/
*__pycache__/
13 changes: 13 additions & 0 deletions beagle/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ def get_parser(self, prog_name):
dest='file_pattern',
help='file name pattern',
)
parser.add_argument(
'--exclude',
dest='exclude',
action='append',
default=[],
help='exclude files or paths matching glob pattern (repeatable)',
)
parser.add_argument(
'--ignore-case',
default=False,
Expand Down Expand Up @@ -96,6 +103,12 @@ def check_repo(repo):

for repo, repo_matches in sorted(interesting_repos):
for repo_match in repo_matches['Matches']:
filename = repo_match['Filename']
# Exclude files matching any exclude pattern
if parsed_args.exclude:
if any(fnmatch.fnmatch(filename, pat)
for pat in parsed_args.exclude):
continue
for file_match in repo_match['Matches']:
if (parsed_args.ignore_comments and
file_match['Line'].lstrip().startswith(
Expand Down
Empty file added tests/__init__.py
Empty file.
63 changes: 63 additions & 0 deletions tests/test_search.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import unittest


class DummyArgs:
def __init__(self, exclude=None, repo_pattern=None,
ignore_comments=False, comment_marker='#', context_lines=0):
self.exclude = exclude or []
self.repo_pattern = repo_pattern or ''
self.ignore_comments = ignore_comments
self.comment_marker = comment_marker
self.context_lines = context_lines


class TestBeagleSearchExclude(unittest.TestCase):
def setUp(self):
# Simulate results as returned by hound.query
self.results = {
'repo1': {
'Matches': [
{'Filename': 'src/main.py',
'Matches': [{'LineNumber': 1,
'Line': 'foo', 'Before': [], 'After': []}]},
{'Filename': 'src/test_utils.py',
'Matches': [{'LineNumber': 2,
'Line': 'bar', 'Before': [], 'After': []}]},
{'Filename': 'docs/readme.py',
'Matches': [{'LineNumber': 3, 'Line': 'baz',
'Before': [], 'After': []}]},
]
}
}

def test_exclude_pattern(self):
from beagle.search import Search
search = Search(app=None, app_args=None)
args = DummyArgs(exclude=['*test*', '*doc*'])
found = list(search._flatten_results(self.results, args))
# Only src/main.py should remain
self.assertEqual(len(found), 1)
self.assertIn('src/main.py', found[0])

def test_no_exclude(self):
from beagle.search import Search
search = Search(app=None, app_args=None)
args = DummyArgs(exclude=[])
found = list(search._flatten_results(self.results, args))
self.assertEqual(len(found), 3)
self.assertIn('src/main.py', found[0])
self.assertIn('src/test_utils.py', found[1])
self.assertIn('docs/readme.py', found[2])

def test_partial_exclude(self):
from beagle.search import Search
search = Search(app=None, app_args=None)
args = DummyArgs(exclude=['*test*'])
found = list(search._flatten_results(self.results, args))
self.assertEqual(len(found), 2)
self.assertIn('src/main.py', found[0])
self.assertIn('docs/readme.py', found[1])


if __name__ == '__main__':
unittest.main()
10 changes: 9 additions & 1 deletion tox.ini
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tox]
minversion = 3.2.0
envlist = py39,py310,py311,py312,py313,pep8
envlist = py39,py310,py311,py312,py313,pep8,unit

[testenv]
usedevelop = True
Expand Down Expand Up @@ -30,6 +30,14 @@ deps = -r{toxinidir}/doc/requirements.txt
commands =
sphinx-build -a -E -W -b html doc/source doc/build/html

[testenv:unit]
description = Run pytest-based unit tests
deps =
pytest
-rrequirements.txt
commands =
pytest tests

[flake8]
# E123, E125 skipped as they are invalid PEP-8.
# W504 skipped to give priority to W503
Expand Down