Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A `setup.cfg` template for my Python projects
# https://gist.github.com/althonos/6914b896789d3f2078d1e6237642c35c
[metadata]
name = {name}
version = file: {name}/_version.txt
author = Martin Larralde
author_email = martin.larralde@embl.de
url = https://github.com/althonos/{name}
description = {description}
long_description = file: README.md
long_description_content_type = text/markdown
license = MIT
license_file = COPYING
platform = any
keywords = {keywords}
classifiers =
Development Status :: 3 - Alpha
Intended Audience :: Developers
License :: OSI Approved :: MIT License
Operating System :: OS Independent
Programming Language :: Python
Programming Language :: Python :: 3.4
Programming Language :: Python :: 3.5
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Topic :: Software Development :: Libraries :: Python Modules
project_urls =
Bug Tracker = https://github.com/althonos/{name}/issues
Changelog = https://github.com/althonos/{name}/blob/master/CHANGELOG.md
[options]
zip_safe = false
include_package_data = true
python_requires = >= 2.7, != 3.0.*, != 3.1.*, != 3.2.*
packages = {name}
test_suite = tests
setup_requires =
setuptools
# setuptools >=30.3.0 # minimal version for `setup.cfg`
# setuptools >=38.3.0 # version with most `setup.cfg` bugfixes
# setuptools >=46.4.0 # let's you use attr: to extract version from a module
install_requires =
{install_requires}
tests_require =
{tests_require}
[options.package_data]
{name} = py.typed, _version.txt, *.pyi
[bdist_wheel]
universal = true
[sdist]
formats = zip, gztar
[coverage:report]
show_missing = true
exclude_lines =
pragma: no cover
if False
# @abc.abstractmethod
# @abc.abstractproperty
# raise NotImplementedError
# return NotImplemented
# except ImportError
# raise MemoryError
# if __name__ == .__main__.:
# if typing.TYPE_CHECKING:
[green]
file-pattern = test_*.py
verbose = 2
no-skip-report = true
quiet-stdout = true
run-coverage = true
[pydocstyle]
match-dir = (?!tests)(?!resources)(?!docs)[^\.].*
match = (?!test)(?!setup)[^\._].*\.py
inherit = false
ignore = D200, D203, D213, D406, D407 # Google conventions
[flake8]
max-line-length = 99
doctests = True
exclude = .git, .eggs, __pycache__, tests/, docs/, build/, dist/
[mypy]
disallow_any_decorated = true
disallow_any_generics = true
disallow_any_unimported = false
disallow_subclassing_any = false
disallow_untyped_calls = true
disallow_untyped_defs = true
ignore_missing_imports = true
warn_unused_ignores = true
warn_return_any = true
@kyweez
Copy link

kyweez commented Mar 1, 2022

Hi, about the py.typed in [options.package_data], does it mean you place it at the same level than the setup.cfg ? I thought it was supposed to be inside the /src package. I'm tying to figure out how I can generate my package and make supported by MyPy.

@althonos
Copy link
Author

althonos commented Mar 1, 2022

Hi @kyweez ,

the py.typed file goes inside your package, so if you are developing myawesomepackage you should have the following structure:

.
├── myawesomepackage
│   ├── __init__.py
│   ├── __main__.py
│   └── py.typed
├── COPYING
├── README.md
├── setup.cfg
└── setup.py

@kyweez
Copy link

kyweez commented Mar 1, 2022

Ok, thanks a lot, that's what I thought.
So I guess my problem comes from my setup.cfg. I wrote ./myawesomepackage/py.typed instead of a simple py.typed in the [options.package_data].
Happy to find your template, thanks for this.

@althonos
Copy link
Author

althonos commented Mar 1, 2022

Yes, it should be:

[options.package_data]
myawesomepackage = py.typed

filenames are given as relative to the Python package, not full paths.

Also, you may or may not need a MANIFEST.in file as well to make sure py.typed gets in your source distribution and not just the wheel distribution.

Happy to find your template, thanks for this.

Happy that it's useful!

@borgeser
Copy link

borgeser commented Jun 1, 2022

Thank you @althonos, I was wondering where to put the py.typed in my setup.cfg. You saved my day!

@jeremybep
Copy link

jeremybep commented Jun 29, 2022

Hi,

{name}, is an auto-format ? no need to specify anyware ?
Like response to kyweez, if package strcuture is the same, {name} call directlly myawesomepackage ?
regards,

@althonos
Copy link
Author

althonos commented Jun 29, 2022

@jeremybep : no, it's not autoformat, you need to replace every {name} occurence with the name of your package, same for every variable in the template 👍

@jeremybep
Copy link

jeremybep commented Jun 29, 2022

Okay, that's what I thought.
however, I would like to know how you use the var {name}. Is from CI/CD, or another package, or setup.py ?
I would like to understand the logic of your setup.cfg;

thank you,

@althonos
Copy link
Author

althonos commented Jun 29, 2022

Oh, I wrote it that way because you could use Python formatting to fill in the blanks:

import urllib.request

with urllib.request.urlopen("https://gist.githubusercontent.com/althonos/6914b896789d3f2078d1e6237642c35c/raw/d2a95d13181d36dc4aa831f1927d05204da5eda2/setup.cfg") as gist:
    template = gist.read().decode()

with open("setup.cfg", "w") as dst:
    dst.write(template.format(
        name="myawesomepackage", 
        description="My Awesome Package", 
        keywords="awesome, package", 
        install_requires="numpy", 
        tests_requires="mock"
    ))

But it's not like there is a magic formula that's going to fill them for you, at some point you'll have to edit the file yourself when you're creating a new project, it's not a cookiecutter template or anything. I just have it here because i copy that file and then edit it to add what i need every time i create a new package.

@jeremybep
Copy link

jeremybep commented Jun 30, 2022

Ha, ok i see.
Thank you for sharing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment