Skip to content

Instantly share code, notes, and snippets.

@seasonedgeek
Last active February 24, 2020 02:34
Show Gist options
  • Save seasonedgeek/5098e06a54ae01a81e96ff2e5b9ba1e8 to your computer and use it in GitHub Desktop.
Save seasonedgeek/5098e06a54ae01a81e96ff2e5b9ba1e8 to your computer and use it in GitHub Desktop.
Writes user's custom linter and testing configuration files to project directory. (Such as: ~/Exercism/python/<exercise-directory>)
# -*- coding: utf-8 -*-
import argparse
import configparser
import sys
from pathlib import Path
"""Writes configuration files
Writes flake8, mypy, pytests, tox configuration files
in designated project directory.
"""
def configure_flake8(flake8_file):
"""Configures flake8 linter.
This function creates a configuration file.
Args:
flake8_file: .flake8 file in project directory.
A list of codes to ignore:
D100 Missing docstring in public module
D400 First line should end with a period
D401 First line should be in imperative mood
D413 Missing blank line after last section
E133 closing bracket is missing indentation
E501 line too long (87 > 79 characters)
Q000 Remove bad quotes
T001 print found
W293 blank line contains whitespace
"""
config = configparser.ConfigParser()
config["flake8"] = {
"ignore": [
"D100",
"D400",
"D401",
"D413",
"E133",
"E501",
"Q000",
"T001",
"W293",
],
"count": "True",
"statistics": "True",
"tee": "True",
"filename": "*.py",
"disable-noqa": "False",
"max-line-length": 79,
"show-source": "True",
"exclude": [
".git",
".mypy_cache",
".pytest_cache",
"__pycache__",
"docs/source/conf.py",
"old",
"build",
"dist",
],
"max-complexity": 10,
"hang-closing": "True",
}
try:
with open(flake8_file, "w") as configfile:
config.write(configfile, space_around_delimiters=True)
except IOError as err:
err_msg = str(err)
print(f"IOError: {err_msg}")
def configure_mypy(mypy_file):
"""Configures mypy, a type checker.
This function creates a user defined configuration file.
Args:
mypy_file: mypy.ini file in project directory.
"""
config = configparser.ConfigParser()
config["mypy"] = {
"platform": "darwin",
"python_version": 3.8,
"ignore_missing_imports": "True",
"warn_return_any": "True",
"warn_unused_configs": "True",
"disallow_untyped_defs": "False",
}
try:
with open(mypy_file, "w") as configfile:
config.write(configfile, space_around_delimiters=True)
except IOError as err:
err_msg = str(err)
print(f"IOError: {err_msg}")
def configure_pytest(pytest_file):
"""Configures the pytest testing framework.
This function creates a configuration file.
Args:
pytest_file: pytest.ini file in project directory.
"""
config = configparser.ConfigParser()
config["pytest"] = {
"console_output_style": "progress",
"python_files": "*_test.py",
"site_dirs": (
"/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-package"
":/Users/tstewart/Library/Python/3.8/lib/python/site-packages"
),
}
try:
with open(pytest_file, "w") as configfile:
config.write(configfile, space_around_delimiters=True)
except IOError as err:
err_msg = str(err)
print(f"IOError: {err_msg}")
def configure_editor(ec_file):
"""Configures editor config.
This function writes a configuration file to maintain
consistent coding styles.
Args:
ec_file: .editorconfig file in project directory.
"""
config = configparser.ConfigParser(allow_no_value=True)
editor_config = """
# top-most EditorConfig file
root = true
# unix-style newlines
# set default charset
# newline ends every file
[*]
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
# 4 space indentation
[*.py]
max_doc_length = 72
max_line_length = 120
indent_style = space
indent_size = 4
# 2 space indentation
[*.json]
indent_style = space
indent_size = 2
insert_final_newline = ignore
"""
try:
config.read_string(editor_config)
with open(ec_file, "w") as configfile:
config.write(configfile)
except IOError as err:
err_msg = str(err)
print(f"IOError: {err_msg}")
def configure_tox(tox_file):
"""Configures tox test automation.
This function creates a configuration file.
Args:
tox_file: tox.ini file in project directory.
"""
config = configparser.ConfigParser()
config["tox"] = {
"envlist": "flake8",
"skipsdist": True,
}
testenv_flake8 = config["testenv:flake8"] = {}
testenv_flake8["basepython"] = "python3.8"
testenv_flake8["deps"] = "-r{toxinidir}/requirements.txt"
testenv_flake8["commands"] = "paver flake8"
try:
with open(tox_file, "w") as configfile:
config.write(configfile, space_around_delimiters=True)
except IOError as err:
err_msg = str(err)
print(f"IOError: {err_msg}")
def is_venv():
"""Is a Virtual Environment is in effect?
The value of `sys.prefix` will be changed in `site.py` to point
to the virtual environment when in effect. The value for the system Python
or user installation will still be available, via `sys.base_prefix`.
Returns: True when a virtual environment is in effect. Otherwise, false.
Type: Boolean
"""
return sys.base_prefix != sys.prefix
def main():
"""Appends user configuration files to project folder."""
parser = argparse.ArgumentParser(
prog="argparse_example.py",
description="Appends user configuration files to project folder.",
)
parser.add_argument(
"--tox", action="store_true", help="Includes tox.ini file when venv is active."
)
parser.add_argument("projectpath", help="project path: /path/to/project")
args = parser.parse_args()
if args.projectpath:
destination = Path(args.projectpath)
if destination.is_dir():
if is_venv() and args.tox:
tox_file = destination.joinpath("tox.ini")
configure_tox(tox_file)
#
# add default files
flake8_file = destination.joinpath(".flake8")
configure_flake8(flake8_file)
# and
mypy_file = destination.joinpath("mypy.ini")
configure_mypy(mypy_file)
# and
pytest_file = destination.joinpath("pytests.ini")
configure_pytest(pytest_file)
# and
ec_file = destination.joinpath(".editorconfig")
configure_editor(ec_file)
else:
parser.print_help()
else:
parser.print_help()
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment