• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pyta-uoft / pyta / 29655257500

18 Jul 2026 06:07PM UTC coverage: 90.835% (-0.1%) from 90.931%
29655257500

push

github

web-flow
Fixed PyTA CLI output format behaviour (#1367)

Added new `pylint_args` argument to `python_ta.check_all`

15 of 21 new or added lines in 4 files covered. (71.43%)

3697 of 4070 relevant lines covered (90.84%)

17.65 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.29
/packages/python-ta/src/python_ta/config/__init__.py
1
"""
2
Within the config submodule, this .py file encompasses functions responsible
3
 for managing all configuration-related tasks.
4
"""
5

6
import logging
20✔
7
import os
20✔
8
import sys
20✔
9
from pathlib import Path
20✔
10
from typing import AnyStr, Optional
20✔
11

12
import toml
20✔
13
from pylint.config.config_file_parser import _ConfigurationFileParser
20✔
14
from pylint.config.config_initialization import _config_initialization
20✔
15
from pylint.config.exceptions import _UnrecognizedOptionError
20✔
16
from pylint.lint import PyLinter
20✔
17

18
DEFAULT_CONFIG_LOCATION = os.path.join("config", ".pylintrc")
20✔
19

20

21
def find_local_config(curr_dir: AnyStr) -> Optional[AnyStr]:
20✔
22
    """Search for a configuration file provided in same (user)
23
    location as the source file to check.
24
    Return absolute path to the file, or None.
25
    `curr_dir` is an absolute path to a directory, containing a file to check.
26
    For more info see, pylint.config.find_default_config_files
27
    """
28
    if curr_dir.endswith(".py"):
20✔
29
        curr_dir = os.path.dirname(curr_dir)
20✔
30
    if os.path.exists(os.path.join(curr_dir, "config", ".pylintrc")):
20✔
31
        return os.path.join(curr_dir, "config", ".pylintrc")
20✔
32
    elif os.path.exists(os.path.join(curr_dir, "config", "pylintrc")):
20✔
33
        return os.path.join(curr_dir, "config", "pylintrc")
×
34
    elif os.path.exists(os.path.join(curr_dir, "config", "pyproject.toml")):
20✔
35
        return os.path.join(curr_dir, "config", "pyproject.toml")
×
36

37

38
def load_config(
20✔
39
    linter: PyLinter,
40
    config_location: AnyStr,
41
    pylint_args: Optional[list[str]] = None,
42
) -> None:
43
    """Load configuration into the linter."""
44
    args_list = _get_pyta_toml_args(config_location, linter)
20✔
45
    if pylint_args:
20✔
NEW
46
        args_list.extend(pylint_args)
×
47
    _config_initialization(linter, args_list=args_list, config_file=config_location)
20✔
48
    linter.config_file = config_location
20✔
49

50

51
def override_config(
20✔
52
    linter: PyLinter,
53
    config_location: AnyStr,
54
    pylint_args: Optional[list[str]] = None,
55
) -> None:
56
    """Override the default linter configuration options (if possible).
57

58
    Snippets taken from pylint.config.config_initialization.
59
    """
60
    linter.set_current_module(config_location)
20✔
61

62
    # Read the configuration file.
63
    config_file_parser = _ConfigurationFileParser(verbose=True, linter=linter)
20✔
64
    try:
20✔
65
        _, config_args = config_file_parser.parse_config_file(file_path=config_location)
20✔
66
    except OSError as ex:
20✔
67
        logging.error(ex)
20✔
68
        sys.exit(32)
20✔
69

70
    config_args.extend(_get_pyta_toml_args(config_location, linter))
20✔
71
    if pylint_args:
20✔
NEW
72
        config_args.extend(pylint_args)
×
73

74
    # Override the config options by parsing the provided file.
75
    try:
20✔
76
        linter._parse_configuration_file(config_args)
20✔
77
    except _UnrecognizedOptionError as exc:
20✔
78
        unrecognized_options_message = ", ".join(exc.options)
20✔
79
        linter.add_message("unrecognized-option", args=unrecognized_options_message, line=0)
20✔
80

81
    # Everything has been set up already so emit any stashed messages.
82
    linter._emit_stashed_messages()
20✔
83

84
    linter.config_file = config_location
20✔
85

86

87
def load_messages_config(path: str, default_path: str, use_pyta_error_messages: bool) -> dict:
20✔
88
    """Given path (potentially) specified by user and default default_path
89
    of messages config file, merge the config files. We will only add the
90
    PythonTA error messages if use_pyta_error_messages is True.
91
    """
92
    # assume the user is not going to provide a path which is the same as the default
93
    if Path(default_path).resolve() == Path(path).resolve():
20✔
94
        merge_from = {}
20✔
95
    else:
96
        try:
20✔
97
            merge_from = toml.load(path)
20✔
98
        except FileNotFoundError:
20✔
99
            logging.warning(f"Could not find messages config file at {str(Path(path).resolve())}.")
20✔
100
            merge_from = {}
20✔
101

102
    # Flatten the config dictionary to get rid of section headers (if any)
103
    merge_from = flatten(merge_from)
20✔
104

105
    if not use_pyta_error_messages:
20✔
106
        return merge_from
20✔
107

108
    # Merge default pyta error messages into custom error messages
109
    merge_into = flatten(toml.load(default_path))
20✔
110
    merge_into.update(merge_from)
20✔
111
    return merge_into
20✔
112

113

114
def flatten(config_dict: dict) -> dict:
20✔
115
    """Given a nested dictionary, flatten it such that no values are themselves dictionaries."""
116
    flat_dict = {}
20✔
117
    for key, value in config_dict.items():
20✔
118
        if isinstance(value, dict):
20✔
119
            flat_dict.update(flatten(value))
20✔
120
        else:
121
            flat_dict[key] = value
20✔
122
    return flat_dict
20✔
123

124

125
def _get_pyta_toml_args(config_location: AnyStr, linter: PyLinter) -> list[str]:
20✔
126
    """Extracts [tool.python-ta] options from a TOML file and formats them as arguments."""
127
    args_list = []
20✔
128
    if not (config_location and config_location.endswith(".toml")):
20✔
129
        return args_list
20✔
130

131
    try:
20✔
132
        with open(config_location, "r", encoding="utf-8") as f:
20✔
133
            config_data = toml.load(f)
20✔
134
    except OSError as ex:
20✔
135
        logging.error(ex)
20✔
136
        return args_list
20✔
137
    except toml.TomlDecodeError as ex:
20✔
138
        linter.add_message("config-parse-error", line=0, args=str(ex))
20✔
139
        return args_list
20✔
140

141
    pyta_config = config_data.get("tool", {}).get("python-ta", {})
20✔
142
    merged_pyta_config = flatten(pyta_config)
20✔
143

144
    for key, value in merged_pyta_config.items():
20✔
145
        if isinstance(value, list):
20✔
146
            args_list.extend([f"--{key}", ",".join(map(str, value))])
20✔
147
        else:
148
            args_list.extend([f"--{key}", str(value)])
20✔
149

150
    return args_list
20✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc