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

Replacing "print" with "logging" Module #974

Merged
merged 51 commits into from
Dec 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
08c3d3c
init logging
merrickliu888 Oct 10, 2023
fed6c77
formatting
merrickliu888 Oct 10, 2023
385cde6
contracts logger
merrickliu888 Oct 10, 2023
f3761bf
config logger
merrickliu888 Oct 10, 2023
8f33d56
contracts logging test
merrickliu888 Oct 10, 2023
b83198b
cleaning up comments
merrickliu888 Oct 10, 2023
91b64d5
adding return val
merrickliu888 Oct 10, 2023
c0d1375
removing original prefixes for msgs
merrickliu888 Oct 10, 2023
007c3fa
Adding logging
merrickliu888 Oct 10, 2023
3c1dc0e
Adding logging config back and taking out last print statement
merrickliu888 Oct 11, 2023
0ee4c29
Top level init tests
merrickliu888 Oct 12, 2023
13e63f9
cleaning up TODOs
merrickliu888 Oct 20, 2023
81e166a
init version test
merrickliu888 Oct 20, 2023
9aff6a9
tests
merrickliu888 Oct 20, 2023
86ecdca
Merge
merrickliu888 Oct 20, 2023
bc13e8c
test_load_messages test fixed using patch
merrickliu888 Oct 29, 2023
ab7a72c
test_load_messages test fixed using patch
merrickliu888 Nov 3, 2023
f18f687
Reformatting
merrickliu888 Nov 28, 2023
12edcc6
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 28, 2023
e6b09e3
test config done
merrickliu888 Nov 28, 2023
8c00984
test valid files done
merrickliu888 Nov 28, 2023
e469668
test _check logging finished
merrickliu888 Nov 28, 2023
972ec39
adding pylint_comment example file and finish testing
merrickliu888 Nov 28, 2023
c95b494
merge
merrickliu888 Nov 28, 2023
36c4c38
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 28, 2023
ed5ff7d
merge
merrickliu888 Nov 30, 2023
a38c471
pathing fix
merrickliu888 Dec 2, 2023
4949be1
init logging fix
merrickliu888 Dec 2, 2023
8f5cce3
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 2, 2023
76f1b4e
init logging fix
merrickliu888 Dec 5, 2023
7cd3045
init logging unicode bug fix
merrickliu888 Dec 5, 2023
e4128be
Merge branch 'logging' of https://github.com/merrickliu888/pyta-fork …
merrickliu888 Dec 5, 2023
a59aaf5
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 5, 2023
1fb8b82
fixing paths
merrickliu888 Dec 6, 2023
9a0bc41
fixing z3-solver version issue
merrickliu888 Dec 6, 2023
c527359
adding back path
merrickliu888 Dec 6, 2023
8701320
Merge branch 'logging' of https://github.com/merrickliu888/pyta-fork …
merrickliu888 Dec 6, 2023
3e7ce89
fixing tests after commit hooks
merrickliu888 Dec 6, 2023
b13d09c
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 6, 2023
e5dd549
adding monkepatch.undo()
merrickliu888 Dec 7, 2023
4523746
Merge branch 'logging' of https://github.com/merrickliu888/pyta-fork …
merrickliu888 Dec 7, 2023
91125e0
merge
merrickliu888 Dec 7, 2023
2a3e58c
fixing space
merrickliu888 Dec 7, 2023
01bfeb5
moving version logging
merrickliu888 Dec 7, 2023
efd7245
fixing comment
merrickliu888 Dec 7, 2023
6e7ea88
fixing init testing
merrickliu888 Dec 7, 2023
88c4cc8
spacing
merrickliu888 Dec 7, 2023
4a580c4
removing import
merrickliu888 Dec 7, 2023
e9c25f1
Merge remote-tracking branch 'origin/master' into logging
david-yz-liu Dec 10, 2023
d8ff8a9
Move logging config into _check function
david-yz-liu Dec 10, 2023
6720186
Some updates to logging branch.
david-yz-liu Dec 11, 2023
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
60 changes: 32 additions & 28 deletions python_ta/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
pass

import importlib.util
import logging
import os
import sys
import tokenize
Expand All @@ -55,10 +56,6 @@

HELP_URL = "http://www.cs.toronto.edu/~david/pyta/checkers/index.html"

# check the python version
if sys.version_info < (3, 7, 0):
print("[WARNING] You need Python 3.7 or later to run PythonTA.")


# Flag to determine if we've previously patched pylint
PYLINT_PATCHED = False
Expand Down Expand Up @@ -115,6 +112,13 @@ def _check(
`load_default_config` is used to specify whether to load the default .pylintrc file that comes
with PythonTA. It will load it by default.
"""
# Configuring logger
logging.basicConfig(format="[%(levelname)s] %(message)s", level=logging.NOTSET)

# check the python version
if sys.version_info < (3, 7, 0):
logging.warning("You need Python 3.7 or later to run PythonTA.")

linter = reset_linter(config=local_config, load_default_config=load_default_config)
current_reporter = linter.reporter
current_reporter.set_output(output)
Expand Down Expand Up @@ -174,17 +178,15 @@ def _check(
current_reporter.print_messages(level)
if linter.config.pyta_file_permission:
f_paths.append(file_py) # Appending paths for upload
print(
"[INFO] File: {} was checked using the configuration file: {}".format(
logging.info(
"File: {} was checked using the configuration file: {}".format(
file_py, linter.config_file
),
file=sys.stderr,
)
)
print(
"[INFO] File: {} was checked using the messages-config file: {}".format(
logging.info(
"File: {} was checked using the messages-config file: {}".format(
file_py, messages_config_path
),
file=sys.stderr,
)
)
if linter.config.pyta_error_permission:
errs = list(current_reporter.messages.values())
Expand All @@ -206,10 +208,10 @@ def _check(
linter.generate_reports()
return current_reporter
except Exception as e:
print(
"[ERROR] Unexpected error encountered! Please report this to your instructor (and attach the code that caused the error)."
logging.error(
"Unexpected error encountered! Please report this to your instructor (and attach the code that caused the error)."
)
print('[ERROR] Error message: "{}"'.format(e))
logging.error('Error message: "{}"'.format(e))
raise e


Expand Down Expand Up @@ -386,32 +388,32 @@ def _verify_pre_check(filepath: AnyStr, allow_pylint_comments: bool) -> bool:
continue
match = OPTION_PO.search(content)
if match is not None:
print(
'[ERROR] String "pylint:" found in comment. '
logging.error(
'String "pylint:" found in comment. '
+ "No check run on file `{}.`\n".format(filepath)
)
return False
except IndentationError as e:
print(
"[ERROR] python_ta could not check your code due to an "
logging.error(
"python_ta could not check your code due to an "
+ "indentation error at line {}.".format(e.lineno)
)
return False
except tokenize.TokenError as e:
print(
"[ERROR] python_ta could not check your code due to a " + "syntax error in your file."
logging.error(
"python_ta could not check your code due to a " + "syntax error in your file."
)
return False
except UnicodeDecodeError:
print(
"[ERROR] python_ta could not check your code due to an "
logging.error(
"python_ta could not check your code due to an "
+ "invalid character. Please check the following lines "
"in your file and all characters that are marked with a �."
)
with open(os.path.expanduser(filepath), encoding="utf-8", errors="replace") as f:
for i, line in enumerate(f):
if "�" in line:
print(f" Line {i}: {line}", end="")
logging.error(f" Line {i + 1}: {line}")
return False
return True

Expand All @@ -428,7 +430,7 @@ def _get_valid_files_to_check(module_name: Union[List[str], str]) -> Generator[A
module_name = [module_name]
# Otherwise, enforce API to expect `module_name` type as list
elif not isinstance(module_name, list):
print(
logging.error(
"No checks run. Input to check, `{}`, has invalid type, must be a list of strings.".format(
module_name
)
Expand All @@ -438,7 +440,9 @@ def _get_valid_files_to_check(module_name: Union[List[str], str]) -> Generator[A
# Filter valid files to check
for item in module_name:
if not isinstance(item, str): # Issue errors for invalid types
print("No check run on file `{}`, with invalid type. Must be type: str.\n".format(item))
logging.error(
"No check run on file `{}`, with invalid type. Must be type: str.\n".format(item)
)
elif os.path.isdir(item):
yield item
elif not os.path.exists(os.path.expanduser(item)):
Expand All @@ -448,9 +452,9 @@ def _get_valid_files_to_check(module_name: Union[List[str], str]) -> Generator[A
if os.path.exists(filepath):
yield filepath
else:
print("Could not find the file called, `{}`\n".format(item))
logging.error("Could not find the file called, `{}`\n".format(item))
except ImportError:
print("Could not find the file called, `{}`\n".format(item))
logging.error("Could not find the file called, `{}`\n".format(item))
else:
yield item # Check other valid files.

Expand Down
6 changes: 3 additions & 3 deletions python_ta/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Within the config submodule, this .py file encompasses functions responsible
for managing all configuration-related tasks.
"""

import logging
import os
import sys
from pathlib import Path
Expand Down Expand Up @@ -48,7 +48,7 @@ def override_config(linter: PyLinter, config_location: AnyStr) -> None:
try:
_, config_args = config_file_parser.parse_config_file(file_path=config_location)
except OSError as ex:
print(ex, file=sys.stderr)
logging.error(ex)
sys.exit(32)

# Override the config options by parsing the provided file.
Expand Down Expand Up @@ -76,7 +76,7 @@ def load_messages_config(path: str, default_path: str, use_pyta_error_messages:
try:
merge_from = toml.load(path)
except FileNotFoundError:
print(f"[WARNING] Could not find messages config file at {str(Path(path).resolve())}.")
logging.warning(f"Could not find messages config file at {str(Path(path).resolve())}.")
merge_from = {}

if not use_pyta_error_messages:
Expand Down
5 changes: 3 additions & 2 deletions python_ta/contracts/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
[(assertion, compiled, return_val_var_name)].
"""
import inspect
import logging
import sys
import typing
from types import CodeType, FunctionType, ModuleType
Expand Down Expand Up @@ -613,8 +614,8 @@ def _debug(msg: str) -> None:
"""
if not DEBUG_CONTRACTS:
return

print("[PyTA]", msg, file=sys.stderr)
logging.basicConfig(format="[%(levelname)s] %(message)s", level=logging.DEBUG)
logging.debug(msg)


def _set_invariants(klass: type) -> None:
Expand Down
1 change: 1 addition & 0 deletions tests/fixtures/pylint_comment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# pylint: disable=unbalanced-tuple-unpacking
5 changes: 5 additions & 0 deletions tests/fixtures/unicode_decode_error.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"�"
"�"
"foo"
"foo"
"�"
5 changes: 3 additions & 2 deletions tests/test_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""
import subprocess
import sys
from os import path, remove
from os import environ, path, remove
from unittest.mock import Mock

import python_ta
Expand Down Expand Up @@ -254,7 +254,8 @@ def test_check_exit_zero() -> None:
"--config",
"tests/test.pylintrc",
"examples/nodes/name.py",
]
],
env={**environ, "PYTHONIOENCODING": "utf-8"},
)

assert output.returncode == 0
Expand Down
22 changes: 22 additions & 0 deletions tests/test_config/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
from unittest.mock import mock_open, patch

import pytest
from pylint import lint

import python_ta
from python_ta.config import load_messages_config, override_config

TEST_CONFIG = {
"pyta-number-of-messages": 10,
Expand Down Expand Up @@ -229,6 +231,26 @@ def test_config_parse_error_has_no_snippet() -> None:
assert snippet == ""


def test_override_config_logging(caplog) -> None:
"""Testing that the OSError in override_config is logged correctly"""
path = "C:\\foo\\tests\\file_fixtures\\test_f0011.pylintrc"
linter = lint.PyLinter()

with pytest.raises(SystemExit):
override_config(linter, path)
assert caplog.records[0].levelname == "ERROR"
assert f"The config file {path} doesn't exist!" in caplog.text


@patch("python_ta.config.toml.load", side_effect=FileNotFoundError)
def test_load_messages_config_logging(_, caplog):
try:
load_messages_config("non_existent_file.toml", "default_file.toml", True)
except FileNotFoundError:
assert "Could not find messages config file at" in caplog.text
assert "WARNING" in [record.levelname for record in caplog.records]


def test_allow_pylint_comments() -> None:
"""Test that checks whether the allow-pylint-comments configuration option works as expected when it is
set to True
Expand Down
1 change: 0 additions & 1 deletion tests/test_config/test_num_error_occurrences.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""
Test suite for checking that the correct number of error occurrences are being displayed.
"""

import contextlib
import io
import os
Expand Down
29 changes: 29 additions & 0 deletions tests/test_contracts/test_contracts_debug.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import logging

from python_ta import contracts

contracts.DEBUG_CONTRACTS = True
from python_ta.contracts import check_contracts


def test_contracts_debug(caplog) -> None:
"""Test to see if _debug function is logging messages correctly"""
caplog.set_level(logging.DEBUG)

@check_contracts
def divide(x: int, y: int) -> int:
"""Return x // y.
Preconditions:
- invalid precondition
"""
return x // y

divide(6, 2)

for record in caplog.records:
assert record.levelname == "DEBUG"
assert (
"Warning: precondition invalid precondition could not be parsed as a valid Python expression"
in caplog.text
)
Loading
Loading