From 826bc59e998fba3fe01d412adc8c00bab9575d4b Mon Sep 17 00:00:00 2001 From: Veronika Juraskova Date: Mon, 3 Jun 2024 17:17:23 +0200 Subject: [PATCH] Initial commit --- .cheat/.github/workflows/basic.yml | 14 ++ .cheat/.github/workflows/coverage.yml | 39 ++++++ .cheat/.github/workflows/os_versions.yml | 37 ++++++ .cheat/.github/workflows/python_versions.yml | 37 ++++++ .cheat/docs/Makefile | 20 +++ .cheat/docs/conf.py | 51 ++++++++ .cheat/docs/index.rst | 24 ++++ .cheat/docs/install.rst | 4 + .cheat/docs/make.bat | 35 +++++ .cheat/docs/quickstart.rst | 7 + .cheat/docs/reference.rst | 6 + .coveragerc | 4 + .flake8 | 6 + .gitignore | 129 +++++++++++++++++++ .readthedocs.yml | 14 ++ LICENSE | 21 +++ README.md | 46 +++++++ ci_course/__init__.py | 4 + ci_course/functionality.py | 43 +++++++ ci_course/tests/__init__.py | 0 ci_course/tests/test_functionality.py | 18 +++ setup.py | 29 +++++ 22 files changed, 588 insertions(+) create mode 100644 .cheat/.github/workflows/basic.yml create mode 100644 .cheat/.github/workflows/coverage.yml create mode 100644 .cheat/.github/workflows/os_versions.yml create mode 100644 .cheat/.github/workflows/python_versions.yml create mode 100644 .cheat/docs/Makefile create mode 100644 .cheat/docs/conf.py create mode 100644 .cheat/docs/index.rst create mode 100644 .cheat/docs/install.rst create mode 100644 .cheat/docs/make.bat create mode 100644 .cheat/docs/quickstart.rst create mode 100644 .cheat/docs/reference.rst create mode 100644 .coveragerc create mode 100644 .flake8 create mode 100644 .gitignore create mode 100644 .readthedocs.yml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 ci_course/__init__.py create mode 100644 ci_course/functionality.py create mode 100644 ci_course/tests/__init__.py create mode 100644 ci_course/tests/test_functionality.py create mode 100644 setup.py diff --git a/.cheat/.github/workflows/basic.yml b/.cheat/.github/workflows/basic.yml new file mode 100644 index 0000000..08e241d --- /dev/null +++ b/.cheat/.github/workflows/basic.yml @@ -0,0 +1,14 @@ +name: Basic GitHub Actions Workflow + +on: + push: + pull_request: + workflow_dispatch: + +jobs: + basic-job: + runs-on: ubuntu-latest + + steps: + - name: Run a one-line script + run: echo "Hello, world!" diff --git a/.cheat/.github/workflows/coverage.yml b/.cheat/.github/workflows/coverage.yml new file mode 100644 index 0000000..10746c2 --- /dev/null +++ b/.cheat/.github/workflows/coverage.yml @@ -0,0 +1,39 @@ +name: Coverage + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + workflow_dispatch: + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + + - uses: actions/checkout@v3 + + - name: Set up Python 3.10 + uses: actions/setup-python@v3 + with: + python-version: "3.10" + + - name: Install dependencies + run: | + python -m pip install --upgrade pip setuptools wheel + python -m pip install .[dev] + + - name: Run coverage + run: | + pytest --cov-config=.coveragerc --cov=./ci_course --cov-report=xml + cat coverage.xml + + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v3 + with: + token: ${{ secrets.CODECOV_TOKEN }} + fail_ci_if_error: true + files: coverage.xml diff --git a/.cheat/.github/workflows/os_versions.yml b/.cheat/.github/workflows/os_versions.yml new file mode 100644 index 0000000..b2e5a1e --- /dev/null +++ b/.cheat/.github/workflows/os_versions.yml @@ -0,0 +1,37 @@ +# This workflow will install Python dependencies, run tests and lint with a variety of Python versions +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python + +name: Operating systems + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + workflow_dispatch: + +jobs: + build: + + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + + steps: + - uses: actions/checkout@v3 + - name: Set up Python 3.10 + uses: actions/setup-python@v3 + with: + python-version: "3.10" + - name: Install dependencies + run: | + python -m pip install --upgrade pip setuptools wheel + python -m pip install .[dev] + - name: Lint with flake8 + run: | + flake8 + - name: Test with pytest + run: | + pytest diff --git a/.cheat/.github/workflows/python_versions.yml b/.cheat/.github/workflows/python_versions.yml new file mode 100644 index 0000000..e675f99 --- /dev/null +++ b/.cheat/.github/workflows/python_versions.yml @@ -0,0 +1,37 @@ +# This workflow will install Python dependencies, run tests and lint with a variety of Python versions +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python + +name: Python versions + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + workflow_dispatch: + +jobs: + build: + + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ["3.8", "3.9", "3.10"] + + steps: + - uses: actions/checkout@v3 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v3 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip setuptools wheel + python -m pip install .[dev] + - name: Lint with flake8 + run: | + flake8 + - name: Test with pytest + run: | + pytest diff --git a/.cheat/docs/Makefile b/.cheat/docs/Makefile new file mode 100644 index 0000000..d4bb2cb --- /dev/null +++ b/.cheat/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal 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 + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# 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) diff --git a/.cheat/docs/conf.py b/.cheat/docs/conf.py new file mode 100644 index 0000000..17e0d04 --- /dev/null +++ b/.cheat/docs/conf.py @@ -0,0 +1,51 @@ +# Configuration file for the Sphinx documentation builder. +# +# 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 + +# -- Path setup -------------------------------------------------------------- + +# 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. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + + +# -- Project information ----------------------------------------------------- + +project = 'CI demo' +copyright = '2020, Fergus Cooper' +author = 'Fergus Cooper' + + +# -- General configuration --------------------------------------------------- + +# 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.napoleon'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + + +# -- 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' + +# 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 = [] diff --git a/.cheat/docs/index.rst b/.cheat/docs/index.rst new file mode 100644 index 0000000..f90bda1 --- /dev/null +++ b/.cheat/docs/index.rst @@ -0,0 +1,24 @@ +.. CI demo documentation master file, created by + sphinx-quickstart on Tue Jul 21 17:19:37 2020. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to CI demo's documentation! +=================================== + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + install + quickstart + reference + + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/.cheat/docs/install.rst b/.cheat/docs/install.rst new file mode 100644 index 0000000..db21262 --- /dev/null +++ b/.cheat/docs/install.rst @@ -0,0 +1,4 @@ +Installation +============ + +Make sure your users know how to install your software! diff --git a/.cheat/docs/make.bat b/.cheat/docs/make.bat new file mode 100644 index 0000000..2119f51 --- /dev/null +++ b/.cheat/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=. +set BUILDDIR=_build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/.cheat/docs/quickstart.rst b/.cheat/docs/quickstart.rst new file mode 100644 index 0000000..481bd04 --- /dev/null +++ b/.cheat/docs/quickstart.rst @@ -0,0 +1,7 @@ +Getting started +=============== + +It's good practice to provide a brief, head-first "getting started" guide... for +impatient users to get a feel of the features of your package/scripts. + +They can always consult the reference at a later stage if they want to go deeper. diff --git a/.cheat/docs/reference.rst b/.cheat/docs/reference.rst new file mode 100644 index 0000000..aed37fe --- /dev/null +++ b/.cheat/docs/reference.rst @@ -0,0 +1,6 @@ +functionality module reference +============================== + +.. autofunction:: ci_course.functionality.greet + +.. autofunction:: ci_course.functionality.minimum diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 0000000..d05a909 --- /dev/null +++ b/.coveragerc @@ -0,0 +1,4 @@ +[run] +source = ci_course +omit = + ci_course/tests/* diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000..1743687 --- /dev/null +++ b/.flake8 @@ -0,0 +1,6 @@ +[flake8] +ignore = E203, E266, E501, W503, F403, F401 +exclude = docs/* +max-line-length = 120 +max-complexity = 18 +select = B,C,E,F,W,T4,B9 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b6e4761 --- /dev/null +++ b/.gitignore @@ -0,0 +1,129 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ diff --git a/.readthedocs.yml b/.readthedocs.yml new file mode 100644 index 0000000..ccfa40c --- /dev/null +++ b/.readthedocs.yml @@ -0,0 +1,14 @@ +version: 2 + +python: + version: 3.8 + install: + - method: pip + path: . + extra_requirements: + - docs + +sphinx: + builder: html + configuration: docs/conf.py + fail_on_warning: true diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..7c56f95 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 University of Oxford + +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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..90e1c78 --- /dev/null +++ b/README.md @@ -0,0 +1,46 @@ +# OxRSE Continuous Integration course + +This project contains a small Python project. We are going to use free cloud services to automate: + +- unit testing on multiple Python versions +- unit testing on multiple operating systems +- coverage testing +- static analysis +- documentation generation + +To make sure all dependencies are installed, we recommend creating a new virtual environment. +From the directory containing this file: + +```bash +python3 -m pip install --user virtualenv +python3 -m venv venv +``` + +Activate the virtual environment: + +Linux / macOS: +```bash +source venv/bin/activate +``` + +Windows cmd.exe: +```bash +venv\Scripts\activate.bat +``` + +Windows PowerShell: +```bash +venv\Scripts\Activate.ps1 +``` + +Windows using Git Bash: +```bash +source venv\Scripts\activate +``` + +Upgrade the build tools and install this project: + +```bash +pip install --upgrade pip setuptools wheel +pip install -e .[dev,docs] +``` diff --git a/ci_course/__init__.py b/ci_course/__init__.py new file mode 100644 index 0000000..063c9ad --- /dev/null +++ b/ci_course/__init__.py @@ -0,0 +1,4 @@ +from .functionality import greet +from .functionality import minimum + +__all__ = ['greet', 'minimum'] diff --git a/ci_course/functionality.py b/ci_course/functionality.py new file mode 100644 index 0000000..5dc4c85 --- /dev/null +++ b/ci_course/functionality.py @@ -0,0 +1,43 @@ +import numbers + + +def greet(name=""): + """ + A function that takes a name and returns a greeting. + + Parameters + ---------- + name : str, optional + The name to greet (default is "") + + Returns + ------- + str + The greeting + """ + return f"Hello {name}" + + +def minimum(*args): + """ + A function taking some arguments and returning the minimum number among the arguments. + + Parameters + ---------- + args : int, float + The numbers from which to return the minimum + + Returns + ------- + int, float + The minimum + """ + if not any([isinstance(arg, numbers.Real) for arg in args]): + return + + the_min = float("inf") + for arg in args: + if isinstance(arg, numbers.Real): + the_min = min(the_min, arg) + + return the_min diff --git a/ci_course/tests/__init__.py b/ci_course/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ci_course/tests/test_functionality.py b/ci_course/tests/test_functionality.py new file mode 100644 index 0000000..e83e011 --- /dev/null +++ b/ci_course/tests/test_functionality.py @@ -0,0 +1,18 @@ +import ci_course + + +def test_greet(): + """ + Test the function `greet` in functionality.py + """ + assert ci_course.greet() == "Hello " + assert ci_course.greet("Fergus") == "Hello Fergus" + + +def test_minimum(): + """ + Test the function `minimum` in functionality.py + """ + assert ci_course.minimum(1, 2, 3) == 1 + assert ci_course.minimum(1.2, 2.3) == 1.2 + assert ci_course.minimum(-1.2, -3) == -3 diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..464b102 --- /dev/null +++ b/setup.py @@ -0,0 +1,29 @@ +from setuptools import setup + +setup( + name='ci_course', + + version='0.1', + + description='Demonstration of setting up continuous integration for a Python project', + + license='MIT', + + packages=['ci_course'], + + install_requires=[ + ], + + extras_require={ + 'docs': [ + 'sphinx' + ], + 'dev': [ + 'flake8', + 'pytest', + 'pytest-cov', + ], + }, + + zip_safe=False +)