Skip to content
Snippets Groups Projects
Commit c0548b54 authored by Mayr, Hannes's avatar Mayr, Hannes
Browse files

Merge branch 'dev' into '69-enable-basic-customization'

# Conflicts:
#   plotid/tagplot.py
#   tests/test_tagplot.py
parents d92b1284 e63ca243
Branches
Tags
6 merge requests!65Release v0.3.0,!64New year developments,!63Improve handling of long IDs,!62Export imported modules,!61Custom IDs,!60Enable customization of plotted IDs
Pipeline #878012 failed
Showing
with 223 additions and 119 deletions
......@@ -4,6 +4,8 @@ stages:
- testing
- security
- docs
- package
- release
# Change pip's cache directory to be inside the project directory since we can
# only cache local items.
......@@ -17,31 +19,36 @@ before_script:
- pip install --user --no-warn-script-location -r requirements.txt # install dependencies from file
PEP8:
stage: linting
needs: []
script:
- pip install flake8
- flake8 --count --max-line-length=88 .
Pylint:
stage: linting
needs: []
script:
- pip install pylint
- find . -type f -name '*.py' | xargs pylint -rn --rcfile='plotid/.pylintrc' # Find all python files and check the code with pylint
Autoformatting:
stage: linting
needs: []
script:
- pip install black
- black --check --verbose --diff --color .
Typechecker:
stage: linting
needs: []
script:
- pip install mypy
- mypy --ignore-missing-imports --strict plotid tests examples
- mypy --ignore-missing-imports --strict plotid examples
allow_failure: true
test:
stage: testing
needs: []
tags:
- docker
script:
......@@ -85,6 +92,28 @@ include:
- template: Security/Dependency-Scanning.gitlab-ci.yml
- template: Security/License-Scanning.gitlab-ci.yml
build_and_upload:
stage: package
script:
- pip install build twine
- python3 -m build
- TWINE_PASSWORD=${CI_PYPI_TOKEN} TWINE_USERNAME=__token__ python3 -m twine upload dist/*
rules:
- if: $CI_COMMIT_TAG
release_job:
stage: release
image: registry.gitlab.com/gitlab-org/release-cli:latest
rules:
- if: $CI_COMMIT_TAG # Run this job when a tag is created
before_script:
- echo "No before script pls"
script:
- echo "running release_job"
release: # See https://docs.gitlab.com/ee/ci/yaml/#release for available properties
tag_name: '$CI_COMMIT_TAG'
description: '$CI_COMMIT_TAG'
# You can override the included template(s) by including variable overrides
# SAST customization: https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
# Secret Detection customization: https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings
......
cff-version: 1.2.0
message: "If you use this software, please cite it as below."
type: software
title: plotID
authors:
- family-names: Mayr
given-names: Hannes
email: hannes.mayr@stud.tu-darmstadt.de
affiliation: Institut für Fluidsystemtechnik - TU Darmstadt
- family-names: Hock
given-names: Martin
email: Martin.Hock@fst.tu-darmstadt.de
affiliation: Institut für Fluidsystemtechnik - TU Darmstadt
orcid: https://orcid.org/0000-0001-9917-3152
- family-names: Richter
given-names: Manuela
email: Manuela.Richter@fst.tu-darmstadt.de
affiliation: Institut für Fluidsystemtechnik - TU Darmstadt
# Contributing
Feel free to **report** all **issues** you encounter with plotID in our [issue tracker](https://git.rwth-aachen.de/plotid/plotid_python/-/issues). This will greatly help to improve plotID.
Contributing to plotID via **merge requests** is also highly appreciated. Please make sure that your code complies with the [PEP 8 - Style Guide](https://peps.python.org/pep-0008/) before creating a merge request. We try to have the whole code of plotID covered by unittests. So if you contribute new code to plotid please also provide unittests that cover the new functionality. Should you be interested in adding another plot engine to be supported by plotID, have a look at the section [Implement a new plot engine](#add-plot-engine). There are some hints how to proceed in this case.
Contributing to plotID via **merge requests** is also highly appreciated. Please make sure that your code complies with the [PEP 8 - Style Guide](https://peps.python.org/pep-0008/) before creating a merge request. We enforce the [**black code style**](https://black.readthedocs.io/en/stable/). We try to have the whole code of plotID covered by unittests. So if you contribute new code to plotid please also provide unittests that cover the new functionality. Should you be interested in adding another plot engine to be supported by plotID, have a look at the section [Implement a new plot engine](#add-plot-engine). There are some hints how to proceed in this case.
## Setup development environment
Clone the repository and install the dependencies:
......
......@@ -40,6 +40,7 @@ autoapi_type = "python"
autoapi_dirs = ["../../plotid", "../../tests"]
# autoapi_keep_files = True
myst_heading_anchors = 2
autodoc_typehints = "description"
# Add any paths that contain templates here, relative to this directory.
templates_path = ["_templates"]
......
......@@ -10,5 +10,5 @@ research data, the plot is based on. Additionally, the script that created the
plot will also be copied to the directory.
"""
__version__ = "0.2.2"
__version__ = "0.2.2-b3"
__author__ = "Institut Fluidsystemtechnik within nfdi4ing at TU Darmstadt"
......@@ -8,9 +8,10 @@ Functions:
import time
import uuid
import qrcode
from PIL import Image
def create_id(id_method):
def create_id(id_method: str) -> str:
"""
Create an Identifier (str).
......@@ -28,8 +29,7 @@ def create_id(id_method):
"""
match id_method:
case "time":
figure_id = time.time() # UNIX Time
figure_id = hex(int(figure_id)) # convert time to hexadecimal str
figure_id = hex(int(time.time())) # convert UNIX Time to hexadecimal str
time.sleep(1) # break for avoiding duplicate IDs
case "random":
figure_id = str(uuid.uuid4()) # creates a random UUID
......@@ -44,7 +44,7 @@ def create_id(id_method):
return figure_id
def create_qrcode(figure_id):
def create_qrcode(figure_id: str) -> Image:
"""
Create a QR Code from an identifier.
......
......@@ -3,6 +3,19 @@
"""Contains the PlotOptions and PlotIDTransfer classes."""
import os
from typing import Any, Literal, TypedDict, TypeVar
import matplotlib.pyplot as plt
from PIL.Image import Image
kwargs_types = TypedDict(
"kwargs_types",
{
"prefix": str,
"id_method": Literal["time", "random"],
"qrcode": bool,
},
)
class PlotOptions:
......@@ -19,19 +32,19 @@ class PlotOptions:
Attributes
----------
figs : figure object or list of figures
figs :
Figures that will be tagged.
figure_ids: str or list of str
IDs that the figures are tagged with.
rotation : int
rotation :
Rotation angle for the ID.
position : tuple
position :
Relative position of the ID on the plot (x,y).
**kwargs : dict, optional
Extra arguments for additional plot options.
Other Parameters
----------------
figure_ids: str or list of str
IDs that the figures are tagged with.
prefix : str, optional
Will be added as prefix to the ID.
id_method : str, optional
......@@ -58,7 +71,13 @@ class PlotOptions:
each value between [0, 1]. Default: (0, 0, 0).
"""
def __init__(self, figs, rotation, position, **kwargs):
def __init__(
self,
figs: plt.Figure | Image | list[plt.Figure | Image],
rotation: int,
position: tuple[float, float],
**kwargs: Any,
) -> None:
self.figs = figs
self.figure_ids = kwargs.get("figure_ids", [])
......@@ -76,11 +95,11 @@ class PlotOptions:
self.fontsize = kwargs.get("fontsize", 12)
self.fontcolor = kwargs.get("fontcolor", (0, 0, 0))
def __str__(self):
def __str__(self) -> str:
"""Representation if an object of this class is printed."""
return str(self.__class__) + ": " + str(self.__dict__)
def validate_input(self):
def validate_input(self) -> None:
"""
Validate if input for PlotOptions is correct type.
......@@ -92,7 +111,7 @@ class PlotOptions:
Returns
-------
0, if all checks succeed.
None.
"""
# Input validation for figs is done in submodules tagplot_$engine.py
......@@ -106,8 +125,6 @@ class PlotOptions:
if not isinstance(self.figs, list):
self.figs = [self.figs]
return 0
class PlotIDTransfer:
"""
......@@ -119,29 +136,36 @@ class PlotIDTransfer:
Attributes
----------
figs : figure object or list of figures
figs :
Tagged figures.
figure_ids: str or list of str
figure_ids:
IDs that the figures are tagged with.
"""
def __init__(self, figs, figure_ids):
def __init__(
self, figs: plt.Figure | Image | list[plt.Figure | Image], figure_ids: list[str]
) -> None:
self.figs = figs
self.figure_ids = figure_ids
self.figure_ids = validate_list(self.figure_ids)
def __str__(self):
def __str__(self) -> str:
"""Representation if an object of this class is printed."""
return str(self.__class__) + ": " + str(self.__dict__)
def validate_list(list_var, elt_type=str, is_file=False):
T = TypeVar("T")
def validate_list(
list_var: T | list[T] | object, elt_type: type = str, is_file: bool = False
) -> list[T]:
"""
Validate if contents of a list are of specific type.
Parameters
----------
list_var : list or str
list_var :
List or single string which contents will be validated.
elt_type : datatype, optional
Datatype of which the list elements must be type of. Otherwise
......@@ -175,7 +199,7 @@ def validate_list(list_var, elt_type=str, is_file=False):
)
if is_file:
# Check if directory and files exist
if not os.path.exists(elt):
if not os.path.exists(elt): # type: ignore
raise FileNotFoundError(
"The specified directory" f"/file {elt} does not exist."
)
......
......@@ -6,16 +6,13 @@ Publish a tagged plot along the corresponding research data.
Export the tagged figure to a directory that also contains the raw data where
the plot is based on. Additionally, the script that produced the plot will be
copied to the destination directory.
Functions:
publish(PlotIDTransfer object, str or list of str, str or list of str)
-> None
"""
import os
import shutil
import sys
import warnings
from typing import TypedDict, Any
from plotid.save_plot import save_plot
from plotid.plotoptions import PlotIDTransfer, validate_list
......@@ -33,7 +30,13 @@ class PublishOptions:
Export the plot and copy specified files to the destiantion folder.
"""
def __init__(self, figs_and_ids, src_datapaths, dst_path, **kwargs):
def __init__(
self,
figs_and_ids: PlotIDTransfer,
src_datapaths: str | list[str],
dst_path: str,
**kwargs: Any,
) -> None:
if not isinstance(figs_and_ids, PlotIDTransfer):
raise RuntimeError("figs_and_ids is not an instance of PlotIDTransfer.")
......@@ -45,11 +48,11 @@ class PublishOptions:
self.dst_path_head, self.dst_dirname = os.path.split(self.dst_path)
self.plot_names = kwargs.get("plot_names", self.figure_ids)
def __str__(self):
def __str__(self) -> str:
"""Representation if an object of this class is printed."""
return str(self.__class__) + ": " + str(self.__dict__)
def validate_input(self):
def validate_input(self) -> None:
"""
Validate if input for PublishOptions is correct type.
......@@ -92,7 +95,7 @@ class PublishOptions:
if not isinstance(self.data_storage, str):
raise TypeError("The specified data_storage method is not a string.")
def export(self):
def export(self) -> None:
"""
Export the plot and copy specified files to the destination folder.
......@@ -172,7 +175,7 @@ class PublishOptions:
f"\nwere copied to {self.dst_path}."
)
def centralized_data_storage(self):
def centralized_data_storage(self) -> None:
"""
[not implemented yet].
......@@ -185,15 +188,15 @@ class PublishOptions:
"""
# Does nothing, not implemented yet
def individual_data_storage(self, destination, pic_path):
def individual_data_storage(self, destination: str, pic_path: str) -> None:
"""
Store all the data in an individual directory.
Parameters
----------
destination : str
destination :
Directory where the data should be stored.
pic_paths : list
pic_path :
Paths to the picture file that will be stored in destination.
Returns
......@@ -237,19 +240,33 @@ class PublishOptions:
)
def publish(figs_and_ids, src_datapath, dst_path, **kwargs):
kwargs_types_publish = TypedDict(
"kwargs_types_publish",
{
"data_storage": str,
"plot_names": str | list[str],
},
)
def publish(
figs_and_ids: PlotIDTransfer,
src_datapath: str | list[str],
dst_path: str,
**kwargs: kwargs_types_publish,
) -> None:
"""
Save plot, data and measuring script.
Parameters
----------
figs_and_ids : PlotIDTransfer object
figs_and_ids :
Contains figures tagged by tagplot() and their corresponding IDs.
src_datapath : str or list of str
src_datapath :
Path to data that should be published.
dst_path : str
dst_path :
Path to the destination directory.
**kwargs : dict, optional
**kwargs :
Extra arguments for additional publish options.
Other Parameters
......
......@@ -10,9 +10,12 @@ Functions:
import warnings
import matplotlib
import matplotlib.pyplot as plt
from PIL.Image import Image
def save_plot(figures, plot_names, extension="png"):
def save_plot(
figures: plt.Figure | Image, plot_names: str | list[str], extension: str = "png"
) -> list[str]:
"""
Export plot(s).
......@@ -48,7 +51,7 @@ def save_plot(figures, plot_names, extension="png"):
" will be taken for all plots with an appended number."
)
first_name = plot_names[0]
plot_names = [None] * len(figures)
plot_names = [""] * len(figures)
for i, _ in enumerate(plot_names):
plot_names[i] = first_name + f"{i+1}"
elif len(plot_names) > len(figures):
......
......@@ -11,12 +11,21 @@ Functions:
"""
import warnings
from plotid.plotoptions import PlotOptions
from typing import Any, Literal
import matplotlib.pyplot as plt
from PIL.Image import Image
from plotid.plotoptions import PlotOptions, PlotIDTransfer
from plotid.tagplot_matplotlib import tagplot_matplotlib
from plotid.tagplot_image import tagplot_image
def tagplot(figs, engine, **kwargs):
def tagplot(
figs: plt.Figure | Image | list[plt.Figure | Image],
engine: Literal["matplotlib", "image"],
location: str = "east",
**kwargs: Any,
) -> PlotIDTransfer:
"""
Tag your figure/plot with an ID.
......@@ -25,9 +34,9 @@ def tagplot(figs, engine, **kwargs):
Parameters
----------
figs : list
figs :
Figures that should be tagged.
engine : str
engine :
Plot engine which should be used to tag the plot.
**kwargs : dict, optional
Extra arguments for additional plot options.
......
......@@ -12,7 +12,7 @@ from plotid.create_id import create_id, create_qrcode
from plotid.plotoptions import PlotOptions, PlotIDTransfer
def tagplot_image(plotid_object):
def tagplot_image(plotid_object: PlotOptions) -> PlotIDTransfer:
"""
Add IDs to images/pictures with pillow.
......
# -*- coding: utf-8 -*-
"""
Tag your matplotlib plot with an ID.
Functions:
tagplot_matplotlib(PlotOptions instance) -> PlotIDTransfer instance
"""
"""Tag your matplotlib plot with an ID."""
import matplotlib
import matplotlib.pyplot as plt
......@@ -13,7 +8,7 @@ from plotid.create_id import create_id, create_qrcode
from plotid.plotoptions import PlotOptions, PlotIDTransfer
def tagplot_matplotlib(plotid_object):
def tagplot_matplotlib(plotid_object: PlotOptions) -> PlotIDTransfer:
"""
Add IDs to figures with matplotlib.
......@@ -22,7 +17,8 @@ def tagplot_matplotlib(plotid_object):
Parameters
----------
plotid_object : instance of PlotOptions
plotid_object :
Object containing the figures and all additional options.
Returns
-------
......@@ -41,7 +37,7 @@ def tagplot_matplotlib(plotid_object):
# Loop to create and position the IDs
for fig in plotid_object.figs:
fig_id = create_id(plotid_object.id_method)
fig_id: str = create_id(plotid_object.id_method)
fig_id = plotid_object.prefix + fig_id
plotid_object.figure_ids.append(fig_id)
plt.figure(fig)
......
......@@ -6,7 +6,7 @@ matplotlib==3.5.2
myst-parser==0.18.0
numpy==1.22.3
packaging==21.3
Pillow==9.1.1
Pillow==9.3.0
pyparsing==3.0.8
python-dateutil==2.8.2
qrcode==7.3.1
......
......@@ -15,24 +15,24 @@ class TestCreateID(unittest.TestCase):
Class for all unittests of the create_id module.
"""
def test_existence(self):
def test_existence(self) -> None:
"""Test if create_id returns a string."""
self.assertIsInstance(cid.create_id("time"), str)
self.assertIsInstance(cid.create_id("random"), str)
def test_errors(self):
def test_errors(self) -> None:
"""Test if Errors are raised when id_method is wrong."""
with self.assertRaises(ValueError):
cid.create_id(3)
with self.assertRaises(ValueError):
cid.create_id("h")
def test_length(self):
def test_length(self) -> None:
"""Test if figure_id has the correct length."""
self.assertEqual(len(cid.create_id("time")), 10)
self.assertEqual(len(cid.create_id("random")), 8)
def test_qrcode(self):
def test_qrcode(self) -> None:
"""Test if qrcode returns a image."""
self.assertIsInstance(create_qrcode("test_ID"), qrcode.image.pil.PilImage)
......
......@@ -16,7 +16,7 @@ class TestTagplot(unittest.TestCase):
Class for all unittests of the plotoptions module.
"""
def test_validate_input(self):
def test_validate_input(self) -> None:
"""
Test if input validation runs successful.
"""
......@@ -24,17 +24,17 @@ class TestTagplot(unittest.TestCase):
"FIG", ROTATION, POSITION, prefix="xyz", id_method="random"
).validate_input()
def test_prefix(self):
def test_prefix(self) -> None:
"""Test if Error is raised if prefix is not a string."""
with self.assertRaises(TypeError):
PlotOptions(["FIG"], ROTATION, POSITION, prefix=3).validate_input()
def test_data_storage(self):
def test_data_storage(self) -> None:
"""Test if Error is raised if id_method is not a string."""
with self.assertRaises(TypeError):
PlotOptions(["FIG"], ROTATION, POSITION, id_method=4).validate_input()
def test_str_plotoptions(self):
def test_str_plotoptions(self) -> None:
"""
Test if the string representation of a PlotOptions object is correct.
"""
......@@ -55,7 +55,7 @@ class TestTagplot(unittest.TestCase):
"(0, 0, 0)}",
)
def test_str_plotidtransfer(self):
def test_str_plotidtransfer(self) -> None:
"""
Test if the string representation of a PlotIDTransfer object is
correct.
......
......@@ -35,7 +35,7 @@ class TestPublish(unittest.TestCase):
Class for all unittests of the publish module.
"""
def setUp(self):
def setUp(self) -> None:
"""Generate source and destination directory and source files."""
os.makedirs(SRC_DIR, exist_ok=True)
os.makedirs(DST_PARENT_DIR, exist_ok=True)
......@@ -48,7 +48,7 @@ class TestPublish(unittest.TestCase):
"Publish is not called from a Python script. Therefore, the script cannot be "
"copied.",
)
def test_publish(self):
def test_publish(self) -> None:
"""
Test publish and check if an exported picture file exists.
The destination path is given with trailing slash.
......@@ -69,7 +69,7 @@ class TestPublish(unittest.TestCase):
"from a Python script. Therefore, the script cannot be "
"copied.",
)
def test_publish_multiple_figs_custom_name(self):
def test_publish_multiple_figs_custom_name(self) -> None:
"""
Test publish with multiple figures and check if all exported picture
files exist with the provided strings as their names.
......@@ -85,7 +85,7 @@ class TestPublish(unittest.TestCase):
"from a Python script. Therefore, the script cannot be "
"copied.",
)
def test_publish_multiple_figs_standard_name(self):
def test_publish_multiple_figs_standard_name(self) -> None:
"""
Test publish with multiple figures and check if all exported picture
files exist with the IDs as their names.
......@@ -96,7 +96,7 @@ class TestPublish(unittest.TestCase):
os.path.join(DST_PATH, identifier, identifier + ".png")
)
def test_figs_and_ids(self):
def test_figs_and_ids(self) -> None:
"""
Test if RuntimeError is raised when figs_and_ids is not an
PlotIDTransfer object.
......@@ -104,7 +104,7 @@ class TestPublish(unittest.TestCase):
with self.assertRaises(RuntimeError):
publish("FIGS_AND_IDS", SRC_DIR, DST_PATH)
def test_wrong_ids(self):
def test_wrong_ids(self) -> None:
"""Test if Error is raised if IDs are of wrong type."""
with self.assertRaises(TypeError):
publish(PlotIDTransfer(FIG, 3), SRC_DIR, DST_PATH)
......@@ -117,7 +117,7 @@ class TestPublish(unittest.TestCase):
"Publish is not called from a Python script. Therefore, the script cannot be "
"copied.",
)
def test_publish_multiple_src_files(self):
def test_publish_multiple_src_files(self) -> None:
"""
Test publish with multiple source files and check
if the exported data files exist.
......@@ -137,7 +137,7 @@ class TestPublish(unittest.TestCase):
assert os.path.isdir(path)
assert os.path.isfile(os.path.join(path, file))
def test_src_directory(self):
def test_src_directory(self) -> None:
"""Test if Error is raised when source directory does not exist."""
with self.assertRaises(FileNotFoundError):
publish(FIGS_AND_IDS, "not_existing_folder", DST_PATH)
......@@ -148,14 +148,14 @@ class TestPublish(unittest.TestCase):
"Publish is not called from a Python script. Therefore, the script cannot be "
"copied.",
)
def test_src_directory_type(self):
def test_src_directory_type(self) -> None:
"""Test if Error is raised when source directory is not a string."""
with self.assertRaises(TypeError):
publish(FIGS_AND_IDS, [SRC_DIR, 4], DST_PATH)
with self.assertRaises(TypeError):
publish(FIGS_AND_IDS, 4, DST_PATH)
def test_dst_directory(self):
def test_dst_directory(self) -> None:
"""
Test if Error is raised when the directory above the
destination dir does not exist.
......@@ -163,7 +163,7 @@ class TestPublish(unittest.TestCase):
with self.assertRaises(FileNotFoundError):
publish(FIGS_AND_IDS, SRC_DIR, "not_existing_folder/data")
def test_script_exists(self):
def test_script_exists(self) -> None:
"""
Test if Error is raised when publish is called from a shell.
......@@ -217,7 +217,7 @@ class TestPublish(unittest.TestCase):
"from a Python script. Therefore, the script cannot be "
"copied.",
)
def test_dst_already_exists_yes(self):
def test_dst_already_exists_yes(self) -> None:
"""
Test if publish succeeds if the user wants to overwrite an existing
destination directory.
......@@ -235,7 +235,7 @@ class TestPublish(unittest.TestCase):
"from a Python script. Therefore, the script cannot be "
"copied.",
)
def test_dst_already_exists_no(self):
def test_dst_already_exists_no(self) -> None:
"""
Test if publish exits with error if the user does not want to overwrite
an existing destination directory by user input 'no'.
......@@ -255,7 +255,7 @@ class TestPublish(unittest.TestCase):
"from a Python script. Therefore, the script cannot be "
"copied.",
)
def test_dst_already_exists_empty(self):
def test_dst_already_exists_empty(self) -> None:
"""
Test if publish exits with error if the user does not want to overwrite
an existing destination directory by missing user input.
......@@ -274,7 +274,7 @@ class TestPublish(unittest.TestCase):
"Publish is not called from a Python script. Therefore, the script cannot be "
"copied.",
)
def test_dst_invisible_already_exists(self):
def test_dst_invisible_already_exists(self) -> None:
"""
Test if after a crash of publish the partially copied data is
removed.
......@@ -291,14 +291,20 @@ class TestPublish(unittest.TestCase):
os.remove("test_picture1.tmp.png")
os.remove("test_picture2.tmp.png")
def test_plot_names(self):
def test_plot_names(self) -> None:
"""Test if Error is raised if plot_name is not a string."""
with self.assertRaises(TypeError):
publish(FIGS_AND_IDS, SRC_DIR, DST_PATH, 7.6, data_storage="individual")
publish(
FIGS_AND_IDS,
SRC_DIR,
DST_PATH,
plot_names=7.6,
data_storage="individual",
)
with self.assertRaises(TypeError):
publish(FIGS_AND_IDS, SRC_DIR, DST_PATH, ())
publish(FIGS_AND_IDS, SRC_DIR, DST_PATH, plot_names=())
with self.assertRaises(TypeError):
publish(FIGS_AND_IDS, SRC_DIR, DST_PATH, ["test", 3])
publish(FIGS_AND_IDS, SRC_DIR, DST_PATH, plot_names=["test", 3])
# Skip test if tests are run from command line.
@unittest.skipIf(
......@@ -306,7 +312,7 @@ class TestPublish(unittest.TestCase):
"Publish is not called from a Python script. Therefore, the script cannot be "
"copied.",
)
def test_data_storage(self):
def test_data_storage(self) -> None:
"""
Test if Error is raised when unsupported storage method was chosen.
"""
......@@ -319,7 +325,7 @@ class TestPublish(unittest.TestCase):
with self.assertRaises(TypeError):
publish(FIGS_AND_IDS, SRC_DIR, DST_PATH, data_storage=[])
def test_str(self):
def test_str(self) -> None:
"""
Test if the string representation of a PublishOptions object is
correct.
......@@ -335,7 +341,7 @@ class TestPublish(unittest.TestCase):
str(publish_obj),
)
def tearDown(self):
def tearDown(self) -> None:
"""Delete all files created in setUp."""
shutil.rmtree(SRC_DIR)
shutil.rmtree(DST_PARENT_DIR)
......
......@@ -21,11 +21,11 @@ class TestSavePlot(unittest.TestCase):
Class for all unittests of the save_plot module.
"""
def setUp(self):
def setUp(self) -> None:
plt.savefig(IMG1)
plt.savefig(IMG2)
def test_save_plot_matplotlib(self):
def test_save_plot_matplotlib(self) -> None:
"""
Test if save_plot succeeds with valid arguments
using the matplotlib engine.
......@@ -34,7 +34,7 @@ class TestSavePlot(unittest.TestCase):
self.assertIsInstance(plot_paths, list)
os.remove(PLOT_NAME + ".tmp.jpg")
def test_save_plot_image_png(self):
def test_save_plot_image_png(self) -> None:
"""
Test if save_plot succeeds with valid arguments using the image engine
and a png file.
......@@ -44,7 +44,7 @@ class TestSavePlot(unittest.TestCase):
self.assertIsInstance(plot_paths, list)
os.remove(PLOT_NAME + ".tmp.png")
def test_save_plot_image_jpg(self):
def test_save_plot_image_jpg(self) -> None:
"""
Test if save_plot succeeds with valid arguments using the image engine
and a list of jpg files.
......@@ -56,7 +56,7 @@ class TestSavePlot(unittest.TestCase):
os.remove(PLOT_NAME + "1.tmp.jpg")
os.remove(PLOT_NAME + "2.tmp.jpg")
def test_more_figs_than_names(self):
def test_more_figs_than_names(self) -> None:
"""
Test if a warning is raised if more figures than plot names are given.
Additionally, check if files are named correctly.
......@@ -67,17 +67,17 @@ class TestSavePlot(unittest.TestCase):
assert os.path.isfile(PLOT_NAME + f"{i}.tmp.png")
os.remove(PLOT_NAME + f"{i}.tmp.png")
def test_more_names_than_figs(self):
def test_more_names_than_figs(self) -> None:
"""Test if Error is raised if more names than figures are given."""
with self.assertRaises(IndexError):
save_plot([FIGURE, FIGURE], [PLOT_NAME, PLOT_NAME, PLOT_NAME])
def test_wrong_fig_type(self):
def test_wrong_fig_type(self) -> None:
"""Test if Error is raised when not a figure object is given."""
with self.assertRaises(TypeError):
save_plot("figure", "PLOT_NAME", extension="jpg")
def test_wrong_fig_in_list(self):
def test_wrong_fig_in_list(self) -> None:
"""
Test if Error is raised when one figure is invalid in a list of
valid figures.
......@@ -86,7 +86,7 @@ class TestSavePlot(unittest.TestCase):
save_plot([FIGURE, "figure", FIGURE], "PLOT_NAME", extension="jpg")
os.remove("PLOT_NAME1.tmp.jpg")
def tearDown(self):
def tearDown(self) -> None:
os.remove(IMG1)
os.remove(IMG2)
......
......@@ -27,11 +27,11 @@ class TestTagplot(unittest.TestCase):
Class for all unittests of the tagplot module.
"""
def setUp(self):
def setUp(self) -> None:
plt.savefig(IMG1)
plt.savefig(IMG2)
def test_tagplot(self):
def test_tagplot(self) -> None:
"""
Test if tagplot runs successful.
"""
......@@ -39,12 +39,12 @@ class TestTagplot(unittest.TestCase):
tagplot(FIGS_AS_LIST, PLOT_ENGINE, rotation=42, position=(0.3, 0.14))
tagplot(IMGS_AS_LIST, "image", location="north")
def test_rotation(self):
def test_rotation(self) -> None:
"""Test if Error is raised if rotation is not a number."""
with self.assertRaises(TypeError):
tagplot(FIGS_AS_LIST, PLOT_ENGINE, rotation="42")
def test_position(self):
def test_position(self) -> None:
"""Test if Error is raised if position is not a tuple containing two numbers."""
with self.assertRaises(ValueError):
tagplot(FIGS_AS_LIST, PLOT_ENGINE, position=(0.3, 0.14, 5))
......@@ -53,7 +53,7 @@ class TestTagplot(unittest.TestCase):
with self.assertRaises(TypeError):
tagplot(FIGS_AS_LIST, PLOT_ENGINE, position=(0.3, True))
def test_prefix(self):
def test_prefix(self) -> None:
"""Test if Error is raised if prefix is not a string."""
with self.assertRaises(TypeError):
tagplot(
......@@ -64,7 +64,7 @@ class TestTagplot(unittest.TestCase):
id_method=METHOD,
)
def test_plotengine(self):
def test_plotengine(self) -> None:
"""
Test if Errors are raised if the provided plot engine is not supported.
"""
......@@ -73,7 +73,7 @@ class TestTagplot(unittest.TestCase):
with self.assertRaises(ValueError):
tagplot(FIGS_AS_LIST, "xyz", location="south")
def test_idmethod(self):
def test_idmethod(self) -> None:
"""
Test if Errors are raised if the id_method is not an string.
"""
......@@ -84,7 +84,7 @@ class TestTagplot(unittest.TestCase):
with self.assertRaises(TypeError):
tagplot(FIGS_AS_LIST, PLOT_ENGINE, id_method=[0, 1])
def test_location(self):
def test_location(self) -> None:
"""
Test if Errors are raised if the provided location is not supported.
"""
......@@ -93,7 +93,7 @@ class TestTagplot(unittest.TestCase):
with self.assertWarns(Warning):
tagplot(FIGS_AS_LIST, PLOT_ENGINE, location="up")
def tearDown(self):
def tearDown(self) -> None:
os.remove(IMG1)
os.remove(IMG2)
......
......@@ -30,11 +30,11 @@ class TestTagplotImage(unittest.TestCase):
Class for all unittests of the tagplot_image module.
"""
def setUp(self):
def setUp(self) -> None:
plt.savefig(IMG1)
plt.savefig(IMG2)
def test_images(self):
def test_images(self) -> None:
"""
Test of returned objects. Check if they are png and jpg files,
respectively.
......@@ -55,7 +55,7 @@ class TestTagplotImage(unittest.TestCase):
self.assertIsInstance(figs_and_ids.figs[0], PngImagePlugin.PngImageFile)
self.assertIsInstance(figs_and_ids.figs[1], JpegImagePlugin.JpegImageFile)
def test_single_image(self):
def test_single_image(self) -> None:
"""
Test of returned objects. Check if png files are returned,
if a single matplot figure is given (not as a list).
......@@ -65,7 +65,7 @@ class TestTagplotImage(unittest.TestCase):
figs_and_ids = tagplot_image(options)
self.assertIsInstance(figs_and_ids.figs[0], PngImagePlugin.PngImageFile)
def test_image_not_str(self):
def test_image_not_str(self) -> None:
"""Test if Error is raised if wrong type of image is given."""
options = PlotOptions(
3, ROTATION, POSITION, prefix=PROJECT_ID, id_method=METHOD
......@@ -74,21 +74,21 @@ class TestTagplotImage(unittest.TestCase):
with self.assertRaises(TypeError):
tagplot_image(options)
def test_image_not_file(self):
def test_image_not_file(self) -> None:
"""Test if Error is raised if the image file does not exist."""
options = PlotOptions("xyz", ROTATION, POSITION)
options.validate_input()
with self.assertRaises(TypeError):
tagplot_image(options)
def test_image_plotoptions(self):
def test_image_plotoptions(self) -> None:
"""
Test if Error is raised if not an instance of PlotOptions is passed.
"""
with self.assertRaises(TypeError):
tagplot_image("wrong_object")
def tearDown(self):
def tearDown(self) -> None:
os.remove(IMG1)
os.remove(IMG2)
......
......@@ -27,7 +27,7 @@ class TestTagplotMatplotlib(unittest.TestCase):
Class for all unittests of the tagplot_matplotlib module.
"""
def test_mplfigures(self):
def test_mplfigures(self) -> None:
"""Test of returned objects. Check if they are matplotlib figures."""
options = PlotOptions(
FIGS_AS_LIST,
......@@ -45,7 +45,7 @@ class TestTagplotMatplotlib(unittest.TestCase):
self.assertIsInstance(figs_and_ids.figs[0], Figure)
self.assertIsInstance(figs_and_ids.figs[1], Figure)
def test_single_mplfigure(self):
def test_single_mplfigure(self) -> None:
"""
Test of returned objects. Check if matplotlib figures are returned,
if a single matplot figure is given (not as a list).
......@@ -55,14 +55,14 @@ class TestTagplotMatplotlib(unittest.TestCase):
figs_and_ids = tagplot_matplotlib(options)
self.assertIsInstance(figs_and_ids.figs[0], Figure)
def test_mplerror(self):
def test_mplerror(self) -> None:
"""Test if Error is raised if wrong type of figures is given."""
options = PlotOptions(3, ROTATION, POSITION)
options.validate_input()
with self.assertRaises(TypeError):
tagplot_matplotlib(options)
def test_mpl_plotoptions(self):
def test_mpl_plotoptions(self) -> None:
"""
Test if Error is raised if not an instance of PlotOptions is passed.
"""
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment