Browse Source

Update CookieCutter

Add fixes to setup.py for the inability to import pip for parsing
requirements files.

Update tox with new coverage commands and only test on a single Python3
version.

Create venv if one doesn't exist with direnv.

Remove encoding pragma as this is no longer necessary as of ~Python3.6?

Remove _compat.py as six does a better job and Python2.7 shouldn't be in
use anymore.

Add the requirements directory text files to the Manifest.in.

Update versions of pre-commit repos.
master
Nate Bohman 2 years ago
parent
commit
959cfc2da9
Signed by: Nate Bohman <natrinicle@gmail.com> GPG Key ID: C10546A54ABA1CE5
14 changed files with 71 additions and 147 deletions
  1. +3
    -0
      {{cookiecutter.project_slug}}/.envrc
  2. +5
    -7
      {{cookiecutter.project_slug}}/.pre-commit-config.yaml
  3. +1
    -0
      {{cookiecutter.project_slug}}/MANIFEST.in
  4. +0
    -1
      {{cookiecutter.project_slug}}/docs/source/coverage/extract_source.py
  5. +3
    -0
      {{cookiecutter.project_slug}}/requirements-all.txt
  6. +1
    -0
      {{cookiecutter.project_slug}}/requirements/test.txt
  7. +29
    -31
      {{cookiecutter.project_slug}}/setup.py
  8. +0
    -1
      {{cookiecutter.project_slug}}/tests/__init__.py
  9. +1
    -3
      {{cookiecutter.project_slug}}/tests/conftest.py
  10. +12
    -6
      {{cookiecutter.project_slug}}/tests/test_{{cookiecutter.project_slug}}.py
  11. +4
    -5
      {{cookiecutter.project_slug}}/tox.ini
  12. +11
    -5
      {{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/__init__.py
  13. +0
    -86
      {{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/_compat.py
  14. +1
    -2
      {{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}.py

+ 3
- 0
{{cookiecutter.project_slug}}/.envrc View File

if [ ! -d venv ]; then
python3 -m venv venv
fi
source venv/bin/activate source venv/bin/activate
unset PS1 unset PS1

+ 5
- 7
{{cookiecutter.project_slug}}/.pre-commit-config.yaml View File

exclude: '^$'
exclude: '^(.*\.(svg))?$'
fail_fast: false fail_fast: false
default_language_version: default_language_version:
python: python3.9 python: python3.9
repos: repos:
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.3.0
rev: v4.1.0
hooks: hooks:
- id: check-added-large-files - id: check-added-large-files
- id: check-ast - id: check-ast
types: [file, text] types: [file, text]
- id: end-of-file-fixer - id: end-of-file-fixer
types: [file, python] types: [file, python]
- id: fix-encoding-pragma
types: [file, python]
- id: requirements-txt-fixer - id: requirements-txt-fixer
types: [file, text] types: [file, text]
- id: trailing-whitespace - id: trailing-whitespace
types: [file, text] types: [file, text]
exclude: ^docs/.*/coverage/.*\.html$ exclude: ^docs/.*/coverage/.*\.html$
- repo: https://github.com/PyCQA/isort - repo: https://github.com/PyCQA/isort
rev: 5.6.4
rev: 5.10.1
hooks: hooks:
- id: isort - id: isort
types: [file, python] types: [file, python]
rev: stable rev: stable
hooks: hooks:
- id: black - id: black
language_version: python3.8
language_version: python3.9
- repo: https://gitlab.com/pycqa/flake8 - repo: https://gitlab.com/pycqa/flake8
rev: 3.8.4
rev: 4.0.1
hooks: hooks:
- id: flake8 - id: flake8
exclude: ^setup.py$ exclude: ^setup.py$

+ 1
- 0
{{cookiecutter.project_slug}}/MANIFEST.in View File

recursive-include . *.gitkeep recursive-include . *.gitkeep
recursive-include docs/source *.rst recursive-include docs/source *.rst
recursive-include docs/source/coverage *.source.html recursive-include docs/source/coverage *.source.html
recursive-include requirements *.txt
recursive-include tests * recursive-include tests *
recursive-exclude * __pycache__ recursive-exclude * __pycache__
recursive-exclude * *.py[co] recursive-exclude * *.py[co]

+ 0
- 1
{{cookiecutter.project_slug}}/docs/source/coverage/extract_source.py View File

#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*-


import os import os
import re import re

+ 3
- 0
{{cookiecutter.project_slug}}/requirements-all.txt View File

-r requirements/dev.txt
-r requirements/prod.txt
-r requirements/test.txt

+ 1
- 0
{{cookiecutter.project_slug}}/requirements/test.txt View File

pylint; python_version >= "3.4" pylint; python_version >= "3.4"
pylint-fail-under pylint-fail-under
pytest pytest
pytest-asyncio
pytest-cov pytest-cov
pytest-mock pytest-mock
pytest-runner pytest-runner

+ 29
- 31
{{cookiecutter.project_slug}}/setup.py View File

#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*-

import pip

try: # for pip >= 10
from pip._internal.req import parse_requirements
except ImportError: # for pip <= 9.0.3
from pip.req import parse_requirements


try: try:
from setuptools import setup from setuptools import setup
except ImportError: except ImportError:
from distutils.core import setup from distutils.core import setup


with open("README.md") as readme_file:
readme = readme_file.read()

with open("HISTORY.md") as history_file:
history = history_file.read()

github_url = "https://github.com/{{ cookiecutter.github_username }}/{{ cookiecutter.project_slug }}"

## workaround derived from: https://github.com/pypa/pip/issues/7645#issuecomment-578210649
parsed_requirements = parse_requirements("requirements/prod.txt", session="workaround")
parsed_dev_requirements = parse_requirements(
"requirements/dev.txt", session="workaround"
)
parsed_test_requirements = parse_requirements(
"requirements/test.txt", session="workaround"
)

requirements = [str(ir.req) for ir in parsed_requirements]
dev_requirements = [str(ir.req) for ir in parsed_dev_requirements]
test_requirements = [str(tr.req) for tr in parsed_test_requirements]
DESCRIPTION = "{{ cookiecutter.project_short_description }}"
GITHUB_URL = "https://github.com/{{ cookiecutter.github_username }}/{{ cookiecutter.project_slug }}"

with open("requirements/prod.txt", encoding="utf-8") as file:
requirements = file.read().split("\n")
with open("requirements/test.txt", encoding="utf-8") as file:
test_requirements = list(
filter(
lambda req: not req.startswith("-"),
file.read().split("\n"),
)
)
with open("requirements/dev.txt", encoding="utf-8") as file:
dev_requirements = list(
filter(
lambda req: not req.startswith("-"),
file.read().split("\n"),
)
)
test_requirements.extend(requirements)
dev_requirements.extend(test_requirements)

with open("README.md", encoding="utf-8") as file:
readme = file.read()
with open("HISTORY.md", encoding="utf-8") as file:
history = file.read()


setup( setup(
name="{{ cookiecutter.project_slug }}", name="{{ cookiecutter.project_slug }}",
version="{{ cookiecutter.version }}", version="{{ cookiecutter.version }}",
description="{{ cookiecutter.project_short_description }}",
description=DESCRIPTION,
long_description=readme + "\n\n" + history, long_description=readme + "\n\n" + history,
long_description_content_type="text/markdown", long_description_content_type="text/markdown",
author="{{ cookiecutter.full_name }}", author="{{ cookiecutter.full_name }}",
author_email="{{ cookiecutter.email }}", author_email="{{ cookiecutter.email }}",
url=github_url,
url=GITHUB_URL,
license="LGPL-3", license="LGPL-3",
keywords="{{ cookiecutter.project_slug }}", keywords="{{ cookiecutter.project_slug }}",
project_urls={"Source": github_url},
project_urls={"Source": GITHUB_URL},
packages=[ packages=[
"{{ cookiecutter.project_slug }}", "{{ cookiecutter.project_slug }}",
], ],

+ 0
- 1
{{cookiecutter.project_slug}}/tests/__init__.py View File

# -*- coding: utf-8 -*-

+ 1
- 3
{{cookiecutter.project_slug}}/tests/conftest.py View File

# -*- coding: utf-8 -*-
""" """
Conftest Fixtures Conftest Fixtures


absolute_import, absolute_import,
division, division,
print_function, print_function,
with_statement,
unicode_literals, unicode_literals,
with_statement,
) )


import logging import logging
import mock import mock
import pytest import pytest



logger = logging.getLogger(__name__) # pylint: disable=invalid-name logger = logging.getLogger(__name__) # pylint: disable=invalid-name


FIXTURE_PATH = "{}/fixtures".format(os.path.dirname(os.path.abspath(__file__))) FIXTURE_PATH = "{}/fixtures".format(os.path.dirname(os.path.abspath(__file__)))

+ 12
- 6
{{cookiecutter.project_slug}}/tests/test_{{cookiecutter.project_slug}}.py View File

# -*- coding: utf-8 -*-
""" """
Tests for `{{ cookiecutter.project_slug }}` module. Tests for `{{ cookiecutter.project_slug }}` module.
""" """
absolute_import, absolute_import,
division, division,
print_function, print_function,
unicode_literals,
with_statement, with_statement,
unicode_literals
) )


import logging import logging
import pytest

from {{ cookiecutter.project_slug }} import {{ (cookiecutter.project_slug.title()).replace('_', '') }}


logger = logging.getLogger(__name__) # pylint: disable=invalid-name
import pytest
from {{cookiecutter.project_slug}} import ( # pylint: disable=invalid-name
'' }},
'_',
.replace,
=,
__name__,
logger,
logging.getLogger,
{{ cookiecutter.project_slug.title,
)


FIXTURE_PATH = "{}/fixtures".format(os.path.dirname(os.path.abspath(__file__))) FIXTURE_PATH = "{}/fixtures".format(os.path.dirname(os.path.abspath(__file__)))



+ 4
- 5
{{cookiecutter.project_slug}}/tox.ini View File

[tox] [tox]
envlist = cov_init, py{37,38,39}, cov_report, docs, bandit, pylint
envlist = cov_init, py3, cov_report, docs, bandit, pylint


[testenv] [testenv]
basepython = basepython =
py3: {env:TOXPYTHON:python3}
py37: {env:TOXPYTHON:python3.7} py37: {env:TOXPYTHON:python3.7}
py38: {env:TOXPYTHON:python3.8} py38: {env:TOXPYTHON:python3.8}
py39: {env:TOXPYTHON:python3.9} py39: {env:TOXPYTHON:python3.9}
{bandit,cov_init,cov_report,docs,lint,pur,pylint}: {env:TOXPYTHON:python3} {bandit,cov_init,cov_report,docs,lint,pur,pylint}: {env:TOXPYTHON:python3}
setenv = setenv =
COVERAGE_FILE=.coverage.{envname}
PYTHONPATH={toxinidir}:{toxinidir}/{{ cookiecutter.project_slug }} PYTHONPATH={toxinidir}:{toxinidir}/{{ cookiecutter.project_slug }}
PYTHONUNBUFFERED=yes PYTHONUNBUFFERED=yes
HOME={env:HOME:/tmp} HOME={env:HOME:/tmp}
--basetemp={envtmpdir} \ --basetemp={envtmpdir} \
--confcutdir=.. \ --confcutdir=.. \
--cov \ --cov \
--cov-append \
-n 0 \ -n 0 \
{posargs} {posargs}


coverage coverage
skip_install = True skip_install = True
commands = commands =
coverage combine
coverage html coverage html
{toxinidir}/docs/source/coverage/extract_source.py {toxinidir}/docs/source/coverage/extract_source.py


description = description =
Invoke sphinx-build to build the HTML docs Invoke sphinx-build to build the HTML docs
commands = commands =
sphinx-build -b linkcheck
sphinx-build -b html -q {posargs}
python setup.py build_sphinx -q {posargs}

+ 11
- 5
{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/__init__.py View File

#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*-
""" """


{{ cookiecutter.project_slug }} {{ cookiecutter.project_slug }}
absolute_import, absolute_import,
division, division,
print_function, print_function,
with_statement,
unicode_literals, unicode_literals,
with_statement,
) )


from pkgutil import extend_path from pkgutil import extend_path


__path__ = extend_path(__path__, __name__) __path__ = extend_path(__path__, __name__)


from .{{ cookiecutter.project_slug }} import {{ (cookiecutter.project_slug.title()).replace('_', '') }}

__all__ = ["{{ (cookiecutter.project_slug.title()).replace('_', '') }}"]
from .{{cookiecutter.project_slug}} import (
'' }},
'' }}"],
'_',
.replace,
=,
["{{ cookiecutter.project_slug.title,
__all__,
{{ cookiecutter.project_slug.title,
)

+ 0
- 86
{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/_compat.py View File

import sys

# https://lucumr.pocoo.org/2013/5/21/porting-to-python-3-redux/
# https://github.com/tony/cookiecutter-pypackage-pythonic/blob/master/%7B%7Bcookiecutter.repo_name%7D%7D/%7B%7Bcookiecutter.repo_name%7D%7D/_compat.py

PY2 = sys.version_info[0] == 2

_identity = lambda x: x

if PY2:
unichr = unichr
text_type = unicode
string_types = (str, unicode)
integer_types = (int, long)
from urllib import urlretrieve

text_to_native = lambda s, enc: s.encode(enc)

iterkeys = lambda d: d.iterkeys()
itervalues = lambda d: d.itervalues()
iteritems = lambda d: d.iteritems()

from cStringIO import StringIO as BytesIO
from StringIO import StringIO
import cPickle as pickle
import ConfigParser as configparser

from itertools import izip, imap

range_type = xrange

cmp = cmp

input = raw_input
from string import lower as ascii_lowercase
import urlparse

def console_to_str(s):
return s.decode("utf_8")

exec("def reraise(tp, value, tb=None):\n raise tp, value, tb")

else:
unichr = chr
text_type = str
string_types = (str,)
integer_types = (int,)

text_to_native = lambda s, enc: s

iterkeys = lambda d: iter(d.keys())
itervalues = lambda d: iter(d.values())
iteritems = lambda d: iter(d.items())

from io import StringIO, BytesIO
import pickle
import configparser

izip = zip
imap = map
range_type = range

cmp = lambda a, b: (a > b) - (a < b)

input = input
from string import ascii_lowercase
import urllib.parse as urllib
import urllib.parse as urlparse
from urllib.request import urlretrieve

console_encoding = sys.__stdout__.encoding

def console_to_str(s):
""" From pypa/pip project, pip.backwardwardcompat. License MIT. """
try:
return s.decode(console_encoding)
except UnicodeDecodeError:
return s.decode("utf_8")

def reraise(tp, value, tb=None):
if value.__traceback__ is not tb:
raise (value.with_traceback(tb))
raise value


number_types = integer_types + (float,)

+ 1
- 2
{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}.py View File

#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*-


from __future__ import ( from __future__ import (
absolute_import, absolute_import,
division, division,
print_function, print_function,
unicode_literals,
with_statement, with_statement,
unicode_literals
) )


import logging import logging

Loading…
Cancel
Save