Skip to content
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

CHORE: Code Quality, long-standing issues #351

Merged
merged 7 commits into from
Jun 19, 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
2 changes: 1 addition & 1 deletion .github/workflows/todoon-issues-prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
MAXIMUM_ISSUES_GENERATED: 10
run: |
echo "Generate GitHub issues for each problem found, but don't fail the workflow unless one is found that has already been closed."
todoon -si
todoon -si --github-env
- name: Check duplicate closed issues
run: |
if [ "${{ env.TODOON_DUPLICATE_CLOSED_ISSUES }}" != "1" ]; then
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "todo-or-not"
version = "0.13.17"
version = "0.13.21"
description = "todoon integrates the TODOs in your codebase with your GitHub repository"
authors = ["TrentonYo <trentonyo@gmail.com>"]
license = "GPL-3.0-only"
Expand Down
4 changes: 3 additions & 1 deletion scripts/_update_versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,6 @@
last_line = init_file.tell()
line = init_file.readline()

print(f'New info:\n{semver_string}\n{today_string}\n\nUpdated pyproject.toml and __init__.py')
print(
f"New info:\n{semver_string}\n{today_string}\n\nUpdated pyproject.toml and __init__.py"
)
Empty file.
4 changes: 4 additions & 0 deletions tests/resources/multilanguage/example.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
void bar() {
int a = 2;
int b = a * a; //TODO doc this mathematical breakthrough.
}
2 changes: 2 additions & 0 deletions tests/resources/multilanguage/example.mal
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
(=<`#9]~6ZY327Uv4-QsqpMn&+Ij"'E%e{Ab~w=_:]Kw%o44Uqp0/Q?xNvL:`H%c#DD2^WV>gY;dts76qKJImZkj
// TODO I don't think that malbolge supports comments...
2 changes: 2 additions & 0 deletions tests/resources/multilanguage/example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
def foo(): # Hey FIXME why don't ya?
return "foo"
1 change: 1 addition & 0 deletions tests/resources/multilanguage/example.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SELECT * FROM Test; -- TODO use a database...
14 changes: 6 additions & 8 deletions tests/test_find_lines.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@ def test_find_lines(
):
parsers = {}

hits, _ = todo_or_not.todo_check.find_hits(
self.hit_tests, False, "# todoon", parsers
)
hits, _ = todo_or_not.todo_check.find_hits(self.hit_tests, "# todoon", parsers)

hits_by_name = {}
for hit in hits:
Expand Down Expand Up @@ -124,7 +122,7 @@ def test_non_verbose_print(self, stderr):
parsers = {}

_, _ = todo_or_not.todo_check.find_hits(
self.unsupported_encoding_test, False, "# todoon", parsers
self.unsupported_encoding_test, "# todoon", parsers
)

self.assertEqual(stderr.getvalue(), "")
Expand All @@ -134,7 +132,7 @@ def test_verbose_print(self, stderr):
parsers = {}

_, _ = todo_or_not.todo_check.find_hits(
self.unsupported_encoding_test, True, "# todoon", parsers
self.unsupported_encoding_test, "# todoon", parsers
)

expected_value = "WARNING: File uses unsupported encoding, we will skip it but consider adding to .todo-ignore (Supported encodings: ['utf-8', 'utf-16']) \n * tests\\resources\\logo.png"
Expand All @@ -149,22 +147,22 @@ def test_unsupported_encoding(self):
parsers = {}

_, _ = todo_or_not.todo_check.find_hits(
self.unsupported_encoding_test, False, "# todoon", parsers
self.unsupported_encoding_test, "# todoon", parsers
)

def test_broken_file_appears_utf(self):
parsers = {}

hits, encoding = todo_or_not.todo_check.find_hits(
self.broken_encoding_test, False, "# todoon", parsers
self.broken_encoding_test, "# todoon", parsers
)

assert len(hits) == 0
assert encoding == "utf-8"
parsers = {}

hits, encoding = todo_or_not.todo_check.find_hits(
self.really_broken_encoding_test, False, "# todoon", parsers
self.really_broken_encoding_test, "# todoon", parsers
)

assert len(hits) == 0
Expand Down
21 changes: 1 addition & 20 deletions tests/test_github_issues.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ def test_unformatted_hits_not_formatted(

class TestIssueHelperFunctions(unittest.TestCase):
def test_hash(self):
output = todo_or_not.utility._hash("test")
output = todo_or_not.utility.sha1_hash("test")
self.assertEqual(
output, "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3"
) # add assertion here
Expand Down Expand Up @@ -213,25 +213,6 @@ def test_live_submit_test_issue(self):

self._environment_down()

#######################################
# Removed from test suite because
# test environment sets these env vars
#
# def test_hit_with_no_env(self):
# none_env = [
# ("GITHUB_REPOSITORY", "$NONE"),
# ("GITHUB_REF_NAME", "$NONE"),
# ("GITHUB_TRIGGERING_ACTOR", "$NONE")
# ]
# self._environment_up(".", env_variables=none_env)
#
# test_hit = todo_or_not.todo_check.Hit('source.txt', 6, ['todo'], ["todo"], 0)
# issue_outcome = test_hit.generate_issue()
#
# assert issue_outcome is False
#
# self._environment_down()


def test_debug_submit_test_issue(example_hit_todo):
response = example_hit_todo.generate_issue(_test=True)
Expand Down
2 changes: 1 addition & 1 deletion tests/test_todo_grammar.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ def test_leading_code_line_comment_with_leading_and_trailing_comment(self):
result = self.grammar.safe_parse(code)
assert expected_hit == result

def test_complex_comment_with_labels(self): # TODO that
def test_complex_comment_with_labels(self):
code = "123 # a todo z #bug"
expected_hit = Hit("file", 1, ["todo"], [code], 0)
expected_hit.structured_labels = ["bug"]
Expand Down
20 changes: 20 additions & 0 deletions tests/test_todoignore_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,3 +204,23 @@ def test_todoignore_util_does_not_override_in_create_mode(self):
td.todo_ignore_util(["do not write"], create_mode=True, source_is_text=True)

os.chdir(old_dir)

def test_todoignore_util_with_directory_target(self):
# Set up
safe_dir = os.path.join("tests", "resources", "todoignore_util_dir")
old_dir = os.getcwd()
os.chdir(safe_dir)

with open(".todo-ignore", "r") as _old:
old_todoignore = _old.read()

os.remove(".todo-ignore")

# Run util
td.todo_ignore_util(["res"], source_is_text=False)

# Tear down
with open(".todo-ignore", "w") as _new:
_new.write(old_todoignore)

os.chdir(old_dir)
13 changes: 12 additions & 1 deletion tests/test_todoon.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ def test_plural_passages_in_summary(self):
self._environment_down()

def test_todoon_version_print(self):
with self.assertRaises(SystemExit) as context:
with self.assertRaises(SystemExit) as _:
td.todoon(silent=True, version=True)

def test_todoon_progress_bar(self):
Expand Down Expand Up @@ -348,6 +348,17 @@ def test_todoon_push_to_github_env_vars(self):

self._environment_down()

def test_todoon_with_multiple_languages(self):
self._environment_up("multilanguage")

with self.assertRaises(SystemExit) as _:
td.todoon()

assert os.environ["TODOON_TODOS_FOUND"] == "3"
assert os.environ["TODOON_FIXMES_FOUND"] == "1"

self._environment_down()


if __name__ == "__main__":
unittest.main()
2 changes: 1 addition & 1 deletion todo_or_not/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#
#####################################################

__version__ = "0.13.17"
__version__ = "0.13.21"
iso_string = "2024-06-18"

version_date = datetime.date.fromisoformat(iso_string)
1 change: 1 addition & 0 deletions todo_or_not/localize.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"error_exceeded_maximum_issues": "ERROR: Exceeded maximum number of issues for this run, exiting now",
"warning_force_overrides_ignore": "WARNING: --force will ignore the contents of the .todo-ignore generated when you specified (.todo-ignore will still be changed, just not used)",
"warning_file_does_not_exist": "WARNING: File doesn't exist",
"warning_is_a_directory": "WARNING: Expected a file, got a directory",
"warning_run_with_empty_todo_ignore": "WARNING: .todo-ignore was empty (if the file isn't empty, check its encoding), running anyway. To cancel use ",
"warning_run_without_todo_ignore": "WARNING: Running without a .todo-ignore, to cancel use ",
"warning_encoding_not_supported": f"WARNING: File uses unsupported encoding, we will skip it but consider adding to .todo-ignore (Supported encodings: {SUPPORTED_ENCODINGS_TODO_CHECK})",
Expand Down
169 changes: 169 additions & 0 deletions todo_or_not/todo_app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
import os

from todo_or_not.utility import loc


class TodoRun:
def __init__(self, settings: dict):
self.fail_closed_duplicates = settings["fail_closed_duplicates"]
self.silent = settings["silent"]
self.print_mode = settings["print_mode"]
self.push_github_env_vars = settings["push_github_env_vars"]

# Tracks the files attempted to be read, regardless of errors
self.number_of_files_scanned = 0

# Tracks the files unread due to encoding error
self.number_of_encoding_failures = 0

# Tracks the number of targets found
self.number_of_hits = 0
self.number_of_todo = 0
self.number_of_fixme = 0

# Tracks the number of issues generated
self.number_of_issues = 0

# Tracks the number of issues avoided because they are already mentioned
self.number_of_duplicate_issues_avoided = 0

# Tracks the number of issues found that may already be "Closed" on GitHub
self.number_of_closed_issues = 0

@staticmethod
def initialize_environment_variables():
os.environ["TODOON_STATUS"] = "starting"
os.environ["TODOON_PROGRESS"] = "0.0"
os.environ["TODOON_FILES_SCANNED"] = "0"
os.environ["TODOON_TODOS_FOUND"] = "0"
os.environ["TODOON_FIXMES_FOUND"] = "0"
os.environ["TODOON_ENCODING_ERRORS"] = "0"
os.environ["TODOON_ISSUES_GENERATED"] = "0"
os.environ["TODOON_DUPLICATE_ISSUES_AVOIDED"] = "0"

def report_environment_variables(self):
os.environ["TODOON_STATUS"] = "finished"
os.environ["TODOON_PROGRESS"] = "100.0"
os.environ["TODOON_FILES_SCANNED"] = str(self.number_of_files_scanned)
os.environ["TODOON_TODOS_FOUND"] = str(self.number_of_todo)
os.environ["TODOON_FIXMES_FOUND"] = str(self.number_of_fixme)
os.environ["TODOON_ENCODING_ERRORS"] = str(self.number_of_encoding_failures)
os.environ["TODOON_ISSUES_GENERATED"] = str(self.number_of_issues)
os.environ["TODOON_DUPLICATE_ISSUES_AVOIDED"] = str(
self.number_of_duplicate_issues_avoided
)
os.environ["TODOON_DUPLICATE_CLOSED_ISSUES"] = str(self.number_of_closed_issues)

if self.push_github_env_vars:
os.system(f'echo TODOON_STATUS={"finished"} >> $GITHUB_ENV')
os.system(f'echo TODOON_PROGRESS={"100.0"} >> $GITHUB_ENV')
os.system(
f"echo TODOON_FILES_SCANNED={str(self.number_of_files_scanned)} >> $GITHUB_ENV"
)
os.system(
f"echo TODOON_TODOS_FOUND={str(self.number_of_todo)} >> $GITHUB_ENV"
)
os.system(
f"echo TODOON_FIXMES_FOUND={str(self.number_of_fixme)} >> $GITHUB_ENV"
)
os.system(
f"echo TODOON_ENCODING_ERRORS={str(self.number_of_encoding_failures)} >> $GITHUB_ENV"
)
os.system(
f"echo TODOON_ISSUES_GENERATED={str(self.number_of_issues)} >> $GITHUB_ENV"
)
os.system(
f"echo TODOON_DUPLICATE_ISSUES_AVOIDED={str(self.number_of_duplicate_issues_avoided)} >> $GITHUB_ENV"
)
os.system(
f"echo TODOON_DUPLICATE_CLOSED_ISSUES={str(self.number_of_closed_issues)} >> $GITHUB_ENV"
)

def generate_summary_message(self):
summary = f"\n##########################\n# {loc('summary_title')}\n"
# Mode the tool was run in
if self.print_mode:
summary += "# (PRINT MODE)\n"
else:
summary += "# (ISSUE MODE)\n"

# Number of TODOs and FIXMEs found # todoon
summary += (
f"# {self.number_of_todo} TODO | {self.number_of_fixme} FIXME\n" # todoon
)

# Number of encoding failures
if self.number_of_encoding_failures > 1:
summary += f"# {self.number_of_encoding_failures} {loc('summary_encoding_unsupported_plural')}\n"
elif self.number_of_encoding_failures == 1:
summary += f"# {self.number_of_encoding_failures} {loc('summary_encoding_unsupported_singular')}\n"

# Total number of files scanned
if self.number_of_files_scanned > 1:
summary += (
f"# {self.number_of_files_scanned} "
f"{loc('summary_files_scanned_plural')}\n"
)
elif self.number_of_files_scanned == 1:
summary += (
f"# {self.number_of_files_scanned} "
f"{loc('summary_files_scanned_singular')}\n"
)

# Number of issues (if any) that were generated
if not self.print_mode:
# Total number of issues generated
if self.number_of_issues > 1:
summary += (
f"# {self.number_of_issues} "
f"{loc('summary_issues_generated_plural')}\n"
)
elif self.number_of_issues == 1:
summary += (
f"# {self.number_of_issues} "
f"{loc('summary_issues_generated_singular')}\n"
)
else:
summary += f"# " f"{loc('summary_issues_generated_none')}\n"

# Total number of duplicate issues avoided
if self.number_of_duplicate_issues_avoided > 1:
summary += (
f"# {self.number_of_duplicate_issues_avoided} "
f"{loc('summary_duplicate_issues_avoided_plural')}\n"
)
elif self.number_of_duplicate_issues_avoided == 1:
summary += (
f"# {self.number_of_duplicate_issues_avoided} "
f"{loc('summary_duplicate_issues_avoided_singular')}\n"
)

# Total number of duplicate closed issues
if self.number_of_closed_issues > 1:
summary += (
f"# {self.number_of_closed_issues} "
f"{loc('summary_duplicate_closed_issues_plural')}\n"
)
elif self.number_of_closed_issues == 1:
summary += (
f"# {self.number_of_closed_issues} "
f"{loc('summary_duplicate_closed_issues_singular')}\n"
)

summary += "##########################\n\n"

# Overall results of the run
if self.number_of_hits > 0:
if self.silent:
summary += f" * {loc('summary_found_issues_silent')}\n"
else:
summary += f" * {loc('summary_fail_issues_no_silent')}\n"

if self.number_of_closed_issues > 0 and self.fail_closed_duplicates:
summary += f" * {loc('summary_fail_duplicate_closed_issues')}\n"

# Total success
if self.number_of_hits == 0:
summary += f" * {loc('summary_success')}\n"

return summary
Loading
Loading