git.lirion.de

Of git, get, and gud

aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormail_redacted_for_web 2025-08-20 09:59:42 +0200
committermail_redacted_for_web 2025-08-20 09:59:42 +0200
commit865e3aabe2d1f46a9c3692e8d51eb4379d7cc970 (patch)
tree86cc747bf72a802f185dd517708d6f70b895d0a1
downloadpython-skeleton-865e3aabe2d1f46a9c3692e8d51eb4379d7cc970.tar.bz2
Initial Commit
-rw-r--r--.gitignore21
-rw-r--r--.nojekyll0
-rw-r--r--MANIFEST.in1
-rw-r--r--Makefile31
-rw-r--r--README.md32
-rw-r--r--classifiers.txt12
-rw-r--r--codecov.yml7
-rw-r--r--project_dummy/__init__.py3
-rw-r--r--project_dummy/db.py26
-rw-r--r--project_dummy/hemlo_world.py15
-rw-r--r--pyproject.toml121
-rw-r--r--requirements.txt0
-rw-r--r--setup.py.bak88
-rw-r--r--tests/dummy_test.py44
l---------tests/project_dummy1
-rw-r--r--tox.ini20
16 files changed, 422 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..221da88
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,21 @@
+coverage.xml
+packages/
+__pycache__
+poetry.lock
+*.pyc
+.tox/
+doc/build
+dist
+doc/html
+*.swp
+build
+
+# Testing clutter
+.coverage
+.mypy_cache/
+.pytest_cache/
+
+# IDE and framework garbage
+.idea
+.hypothesis
+.ropeproject/
diff --git a/.nojekyll b/.nojekyll
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/.nojekyll
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..2b0b5ab
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1 @@
+include Makefile
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..42b0160
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,31 @@
+PYTHON ?= python
+
+all:
+
+test:
+ $(MAKE) test-noclean
+ $(MAKE) clean
+
+test-noclean:
+ python3 -m pytest --benchmark-disable --tb=short
+
+typecheck:
+ $(MAKE) typecheck-noclean
+ $(MAKE) clean
+
+typecheck-noclean:
+ mypy -p project-dummy --warn-redundant-casts
+
+coverage:
+ $(MAKE) coverage-noclean
+ $(MAKE) clean
+
+coverage-noclean:
+ python3 -m pytest --cov project-dummy --benchmark-disable --tb=short
+
+clean:
+ @rm -rf ./dist/ ./__pycache__/ ./tests/__pycache__/
+ @rm -rf ./.benchmarks ./.pytest_cache ./.mypy_cache
+ @rm -rf ./packages/
+
+.PHONY: all clean test typecheck coverage
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..0e2de4d
--- /dev/null
+++ b/README.md
@@ -0,0 +1,32 @@
+# project-dummy
+
+## Explanation
+
+This is a project dummy. It serves (me, maybe you?) as a "template" for the basic structure of
+a Python project. As simple as it can be - copy and adjust.
+
+## Structure
+
+This is a project folder containing the folders and files for creating a Python module called
+"project-dummy".
+
+## Credits
+
+This setup was kicked off while reading Jeff Knupp's ideas[^1] on how to set up a python project.
+
+Changes since then will be incorporated, like:
+
+- Define metadata in pyproject.toml which setuptools have adapted since 61.0.0[^2]
+
+# Resources
+
+This will list some useful resources to fill in pyproject.toml etc.
+
+- [Writing pyproject.toml](https://packaging.python.org/en/latest/guides/writing-pyproject-toml/)
+- [Setuptools-specific pyproject.toml configuration](https://setuptools.pypa.io/en/latest/userguide/pyproject_config.html)
+- [PyPi classifiers](https://pypi.org/classifiers/)
+
+# Sources
+
+[^1] [Internet Archive Wayback Machine, 2024-01-05](https://web.archive.org/web/20240105220829/https://www.jeffknupp.com/blog/2013/08/16/open-sourcing-a-python-project-the-right-way/)
+[^2] [Setuptools, pyproject_config](https://setuptools.pypa.io/en/latest/userguide/pyproject_config.html)
diff --git a/classifiers.txt b/classifiers.txt
new file mode 100644
index 0000000..1d953e4
--- /dev/null
+++ b/classifiers.txt
@@ -0,0 +1,12 @@
+Development Status :: 2 - Pre-Alpha
+Environment :: Console
+Framework :: Pytest
+Framework :: Sphinx
+Intended Audience :: Developers
+License :: Other/Proprietary License :: WTFPL
+Natural Language :: English
+Operating System :: OS Independent
+Programming Language :: Python :: 3
+Topic :: Software Development
+Recommendation :: Useless for Developers :: Windows
+Recommendation :: Useless for Administrators :: PowerShell
diff --git a/codecov.yml b/codecov.yml
new file mode 100644
index 0000000..79fafb0
--- /dev/null
+++ b/codecov.yml
@@ -0,0 +1,7 @@
+comment:
+ layout: "condensed_header, diff, condensed_files, condensed_footer"
+ behavior: default
+ require_changes: false # if true: only post the comment if coverage changes
+ require_base: false # [true :: must have a base report to post]
+ require_head: true # [true :: must have a head report to post]
+ hide_project_coverage: false # [true :: only show coverage on the git diff]
diff --git a/project_dummy/__init__.py b/project_dummy/__init__.py
new file mode 100644
index 0000000..5693b97
--- /dev/null
+++ b/project_dummy/__init__.py
@@ -0,0 +1,3 @@
+#!/usr/bin/env python3
+
+__all__ = [ "hemlo_world" ]
diff --git a/project_dummy/db.py b/project_dummy/db.py
new file mode 100644
index 0000000..5b67af4
--- /dev/null
+++ b/project_dummy/db.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python3
+"""DBaaS - DB as a String."""
+
+
+class Db:
+ """Here's your db."""
+
+ @property
+ def dbt(self):
+ """Here's a string."""
+ mystr = '⠀⠀⠀⠀⠀⣠⠶⠚⠛⠛⠛⠲⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\n⠀⠀⠀⣴⠟⠁⠀⠀⠀⠀⠀⠀⠀⠻⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀'
+ mystr += '⠀⠀⠀⠀⠀⠀\n⠀⣠⣾⣷⣄⠀⠀⠀⢀⣠⣤⣤⡀⠀⢿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\n⢸⣿⡿⢃⣸⡶⠂⢠⣿⣿⡿⠁⣱⠀⢸'
+ mystr += '⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\n⢸⡏⠉⠩⣏⣐⣦⠀⠛⠦⠴⠚⠁⠀⣸⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\n⣼⠧⠶⠶⠶⠿'
+ mystr += '⠶⠶⠖⠚⠛⠉⠁⠀⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⠶⠶⡄⠀⠀\n⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⠀⠀⠀⠀⠀⠀⠀⠀⢠⡟⠀⠀⢹⠀'
+ mystr += '⠀\n⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⢤⢠⡆⠀⢸⡄⠀⠀⠀⠀⠀⠀⢀⡿⠁⠀⠀⡾⠀⠀\n⢹⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⠈⡇⠀⠸⣧⣠⠴⠶⠖'
+ mystr += '⠲⢶⡞⠁⠀⢈⡼⢃⠀⠀\n⠸⡆⠀⠀⠀⠀⠀⠀⠀⠀⢸⠀⡇⠀⠀⢿⠁⠄⣲⡶⠶⠿⢤⣄⡀⠛⢛⠉⢻⠀\n⠀⢿⡀⠀⠀⠀⠀⠀⠀⠀⢸'
+ mystr += '⠠⣇⠀⠀⠀⠀⠊⠁⠀⠀⠀⠀⠀⠙⢦⠈⠙⠓⣆\n⠀⠈⢷⡀⠀⠀⠀⠀⠀⢠⠏⡀⣬⣹⣦⠀⠀⠀⠀⠀⠁⠀⠀⠀⠀⠈⡿⠶⠶⠋\n⠀⠀'
+ mystr += '⠈⢷⡀⠀⠀⠀⠀⠘⠛⠛⠋⠀⠀⠀⠀⠀⠀⠄⠀⠀⠀⠀⠀⣼⠃⠀⠀⠀\n⠀⠀⠀⠀⠙⢦⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠄⠀⠀⣠⡞'
+ mystr += '⠁⠀⠀⠀⠀\n⠀⠀⠀⠀⠀⠀⠈⠛⣷⢶⣦⣤⣄⣀⣠⣤⣤⠀⣶⠶⠶⠶⠛⠁⠀⠀⠀⠀⠀⠀\n⠀⠀⠀⠀⣀⡀⠀⣰⠇⣾⠀⠀⠈⣩⣥⣄'
+ mystr += '⣿⠀⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\n⠀⠀⠀⠀⢿⡉⠳⡟⣸⠃⠀⠀⠀⠘⢷⣌⠉⠀⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\n⠀⠀⠀⠀⠀⠙⢦'
+ mystr += '⣴⠏⠀⠀⠀⠀⠀⠀⠉⠳⠶⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\n'
+ return mystr
+
+ def print_db(self):
+ """Output."""
+ print(f'{self.dbt}')
diff --git a/project_dummy/hemlo_world.py b/project_dummy/hemlo_world.py
new file mode 100644
index 0000000..44f4fb9
--- /dev/null
+++ b/project_dummy/hemlo_world.py
@@ -0,0 +1,15 @@
+#!/usr/bin/env python3
+"""Hello."""
+
+
+def hemlo():
+ """Hello!.
+
+ Yeah, there's your fucking period, 's if an exclamation
+ mark were not the end of a sentence!!1!eleven
+ """
+ return 'hemlo world (づ^•ω•^)づ'
+
+
+if __name__ == '__main__':
+ print(hemlo())
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..803a5cd
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,121 @@
+[build-system]
+requires = ["setuptools >= 61.0"]
+build-backend = "setuptools.build_meta"
+
+[project]
+name = "project-dummy"
+description = "A dummy as base directory for actual projects"
+authors = [
+ { name = "Glenn Matthews", email = "janitor@sacredheart.com" }
+]
+license = { text = "License :: OSI Approved :: GNU General Public License v2 (GPLv2)" }
+readme = "README.md"
+requires-python = ">=3.6.0"
+dependencies = [
+ "ansible",
+ "ansible-compat",
+ "ansible-core>=2.12.0"
+]
+dynamic = ["version"]
+
+[project.scripts]
+# install a command as part of the package
+hemlo = "project_dummy:hemlo_world"
+
+[project.urls]
+Source = "https://git.lirion.de/python-project-dummy"
+Documentation = "https://wiki.lirion.example.com/python-project-dummy"
+
+[tool.pytest.ini_options]
+# both mode and loop fixture see https://github.com/pytest-dev/pytest-asyncio/issues/924
+asyncio_mode = "auto"
+# Valid fixture loop scopes are: "function", "class", "module", "package", "session"
+# Caution: This works only on "more recent" versions of pytest (7.2.1 doesn't know this, 8.3.3 does)
+asyncio_default_fixture_loop_scope = "function"
+
+[tool.ruff]
+# Assume Python 3.6.
+target-version = "py36"
+fix = true
+show-fixes = true
+preview = true
+
+[tool.ruff.lint]
+select = [
+ "E", # pycodestyle
+ "F", # Pyflakes
+ "I001", # isort
+ "UP", # pyupgrade
+ "ASYNC", # flake8-async
+ "C4", # flake8-comprehensions
+ "T10", # flake8-debugger
+ "FA", # flake8-future-annotations
+ "PT", # flake8-pytest-style
+ "RSE", # flake8-raise
+ "PERF", # Perflint
+ "FURB", # refurb
+]
+ignore = [
+ "E501" # https://www.flake8rules.com/rules/E501.html - Let `black` handle this.
+]
+# Allow autofix for all enabled rules (when `--fix`) is provided.
+fixable = ["ALL"]
+unfixable = []
+# Exclude a variety of commonly ignored directories.
+exclude = [
+ ".bzr",
+ ".direnv",
+ ".eggs",
+ ".git",
+ ".git-rewrite",
+ ".hg",
+ ".mypy_cache",
+ ".nox",
+ ".pants.d",
+ ".pytype",
+ ".ruff_cache",
+ ".svn",
+ ".tox",
+ ".venv",
+ "__pypackages__",
+ "_build",
+ "buck-out",
+ "build",
+ "dist",
+ "node_modules",
+ "venv",
+ "venv*",
+ "tests"
+]
+
+[tool.ruff.lint.per-file-ignores]
+"__init__.py" = [
+ "I001",
+]
+
+[tool.ruff.lint.pyupgrade]
+# Preserve types, even if a file imports `from __future__ import annotations`.
+# Needed for python < 3.10, should be removed afterward.
+keep-runtime-typing = true
+
+[tools.setuptools.dynamic]
+version = {attr = 'project_dummy.__version__'}
+readme = {file = ['README.md', 'README.rst', 'USAGE.rst']}
+classifiers = {file = ['classifiers.txt']}
+# # dependencies supports "file" but does not support comments in requirements.txt ... :|
+# dependencies = {file = ['requirements.txt']}
+# # ...same for optional dependencies...
+# optional-dependencies = {file = ['requirements.txt']}
+
+# look for packages:
+[tools.setuptools.packages.find]
+# Not using "src/" for now. I'm starting with /package_name folders, using "src" as a folder
+# feels redundant. May change when I use larger projects.
+# where = ["src"] # list of folders that contain the packages (["."] by default)
+include = ["project_*"] # package names should match these glob patterns (["*"] by default)
+exclude = ["project_*.tests*"] # exclude packages matching these glob patterns (empty by default)
+namespaces = false # to disable scanning PEP 420 namespaces (true by default)
+
+# ...or list the packages explicitly:
+# [tool.setuptools]
+# packages = ["my_package"] # use [] for meta-dists that just collect dependencies
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/requirements.txt
diff --git a/setup.py.bak b/setup.py.bak
new file mode 100644
index 0000000..d72fff4
--- /dev/null
+++ b/setup.py.bak
@@ -0,0 +1,88 @@
+#!/usr/bin/env python3
+"""Install this beautiful module to your python ecosystem (づ。•◡ •。)づ ᯓᡣ𐭩.
+
+This is vastly derived from Jeff Knupp's python project ideas.
+"""
+
+from __future__ import print_function
+
+import io
+import os
+import sys
+
+import project_dummy
+
+from setuptools import setup, find_packages
+from setuptools.command.test import test as TestCommand
+
+
+print('This file is obsolete, it should be replaced by pyproject.toml et al.')
+sys.exit(0)
+
+here = os.path.abspath(os.path.dirname(__file__))
+
+
+def read(*filenames, **kwargs):
+ """Read project files."""
+ encoding = kwargs.get('encoding', 'utf-8')
+ sep = kwargs.get('sep', '\n')
+ buf = []
+ for filename in filenames:
+ with io.open(filename, encoding=encoding) as f:
+ buf.append(f.read())
+ return sep.join(buf)
+
+
+long_description = read('README.md', 'CHANGES.md')
+
+
+class PyTest(TestCommand):
+ """Use pytest for testing."""
+
+ def finalize_options(self):
+ """Finalise options."""
+ TestCommand.finalize_options(self)
+ self.test_args = []
+ self.test_suite = True
+
+ def run_tests(self):
+ """Run tests."""
+ import pytest
+ errcode = pytest.main(self.test_args)
+ sys.exit(errcode)
+
+
+setup(
+ name='project_dummy',
+ version=project_dummy.__version__,
+ url='https://git.lirion.de/python-project-dummy/',
+ license='LGPLv3',
+ author='Glenn Matthews',
+ tests_require=['pytest'],
+ install_requires=['ansible',
+ 'ansible-compat',
+ 'ansible-core>=2.12.0',
+ ],
+ cmdclass={'test': PyTest},
+ author_email='janitor@sacredheart.com',
+ description='A dummy as base directory for actual projects',
+ long_description=long_description,
+ packages=['project_dummy'],
+ include_package_data=True,
+ platforms='any',
+ test_suite='project_dummy.tests.dummy_test',
+ classifiers=[
+ 'Programming Language :: Python',
+ 'Development Status :: 2 - Pre-Alpha',
+ 'Natural Language :: English',
+ 'Environment :: Console',
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: GNU General Public License v2 (GPLv2)',
+ 'Operating System :: OS Independent',
+ 'Topic :: Software Development :: Libraries :: Python Modules',
+ 'Topic :: Software Development :: Libraries :: Application Frameworks',
+ ],
+ extras_require={
+ 'testing': ['pytest'],
+ }
+)
diff --git a/tests/dummy_test.py b/tests/dummy_test.py
new file mode 100644
index 0000000..2320f8b
--- /dev/null
+++ b/tests/dummy_test.py
@@ -0,0 +1,44 @@
+#!/usr/bin/env python3
+"""Test some shtuffs."""
+
+import pytest
+
+from project_dummy import db, hemlo_world
+
+
+@pytest.fixture
+def test_fix_to_true():
+ """A fixture."""
+ return True
+
+
+def test_assert_true():
+ """A simple assertion."""
+ assert True
+
+
+def test_hello_world():
+ """Just check that we can import and run this."""
+ assert isinstance(hemlo_world.hemlo(), str)
+
+
+def test_db():
+ """A string."""
+ assert isinstance(db.Db().dbt, str)
+ db.Db().print_db()
+
+
+if __name__ == '__main__':
+ hemlo_world.hemlo()
+
+
+# Some random things
+# Async fixtures and tests:
+#
+# @pytest.mark.asyncio
+# async def test_async_part():
+# ...
+#
+# @pytest.fixture
+# async def create_x():
+# ...
diff --git a/tests/project_dummy b/tests/project_dummy
new file mode 120000
index 0000000..d758124
--- /dev/null
+++ b/tests/project_dummy
@@ -0,0 +1 @@
+../project_dummy \ No newline at end of file
diff --git a/tox.ini b/tox.ini
new file mode 100644
index 0000000..6f4ef0a
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,20 @@
+[tox]
+envlist = coverage
+isolated_build = True
+
+[testenv]
+passenv =
+ CI
+commands = pytest --benchmark-disable
+
+[testenv:coverage]
+commands =
+ coverage erase
+ pytest --cov={envsitepackagesdir}/nio --cov-report term-missing --benchmark-disable
+ coverage xml
+ coverage report --show-missing
+deps =
+ .[dev]
+ coverage
+setenv =
+ COVERAGE_FILE=.coverage