Skip to content

Commit

Permalink
Merge 26f92fe into 869523a
Browse files Browse the repository at this point in the history
  • Loading branch information
DeviousStoat committed Feb 19, 2023
2 parents 869523a + 26f92fe commit 7a850ae
Show file tree
Hide file tree
Showing 26 changed files with 6,764 additions and 398 deletions.
3 changes: 3 additions & 0 deletions DEVGUIDE.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ isort_ Import statement formatter ``setup.cfg``
docformatter_ Docstring formatter ``setup.cfg``
flake8_ Code linter ``setup.cfg``
pylint_ Code linter ``pylintrc``
mypy_ Type checker ``setup.cfg``
pytest_ Test framework ``setup.cfg``
tox_ Test environment manager ``tox.ini``
invoke_ CLI task execution library ``tasks.py``
Expand Down Expand Up @@ -81,6 +82,7 @@ This is the same as running each linter individually:

inv flake8
inv pylint
inv mypy


Test
Expand Down Expand Up @@ -189,6 +191,7 @@ This project uses `Github Actions <https://docs.github.com/en/free-pro-team@late
.. _docformatter: https://github.com/myint/docformatter
.. _flake8: https://flake8.pycqa.org
.. _pylint: https://www.pylint.org/
.. _mypy: http://mypy-lang.org/
.. _pytest: https://docs.pytest.org
.. _tox: https://tox.readthedocs.io
.. _invoke: http://docs.pyinvoke.org
2 changes: 2 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ include tox.ini
include pylintrc
include tasks.py

global-include py.typed

global-exclude *.py[cod] __pycache__ *.so
74 changes: 74 additions & 0 deletions scripts/mypy_doctests_generator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import re
import typing as t
from pathlib import Path


class DocString(t.NamedTuple):
content: str
function_name: str

def example_block(self) -> t.Union[t.Iterable[str], None]:
expression_re = re.compile(r"Examples?:\n+((?:\s{8}.+?\n)+)")

match = expression_re.search(self.content)
if not match:
return None

example = match.group(1)

return (line.strip() for line in example.strip().splitlines())


def docstrings(path: Path) -> t.Iterable[DocString]:
docstring_re = re.compile(r"def (.+?)\((?:.|\n)+?:[\s\n]+?r?\"\"\"((?:.|\s|\n)+?)\"\"\"")

with open(path) as f:
text = f.read()
docstrings = docstring_re.finditer(text)

return map(
lambda match: DocString(function_name=match.group(1), content=match.group(2)), docstrings
)


def generate_test_function(docstring: DocString) -> str:
if not (example_block := docstring.example_block()):
return ""

built_function = ""

built_function += "@pytest.mark.mypy_testing\n"
built_function += f"def test_mypy_{docstring.function_name}() -> None:\n"

for line in map(lambda l: l.strip(), example_block):
if not line:
continue

to_be_revealed = line.replace(">>> ", "")
if line.startswith(">>> "):
to_be_revealed = f"_.{to_be_revealed}"

built_function += f" reveal_type({to_be_revealed}) # R:\n"

return built_function


def main(path: Path) -> str:
imports = "import pytest\n\n"
imports += f"import pydash as _\n\n\n"

return imports + "\n\n".join(map(generate_test_function, docstrings(path)))


if __name__ == "__main__":
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("filename", help="path to python file", type=Path)
args = parser.parse_args()

if not args.filename.exists():
print(f"`{args.filename}` does not exist")
exit(1)

print(main(args.filename))
19 changes: 19 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ package_dir =
= src
packages = find:
python_requires = >=3.7
include_package_data = True
install_requires =

[options.packages.find]
Expand All @@ -47,8 +48,10 @@ dev =
importlib_metadata<5; python_version=="3.7"
invoke
isort
mypy
pylint
pytest
pytest-mypy-testing @ git+https://github.com/davidfritzsche/pytest-mypy-testing.git
pytest-cov
Sphinx
sphinx-rtd-theme
Expand All @@ -70,6 +73,16 @@ max_complexity = 12
# W503 - line break before binary operator
ignore = F401,F811,E203,W503

[mypy]
show_column_numbers = True
show_error_context = False
ignore_missing_imports = True
warn_return_any = False
strict_optional = True
warn_no_return = True
warn_redundant_casts = False
warn_unused_ignores = False

[tool:isort]
line_length = 100
multi_line_output = 3
Expand Down Expand Up @@ -97,3 +110,9 @@ omit =
*/tests/*
*/test_*
*/_compat.py
*/types.py

[coverage:report]
exclude_lines =
pragma: no cover
@t.overload

0 comments on commit 7a850ae

Please sign in to comment.