Browse Source

Initial commit

Thomas Verchow 5 months ago
commit
1bb0a2722e
24 changed files with 973 additions and 0 deletions
  1. 28 0
      .coveragerc
  2. 53 0
      .gitignore
  3. 22 0
      .readthedocs.yml
  4. 5 0
      AUTHORS.rst
  5. 10 0
      CHANGELOG.rst
  6. 21 0
      LICENSE.txt
  7. 21 0
      README.rst
  8. 29 0
      docs/Makefile
  9. 1 0
      docs/_static/.gitignore
  10. 2 0
      docs/authors.rst
  11. 2 0
      docs/changelog.rst
  12. 282 0
      docs/conf.py
  13. 60 0
      docs/index.rst
  14. 7 0
      docs/license.rst
  15. 2 0
      docs/readme.rst
  16. 5 0
      docs/requirements.txt
  17. 8 0
      pyproject.toml
  18. 126 0
      setup.cfg
  19. 21 0
      setup.py
  20. 16 0
      src/rfidacd/__init__.py
  21. 149 0
      src/rfidacd/skeleton.py
  22. 10 0
      tests/conftest.py
  23. 25 0
      tests/test_skeleton.py
  24. 68 0
      tox.ini

+ 28 - 0
.coveragerc

@@ -0,0 +1,28 @@
+# .coveragerc to control coverage.py
+[run]
+branch = True
+source = rfidacd
+# omit = bad_file.py
+
+[paths]
+source =
+    src/
+    */site-packages/
+
+[report]
+# Regexes for lines to exclude from consideration
+exclude_lines =
+    # Have to re-enable the standard pragma
+    pragma: no cover
+
+    # Don't complain about missing debug-only code:
+    def __repr__
+    if self\.debug
+
+    # Don't complain if tests don't hit defensive assertion code:
+    raise AssertionError
+    raise NotImplementedError
+
+    # Don't complain if non-runnable code isn't run:
+    if 0:
+    if __name__ == .__main__.:

+ 53 - 0
.gitignore

@@ -0,0 +1,53 @@
+# Temporary and binary files
+*~
+*.py[cod]
+*.so
+*.cfg
+!.isort.cfg
+!setup.cfg
+*.orig
+*.log
+*.pot
+__pycache__/*
+.cache/*
+.*.swp
+*/.ipynb_checkpoints/*
+.DS_Store
+
+# Project files
+.ropeproject
+.project
+.pydevproject
+.settings
+.idea
+.vscode
+tags
+
+# Package files
+*.egg
+*.eggs/
+.installed.cfg
+*.egg-info
+
+# Unittest and coverage
+htmlcov/*
+.coverage
+.coverage.*
+.tox
+junit*.xml
+coverage.xml
+.pytest_cache/
+
+# Build and docs folder/files
+build/*
+dist/*
+sdist/*
+docs/api/*
+docs/_rst/*
+docs/_build/*
+cover/*
+MANIFEST
+
+# Per-project virtualenvs
+.venv*/
+.conda*/

+ 22 - 0
.readthedocs.yml

@@ -0,0 +1,22 @@
+# Read the Docs configuration file
+# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
+
+# Required
+version: 2
+
+# Build documentation in the docs/ directory with Sphinx
+sphinx:
+  configuration: docs/conf.py
+
+# Build documentation with MkDocs
+#mkdocs:
+#  configuration: mkdocs.yml
+
+# Optionally build your docs in additional formats such as PDF
+formats:
+  - pdf
+
+python:
+  version: 3.8
+  install:
+    - requirements: docs/requirements.txt

+ 5 - 0
AUTHORS.rst

@@ -0,0 +1,5 @@
+============
+Contributors
+============
+
+* Thomas Verchow <thomas.verchow@in-ulm.de>

+ 10 - 0
CHANGELOG.rst

@@ -0,0 +1,10 @@
+=========
+Changelog
+=========
+
+Version 0.1
+===========
+
+- Feature A added
+- FIX: nasty bug #1729 fixed
+- add your changes here!

+ 21 - 0
LICENSE.txt

@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2021 Thomas Verchow
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 21 - 0
README.rst

@@ -0,0 +1,21 @@
+=======
+rfidacd
+=======
+
+
+RFID action commander daemon
+
+
+Description
+===========
+
+A longer description of your project goes here...
+
+
+.. _pyscaffold-notes:
+
+Note
+====
+
+This project has been set up using PyScaffold 4.0.1. For details and usage
+information on PyScaffold see https://pyscaffold.org/.

+ 29 - 0
docs/Makefile

@@ -0,0 +1,29 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line, and also
+# from the environment for the first two.
+SPHINXOPTS    ?=
+SPHINXBUILD   ?= sphinx-build
+SOURCEDIR     = .
+BUILDDIR      = _build
+AUTODOCDIR    = api
+
+# User-friendly check for sphinx-build
+ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $?), 1)
+$(error "The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/")
+endif
+
+.PHONY: help clean Makefile
+
+# Put it first so that "make" without argument is like "make help".
+help:
+	@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+clean:
+	rm -rf $(BUILDDIR)/* $(AUTODOCDIR)
+
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).
+%: Makefile
+	@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

+ 1 - 0
docs/_static/.gitignore

@@ -0,0 +1 @@
+# Empty directory

+ 2 - 0
docs/authors.rst

@@ -0,0 +1,2 @@
+.. _authors:
+.. include:: ../AUTHORS.rst

+ 2 - 0
docs/changelog.rst

@@ -0,0 +1,2 @@
+.. _changes:
+.. include:: ../CHANGELOG.rst

+ 282 - 0
docs/conf.py

@@ -0,0 +1,282 @@
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# This file only contains a selection of the most common options. For a full
+# list see the documentation:
+# https://www.sphinx-doc.org/en/master/usage/configuration.html
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import os
+import sys
+import inspect
+import shutil
+
+# -- Path setup --------------------------------------------------------------
+
+__location__ = os.path.join(
+    os.getcwd(), os.path.dirname(inspect.getfile(inspect.currentframe()))
+)
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+sys.path.insert(0, os.path.join(__location__, "../src"))
+
+# -- Run sphinx-apidoc -------------------------------------------------------
+# This hack is necessary since RTD does not issue `sphinx-apidoc` before running
+# `sphinx-build -b html . _build/html`. See Issue:
+# https://github.com/rtfd/readthedocs.org/issues/1139
+# DON'T FORGET: Check the box "Install your project inside a virtualenv using
+# setup.py install" in the RTD Advanced Settings.
+# Additionally it helps us to avoid running apidoc manually
+
+try:  # for Sphinx >= 1.7
+    from sphinx.ext import apidoc
+except ImportError:
+    from sphinx import apidoc
+
+output_dir = os.path.join(__location__, "api")
+module_dir = os.path.join(__location__, "../src/rfidacd")
+try:
+    shutil.rmtree(output_dir)
+except FileNotFoundError:
+    pass
+
+try:
+    import sphinx
+
+    cmd_line_template = (
+        "sphinx-apidoc --implicit-namespaces -f -o {outputdir} {moduledir}"
+    )
+    cmd_line = cmd_line_template.format(outputdir=output_dir, moduledir=module_dir)
+
+    args = cmd_line.split(" ")
+    if tuple(sphinx.__version__.split(".")) >= ("1", "7"):
+        # This is a rudimentary parse_version to avoid external dependencies
+        args = args[1:]
+
+    apidoc.main(args)
+except Exception as e:
+    print("Running `sphinx-apidoc` failed!\n{}".format(e))
+
+# -- General configuration ---------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+# needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = [
+    "sphinx.ext.autodoc",
+    "sphinx.ext.intersphinx",
+    "sphinx.ext.todo",
+    "sphinx.ext.autosummary",
+    "sphinx.ext.viewcode",
+    "sphinx.ext.coverage",
+    "sphinx.ext.doctest",
+    "sphinx.ext.ifconfig",
+    "sphinx.ext.mathjax",
+    "sphinx.ext.napoleon",
+]
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ["_templates"]
+
+# The suffix of source filenames.
+source_suffix = ".rst"
+
+# The encoding of source files.
+# source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = "index"
+
+# General information about the project.
+project = "rfidacd"
+copyright = "2021, Thomas Verchow"
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = ""  # Is set by calling `setup.py docs`
+# The full version, including alpha/beta/rc tags.
+release = ""  # Is set by calling `setup.py docs`
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+# language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+# today = ''
+# Else, today_fmt is used as the format for a strftime call.
+# today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", ".venv"]
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+# default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+# add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+# add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+# show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = "sphinx"
+
+# A list of ignored prefixes for module index sorting.
+# modindex_common_prefix = []
+
+# If true, keep warnings as "system message" paragraphs in the built documents.
+# keep_warnings = False
+
+
+# -- Options for HTML output -------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  See the documentation for
+# a list of builtin themes.
+html_theme = "alabaster"
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+html_theme_options = {
+    "sidebar_width": "300px",
+    "page_width": "1200px"
+}
+
+# Add any paths that contain custom themes here, relative to this directory.
+# html_theme_path = []
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+try:
+    from rfidacd import __version__ as version
+except ImportError:
+    pass
+else:
+    release = version
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+# html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+# html_logo = ""
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+# html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ["_static"]
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+# html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+# html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+# html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+# html_additional_pages = {}
+
+# If false, no module index is generated.
+# html_domain_indices = True
+
+# If false, no index is generated.
+# html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+# html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+# html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+# html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+# html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+# html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+# html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = "rfidacd-doc"
+
+
+# -- Options for LaTeX output ------------------------------------------------
+
+latex_elements = {
+    # The paper size ("letterpaper" or "a4paper").
+    # "papersize": "letterpaper",
+    # The font size ("10pt", "11pt" or "12pt").
+    # "pointsize": "10pt",
+    # Additional stuff for the LaTeX preamble.
+    # "preamble": "",
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+    ("index", "user_guide.tex", "rfidacd Documentation", "Thomas Verchow", "manual")
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+# latex_logo = ""
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+# latex_use_parts = False
+
+# If true, show page references after internal links.
+# latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+# latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+# latex_appendices = []
+
+# If false, no module index is generated.
+# latex_domain_indices = True
+
+# -- External mapping --------------------------------------------------------
+python_version = ".".join(map(str, sys.version_info[0:2]))
+intersphinx_mapping = {
+    "sphinx": ("http://www.sphinx-doc.org/en/stable", None),
+    "python": ("https://docs.python.org/" + python_version, None),
+    "matplotlib": ("https://matplotlib.org", None),
+    "numpy": ("https://docs.scipy.org/doc/numpy", None),
+    "sklearn": ("https://scikit-learn.org/stable", None),
+    "pandas": ("https://pandas.pydata.org/pandas-docs/stable", None),
+    "scipy": ("https://docs.scipy.org/doc/scipy/reference", None),
+    "pyscaffold": ("https://pyscaffold.org/en/stable", None),
+}

+ 60 - 0
docs/index.rst

@@ -0,0 +1,60 @@
+=======
+rfidacd
+=======
+
+This is the documentation of **rfidacd**.
+
+.. note::
+
+    This is the main page of your project's `Sphinx`_ documentation.
+    It is formatted in `reStructuredText`_. Add additional pages
+    by creating rst-files in ``docs`` and adding them to the `toctree`_ below.
+    Use then `references`_ in order to link them from this page, e.g.
+    :ref:`authors` and :ref:`changes`.
+
+    It is also possible to refer to the documentation of other Python packages
+    with the `Python domain syntax`_. By default you can reference the
+    documentation of `Sphinx`_, `Python`_, `NumPy`_, `SciPy`_, `matplotlib`_,
+    `Pandas`_, `Scikit-Learn`_. You can add more by extending the
+    ``intersphinx_mapping`` in your Sphinx's ``conf.py``.
+
+    The pretty useful extension `autodoc`_ is activated by default and lets
+    you include documentation from docstrings. Docstrings can be written in
+    `Google style`_ (recommended!), `NumPy style`_ and `classical style`_.
+
+
+Contents
+========
+
+.. toctree::
+   :maxdepth: 2
+
+   Overview <readme>
+   License <license>
+   Authors <authors>
+   Changelog <changelog>
+   Module Reference <api/modules>
+
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+
+.. _toctree: http://www.sphinx-doc.org/en/master/usage/restructuredtext/directives.html
+.. _reStructuredText: http://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html
+.. _references: http://www.sphinx-doc.org/en/stable/markup/inline.html
+.. _Python domain syntax: http://sphinx-doc.org/domains.html#the-python-domain
+.. _Sphinx: http://www.sphinx-doc.org/
+.. _Python: http://docs.python.org/
+.. _Numpy: http://docs.scipy.org/doc/numpy
+.. _SciPy: http://docs.scipy.org/doc/scipy/reference/
+.. _matplotlib: https://matplotlib.org/contents.html#
+.. _Pandas: http://pandas.pydata.org/pandas-docs/stable
+.. _Scikit-Learn: http://scikit-learn.org/stable
+.. _autodoc: http://www.sphinx-doc.org/en/stable/ext/autodoc.html
+.. _Google style: https://github.com/google/styleguide/blob/gh-pages/pyguide.md#38-comments-and-docstrings
+.. _NumPy style: https://numpydoc.readthedocs.io/en/latest/format.html
+.. _classical style: http://www.sphinx-doc.org/en/stable/domains.html#info-field-lists

+ 7 - 0
docs/license.rst

@@ -0,0 +1,7 @@
+.. _license:
+
+=======
+License
+=======
+
+.. include:: ../LICENSE.txt

+ 2 - 0
docs/readme.rst

@@ -0,0 +1,2 @@
+.. _readme:
+.. include:: ../README.rst

+ 5 - 0
docs/requirements.txt

@@ -0,0 +1,5 @@
+# Requirements file for ReadTheDocs, check .readthedocs.yml.
+# To build the module reference correctly, make sure every external package
+# under `install_requires` in `setup.cfg` is also listed here!
+sphinx>=3.2.1
+# sphinx_rtd_theme

+ 8 - 0
pyproject.toml

@@ -0,0 +1,8 @@
+[build-system]
+# AVOID CHANGING REQUIRES: IT WILL BE UPDATED BY PYSCAFFOLD!
+requires = ["setuptools>=46.1.0", "setuptools_scm[toml]>=5", "wheel"]
+build-backend = "setuptools.build_meta"
+
+[tool.setuptools_scm]
+# See configuration details in https://github.com/pypa/setuptools_scm
+version_scheme = "no-guess-dev"

+ 126 - 0
setup.cfg

@@ -0,0 +1,126 @@
+# This file is used to configure your project.
+# Read more about the various options under:
+# http://setuptools.readthedocs.io/en/latest/setuptools.html#configuring-setup-using-setup-cfg-files
+
+[metadata]
+name = rfidacd
+description = RFID action commander daemon
+author = Thomas Verchow
+author_email = thomas.verchow@in-ulm.de
+license = MIT
+long_description = file: README.rst
+long_description_content_type = text/x-rst; charset=UTF-8
+url = https://github.com/pyscaffold/pyscaffold/
+# Add here related links, for example:
+project_urls =
+    Documentation = https://pyscaffold.org/
+#    Source = https://github.com/pyscaffold/pyscaffold/
+#    Changelog = https://pyscaffold.org/en/latest/changelog.html
+#    Tracker = https://github.com/pyscaffold/pyscaffold/issues
+#    Conda-Forge = https://anaconda.org/conda-forge/pyscaffold
+#    Download = https://pypi.org/project/PyScaffold/#files
+#    Twitter = https://twitter.com/PyScaffold
+
+# Change if running only on Windows, Mac or Linux (comma-separated)
+platforms = any
+
+# Add here all kinds of additional classifiers as defined under
+# https://pypi.python.org/pypi?%3Aaction=list_classifiers
+classifiers =
+    Development Status :: 4 - Beta
+    Programming Language :: Python
+
+
+[options]
+zip_safe = False
+packages = find_namespace:
+include_package_data = True
+package_dir =
+    =src
+
+# Require a min/specific Python version (comma-separated conditions)
+# python_requires = >=3.8
+
+# Add here dependencies of your project (line-separated), e.g. requests>=2.2,<3.0.
+# Version specifiers like >=2.2,<3.0 avoid problems due to API changes in
+# new major versions. This works if the required packages follow Semantic Versioning.
+# For more information, check out https://semver.org/.
+install_requires =
+    importlib-metadata; python_version<"3.8"
+
+
+[options.packages.find]
+where = src
+exclude =
+    tests
+
+[options.extras_require]
+# Add here additional requirements for extra features, to install with:
+# `pip install rfidacd[PDF]` like:
+# PDF = ReportLab; RXP
+
+# Add here test requirements (semicolon/line-separated)
+testing =
+    setuptools
+    pytest
+    pytest-cov
+
+[options.entry_points]
+# Add here console scripts like:
+# console_scripts =
+#     script_name = rfidacd.module:function
+# For example:
+# console_scripts =
+#     fibonacci = rfidacd.skeleton:run
+# And any other entry points, for example:
+# pyscaffold.cli =
+#     awesome = pyscaffoldext.awesome.extension:AwesomeExtension
+
+[tool:pytest]
+# Specify command line options as you would do when invoking pytest directly.
+# e.g. --cov-report html (or xml) for html/xml output or --junitxml junit.xml
+# in order to write a coverage file that can be read by Jenkins.
+# CAUTION: --cov flags may prohibit setting breakpoints while debugging.
+#          Comment those flags to avoid this py.test issue.
+addopts =
+    --cov rfidacd --cov-report term-missing
+    --verbose
+norecursedirs =
+    dist
+    build
+    .tox
+testpaths = tests
+# Use pytest markers to select/deselect specific tests
+# markers =
+#     slow: mark tests as slow (deselect with '-m "not slow"')
+#     system: mark end-to-end system tests
+
+[bdist_wheel]
+# Use this option if your package is pure-python
+universal = 1
+
+[devpi:upload]
+# Options for the devpi: PyPI server and packaging tool
+# VCS export must be deactivated since we are using setuptools-scm
+no_vcs = 1
+formats = bdist_wheel
+
+[flake8]
+# Some sane defaults for the code style checker flake8
+max_line_length = 88
+extend_ignore = E203, W503
+# ^  Black-compatible
+#    E203 and W503 have edge cases handled by black
+exclude =
+    .tox
+    build
+    dist
+    .eggs
+    docs/conf.py
+
+[pyscaffold]
+# PyScaffold's parameters when the project was created.
+# This will be used when updating. Do not change!
+version = 4.0.1
+package = rfidacd
+extensions = 

+ 21 - 0
setup.py

@@ -0,0 +1,21 @@
+"""
+    Setup file for rfidacd.
+    Use setup.cfg to configure your project.
+
+    This file was generated with PyScaffold 4.0.1.
+    PyScaffold helps you to put up the scaffold of your new Python project.
+    Learn more under: https://pyscaffold.org/
+"""
+from setuptools import setup
+
+if __name__ == "__main__":
+    try:
+        setup(use_scm_version={"version_scheme": "no-guess-dev"})
+    except:  # noqa
+        print(
+            "\n\nAn error occurred while building the project, "
+            "please ensure you have the most updated version of setuptools, "
+            "setuptools_scm and wheel with:\n"
+            "   pip install -U setuptools setuptools_scm wheel\n\n"
+        )
+        raise

+ 16 - 0
src/rfidacd/__init__.py

@@ -0,0 +1,16 @@
+import sys
+
+if sys.version_info[:2] >= (3, 8):
+    # TODO: Import directly (no need for conditional) when `python_requires = >= 3.8`
+    from importlib.metadata import PackageNotFoundError, version  # pragma: no cover
+else:
+    from importlib_metadata import PackageNotFoundError, version  # pragma: no cover
+
+try:
+    # Change here if project is renamed and does not equal the package name
+    dist_name = __name__
+    __version__ = version(dist_name)
+except PackageNotFoundError:  # pragma: no cover
+    __version__ = "unknown"
+finally:
+    del version, PackageNotFoundError

+ 149 - 0
src/rfidacd/skeleton.py

@@ -0,0 +1,149 @@
+"""
+This is a skeleton file that can serve as a starting point for a Python
+console script. To run this script uncomment the following lines in the
+``[options.entry_points]`` section in ``setup.cfg``::
+
+    console_scripts =
+         fibonacci = rfidacd.skeleton:run
+
+Then run ``pip install .`` (or ``pip install -e .`` for editable mode)
+which will install the command ``fibonacci`` inside your current environment.
+
+Besides console scripts, the header (i.e. until ``_logger``...) of this file can
+also be used as template for Python modules.
+
+Note:
+    This skeleton file can be safely removed if not needed!
+
+References:
+    - https://setuptools.readthedocs.io/en/latest/userguide/entry_point.html
+    - https://pip.pypa.io/en/stable/reference/pip_install
+"""
+
+import argparse
+import logging
+import sys
+
+from rfidacd import __version__
+
+__author__ = "Thomas Verchow"
+__copyright__ = "Thomas Verchow"
+__license__ = "MIT"
+
+_logger = logging.getLogger(__name__)
+
+
+# ---- Python API ----
+# The functions defined in this section can be imported by users in their
+# Python scripts/interactive interpreter, e.g. via
+# `from rfidacd.skeleton import fib`,
+# when using this Python module as a library.
+
+
+def fib(n):
+    """Fibonacci example function
+
+    Args:
+      n (int): integer
+
+    Returns:
+      int: n-th Fibonacci number
+    """
+    assert n > 0
+    a, b = 1, 1
+    for i in range(n - 1):
+        a, b = b, a + b
+    return a
+
+
+# ---- CLI ----
+# The functions defined in this section are wrappers around the main Python
+# API allowing them to be called directly from the terminal as a CLI
+# executable/script.
+
+
+def parse_args(args):
+    """Parse command line parameters
+
+    Args:
+      args (List[str]): command line parameters as list of strings
+          (for example  ``["--help"]``).
+
+    Returns:
+      :obj:`argparse.Namespace`: command line parameters namespace
+    """
+    parser = argparse.ArgumentParser(description="Just a Fibonacci demonstration")
+    parser.add_argument(
+        "--version",
+        action="version",
+        version="rfidacd {ver}".format(ver=__version__),
+    )
+    parser.add_argument(dest="n", help="n-th Fibonacci number", type=int, metavar="INT")
+    parser.add_argument(
+        "-v",
+        "--verbose",
+        dest="loglevel",
+        help="set loglevel to INFO",
+        action="store_const",
+        const=logging.INFO,
+    )
+    parser.add_argument(
+        "-vv",
+        "--very-verbose",
+        dest="loglevel",
+        help="set loglevel to DEBUG",
+        action="store_const",
+        const=logging.DEBUG,
+    )
+    return parser.parse_args(args)
+
+
+def setup_logging(loglevel):
+    """Setup basic logging
+
+    Args:
+      loglevel (int): minimum loglevel for emitting messages
+    """
+    logformat = "[%(asctime)s] %(levelname)s:%(name)s:%(message)s"
+    logging.basicConfig(
+        level=loglevel, stream=sys.stdout, format=logformat, datefmt="%Y-%m-%d %H:%M:%S"
+    )
+
+
+def main(args):
+    """Wrapper allowing :func:`fib` to be called with string arguments in a CLI fashion
+
+    Instead of returning the value from :func:`fib`, it prints the result to the
+    ``stdout`` in a nicely formated message.
+
+    Args:
+      args (List[str]): command line parameters as list of strings
+          (for example  ``["--verbose", "42"]``).
+    """
+    args = parse_args(args)
+    setup_logging(args.loglevel)
+    _logger.debug("Starting crazy calculations...")
+    print("The {}-th Fibonacci number is {}".format(args.n, fib(args.n)))
+    _logger.info("Script ends here")
+
+
+def run():
+    """Calls :func:`main` passing the CLI arguments extracted from :obj:`sys.argv`
+
+    This function can be used as entry point to create console scripts with setuptools.
+    """
+    main(sys.argv[1:])
+
+
+if __name__ == "__main__":
+    # ^  This is a guard statement that will prevent the following code from
+    #    being executed in the case someone imports this file instead of
+    #    executing it as a script.
+    #    https://docs.python.org/3/library/__main__.html
+
+    # After installing your project with pip, users can also run your Python
+    # modules as scripts via the ``-m`` flag, as defined in PEP 338::
+    #
+    #     python -m rfidacd.skeleton 42
+    #
+    run()

+ 10 - 0
tests/conftest.py

@@ -0,0 +1,10 @@
+"""
+    Dummy conftest.py for rfidacd.
+
+    If you don't know what this is for, just leave it empty.
+    Read more about conftest.py under:
+    - https://docs.pytest.org/en/stable/fixture.html
+    - https://docs.pytest.org/en/stable/writing_plugins.html
+"""
+
+# import pytest

+ 25 - 0
tests/test_skeleton.py

@@ -0,0 +1,25 @@
+import pytest
+
+from rfidacd.skeleton import fib, main
+
+__author__ = "Thomas Verchow"
+__copyright__ = "Thomas Verchow"
+__license__ = "MIT"
+
+
+def test_fib():
+    """API Tests"""
+    assert fib(1) == 1
+    assert fib(2) == 1
+    assert fib(7) == 13
+    with pytest.raises(AssertionError):
+        fib(-10)
+
+
+def test_main(capsys):
+    """CLI Tests"""
+    # capsys is a pytest fixture that allows asserts agains stdout/stderr
+    # https://docs.pytest.org/en/stable/capture.html
+    main(["7"])
+    captured = capsys.readouterr()
+    assert "The 7-th Fibonacci number is 13" in captured.out

+ 68 - 0
tox.ini

@@ -0,0 +1,68 @@
+# Tox configuration file
+# Read more under https://tox.readthedocs.org/
+# THIS SCRIPT IS SUPPOSED TO BE AN EXAMPLE. MODIFY IT ACCORDING TO YOUR NEEDS!
+
+[tox]
+minversion = 3.15
+envlist = default
+
+
+[testenv]
+description = invoke pytest to run automated tests
+isolated_build = True
+setenv =
+    TOXINIDIR = {toxinidir}
+passenv =
+    HOME
+extras =
+    testing
+commands =
+    pytest {posargs}
+
+
+[testenv:{clean,build}]
+description =
+    Build (or clean) the package in isolation according to instructions in:
+    https://setuptools.readthedocs.io/en/latest/build_meta.html#how-to-use-it
+    https://github.com/pypa/pep517/issues/91
+    https://github.com/pypa/build
+# NOTE: build is still experimental, please refer to the links for updates/issues
+skip_install = True
+changedir = {toxinidir}
+deps =
+    build: build[virtualenv]
+commands =
+    clean: python -c 'from shutil import rmtree; rmtree("build", True); rmtree("dist", True)'
+    build: python -m build .
+# By default `build` produces wheels, you can also explicitly use the flags `--sdist` and `--wheel`
+
+
+[testenv:{docs,doctests}]
+description = invoke sphinx-build to build the docs/run doctests
+setenv =
+    DOCSDIR = {toxinidir}/docs
+    BUILDDIR = {toxinidir}/docs/_build
+    docs: BUILD = html
+    doctests: BUILD = doctest
+deps =
+    -r {toxinidir}/docs/requirements.txt
+    # ^  requirements.txt shared with Read The Docs
+commands =
+    sphinx-build -b {env:BUILD} -d "{env:BUILDDIR}/doctrees" "{env:DOCSDIR}" "{env:BUILDDIR}/{env:BUILD}" {posargs}
+
+
+[testenv:publish]
+description =
+    Publish the package you have been developing to a package index server.
+    By default, it uses testpypi. If you really want to publish your package
+    to be publicly accessible in PyPI, use the `-- --repository pypi` option.
+skip_install = True
+changedir = {toxinidir}
+passenv =
+    TWINE_USERNAME
+    TWINE_PASSWORD
+    TWINE_REPOSITORY
+deps = twine
+commands =
+    python -m twine check dist/*
+    python -m twine upload {posargs:--repository testpypi} dist/*