Skip to content

Enhance and make parsing more lenient in no-todos #24

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 18, 2024
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
13 changes: 11 additions & 2 deletions hooks/no_todos.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,17 @@ def main(argv: Sequence[str] | None = None) -> int:
result = 0

for filename in args.filenames:
with open(filename, encoding='utf-8') as f:
lines = f.readlines()
try:
with open(filename, encoding='utf-8-sig') as f:
lines = f.readlines()
except (UnicodeDecodeError, UnicodeError):
print(f'{filename}: cannot be read as UTF-8, trying UTF-16')
try:
with open(filename, encoding='utf-16') as f:
lines = f.readlines()
except (UnicodeDecodeError, UnicodeError):
print(f'{filename}: cannot be read as UTF-16, skipping it')
continue

for tag in disallowed:
for line in lines:
Expand Down
102 changes: 49 additions & 53 deletions tests/test_cojira.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from __future__ import annotations

import json
import re
import subprocess
import unittest
from os import environ
from typing import Any
from unittest.mock import call
from unittest.mock import patch
from urllib import request
from urllib.error import HTTPError
from urllib.error import URLError
Expand Down Expand Up @@ -461,7 +461,7 @@ def test_jira_pat_as_env_var(tmpdir):
(
'pseudo_commit_msg.txt', '-e=none',
'-u=http://banana', '-p=$YYYJIRA_PAT',
)
),
) == 0


Expand All @@ -470,55 +470,65 @@ def test_version_empty_via_env_var(tmpdir):
environ['EMPTY_VERSION'] = ''
with (
tmpdir.as_cwd(),
unittest.mock.patch('builtins.print') as mocked_print,
patch('builtins.print') as mocked_print,
):
exec_cmd('git', 'init')
f = tmpdir.join('pseudo_commit_msg.txt')
f.write_text('ABC-123: Banana', encoding='utf-8')
assert cojira.main(
(
'pseudo_commit_msg.txt',
f'-v=$EMPTY_VERSION',
'-v=$EMPTY_VERSION',
'-u=http://banana', '-p=pat_on_the_back',
),
) == 0
assert call('Ticket fix version not checked') \
in mocked_print.mock_calls
assert mocked_print.call_args_list[-2].args[0] \
.endswith('Ticket fix version not checked')
assert mocked_print.call_args_list[-1].args[0] \
.endswith('Ticket is OK according to COJIRA rules')


def test_version_multiple_via_env_var(tmpdir):
cojira.request.urlopen = mocked_response
environ['EMPTY_VERSION'] = 'a,b,version'
with (
tmpdir.as_cwd(),
unittest.mock.patch('builtins.print') as mocked_print,
patch('builtins.print') as mocked_print,
):
exec_cmd('git', 'init')
f = tmpdir.join('pseudo_commit_msg.txt')
f.write_text('ABC-123: Banana', encoding='utf-8')
assert cojira.main(
(
'pseudo_commit_msg.txt',
f'-v=$EMPTY_VERSION',
'-v=$EMPTY_VERSION',
'-u=http://banana', '-p=pat_on_the_back',
),
) == 0
assert call('Ticket fix version ("version") is allowed') \
in mocked_print.mock_calls
assert mocked_print.call_args_list[-3].args[0] \
.startswith('Ticket fix version ("version") is allowed')
assert (
call('\t(allowed versions are: ({\'a\', \'b\', \'version\'}))') \
in mocked_print.mock_calls or
call('\t(allowed versions are: ({\'a\', \'version\', \'b\'}))') \
in mocked_print.mock_calls or
call('\t(allowed versions are: ({\'version\', \'a\', \'b\'}))') \
in mocked_print.mock_calls or
call('\t(allowed versions are: ({\'b\', \'a\', \'version\'}))') \
in mocked_print.mock_calls or
call('\t(allowed versions are: ({\'b\', \'version\', \'a\'}))') \
in mocked_print.mock_calls or
call('\t(allowed versions are: ({\'version\', \'b\', \'a\'}))') \
in mocked_print.mock_calls
mocked_print.call_args_list[-2].args[0].endswith(
'\t(allowed versions are: ({\'a\', \'b\', \'version\'}))',
) or
mocked_print.call_args_list[-2].args[0].endswith(
'\t(allowed versions are: ({\'a\', \'version\', \'b\'}))',
) or
mocked_print.call_args_list[-2].args[0].endswith(
'\t(allowed versions are: ({\'version\', \'a\', \'b\'}))',
) or
mocked_print.call_args_list[-2].args[0].endswith(
'\t(allowed versions are: ({\'b\', \'a\', \'version\'}))',
) or
mocked_print.call_args_list[-2].args[0].endswith(
'\t(allowed versions are: ({\'b\', \'version\', \'a\'}))',
) or
mocked_print.call_args_list[-2].args[0].endswith(
'\t(allowed versions are: ({\'version\', \'b\', \'a\'}))',
)
)
assert mocked_print.call_args_list[-1].args[0] \
.endswith('Ticket is OK according to COJIRA rules')


@pytest.mark.parametrize(
Expand All @@ -531,7 +541,6 @@ def test_version_multiple_via_env_var(tmpdir):
texts=[
'Lenient early exit, because no JIRA URI given',
],
alts=[],
),
dict(
e=4,
Expand All @@ -541,7 +550,6 @@ def test_version_multiple_via_env_var(tmpdir):
texts=[
'Could not reify ticket from commit message',
],
alts=[],
),
dict(
e=3,
Expand All @@ -552,23 +560,21 @@ def test_version_multiple_via_env_var(tmpdir):
'-u=http://banana',
),
texts=[
'\t\\(allowed versions are: \\({\'not-this-version\'}\\)\\)',
'Ticket has no fix version, but it is expected',
'\t(allowed versions are: ({\'not-this-version\'}))',
],
alts=[],
),
dict(
e=1,
msg='ABC-123: Banana',
u=lambda _: MockedResponse('<this><is not="a"/><json/></this>'),
args=('pseudo_commit_msg.txt', '-u=http://banana'),
texts=[
'\t disallowed categories are: \\({\'done\'}\\)\\)',
'\t\\(allowed categories are: \\(\\),',
r'Ticket status category \("None"\) is not allowed',
'Ticket fix version not checked',
'Ticket status category ("None") is not allowed',
'\t(allowed categories are: (),',
'\t disallowed categories are: ({\'done\'}))',
],
alts=[],
),
dict(
e=2,
Expand All @@ -579,13 +585,9 @@ def test_version_multiple_via_env_var(tmpdir):
'-u=http://banana',
),
texts=[
'Fix version of ticket ("version") is not allowed',
],
alts=[
[
'\t(allowed versions are: ({\'version2\', \'version3\'}))',
'\t(allowed versions are: ({\'version3\', \'version2\'}))',
],
'\t\\(allowed versions are: \\({\'version[23]\','
' \'version[23]\'}\\)\\)',
r'Fix version of ticket \("version"\) is not allowed',
],
),
dict(
Expand All @@ -597,34 +599,28 @@ def test_version_multiple_via_env_var(tmpdir):
'-u=http://banana',
),
texts=[
'Checking ticket "ABC-123"',
'Ticket fix version ("version") is allowed',
'Ticket is OK according to COJIRA rules',
],
alts=[
[
'\t(allowed versions are: ({\'version2\', \'version\'}))',
'\t(allowed versions are: ({\'version\', \'version2\'}))',
],
'\t\\(allowed versions are: \\({\'version2?\','
' \'version2?\'}\\)\\)',
r'Ticket fix version \("version"\) is allowed',
'Checking ticket "ABC-123"',
],
),
],
)
def test_cojira_outputs(tmpdir, params):
with (
tmpdir.as_cwd(),
unittest.mock.patch('builtins.print') as mocked_print,
patch('builtins.print') as mocked_print,
):
if params['u'] is not None:
cojira.request.urlopen = params['u']
exec_cmd('git', 'init')
f = tmpdir.join('pseudo_commit_msg.txt')
f.write_text(params['msg'], encoding='utf-8')
assert cojira.main(params['args']) == params['e']
index = -1
for t in params['texts']:
assert call(t) in mocked_print.mock_calls
for p in params['alts']:
assert (
call(p[0]) in mocked_print.mock_calls or
call(p[1]) in mocked_print.mock_calls
)
assert re.match(t, mocked_print.call_args_list[index].args[0]) \
is not None
index -= 1
90 changes: 48 additions & 42 deletions tests/test_commiticketing.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@

import random
import subprocess
import unittest
from pathlib import Path
from typing import Any
from unittest.mock import call
from unittest.mock import patch

import pytest
from typing_extensions import Buffer
Expand Down Expand Up @@ -166,13 +165,13 @@ def test_get_prefix(tmpdir, params):


def test_not_reified(tmpdir):
with unittest.mock.patch('builtins.print') as mocked_print:
with patch('builtins.print') as mocked_print:
with tmpdir.as_cwd():
f = tmpdir.join('pseudo_commit_msg.txt')
f.write_text('Abracadabra', encoding='utf-8')
assert commiticketing.main((str(f),)) == 3
assert call('Could not reify branch name.') \
in mocked_print.mock_calls
assert mocked_print.call_args_list[-1].args[0] \
.endswith('Could not reify branch name.')


@pytest.mark.parametrize('branch_name', test_set_2)
Expand All @@ -193,7 +192,7 @@ def test_out_of_scope_branch_default(tmpdir, branch_name):
],
)
def test_out_of_scope_branch_non_default(tmpdir, params):
with unittest.mock.patch('builtins.print') as mocked_print:
with patch('builtins.print') as mocked_print:
with tmpdir.as_cwd():
exec_cmd('git', 'init')
exec_cmd('git', 'checkout', '-b', params['branch'])
Expand All @@ -202,10 +201,11 @@ def test_out_of_scope_branch_non_default(tmpdir, params):
assert commiticketing.main(
('-b', params['proc'], '-t', params['leveled'], str(f)),
) == 1
assert call(
assert mocked_print.call_args_list[-1].args[0] \
.endswith(
f"You wanted to commit to a branch [{params['branch']}], "
'which does not correspond to the commiticketing setup.',
) in mocked_print.mock_calls
)


@pytest.mark.parametrize(
Expand All @@ -216,17 +216,18 @@ def test_out_of_scope_branch_non_default(tmpdir, params):
),
)
def test_in_scope_mismatched_default(tmpdir, branch_name):
with unittest.mock.patch('builtins.print') as mocked_print:
with patch('builtins.print') as mocked_print:
with tmpdir.as_cwd():
exec_cmd('git', 'init')
exec_cmd('git', 'checkout', '-b', branch_name)
f = tmpdir.join('pseudo_commit_msg.txt')
f.write_text('Abracadabra', encoding='utf-8')
assert commiticketing.main((str(f),)) == 2
assert call(
f'[{branch_name}] does not correspond to branch naming '
'rules, consult guidelines.',
) in mocked_print.mock_calls
assert mocked_print.call_args_list[-1].args[0] \
.endswith(
f'[{branch_name}] does not correspond to branch naming '
'rules, consult guidelines.',
)


@pytest.mark.parametrize(
Expand Down Expand Up @@ -264,22 +265,25 @@ def test_in_scope_mismatched_non_default(tmpdir, params):
)
def test_prefix_if_not_there(tmpdir, branch_name):
prefix = commiticketing.get_prefix(branch_name, ['user', 'backup'])
with tmpdir.as_cwd():
with unittest.mock.patch('builtins.print') as mocked_print:
exec_cmd('git', 'init')
exec_cmd('git', 'checkout', '-b', branch_name)
f = tmpdir.join('pseudo_commit_msg.txt')
f.write_text('abracadabra', encoding='utf-8')
assert commiticketing.main((str(f),)) == 0
assert call('Commiticketing did not change your subject line.') \
not in mocked_print.mock_calls
assert call(
with (
tmpdir.as_cwd(),
patch('builtins.print') as mocked_print,
):
exec_cmd('git', 'init')
exec_cmd('git', 'checkout', '-b', branch_name)
f = tmpdir.join('pseudo_commit_msg.txt')
f.write_text('abracadabra', encoding='utf-8')
assert commiticketing.main((str(f),)) == 0
assert not mocked_print.call_args_list[-1].args[0] \
.endswith('Commiticketing did not change your subject line.')
assert mocked_print.call_args_list[-1].args[0] \
.endswith(
'Commiticketing prefixed your subject line '
f'with [{prefix}: ] and made it sentence case'
' after.',
) in mocked_print.mock_calls
with open(f) as msg:
assert msg.readline() == f'{prefix}: Abracadabra'
)
with open(f) as msg:
assert msg.readline() == f'{prefix}: Abracadabra'


@pytest.mark.parametrize(
Expand All @@ -299,24 +303,26 @@ def test_prefix_if_not_there(tmpdir, branch_name):
)
def test_prefix_not_doubling(tmpdir, params):
prefix = commiticketing.get_prefix(params['branch'], ['user', 'backup'])
with tmpdir.as_cwd():
with unittest.mock.patch('builtins.print') as mocked_print:
exec_cmd('git', 'init')
exec_cmd('git', 'checkout', '-b', params['branch'])
f = tmpdir.join('pseudo_commit_msg.txt')
f.write_text(
f"{prefix}: {params['msg']}",
encoding='utf-8',
)
assert commiticketing.main((str(f),)) == 0
with open(f) as msg:
assert msg.readline() == f'{prefix}: Abracadabra'
with (
tmpdir.as_cwd(),
patch('builtins.print') as mocked_print,
):
exec_cmd('git', 'init')
exec_cmd('git', 'checkout', '-b', params['branch'])
f = tmpdir.join('pseudo_commit_msg.txt')
f.write_text(
f"{prefix}: {params['msg']}",
encoding='utf-8',
)
assert commiticketing.main((str(f),)) == 0
with open(f) as msg:
assert msg.readline() == f'{prefix}: Abracadabra'
if params['msg'] == 'Abracadabra':
assert call('Commiticketing did not change your subject line.') \
in mocked_print.mock_calls
assert mocked_print.call_args_list[-1].args[0] \
.endswith('Commiticketing did not change your subject line.')
elif params['msg'] == 'abracadabra':
assert call('Commiticketing did not change your subject line.') \
not in mocked_print.mock_calls
assert not mocked_print.call_args_list[-1].args[0] \
.endswith('Commiticketing did not change your subject line.')


@pytest.mark.parametrize(
Expand Down
Loading
Loading