Initial Commit
This commit is contained in:
commit
0fd2c1f44e
234
.gitignore
vendored
Normal file
234
.gitignore
vendored
Normal file
@ -0,0 +1,234 @@
|
||||
# Test Reports
|
||||
test-reports/
|
||||
|
||||
# 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/
|
||||
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/
|
||||
cover/
|
||||
|
||||
# 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
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .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
|
||||
|
||||
# poetry
|
||||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||
#poetry.lock
|
||||
|
||||
# pdm
|
||||
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||
#pdm.lock
|
||||
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||
# in version control.
|
||||
# https://pdm.fming.dev/#use-with-ide
|
||||
.pdm.toml
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||
__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/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# User-specific stuff
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
.idea/**/usage.statistics.xml
|
||||
.idea/**/dictionaries
|
||||
.idea/**/shelf
|
||||
|
||||
# AWS User-specific
|
||||
.idea/**/aws.xml
|
||||
|
||||
# Generated files
|
||||
.idea/**/contentModel.xml
|
||||
|
||||
# Sensitive or high-churn files
|
||||
.idea/**/dataSources/
|
||||
.idea/**/dataSources.ids
|
||||
.idea/**/dataSources.local.xml
|
||||
.idea/**/sqlDataSources.xml
|
||||
.idea/**/dynamic.xml
|
||||
.idea/**/uiDesigner.xml
|
||||
.idea/**/dbnavigator.xml
|
||||
|
||||
# Gradle
|
||||
.idea/**/gradle.xml
|
||||
.idea/**/libraries
|
||||
|
||||
# Gradle and Maven with auto-import
|
||||
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||
# since they will be recreated, and may cause churn. Uncomment if using
|
||||
# auto-import.
|
||||
# .idea/artifacts
|
||||
# .idea/compiler.xml
|
||||
# .idea/jarRepositories.xml
|
||||
# .idea/modules.xml
|
||||
# .idea/*.iml
|
||||
# .idea/modules
|
||||
# *.iml
|
||||
# *.ipr
|
||||
|
||||
# CMake
|
||||
cmake-build-*/
|
||||
|
||||
# Mongo Explorer plugin
|
||||
.idea/**/mongoSettings.xml
|
||||
|
||||
# File-based project format
|
||||
*.iws
|
||||
|
||||
# IntelliJ
|
||||
out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Cursive Clojure plugin
|
||||
.idea/replstate.xml
|
||||
|
||||
# SonarLint plugin
|
||||
.idea/sonarlint/
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
||||
# Editor-based Rest Client
|
||||
.idea/httpRequests
|
||||
|
||||
# Android studio 3.1+ serialized cache file
|
||||
.idea/caches/build_file_checksums.ser
|
8
.idea/.gitignore
vendored
Normal file
8
.idea/.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
6
.idea/inspectionProfiles/profiles_settings.xml
Normal file
6
.idea/inspectionProfiles/profiles_settings.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
4
.idea/misc.xml
Normal file
4
.idea/misc.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Poetry (pytest-csv-params)" project-jdk-type="Python SDK" />
|
||||
</project>
|
8
.idea/modules.xml
Normal file
8
.idea/modules.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/pytest-csv-params.iml" filepath="$PROJECT_DIR$/.idea/pytest-csv-params.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
14
.idea/pytest-csv-params.iml
Normal file
14
.idea/pytest-csv-params.iml
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PYTHON_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
<component name="PyDocumentationSettings">
|
||||
<option name="format" value="PLAIN" />
|
||||
<option name="myDocStringFormat" value="Plain" />
|
||||
</component>
|
||||
</module>
|
6
.idea/vcs.xml
Normal file
6
.idea/vcs.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
611
.pylintrc
Normal file
611
.pylintrc
Normal file
@ -0,0 +1,611 @@
|
||||
[MAIN]
|
||||
|
||||
# Analyse import fallback blocks. This can be used to support both Python 2 and
|
||||
# 3 compatible code, which means that the block might have code that exists
|
||||
# only in one or another interpreter, leading to false positives when analysed.
|
||||
analyse-fallback-blocks=no
|
||||
|
||||
# Load and enable all available extensions. Use --list-extensions to see a list
|
||||
# all available extensions.
|
||||
#enable-all-extensions=
|
||||
|
||||
# In error mode, messages with a category besides ERROR or FATAL are
|
||||
# suppressed, and no reports are done by default. Error mode is compatible with
|
||||
# disabling specific errors.
|
||||
#errors-only=
|
||||
|
||||
# Always return a 0 (non-error) status code, even if lint errors are found.
|
||||
# This is primarily useful in continuous integration scripts.
|
||||
#exit-zero=
|
||||
|
||||
# A comma-separated list of package or module names from where C extensions may
|
||||
# be loaded. Extensions are loading into the active Python interpreter and may
|
||||
# run arbitrary code.
|
||||
extension-pkg-allow-list=
|
||||
|
||||
# A comma-separated list of package or module names from where C extensions may
|
||||
# be loaded. Extensions are loading into the active Python interpreter and may
|
||||
# run arbitrary code. (This is an alternative name to extension-pkg-allow-list
|
||||
# for backward compatibility.)
|
||||
extension-pkg-whitelist=
|
||||
|
||||
# Return non-zero exit code if any of these messages/categories are detected,
|
||||
# even if score is above --fail-under value. Syntax same as enable. Messages
|
||||
# specified are enabled, while categories only check already-enabled messages.
|
||||
fail-on=
|
||||
|
||||
# Specify a score threshold to be exceeded before program exits with error.
|
||||
fail-under=10
|
||||
|
||||
# Interpret the stdin as a python script, whose filename needs to be passed as
|
||||
# the module_or_package argument.
|
||||
#from-stdin=
|
||||
|
||||
# Files or directories to be skipped. They should be base names, not paths.
|
||||
ignore=CVS .git
|
||||
|
||||
# Add files or directories matching the regex patterns to the ignore-list. The
|
||||
# regex matches against paths and can be in Posix or Windows format.
|
||||
ignore-paths=
|
||||
|
||||
# Files or directories matching the regex patterns are skipped. The regex
|
||||
# matches against base names, not paths. The default value ignores Emacs file
|
||||
# locks
|
||||
ignore-patterns=^\.#
|
||||
|
||||
# List of module names for which member attributes should not be checked
|
||||
# (useful for modules/projects where namespaces are manipulated during runtime
|
||||
# and thus existing member attributes cannot be deduced by static analysis). It
|
||||
# supports qualified module names, as well as Unix pattern matching.
|
||||
ignored-modules=
|
||||
|
||||
# Python code to execute, usually for sys.path manipulation such as
|
||||
# pygtk.require().
|
||||
#init-hook=
|
||||
|
||||
# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the
|
||||
# number of processors available to use, and will cap the count on Windows to
|
||||
# avoid hangs.
|
||||
jobs=1
|
||||
|
||||
# Control the amount of potential inferred values when inferring a single
|
||||
# object. This can help the performance when dealing with large functions or
|
||||
# complex, nested conditions.
|
||||
limit-inference-results=100
|
||||
|
||||
# List of plugins (as comma separated values of python module names) to load,
|
||||
# usually to register additional checkers.
|
||||
load-plugins=
|
||||
|
||||
# Pickle collected data for later comparisons.
|
||||
persistent=yes
|
||||
|
||||
# Minimum Python version to use for version dependent checks. Will default to
|
||||
# the version used to run pylint.
|
||||
py-version=3.8
|
||||
|
||||
# Discover python modules and packages in the file system subtree.
|
||||
recursive=no
|
||||
|
||||
# When enabled, pylint would attempt to guess common misconfiguration and emit
|
||||
# user-friendly hints instead of false-positive error messages.
|
||||
suggestion-mode=yes
|
||||
|
||||
# Allow loading of arbitrary C extensions. Extensions are imported into the
|
||||
# active Python interpreter and may run arbitrary code.
|
||||
unsafe-load-any-extension=no
|
||||
|
||||
# In verbose mode, extra non-checker-related info will be displayed.
|
||||
#verbose=
|
||||
|
||||
|
||||
[REPORTS]
|
||||
|
||||
# Python expression which should return a score less than or equal to 10. You
|
||||
# have access to the variables 'fatal', 'error', 'warning', 'refactor',
|
||||
# 'convention', and 'info' which contain the number of messages in each
|
||||
# category, as well as 'statement' which is the total number of statements
|
||||
# analyzed. This score is used by the global evaluation report (RP0004).
|
||||
evaluation=max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10))
|
||||
|
||||
# Template used to display messages. This is a python new-style format string
|
||||
# used to format the message information. See doc for all details.
|
||||
msg-template={path}:{line}:{column}: {msg_id}: {msg} ({symbol})
|
||||
|
||||
# Set the output format. Available formats are text, parseable, colorized, json
|
||||
# and msvs (visual studio). You can also give a reporter class, e.g.
|
||||
# mypackage.mymodule.MyReporterClass.
|
||||
#output-format=
|
||||
|
||||
# Tells whether to display a full report or only the messages.
|
||||
reports=no
|
||||
|
||||
# Activate the evaluation score.
|
||||
score=yes
|
||||
|
||||
|
||||
[MESSAGES CONTROL]
|
||||
|
||||
# Only show warnings with the listed confidence levels. Leave empty to show
|
||||
# all. Valid levels: HIGH, CONTROL_FLOW, INFERENCE, INFERENCE_FAILURE,
|
||||
# UNDEFINED.
|
||||
confidence=HIGH,
|
||||
CONTROL_FLOW,
|
||||
INFERENCE,
|
||||
INFERENCE_FAILURE,
|
||||
UNDEFINED
|
||||
|
||||
# Disable the message, report, category or checker with the given id(s). You
|
||||
# can either give multiple identifiers separated by comma (,) or put this
|
||||
# option multiple times (only on the command line, not in the configuration
|
||||
# file where it should appear only once). You can also use "--disable=all" to
|
||||
# disable everything first and then re-enable specific checks. For example, if
|
||||
# you want to run only the similarities checker, you can use "--disable=all
|
||||
# --enable=similarities". If you want to run only the classes checker, but have
|
||||
# no Warning level messages displayed, use "--disable=all --enable=classes
|
||||
# --disable=W".
|
||||
disable=raw-checker-failed,
|
||||
bad-inline-option,
|
||||
locally-disabled,
|
||||
file-ignored,
|
||||
suppressed-message,
|
||||
useless-suppression,
|
||||
deprecated-pragma,
|
||||
use-symbolic-message-instead,
|
||||
couldnt-parse
|
||||
|
||||
# Enable the message, report, category or checker with the given id(s). You can
|
||||
# either give multiple identifier separated by comma (,) or put this option
|
||||
# multiple time (only on the command line, not in the configuration file where
|
||||
# it should appear only once). See also the "--disable" option for examples.
|
||||
enable=c-extension-no-member
|
||||
|
||||
|
||||
[LOGGING]
|
||||
|
||||
# The type of string formatting that logging methods do. `old` means using %
|
||||
# formatting, `new` is for `{}` formatting.
|
||||
logging-format-style=new
|
||||
|
||||
# Logging modules to check that the string format arguments are in logging
|
||||
# function parameter format.
|
||||
logging-modules=logging
|
||||
|
||||
|
||||
[SPELLING]
|
||||
|
||||
# Limits count of emitted suggestions for spelling mistakes.
|
||||
max-spelling-suggestions=4
|
||||
|
||||
# Spelling dictionary name. Available dictionaries: none. To make it work,
|
||||
# install the 'python-enchant' package.
|
||||
spelling-dict=
|
||||
|
||||
# List of comma separated words that should be considered directives if they
|
||||
# appear at the beginning of a comment and should not be checked.
|
||||
spelling-ignore-comment-directives=fmt: on,fmt: off,noqa:,noqa,nosec,isort:skip,mypy:
|
||||
|
||||
# List of comma separated words that should not be checked.
|
||||
spelling-ignore-words=
|
||||
|
||||
# A path to a file that contains the private dictionary; one word per line.
|
||||
spelling-private-dict-file=
|
||||
|
||||
# Tells whether to store unknown words to the private dictionary (see the
|
||||
# --spelling-private-dict-file option) instead of raising a message.
|
||||
spelling-store-unknown-words=no
|
||||
|
||||
|
||||
[MISCELLANEOUS]
|
||||
|
||||
# List of note tags to take in consideration, separated by a comma.
|
||||
notes=FIXME,
|
||||
XXX,
|
||||
TODO
|
||||
|
||||
# Regular expression of note tags to take in consideration.
|
||||
notes-rgx=
|
||||
|
||||
|
||||
[TYPECHECK]
|
||||
|
||||
# List of decorators that produce context managers, such as
|
||||
# contextlib.contextmanager. Add to this list to register other decorators that
|
||||
# produce valid context managers.
|
||||
contextmanager-decorators=contextlib.contextmanager
|
||||
|
||||
# List of members which are set dynamically and missed by pylint inference
|
||||
# system, and so shouldn't trigger E1101 when accessed. Python regular
|
||||
# expressions are accepted.
|
||||
generated-members=
|
||||
|
||||
# Tells whether to warn about missing members when the owner of the attribute
|
||||
# is inferred to be None.
|
||||
ignore-none=yes
|
||||
|
||||
# This flag controls whether pylint should warn about no-member and similar
|
||||
# checks whenever an opaque object is returned when inferring. The inference
|
||||
# can return multiple potential results while evaluating a Python object, but
|
||||
# some branches might not be evaluated, which results in partial inference. In
|
||||
# that case, it might be useful to still emit no-member and other checks for
|
||||
# the rest of the inferred objects.
|
||||
ignore-on-opaque-inference=yes
|
||||
|
||||
# List of symbolic message names to ignore for Mixin members.
|
||||
ignored-checks-for-mixins=no-member,
|
||||
not-async-context-manager,
|
||||
not-context-manager,
|
||||
attribute-defined-outside-init
|
||||
|
||||
# List of class names for which member attributes should not be checked (useful
|
||||
# for classes with dynamically set attributes). This supports the use of
|
||||
# qualified names.
|
||||
ignored-classes=optparse.Values,thread._local,_thread._local,argparse.Namespace
|
||||
|
||||
# Show a hint with possible names when a member name was not found. The aspect
|
||||
# of finding the hint is based on edit distance.
|
||||
missing-member-hint=yes
|
||||
|
||||
# The minimum edit distance a name should have in order to be considered a
|
||||
# similar match for a missing member name.
|
||||
missing-member-hint-distance=1
|
||||
|
||||
# The total number of similar names that should be taken in consideration when
|
||||
# showing a hint for a missing member.
|
||||
missing-member-max-choices=1
|
||||
|
||||
# Regex pattern to define which classes are considered mixins.
|
||||
mixin-class-rgx=.*[Mm]ixin
|
||||
|
||||
# List of decorators that change the signature of a decorated function.
|
||||
signature-mutators=
|
||||
|
||||
|
||||
[CLASSES]
|
||||
|
||||
# Warn about protected attribute access inside special methods
|
||||
check-protected-access-in-special-methods=no
|
||||
|
||||
# List of method names used to declare (i.e. assign) instance attributes.
|
||||
defining-attr-methods=__init__,
|
||||
__new__,
|
||||
setUp,
|
||||
__post_init__
|
||||
|
||||
# List of member names, which should be excluded from the protected access
|
||||
# warning.
|
||||
exclude-protected=_asdict,
|
||||
_fields,
|
||||
_replace,
|
||||
_source,
|
||||
_make
|
||||
|
||||
# List of valid names for the first argument in a class method.
|
||||
valid-classmethod-first-arg=cls
|
||||
|
||||
# List of valid names for the first argument in a metaclass class method.
|
||||
valid-metaclass-classmethod-first-arg=cls
|
||||
|
||||
|
||||
[VARIABLES]
|
||||
|
||||
# List of additional names supposed to be defined in builtins. Remember that
|
||||
# you should avoid defining new builtins when possible.
|
||||
additional-builtins=
|
||||
|
||||
# Tells whether unused global variables should be treated as a violation.
|
||||
allow-global-unused-variables=yes
|
||||
|
||||
# List of names allowed to shadow builtins
|
||||
allowed-redefined-builtins=
|
||||
|
||||
# List of strings which can identify a callback function by name. A callback
|
||||
# name must start or end with one of those strings.
|
||||
callbacks=cb_,
|
||||
_cb
|
||||
|
||||
# A regular expression matching the name of dummy variables (i.e. expected to
|
||||
# not be used).
|
||||
dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_
|
||||
|
||||
# Argument names that match this expression will be ignored. Default to name
|
||||
# with leading underscore.
|
||||
ignored-argument-names=_.*|^ignored_|^unused_
|
||||
|
||||
# Tells whether we should check for unused import in __init__ files.
|
||||
init-import=no
|
||||
|
||||
# List of qualified module names which can have objects that can redefine
|
||||
# builtins.
|
||||
redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io
|
||||
|
||||
|
||||
[FORMAT]
|
||||
|
||||
# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
|
||||
expected-line-ending-format=
|
||||
|
||||
# Regexp for a line that is allowed to be longer than the limit.
|
||||
ignore-long-lines=^\s*(# )?<?https?://\S+>?$
|
||||
|
||||
# Number of spaces of indent required inside a hanging or continued line.
|
||||
indent-after-paren=4
|
||||
|
||||
# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
|
||||
# tab).
|
||||
indent-string=' '
|
||||
|
||||
# Maximum number of characters on a single line.
|
||||
max-line-length=120
|
||||
|
||||
# Maximum number of lines in a module.
|
||||
max-module-lines=1000
|
||||
|
||||
# Allow the body of a class to be on the same line as the declaration if body
|
||||
# contains single statement.
|
||||
single-line-class-stmt=no
|
||||
|
||||
# Allow the body of an if to be on the same line as the test if there is no
|
||||
# else.
|
||||
single-line-if-stmt=no
|
||||
|
||||
|
||||
[IMPORTS]
|
||||
|
||||
# List of modules that can be imported at any level, not just the top level
|
||||
# one.
|
||||
allow-any-import-level=
|
||||
|
||||
# Allow wildcard imports from modules that define __all__.
|
||||
allow-wildcard-with-all=no
|
||||
|
||||
# Deprecated modules which should not be used, separated by a comma.
|
||||
deprecated-modules=
|
||||
|
||||
# Output a graph (.gv or any supported image format) of external dependencies
|
||||
# to the given file (report RP0402 must not be disabled).
|
||||
ext-import-graph=
|
||||
|
||||
# Output a graph (.gv or any supported image format) of all (i.e. internal and
|
||||
# external) dependencies to the given file (report RP0402 must not be
|
||||
# disabled).
|
||||
import-graph=
|
||||
|
||||
# Output a graph (.gv or any supported image format) of internal dependencies
|
||||
# to the given file (report RP0402 must not be disabled).
|
||||
int-import-graph=
|
||||
|
||||
# Force import order to recognize a module as part of the standard
|
||||
# compatibility libraries.
|
||||
known-standard-library=
|
||||
|
||||
# Force import order to recognize a module as part of a third party library.
|
||||
known-third-party=enchant
|
||||
|
||||
# Couples of modules and preferred modules, separated by a comma.
|
||||
preferred-modules=
|
||||
|
||||
|
||||
[EXCEPTIONS]
|
||||
|
||||
# Exceptions that will emit a warning when caught.
|
||||
overgeneral-exceptions=BaseException,
|
||||
Exception
|
||||
|
||||
|
||||
[REFACTORING]
|
||||
|
||||
# Maximum number of nested blocks for function / method body
|
||||
max-nested-blocks=5
|
||||
|
||||
# Complete name of functions that never returns. When checking for
|
||||
# inconsistent-return-statements if a never returning function is called then
|
||||
# it will be considered as an explicit return statement and no message will be
|
||||
# printed.
|
||||
never-returning-functions=sys.exit,argparse.parse_error
|
||||
|
||||
|
||||
[SIMILARITIES]
|
||||
|
||||
# Comments are removed from the similarity computation
|
||||
ignore-comments=yes
|
||||
|
||||
# Docstrings are removed from the similarity computation
|
||||
ignore-docstrings=yes
|
||||
|
||||
# Imports are removed from the similarity computation
|
||||
ignore-imports=yes
|
||||
|
||||
# Signatures are removed from the similarity computation
|
||||
ignore-signatures=yes
|
||||
|
||||
# Minimum lines number of a similarity.
|
||||
min-similarity-lines=10
|
||||
|
||||
|
||||
[DESIGN]
|
||||
|
||||
# List of regular expressions of class ancestor names to ignore when counting
|
||||
# public methods (see R0903)
|
||||
exclude-too-few-public-methods=
|
||||
|
||||
# List of qualified class names to ignore when counting class parents (see
|
||||
# R0901)
|
||||
ignored-parents=
|
||||
|
||||
# Maximum number of arguments for function / method.
|
||||
max-args=5
|
||||
|
||||
# Maximum number of attributes for a class (see R0902).
|
||||
max-attributes=7
|
||||
|
||||
# Maximum number of boolean expressions in an if statement (see R0916).
|
||||
max-bool-expr=5
|
||||
|
||||
# Maximum number of branch for function / method body.
|
||||
max-branches=12
|
||||
|
||||
# Maximum number of locals for function / method body.
|
||||
max-locals=20
|
||||
|
||||
# Maximum number of parents for a class (see R0901).
|
||||
max-parents=7
|
||||
|
||||
# Maximum number of public methods for a class (see R0904).
|
||||
max-public-methods=20
|
||||
|
||||
# Maximum number of return / yield for function / method body.
|
||||
max-returns=6
|
||||
|
||||
# Maximum number of statements in function / method body.
|
||||
max-statements=50
|
||||
|
||||
# Minimum number of public methods for a class (see R0903).
|
||||
min-public-methods=2
|
||||
|
||||
|
||||
[STRING]
|
||||
|
||||
# This flag controls whether inconsistent-quotes generates a warning when the
|
||||
# character used as a quote delimiter is used inconsistently within a module.
|
||||
check-quote-consistency=no
|
||||
|
||||
# This flag controls whether the implicit-str-concat should generate a warning
|
||||
# on implicit string concatenation in sequences defined over several lines.
|
||||
check-str-concat-over-line-jumps=no
|
||||
|
||||
|
||||
[BASIC]
|
||||
|
||||
# Naming style matching correct argument names.
|
||||
argument-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct argument names. Overrides argument-
|
||||
# naming-style. If left empty, argument names will be checked with the set
|
||||
# naming style.
|
||||
#argument-rgx=
|
||||
|
||||
# Naming style matching correct attribute names.
|
||||
attr-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct attribute names. Overrides attr-naming-
|
||||
# style. If left empty, attribute names will be checked with the set naming
|
||||
# style.
|
||||
#attr-rgx=
|
||||
|
||||
# Bad variable names which should always be refused, separated by a comma.
|
||||
bad-names=foo,
|
||||
bar,
|
||||
baz,
|
||||
toto,
|
||||
tutu,
|
||||
tata
|
||||
|
||||
# Bad variable names regexes, separated by a comma. If names match any regex,
|
||||
# they will always be refused
|
||||
bad-names-rgxs=
|
||||
|
||||
# Naming style matching correct class attribute names.
|
||||
class-attribute-naming-style=any
|
||||
|
||||
# Regular expression matching correct class attribute names. Overrides class-
|
||||
# attribute-naming-style. If left empty, class attribute names will be checked
|
||||
# with the set naming style.
|
||||
#class-attribute-rgx=
|
||||
|
||||
# Naming style matching correct class constant names.
|
||||
class-const-naming-style=UPPER_CASE
|
||||
|
||||
# Regular expression matching correct class constant names. Overrides class-
|
||||
# const-naming-style. If left empty, class constant names will be checked with
|
||||
# the set naming style.
|
||||
#class-const-rgx=
|
||||
|
||||
# Naming style matching correct class names.
|
||||
class-naming-style=PascalCase
|
||||
|
||||
# Regular expression matching correct class names. Overrides class-naming-
|
||||
# style. If left empty, class names will be checked with the set naming style.
|
||||
#class-rgx=
|
||||
|
||||
# Naming style matching correct constant names.
|
||||
const-naming-style=UPPER_CASE
|
||||
|
||||
# Regular expression matching correct constant names. Overrides const-naming-
|
||||
# style. If left empty, constant names will be checked with the set naming
|
||||
# style.
|
||||
#const-rgx=
|
||||
|
||||
# Minimum line length for functions/classes that require docstrings, shorter
|
||||
# ones are exempt.
|
||||
docstring-min-length=-1
|
||||
|
||||
# Naming style matching correct function names.
|
||||
function-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct function names. Overrides function-
|
||||
# naming-style. If left empty, function names will be checked with the set
|
||||
# naming style.
|
||||
#function-rgx=
|
||||
|
||||
# Good variable names which should always be accepted, separated by a comma.
|
||||
good-names=i,
|
||||
j,
|
||||
k,
|
||||
ex,
|
||||
Run,
|
||||
_
|
||||
|
||||
# Good variable names regexes, separated by a comma. If names match any regex,
|
||||
# they will always be accepted
|
||||
good-names-rgxs=
|
||||
|
||||
# Include a hint for the correct naming format with invalid-name.
|
||||
include-naming-hint=no
|
||||
|
||||
# Naming style matching correct inline iteration names.
|
||||
inlinevar-naming-style=any
|
||||
|
||||
# Regular expression matching correct inline iteration names. Overrides
|
||||
# inlinevar-naming-style. If left empty, inline iteration names will be checked
|
||||
# with the set naming style.
|
||||
#inlinevar-rgx=
|
||||
|
||||
# Naming style matching correct method names.
|
||||
method-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct method names. Overrides method-naming-
|
||||
# style. If left empty, method names will be checked with the set naming style.
|
||||
#method-rgx=
|
||||
|
||||
# Naming style matching correct module names.
|
||||
module-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct module names. Overrides module-naming-
|
||||
# style. If left empty, module names will be checked with the set naming style.
|
||||
#module-rgx=
|
||||
|
||||
# Colon-delimited sets of names that determine each other's naming style when
|
||||
# the name regexes allow several styles.
|
||||
name-group=
|
||||
|
||||
# Regular expression which should only match function or class names that do
|
||||
# not require a docstring.
|
||||
no-docstring-rgx=^_
|
||||
|
||||
# List of decorators that produce properties, such as abc.abstractproperty. Add
|
||||
# to this list to register other decorators that produce valid properties.
|
||||
# These decorators are taken in consideration only for invalid-name.
|
||||
property-classes=abc.abstractproperty
|
||||
|
||||
# Regular expression matching correct type variable names. If left empty, type
|
||||
# variable names will be checked with the set naming style.
|
||||
#typevar-rgx=
|
||||
|
||||
# Naming style matching correct variable names.
|
||||
variable-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct variable names. Overrides variable-
|
||||
# naming-style. If left empty, variable names will be checked with the set
|
||||
# naming style.
|
||||
#variable-rgx=
|
4
.python-version
Normal file
4
.python-version
Normal file
@ -0,0 +1,4 @@
|
||||
3.10.6
|
||||
3.9.13
|
||||
3.8.13
|
||||
3.11-dev
|
20
LICENSE.txt
Normal file
20
LICENSE.txt
Normal file
@ -0,0 +1,20 @@
|
||||
Copyright Juergen Edelbluth and other contributors, https://juergen.rocks/
|
||||
|
||||
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.
|
132
README.md
Normal file
132
README.md
Normal file
@ -0,0 +1,132 @@
|
||||
# pytest-csv-params
|
||||
|
||||
A pytest plugin to parametrize tests by CSV files.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Python 3.8, 3.9 or 3.10
|
||||
- pytest >= 7.1
|
||||
|
||||
There's no operating system dependend code in this plugin, so it should run anywhere where pytest runs.
|
||||
|
||||
## Installation
|
||||
|
||||
Simply install it with pip...
|
||||
|
||||
```bash
|
||||
pip install pytest-csv-plugin
|
||||
```
|
||||
|
||||
... or poetry ...
|
||||
|
||||
```bash
|
||||
poetry add --dev pytest-csv-plugin
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Simply decorate your test method with `@csv_params` and the following parameters:
|
||||
|
||||
| Parameter | Type | Description | Example |
|
||||
|--------------|--------------------------|-----------------------------------------------------------|-------------------------------------|
|
||||
| `data_file` | `str` | The CSV file to use, relative or absolute path | `/var/testdata/test1.csv` |
|
||||
| `base_dir` | `str` (optional) | Directory to look up relative CSV files (see `data_file`) | `join(dirname(__file__), "assets")` |
|
||||
| `id_col` | `str` (optional) | Column name of the CSV that contains test case IDs | `ID#` |
|
||||
| `dialect` | `csv.Dialect` (optional) | CSV Dialect definition (see [1]) | `csv.excel_tab` |
|
||||
| `data_casts` | `dict` (optional) | Cast Methods for the CSV Data (see "Data Casting" below) | `{ "a": int, "b": float }` |
|
||||
|
||||
[1] [Python CSV Documentation](https://docs.python.org/3/library/csv.html#dialects-and-formatting-parameters)
|
||||
|
||||
### Data Casting
|
||||
|
||||
When data is read from CSV, they are always parsed as `str`. If you need them in other formats, you can set a method that should be called with the value.
|
||||
|
||||
These methods can also be lambdas, and are also good for further transformations.
|
||||
|
||||
#### Data Casting Example
|
||||
|
||||
```python
|
||||
from pytest_csv_params.decorator import csv_params
|
||||
|
||||
def normalize(x: str) -> str:
|
||||
return x.strip().upper()
|
||||
|
||||
@csv_params(
|
||||
data_file="/test/data.csv",
|
||||
data_casts={
|
||||
"col_x": normalize,
|
||||
"col_y": float,
|
||||
},
|
||||
)
|
||||
def test_something(col_x, col_y):
|
||||
# Test something...
|
||||
...
|
||||
```
|
||||
|
||||
### CSV Format
|
||||
|
||||
The default CSV format is:
|
||||
|
||||
- `\r\n` as line ending
|
||||
- All non-numeric fields are surrounded by "
|
||||
- If you need a " in the value, use "" (double quote)
|
||||
- Fields are separated by comma (",")
|
||||
|
||||
#### Example CSV
|
||||
|
||||
```text
|
||||
"ID#", "part_a", "part_b", "expected_result"
|
||||
"first", 1, 2, 3
|
||||
"second", 3, 4, 7
|
||||
"third", 10, 11, 21
|
||||
```
|
||||
|
||||
### Usage Example
|
||||
|
||||
This example uses the CSV example from above.
|
||||
|
||||
```python
|
||||
from pytest_csv_params.decorator import csv_params
|
||||
|
||||
@csv_params(
|
||||
data_file="/data/test-lib/cases/addition.csv",
|
||||
id_col="#ID",
|
||||
data_casts={
|
||||
"part_a": int,
|
||||
"part_b": int,
|
||||
"expected_result": int,
|
||||
},
|
||||
)
|
||||
def test_addition(part_a, part_b, expected_result):
|
||||
assert part_a + part_b == expected_result
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
### Build and test
|
||||
|
||||
You need [Poetry](https://python-poetry.org/) in order to build this project.
|
||||
|
||||
Tests are implemented with `pytest`, and `tox` is used to orchestrate them for the supported python versions.
|
||||
|
||||
- Checkout this repo
|
||||
- Run `poetry install`
|
||||
- Run `poetry run tox` (for all supported python versions) or `poetry run pytest` (for your current version)
|
||||
|
||||
### Bugs etc.
|
||||
|
||||
Please send your issues to `csv-params_issues` (at) `jued.de`. Please include the following:
|
||||
|
||||
- Plugin Version used
|
||||
- Pytest version
|
||||
- Python version with operating system
|
||||
|
||||
It would be great if you could include example code that clarifies your issue.
|
||||
|
||||
### Pull Requests
|
||||
|
||||
Pull requests are always welcome. Since this Gitea instance is not open to public, just send an e-mail to discuss options.
|
||||
|
||||
## License
|
||||
|
||||
Code is under MIT license. See [LICENCE.txt](./LICENSE.txt) for details.
|
0
_ptcsvp/__init__.py
Normal file
0
_ptcsvp/__init__.py
Normal file
19
_ptcsvp/configure.py
Normal file
19
_ptcsvp/configure.py
Normal file
@ -0,0 +1,19 @@
|
||||
"""
|
||||
Pytest Plugin Configuration
|
||||
"""
|
||||
|
||||
from _ptcsvp.plugin import Plugin
|
||||
|
||||
|
||||
def pytest_configure(config, plugin_name="csv_params"):
|
||||
"""
|
||||
Register our Plugin
|
||||
"""
|
||||
config.pluginmanager.register(Plugin(config), f"{plugin_name}_plugin")
|
||||
|
||||
|
||||
def pytest_unconfigure(config, plugin_name="csv_params"):
|
||||
"""
|
||||
Remove our Plugin
|
||||
"""
|
||||
config.pluginmanager.unregister(f"{plugin_name}_plugin")
|
101
_ptcsvp/parametrize.py
Normal file
101
_ptcsvp/parametrize.py
Normal file
@ -0,0 +1,101 @@
|
||||
"""
|
||||
Parametrize a test function by CSV file
|
||||
"""
|
||||
import csv
|
||||
from pathlib import Path
|
||||
from typing import List, Optional, TypedDict
|
||||
|
||||
import pytest
|
||||
|
||||
from pytest_csv_params.dialect import CsvParamsDefaultDialect
|
||||
from pytest_csv_params.exception import (
|
||||
CsvParamsDataFileInaccessible,
|
||||
CsvParamsDataFileInvalid,
|
||||
CsvParamsDataFileNotFound,
|
||||
)
|
||||
from pytest_csv_params.types import BaseDir, CsvDialect, DataCastDict, DataFile, IdColName
|
||||
|
||||
|
||||
class TestCaseParameters(TypedDict):
|
||||
"""
|
||||
Type for Test Case
|
||||
"""
|
||||
|
||||
test_id: Optional[str]
|
||||
data: List
|
||||
|
||||
|
||||
def read_csv(base_dir: BaseDir, data_file: DataFile, dialect: CsvDialect):
|
||||
"""
|
||||
Get Data from CSV
|
||||
"""
|
||||
|
||||
if data_file is None:
|
||||
raise CsvParamsDataFileInvalid("Data file is None") from None
|
||||
csv_file = Path(data_file)
|
||||
if not csv_file.is_absolute():
|
||||
if base_dir is not None:
|
||||
csv_file = Path(base_dir) / csv_file
|
||||
if not csv_file.exists() or not csv_file.is_file():
|
||||
raise CsvParamsDataFileNotFound(f"Cannot find file: {str(csv_file)}") from None
|
||||
csv_lines = []
|
||||
try:
|
||||
with open(csv_file, newline="", encoding="utf-8") as csv_file_handle:
|
||||
csv_reader = csv.reader(csv_file_handle, dialect=dialect)
|
||||
for row in csv_reader:
|
||||
csv_lines.append(row)
|
||||
except IOError as err: # pragma: no cover
|
||||
raise CsvParamsDataFileInaccessible(f"Unable to read file: {str(csv_file)}") from err
|
||||
except csv.Error as err:
|
||||
raise CsvParamsDataFileInvalid("Invalid data") from err
|
||||
return csv_lines
|
||||
|
||||
|
||||
def add_parametrization(
|
||||
base_dir: BaseDir = None,
|
||||
data_file: DataFile = None,
|
||||
id_col: IdColName = None,
|
||||
data_casts: DataCastDict = None,
|
||||
dialect: CsvDialect = CsvParamsDefaultDialect,
|
||||
):
|
||||
"""
|
||||
Get data from the files and add things to the tests
|
||||
"""
|
||||
csv_lines = read_csv(base_dir, data_file, dialect)
|
||||
if len(csv_lines) < 2:
|
||||
raise CsvParamsDataFileInvalid("File does not contain a single data row") from None
|
||||
id_index = -1
|
||||
headers = csv_lines.pop(0)
|
||||
if id_col is not None:
|
||||
try:
|
||||
id_index = headers.index(id_col)
|
||||
del headers[id_index]
|
||||
except ValueError as err:
|
||||
raise CsvParamsDataFileInvalid(f"Cannot find ID column '{id_col}'") from err
|
||||
if len(headers) == 0:
|
||||
raise CsvParamsDataFileInvalid("File seems only to have IDs") from None
|
||||
data: List[TestCaseParameters] = []
|
||||
for data_line in csv_lines:
|
||||
line = list(map(str, data_line))
|
||||
if len(line) == 0:
|
||||
continue
|
||||
test_id = None
|
||||
if id_index >= 0:
|
||||
test_id = line.pop(id_index)
|
||||
if len(headers) != len(line):
|
||||
raise CsvParamsDataFileInvalid("Header and Data length mismatch") from None
|
||||
if data_casts is not None:
|
||||
for index, header in enumerate(headers):
|
||||
caster = data_casts.get(header, None)
|
||||
if caster is not None:
|
||||
line[index] = caster(str(line[index]))
|
||||
data.append(
|
||||
{
|
||||
"test_id": test_id,
|
||||
"data": line,
|
||||
}
|
||||
)
|
||||
id_data = None
|
||||
if id_col is not None:
|
||||
id_data = [tc_data["test_id"] for tc_data in data]
|
||||
return pytest.mark.parametrize(headers, [tc_data["data"] for tc_data in data], ids=id_data)
|
15
_ptcsvp/plugin.py
Normal file
15
_ptcsvp/plugin.py
Normal file
@ -0,0 +1,15 @@
|
||||
"""
|
||||
The main Plugin implementation
|
||||
"""
|
||||
|
||||
|
||||
class Plugin: # pylint: disable=too-few-public-methods
|
||||
"""
|
||||
Plugin Class
|
||||
"""
|
||||
|
||||
def __init__(self, config):
|
||||
"""
|
||||
Hold the pytest config
|
||||
"""
|
||||
self.config = config
|
30
_ptcsvp/version.py
Normal file
30
_ptcsvp/version.py
Normal file
@ -0,0 +1,30 @@
|
||||
"""
|
||||
Check Version Information
|
||||
"""
|
||||
import sys
|
||||
|
||||
from attr.exceptions import PythonTooOldError
|
||||
from packaging.version import parse
|
||||
|
||||
|
||||
def check_python_version(min_version=(3, 8)):
|
||||
"""
|
||||
Check if the current version is at least 3.8
|
||||
"""
|
||||
|
||||
if sys.version_info < min_version:
|
||||
raise PythonTooOldError(f"At least Python {'.'.join(map(str, min_version))} required")
|
||||
|
||||
|
||||
def check_pytest_version(min_version=(7, 1)):
|
||||
"""
|
||||
Check if the current version is at least 7.1
|
||||
"""
|
||||
|
||||
from pytest import __version__ as pytest_version # pylint: disable=import-outside-toplevel
|
||||
|
||||
pytest_min_version = ".".join(map(str, min_version))
|
||||
parsed_min_version = parse(pytest_min_version)
|
||||
parsed_actual_version = parse(pytest_version)
|
||||
if parsed_actual_version < parsed_min_version:
|
||||
raise RuntimeError(f"At least Pytest {pytest_min_version} required")
|
690
poetry.lock
generated
Normal file
690
poetry.lock
generated
Normal file
@ -0,0 +1,690 @@
|
||||
[[package]]
|
||||
name = "astroid"
|
||||
version = "2.11.7"
|
||||
description = "An abstract syntax tree for Python with inference support."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6.2"
|
||||
|
||||
[package.dependencies]
|
||||
lazy-object-proxy = ">=1.4.0"
|
||||
typing-extensions = {version = ">=3.10", markers = "python_version < \"3.10\""}
|
||||
wrapt = ">=1.11,<2"
|
||||
|
||||
[[package]]
|
||||
name = "atomicwrites"
|
||||
version = "1.4.1"
|
||||
description = "Atomic file writes."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||
|
||||
[[package]]
|
||||
name = "attrs"
|
||||
version = "22.1.0"
|
||||
description = "Classes Without Boilerplate"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.5"
|
||||
|
||||
[package.extras]
|
||||
dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "mypy (>=0.900,!=0.940)", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"]
|
||||
docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"]
|
||||
tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "mypy (>=0.900,!=0.940)", "pytest-mypy-plugins", "zope.interface", "cloudpickle"]
|
||||
tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "mypy (>=0.900,!=0.940)", "pytest-mypy-plugins", "cloudpickle"]
|
||||
|
||||
[[package]]
|
||||
name = "bandit"
|
||||
version = "1.7.4"
|
||||
description = "Security oriented static analyser for python code."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
|
||||
[package.dependencies]
|
||||
colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""}
|
||||
GitPython = ">=1.0.1"
|
||||
PyYAML = ">=5.3.1"
|
||||
stevedore = ">=1.20.0"
|
||||
|
||||
[package.extras]
|
||||
test = ["coverage (>=4.5.4)", "fixtures (>=3.0.0)", "flake8 (>=4.0.0)", "stestr (>=2.5.0)", "testscenarios (>=0.5.0)", "testtools (>=2.3.0)", "toml", "beautifulsoup4 (>=4.8.0)", "pylint (==1.9.4)"]
|
||||
toml = ["toml"]
|
||||
yaml = ["pyyaml"]
|
||||
|
||||
[[package]]
|
||||
name = "black"
|
||||
version = "22.6.0"
|
||||
description = "The uncompromising code formatter."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6.2"
|
||||
|
||||
[package.dependencies]
|
||||
click = ">=8.0.0"
|
||||
mypy-extensions = ">=0.4.3"
|
||||
pathspec = ">=0.9.0"
|
||||
platformdirs = ">=2"
|
||||
tomli = {version = ">=1.1.0", markers = "python_full_version < \"3.11.0a7\""}
|
||||
typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""}
|
||||
|
||||
[package.extras]
|
||||
colorama = ["colorama (>=0.4.3)"]
|
||||
d = ["aiohttp (>=3.7.4)"]
|
||||
jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
|
||||
uvloop = ["uvloop (>=0.15.2)"]
|
||||
|
||||
[[package]]
|
||||
name = "click"
|
||||
version = "8.1.3"
|
||||
description = "Composable command line interface toolkit"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
|
||||
[package.dependencies]
|
||||
colorama = {version = "*", markers = "platform_system == \"Windows\""}
|
||||
|
||||
[[package]]
|
||||
name = "colorama"
|
||||
version = "0.4.5"
|
||||
description = "Cross-platform colored terminal text."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
|
||||
[[package]]
|
||||
name = "commonmark"
|
||||
version = "0.9.1"
|
||||
description = "Python parser for the CommonMark Markdown spec"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[package.extras]
|
||||
test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"]
|
||||
|
||||
[[package]]
|
||||
name = "coverage"
|
||||
version = "6.4.3"
|
||||
description = "Code coverage measurement for Python"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
|
||||
[package.dependencies]
|
||||
tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""}
|
||||
|
||||
[package.extras]
|
||||
toml = ["tomli"]
|
||||
|
||||
[[package]]
|
||||
name = "dill"
|
||||
version = "0.3.5.1"
|
||||
description = "serialize all of python"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*"
|
||||
|
||||
[package.extras]
|
||||
graph = ["objgraph (>=1.7.2)"]
|
||||
|
||||
[[package]]
|
||||
name = "distlib"
|
||||
version = "0.3.5"
|
||||
description = "Distribution utilities"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "filelock"
|
||||
version = "3.8.0"
|
||||
description = "A platform independent file lock."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
|
||||
[package.extras]
|
||||
testing = ["pytest-timeout (>=2.1)", "pytest-cov (>=3)", "pytest (>=7.1.2)", "coverage (>=6.4.2)", "covdefaults (>=2.2)"]
|
||||
docs = ["sphinx-autodoc-typehints (>=1.19.1)", "sphinx (>=5.1.1)", "furo (>=2022.6.21)"]
|
||||
|
||||
[[package]]
|
||||
name = "gitdb"
|
||||
version = "4.0.9"
|
||||
description = "Git Object Database"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[package.dependencies]
|
||||
smmap = ">=3.0.1,<6"
|
||||
|
||||
[[package]]
|
||||
name = "gitpython"
|
||||
version = "3.1.27"
|
||||
description = "GitPython is a python library used to interact with Git repositories"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
|
||||
[package.dependencies]
|
||||
gitdb = ">=4.0.1,<5"
|
||||
|
||||
[[package]]
|
||||
name = "iniconfig"
|
||||
version = "1.1.1"
|
||||
description = "iniconfig: brain-dead simple config-ini parsing"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "isort"
|
||||
version = "5.10.1"
|
||||
description = "A Python utility / library to sort Python imports."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6.1,<4.0"
|
||||
|
||||
[package.extras]
|
||||
pipfile_deprecated_finder = ["pipreqs", "requirementslib"]
|
||||
requirements_deprecated_finder = ["pipreqs", "pip-api"]
|
||||
colors = ["colorama (>=0.4.3,<0.5.0)"]
|
||||
plugins = ["setuptools"]
|
||||
|
||||
[[package]]
|
||||
name = "lazy-object-proxy"
|
||||
version = "1.7.1"
|
||||
description = "A fast and thorough lazy object proxy."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[[package]]
|
||||
name = "mccabe"
|
||||
version = "0.7.0"
|
||||
description = "McCabe checker, plugin for flake8"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[[package]]
|
||||
name = "mypy-extensions"
|
||||
version = "0.4.3"
|
||||
description = "Experimental type system extensions for programs checked with the mypy typechecker."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "packaging"
|
||||
version = "21.3"
|
||||
description = "Core utilities for Python packages"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[package.dependencies]
|
||||
pyparsing = ">=2.0.2,<3.0.5 || >3.0.5"
|
||||
|
||||
[[package]]
|
||||
name = "pathspec"
|
||||
version = "0.9.0"
|
||||
description = "Utility library for gitignore style pattern matching of file paths."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
|
||||
|
||||
[[package]]
|
||||
name = "pbr"
|
||||
version = "5.10.0"
|
||||
description = "Python Build Reasonableness"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=2.6"
|
||||
|
||||
[[package]]
|
||||
name = "platformdirs"
|
||||
version = "2.5.2"
|
||||
description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
|
||||
[package.extras]
|
||||
docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)", "sphinx (>=4)"]
|
||||
test = ["appdirs (==1.4.4)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)", "pytest (>=6)"]
|
||||
|
||||
[[package]]
|
||||
name = "pluggy"
|
||||
version = "1.0.0"
|
||||
description = "plugin and hook calling mechanisms for python"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[package.extras]
|
||||
dev = ["pre-commit", "tox"]
|
||||
testing = ["pytest", "pytest-benchmark"]
|
||||
|
||||
[[package]]
|
||||
name = "pprintpp"
|
||||
version = "0.4.0"
|
||||
description = "A drop-in replacement for pprint that's actually pretty"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "py"
|
||||
version = "1.11.0"
|
||||
description = "library with cross-python path, ini-parsing, io, code, log facilities"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
|
||||
[[package]]
|
||||
name = "pygments"
|
||||
version = "2.12.0"
|
||||
description = "Pygments is a syntax highlighting package written in Python."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[[package]]
|
||||
name = "pylint"
|
||||
version = "2.14.5"
|
||||
description = "python code static checker"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7.2"
|
||||
|
||||
[package.dependencies]
|
||||
astroid = ">=2.11.6,<=2.12.0-dev0"
|
||||
colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""}
|
||||
dill = ">=0.2"
|
||||
isort = ">=4.2.5,<6"
|
||||
mccabe = ">=0.6,<0.8"
|
||||
platformdirs = ">=2.2.0"
|
||||
tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
|
||||
tomlkit = ">=0.10.1"
|
||||
typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""}
|
||||
|
||||
[package.extras]
|
||||
spelling = ["pyenchant (>=3.2,<4.0)"]
|
||||
testutils = ["gitpython (>3)"]
|
||||
|
||||
[[package]]
|
||||
name = "pyparsing"
|
||||
version = "3.0.9"
|
||||
description = "pyparsing module - Classes and methods to define and execute parsing grammars"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6.8"
|
||||
|
||||
[package.extras]
|
||||
diagrams = ["railroad-diagrams", "jinja2"]
|
||||
|
||||
[[package]]
|
||||
name = "pytest"
|
||||
version = "7.1.2"
|
||||
description = "pytest: simple powerful testing with Python"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
|
||||
[package.dependencies]
|
||||
atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""}
|
||||
attrs = ">=19.2.0"
|
||||
colorama = {version = "*", markers = "sys_platform == \"win32\""}
|
||||
iniconfig = "*"
|
||||
packaging = "*"
|
||||
pluggy = ">=0.12,<2.0"
|
||||
py = ">=1.8.2"
|
||||
tomli = ">=1.0.0"
|
||||
|
||||
[package.extras]
|
||||
testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"]
|
||||
|
||||
[[package]]
|
||||
name = "pytest-bandit"
|
||||
version = "0.6.1"
|
||||
description = "A bandit plugin for pytest"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "~=3.4"
|
||||
|
||||
[package.dependencies]
|
||||
bandit = ">=1.4.0"
|
||||
pytest = ">=3.5.0"
|
||||
|
||||
[[package]]
|
||||
name = "pytest-black"
|
||||
version = "0.3.12"
|
||||
description = "A pytest plugin to enable format checking with black"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=2.7"
|
||||
|
||||
[package.dependencies]
|
||||
black = {version = "*", markers = "python_version >= \"3.6\""}
|
||||
pytest = ">=3.5.0"
|
||||
toml = "*"
|
||||
|
||||
[[package]]
|
||||
name = "pytest-clarity"
|
||||
version = "1.0.1"
|
||||
description = "A plugin providing an alternative, colourful diff output for failing assertions."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||
|
||||
[package.dependencies]
|
||||
pprintpp = ">=0.4.0"
|
||||
pytest = ">=3.5.0"
|
||||
rich = ">=8.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "pytest-cov"
|
||||
version = "3.0.0"
|
||||
description = "Pytest plugin for measuring coverage."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[package.dependencies]
|
||||
coverage = {version = ">=5.2.1", extras = ["toml"]}
|
||||
pytest = ">=4.6"
|
||||
|
||||
[package.extras]
|
||||
testing = ["fields", "hunter", "process-tests", "six", "pytest-xdist", "virtualenv"]
|
||||
|
||||
[[package]]
|
||||
name = "pytest-isort"
|
||||
version = "3.0.0"
|
||||
description = "py.test plugin to check import ordering using isort"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6,<4"
|
||||
|
||||
[package.dependencies]
|
||||
isort = ">=4.0"
|
||||
pytest = ">=5.0"
|
||||
|
||||
[[package]]
|
||||
name = "pytest-mock"
|
||||
version = "3.8.2"
|
||||
description = "Thin-wrapper around the mock package for easier use with pytest"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
|
||||
[package.dependencies]
|
||||
pytest = ">=5.0"
|
||||
|
||||
[package.extras]
|
||||
dev = ["pytest-asyncio", "tox", "pre-commit"]
|
||||
|
||||
[[package]]
|
||||
name = "pytest-pylint"
|
||||
version = "0.18.0"
|
||||
description = "pytest plugin to check source code with pylint"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.5"
|
||||
|
||||
[package.dependencies]
|
||||
pylint = ">=2.3.0"
|
||||
pytest = ">=5.4"
|
||||
toml = ">=0.7.1"
|
||||
|
||||
[[package]]
|
||||
name = "pyyaml"
|
||||
version = "6.0"
|
||||
description = "YAML parser and emitter for Python"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[[package]]
|
||||
name = "rich"
|
||||
version = "12.5.1"
|
||||
description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6.3,<4.0.0"
|
||||
|
||||
[package.dependencies]
|
||||
commonmark = ">=0.9.0,<0.10.0"
|
||||
pygments = ">=2.6.0,<3.0.0"
|
||||
typing-extensions = {version = ">=4.0.0,<5.0", markers = "python_version < \"3.9\""}
|
||||
|
||||
[package.extras]
|
||||
jupyter = ["ipywidgets (>=7.5.1,<8.0.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "six"
|
||||
version = "1.16.0"
|
||||
description = "Python 2 and 3 compatibility utilities"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
|
||||
|
||||
[[package]]
|
||||
name = "smmap"
|
||||
version = "5.0.0"
|
||||
description = "A pure Python implementation of a sliding window memory map manager"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[[package]]
|
||||
name = "stevedore"
|
||||
version = "4.0.0"
|
||||
description = "Manage dynamic plugins for Python applications"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
|
||||
[package.dependencies]
|
||||
pbr = ">=2.0.0,<2.1.0 || >2.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.10.2"
|
||||
description = "Python Library for Tom's Obvious, Minimal Language"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
|
||||
|
||||
[[package]]
|
||||
name = "tomli"
|
||||
version = "2.0.1"
|
||||
description = "A lil' TOML parser"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
|
||||
[[package]]
|
||||
name = "tomlkit"
|
||||
version = "0.11.4"
|
||||
description = "Style preserving TOML library"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6,<4.0"
|
||||
|
||||
[[package]]
|
||||
name = "tox"
|
||||
version = "3.25.1"
|
||||
description = "tox is a generic virtualenv management and test command line tool"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
|
||||
|
||||
[package.dependencies]
|
||||
colorama = {version = ">=0.4.1", markers = "platform_system == \"Windows\""}
|
||||
filelock = ">=3.0.0"
|
||||
packaging = ">=14"
|
||||
pluggy = ">=0.12.0"
|
||||
py = ">=1.4.17"
|
||||
six = ">=1.14.0"
|
||||
toml = ">=0.9.4"
|
||||
virtualenv = ">=16.0.0,<20.0.0 || >20.0.0,<20.0.1 || >20.0.1,<20.0.2 || >20.0.2,<20.0.3 || >20.0.3,<20.0.4 || >20.0.4,<20.0.5 || >20.0.5,<20.0.6 || >20.0.6,<20.0.7 || >20.0.7"
|
||||
|
||||
[package.extras]
|
||||
testing = ["pathlib2 (>=2.3.3)", "psutil (>=5.6.1)", "pytest-randomly (>=1.0.0)", "pytest-mock (>=1.10.0)", "pytest-cov (>=2.5.1)", "pytest (>=4.0.0)", "freezegun (>=0.3.11)", "flaky (>=3.4.0)"]
|
||||
docs = ["towncrier (>=18.5.0)", "sphinxcontrib-autoprogram (>=0.1.5)", "sphinx (>=2.0.0)", "pygments-github-lexers (>=0.0.5)"]
|
||||
|
||||
[[package]]
|
||||
name = "tox-poetry"
|
||||
version = "0.4.1"
|
||||
description = "Tox poetry plugin"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[package.dependencies]
|
||||
pluggy = "*"
|
||||
toml = "*"
|
||||
tox = {version = ">=3.7.0", markers = "python_version >= \"3\""}
|
||||
|
||||
[package.extras]
|
||||
test = ["pylint", "pycodestyle", "pytest", "coverage"]
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.3.0"
|
||||
description = "Backported and Experimental Type Hints for Python 3.7+"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
|
||||
[[package]]
|
||||
name = "virtualenv"
|
||||
version = "20.16.3"
|
||||
description = "Virtual Python Environment builder"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[package.dependencies]
|
||||
distlib = ">=0.3.5,<1"
|
||||
filelock = ">=3.4.1,<4"
|
||||
platformdirs = ">=2.4,<3"
|
||||
|
||||
[package.extras]
|
||||
testing = ["pytest-timeout (>=2.1)", "pytest-randomly (>=3.10.3)", "pytest-mock (>=3.6.1)", "pytest-freezegun (>=0.4.2)", "pytest-env (>=0.6.2)", "pytest (>=7.0.1)", "packaging (>=21.3)", "flaky (>=3.7)", "coverage-enable-subprocess (>=1)", "coverage (>=6.2)"]
|
||||
docs = ["towncrier (>=21.9)", "sphinx-rtd-theme (>=1)", "sphinx-argparse (>=0.3.1)", "sphinx (>=5.1.1)", "proselint (>=0.13)"]
|
||||
|
||||
[[package]]
|
||||
name = "wrapt"
|
||||
version = "1.14.1"
|
||||
description = "Module for decorators, wrappers and monkey patching."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
|
||||
|
||||
[metadata]
|
||||
lock-version = "1.1"
|
||||
python-versions = "^3.8"
|
||||
content-hash = "109ba73e69f54a4f4610c2cc9153499d8d8fb6db5dffc48ab767779e4525be78"
|
||||
|
||||
[metadata.files]
|
||||
astroid = []
|
||||
atomicwrites = []
|
||||
attrs = []
|
||||
bandit = []
|
||||
black = []
|
||||
click = [
|
||||
{file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"},
|
||||
{file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"},
|
||||
]
|
||||
colorama = [
|
||||
{file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"},
|
||||
{file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"},
|
||||
]
|
||||
commonmark = [
|
||||
{file = "commonmark-0.9.1-py2.py3-none-any.whl", hash = "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9"},
|
||||
{file = "commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"},
|
||||
]
|
||||
coverage = []
|
||||
dill = []
|
||||
distlib = []
|
||||
filelock = []
|
||||
gitdb = []
|
||||
gitpython = []
|
||||
iniconfig = [
|
||||
{file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
|
||||
{file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
|
||||
]
|
||||
isort = []
|
||||
lazy-object-proxy = []
|
||||
mccabe = []
|
||||
mypy-extensions = [
|
||||
{file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
|
||||
{file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
|
||||
]
|
||||
packaging = [
|
||||
{file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"},
|
||||
{file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
|
||||
]
|
||||
pathspec = []
|
||||
pbr = []
|
||||
platformdirs = []
|
||||
pluggy = [
|
||||
{file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
|
||||
{file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
|
||||
]
|
||||
pprintpp = [
|
||||
{file = "pprintpp-0.4.0-py2.py3-none-any.whl", hash = "sha256:b6b4dcdd0c0c0d75e4d7b2f21a9e933e5b2ce62b26e1a54537f9651ae5a5c01d"},
|
||||
{file = "pprintpp-0.4.0.tar.gz", hash = "sha256:ea826108e2c7f49dc6d66c752973c3fc9749142a798d6b254e1e301cfdbc6403"},
|
||||
]
|
||||
py = [
|
||||
{file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"},
|
||||
{file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"},
|
||||
]
|
||||
pygments = [
|
||||
{file = "Pygments-2.12.0-py3-none-any.whl", hash = "sha256:dc9c10fb40944260f6ed4c688ece0cd2048414940f1cea51b8b226318411c519"},
|
||||
{file = "Pygments-2.12.0.tar.gz", hash = "sha256:5eb116118f9612ff1ee89ac96437bb6b49e8f04d8a13b514ba26f620208e26eb"},
|
||||
]
|
||||
pylint = []
|
||||
pyparsing = [
|
||||
{file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"},
|
||||
{file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"},
|
||||
]
|
||||
pytest = [
|
||||
{file = "pytest-7.1.2-py3-none-any.whl", hash = "sha256:13d0e3ccfc2b6e26be000cb6568c832ba67ba32e719443bfe725814d3c42433c"},
|
||||
{file = "pytest-7.1.2.tar.gz", hash = "sha256:a06a0425453864a270bc45e71f783330a7428defb4230fb5e6a731fde06ecd45"},
|
||||
]
|
||||
pytest-bandit = []
|
||||
pytest-black = []
|
||||
pytest-clarity = [
|
||||
{file = "pytest-clarity-1.0.1.tar.gz", hash = "sha256:505fe345fad4fe11c6a4187fe683f2c7c52c077caa1e135f3e483fe112db7772"},
|
||||
]
|
||||
pytest-cov = [
|
||||
{file = "pytest-cov-3.0.0.tar.gz", hash = "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470"},
|
||||
{file = "pytest_cov-3.0.0-py3-none-any.whl", hash = "sha256:578d5d15ac4a25e5f961c938b85a05b09fdaae9deef3bb6de9a6e766622ca7a6"},
|
||||
]
|
||||
pytest-isort = []
|
||||
pytest-mock = []
|
||||
pytest-pylint = []
|
||||
pyyaml = []
|
||||
rich = []
|
||||
six = [
|
||||
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
|
||||
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
|
||||
]
|
||||
smmap = []
|
||||
stevedore = []
|
||||
toml = []
|
||||
tomli = [
|
||||
{file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
|
||||
{file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
|
||||
]
|
||||
tomlkit = []
|
||||
tox = []
|
||||
tox-poetry = []
|
||||
typing-extensions = []
|
||||
virtualenv = []
|
||||
wrapt = []
|
132
pyproject.toml
Normal file
132
pyproject.toml
Normal file
@ -0,0 +1,132 @@
|
||||
[tool.poetry]
|
||||
name = "pytest-csv-params"
|
||||
version = "0.0.1"
|
||||
description = "Pytest plugin for Test Case Parametrization with CSV files"
|
||||
authors = ["Juergen Edelbluth <csv_params@jued.de>"]
|
||||
license = "MIT"
|
||||
repository = "https://git.codebau.dev/pytest-plugins/pytest-csv-params"
|
||||
homepage = "https://git.codebau.dev/pytest-plugins/pytest-csv-params"
|
||||
keywords = [
|
||||
"py.test", "pytest", "csv", "params", "parametrize", "pytest-plugin",
|
||||
]
|
||||
classifiers = [
|
||||
"Development Status :: 1 - Planning",
|
||||
"Environment :: Plugins",
|
||||
"Framework :: Pytest",
|
||||
"Intended Audience :: Developers",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Topic :: Software Development :: Testing",
|
||||
"Topic :: Software Development :: Quality Assurance",
|
||||
"Operating System :: POSIX",
|
||||
"Operating System :: Microsoft :: Windows",
|
||||
"Operating System :: MacOS :: MacOS X",
|
||||
"Topic :: Utilities",
|
||||
]
|
||||
packages = [
|
||||
{ include = "_ptcsvp" },
|
||||
{ include = "pytest_csv_params" },
|
||||
]
|
||||
|
||||
[tool.poetry.urls]
|
||||
"Issue Tracker" = "https://git.codebau.dev/pytest-plugins/pytest-csv-params/issues"
|
||||
"Wiki" = "https://git.codebau.dev/pytest-plugins/pytest-csv-params/wiki"
|
||||
"Releases" = "https://git.codebau.dev/pytest-plugins/pytest-csv-params/releases"
|
||||
|
||||
[tool.poetry.plugins."pytest11"]
|
||||
"pytest-csv-params" = "pytest_csv_params.plugin"
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
addopts = "--black --isort --pylint --pylint-rcfile=.pylintrc --cov --cov-report=term-missing --junitxml=test-reports/pytest_csv_params.xml"
|
||||
filterwarnings=[
|
||||
"ignore:.*BlackItem.*:_pytest.warning_types.PytestDeprecationWarning",
|
||||
"ignore:.*BlackItem.*:_pytest.warning_types.PytestRemovedIn8Warning",
|
||||
"ignore:.*PyLintFile.*:_pytest.warning_types.PytestRemovedIn8Warning",
|
||||
"ignore:.*BlackItem.*:_pytest.warning_types.PytestWarning",
|
||||
"ignore:Using the __implements__ inheritance pattern for BaseReporter is no longer supported. Child classes should only inherit BaseReporter",
|
||||
"ignore:.*zipimport.*",
|
||||
"ignore:Creating a LegacyVersion has been deprecated and will be removed in the next major release",
|
||||
]
|
||||
junit_family = "xunit2"
|
||||
junit_logging = "all"
|
||||
junit_log_passing_tests = true
|
||||
junit_duration_report = "call"
|
||||
junit_suite_name = "pytest-csv-params"
|
||||
|
||||
bandit_targets = [
|
||||
"pytest_csv_params",
|
||||
"_ptcsvp",
|
||||
]
|
||||
bandit_recurse = "True"
|
||||
|
||||
[tool.coverage]
|
||||
|
||||
[tool.coverage.run]
|
||||
omit = [
|
||||
"test/*",
|
||||
"tests/*",
|
||||
"*/venv/*",
|
||||
"*/.venv/*",
|
||||
"*/.tox/*",
|
||||
"*/pyvenv/*",
|
||||
"*/JetBrains/*",
|
||||
"*/virtualenv/*",
|
||||
"/etc/python*",
|
||||
"*pip-standalone-pip*",
|
||||
"*pip-build-env*",
|
||||
"*/test_plugin_test_multiplication.py",
|
||||
"*/test_plugin_test_error.py",
|
||||
]
|
||||
relative_files = true
|
||||
|
||||
[tool.coverage.report]
|
||||
exclude_lines = [
|
||||
"pragma: no cover",
|
||||
"def __repr__",
|
||||
"if self\\.debug",
|
||||
"raise AssertionError",
|
||||
"raise NotImplementedError",
|
||||
"if __name__ == .__main__.:",
|
||||
]
|
||||
|
||||
[tool.tox]
|
||||
legacy_tox_ini = """
|
||||
[tox]
|
||||
minversion = 3.25.0
|
||||
envlist = py38,py39,py310
|
||||
|
||||
[testenv]
|
||||
commands =
|
||||
pytest
|
||||
"""
|
||||
|
||||
[tool.black]
|
||||
line-length = 120
|
||||
target-version = ['py38', 'py39', 'py310']
|
||||
include = '\.pyi?$'
|
||||
|
||||
[tool.isort]
|
||||
line_length = 120
|
||||
include_trailing_comma = "True"
|
||||
multi_line_output = 3
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.8"
|
||||
pytest = "^7.1.2"
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
tox = "^3.25.1"
|
||||
tox-poetry = "^0.4.1"
|
||||
pytest-black = "^0.3.12"
|
||||
pytest-isort = "^3.0.0"
|
||||
pytest-cov = "^3.0.0"
|
||||
pytest-pylint = "^0.18.0"
|
||||
pytest-mock = "^3.8.2"
|
||||
pytest-clarity = "^1.0.1"
|
||||
pytest-bandit = "^0.6.1"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core>=1.0.0"]
|
||||
build-backend = "poetry.core.masonry.api"
|
0
pytest_csv_params/__init__.py
Normal file
0
pytest_csv_params/__init__.py
Normal file
6
pytest_csv_params/decorator.py
Normal file
6
pytest_csv_params/decorator.py
Normal file
@ -0,0 +1,6 @@
|
||||
"""
|
||||
Add CSV Data to test
|
||||
"""
|
||||
from _ptcsvp.parametrize import add_parametrization
|
||||
|
||||
csv_params = add_parametrization
|
18
pytest_csv_params/dialect.py
Normal file
18
pytest_csv_params/dialect.py
Normal file
@ -0,0 +1,18 @@
|
||||
"""
|
||||
CSV Dialects
|
||||
"""
|
||||
import csv
|
||||
|
||||
|
||||
class CsvParamsDefaultDialect(csv.Dialect): # pylint: disable=too-few-public-methods
|
||||
"""
|
||||
Basic CSV Dialect for most Tests
|
||||
"""
|
||||
|
||||
delimiter = ","
|
||||
doublequote = True
|
||||
lineterminator = "\r\n"
|
||||
quotechar = '"'
|
||||
quoting = csv.QUOTE_ALL
|
||||
strict = True
|
||||
skipinitialspace = True
|
21
pytest_csv_params/exception.py
Normal file
21
pytest_csv_params/exception.py
Normal file
@ -0,0 +1,21 @@
|
||||
"""
|
||||
Exceptions
|
||||
"""
|
||||
|
||||
|
||||
class CsvParamsDataFileNotFound(FileNotFoundError):
|
||||
"""
|
||||
File Not Found
|
||||
"""
|
||||
|
||||
|
||||
class CsvParamsDataFileInaccessible(IOError):
|
||||
"""
|
||||
Cannot Access the File
|
||||
"""
|
||||
|
||||
|
||||
class CsvParamsDataFileInvalid(ValueError):
|
||||
"""
|
||||
CSV Data is somehow invalid
|
||||
"""
|
15
pytest_csv_params/plugin.py
Normal file
15
pytest_csv_params/plugin.py
Normal file
@ -0,0 +1,15 @@
|
||||
"""
|
||||
Pytest Plugin Entrypoint
|
||||
"""
|
||||
|
||||
from _ptcsvp.configure import pytest_configure as _pytest_configure
|
||||
from _ptcsvp.configure import pytest_unconfigure as _pytest_unconfigure
|
||||
from _ptcsvp.version import check_pytest_version, check_python_version
|
||||
|
||||
# Fist at all, check if the python & pytest version matches
|
||||
check_python_version()
|
||||
check_pytest_version()
|
||||
|
||||
# Basic config
|
||||
pytest_configure = _pytest_configure
|
||||
pytest_unconfigure = _pytest_unconfigure
|
17
pytest_csv_params/types.py
Normal file
17
pytest_csv_params/types.py
Normal file
@ -0,0 +1,17 @@
|
||||
"""
|
||||
Types to ease the usage of the API
|
||||
"""
|
||||
import csv
|
||||
from typing import Callable, Dict, Optional, Type, TypeVar
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
DataCast = Callable[[str], T]
|
||||
DataCastDict = Dict[str, DataCast]
|
||||
|
||||
BaseDir = Optional[str]
|
||||
IdColName = Optional[str]
|
||||
|
||||
DataFile = str
|
||||
|
||||
CsvDialect = Type[csv.Dialect]
|
0
tests/__init__.py
Normal file
0
tests/__init__.py
Normal file
6
tests/assets/test1.csv
Normal file
6
tests/assets/test1.csv
Normal file
@ -0,0 +1,6 @@
|
||||
"#ID", "Animal", "Color"
|
||||
"A1", "Cat", "Blue"
|
||||
"A2", "Dog", "Green"
|
||||
"A3", "Mouse", "Yellow"
|
||||
"A4", "Bird", "Purple"
|
||||
"A5", "Cow", "Red"
|
|
10
tests/assets/test10.csv
Normal file
10
tests/assets/test10.csv
Normal file
@ -0,0 +1,10 @@
|
||||
"#ID", "Animal", "Color"
|
||||
"A1", "Cat", "Blue"
|
||||
"A2", "Dog", "Green"
|
||||
"A3", "Mouse", "Yellow"
|
||||
"A4", "Bird", "Purple"
|
||||
"A5", "Cow", "Red"
|
||||
|
||||
|
||||
|
||||
"A7", "Rat", "Black"
|
|
6
tests/assets/test11.csv
Normal file
6
tests/assets/test11.csv
Normal file
@ -0,0 +1,6 @@
|
||||
"Animal", "Color"
|
||||
"Cat", "Blue"
|
||||
"Dog", "Green"
|
||||
"Mouse", "Yellow"
|
||||
"Bird", "Purple"
|
||||
"Cow", "Red"
|
|
6
tests/assets/test2.csv
Normal file
6
tests/assets/test2.csv
Normal file
@ -0,0 +1,6 @@
|
||||
"#ID", "Animal", "Color"
|
||||
"A1", "Cat", "Blue"
|
||||
"A2", "Dog", "Green"
|
||||
"A3", "Mouse", "Yellow"
|
||||
"A4", "Bird", "Purple"
|
||||
"A5", "Cow", "Red", "46"
|
Can't render this file because it has a wrong number of fields in line 6.
|
6
tests/assets/test3.csv
Normal file
6
tests/assets/test3.csv
Normal file
@ -0,0 +1,6 @@
|
||||
"#ID", "Animal", "Color", "Number"
|
||||
"A1", "Cat", "Blue", "44"
|
||||
"A2", "Dog", "Green", "45"
|
||||
"A3", "Mouse", "Yellow"
|
||||
"A4", "Bird", "Purple"
|
||||
"A5", "Cow", "Red", "46"
|
Can't render this file because it has a wrong number of fields in line 4.
|
6
tests/assets/test4.csv
Normal file
6
tests/assets/test4.csv
Normal file
@ -0,0 +1,6 @@
|
||||
"#ID", "Animal", "Color", "Number"
|
||||
"A1", "Cat", "Blue", "44"
|
||||
"A2", "Dog", "Green", "45"
|
||||
"A3", "Mouse", "Yellow"
|
||||
"A4", "Bird", "Purple
|
||||
"A5", "Cow", "Red", "46"
|
Can't render this file because it has a wrong number of fields in line 4.
|
6
tests/assets/test5.csv
Normal file
6
tests/assets/test5.csv
Normal file
@ -0,0 +1,6 @@
|
||||
"#ID", "Animal", "Color", "Number"
|
||||
"A1", "Cat", "Blue", "44"
|
||||
"A2", "Dog", "Green", "45"
|
||||
"A3", "Mouse", "Yellow"
|
||||
"A4", "Bird", "Purple"
|
||||
"A5", "Cow", "Red", 46
|
Can't render this file because it has a wrong number of fields in line 4.
|
6
tests/assets/test6.csv
Normal file
6
tests/assets/test6.csv
Normal file
@ -0,0 +1,6 @@
|
||||
"#ID###", "Animal", "Color", "Number"
|
||||
"A1", "Cat", "Blue", "44"
|
||||
"A2", "Dog", "Green", "45"
|
||||
"A3", "Mouse", "Yellow"
|
||||
"A4", "Bird", "Purple"
|
||||
"A5", "Cow", "Red", 46
|
Can't render this file because it has a wrong number of fields in line 4.
|
1
tests/assets/test7.csv
Normal file
1
tests/assets/test7.csv
Normal file
@ -0,0 +1 @@
|
||||
"#ID", "Animal", "Color", "Number"
|
|
0
tests/assets/test8.csv
Normal file
0
tests/assets/test8.csv
Normal file
|
4
tests/assets/test9.csv
Normal file
4
tests/assets/test9.csv
Normal file
@ -0,0 +1,4 @@
|
||||
"#ID"
|
||||
"A1"
|
||||
"A2"
|
||||
"A3"
|
|
5
tests/conftest.py
Normal file
5
tests/conftest.py
Normal file
@ -0,0 +1,5 @@
|
||||
"""
|
||||
Conftest project global
|
||||
"""
|
||||
|
||||
pytest_plugins = ["pytester"]
|
0
tests/plugin/__init__.py
Normal file
0
tests/plugin/__init__.py
Normal file
1
tests/plugin/assets/.gitattributes
vendored
Normal file
1
tests/plugin/assets/.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
||||
*.csv text eol=crlf
|
4
tests/plugin/assets/bad-test.csv
Normal file
4
tests/plugin/assets/bad-test.csv
Normal file
@ -0,0 +1,4 @@
|
||||
"#ID","word","expected_length"
|
||||
"Apple_length_5","Apple"
|
||||
"Banana_length_6","Banana",6
|
||||
"Kiwi_length_4","Kiwi",4
|
Can't render this file because it has a wrong number of fields in line 2.
|
13
tests/plugin/assets/fruit_test.tpl
Normal file
13
tests/plugin/assets/fruit_test.tpl
Normal file
@ -0,0 +1,13 @@
|
||||
import pytest
|
||||
from pytest_csv_params.decorator import csv_params
|
||||
|
||||
|
||||
@csv_params(
|
||||
id_col="#ID",
|
||||
data_file=r"{{data_file}}",
|
||||
data_casts={
|
||||
"expected_length": int,
|
||||
}
|
||||
)
|
||||
def test_fruits(word, expected_length):
|
||||
assert len(word) == expected_length
|
5
tests/plugin/assets/simple-test.csv
Normal file
5
tests/plugin/assets/simple-test.csv
Normal file
@ -0,0 +1,5 @@
|
||||
"#ID","word","expected_length"
|
||||
"Apple_length_5","Apple",5
|
||||
"Banana_length_6","Banana",6
|
||||
"Kiwi_length_4","Kiwi",4
|
||||
"Peach_wrong_length_10","Peach",10
|
|
56
tests/plugin/conftest.py
Normal file
56
tests/plugin/conftest.py
Normal file
@ -0,0 +1,56 @@
|
||||
"""
|
||||
Configuration for the tests
|
||||
... and local Plugins
|
||||
"""
|
||||
import subprocess
|
||||
from os.path import dirname, join
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
def get_csv(csv: str):
|
||||
"""
|
||||
Get CSV data
|
||||
"""
|
||||
with open(join(dirname(__file__), "assets", f"{csv}.csv"), "rb") as csv_fh:
|
||||
csv_data = csv_fh.read()
|
||||
return csv_data.decode("utf-8")
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def simple_test_csv():
|
||||
"""
|
||||
Provide simple CSV data
|
||||
"""
|
||||
return get_csv("simple-test")
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def bad_test_csv():
|
||||
"""
|
||||
Provide bad CSV data
|
||||
"""
|
||||
return get_csv("bad-test")
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def simple_fruit_test():
|
||||
"""
|
||||
Provide simple test case
|
||||
"""
|
||||
with open(join(dirname(__file__), "assets", "fruit_test.tpl"), "rt", encoding="utf-8") as test_fh:
|
||||
test_data = test_fh.read()
|
||||
return lambda file: test_data.replace("{{data_file}}", file)
|
||||
|
||||
|
||||
@pytest.fixture(scope="session", autouse=True)
|
||||
def install_plugin_locally(pytestconfig):
|
||||
"""
|
||||
Install the local package
|
||||
"""
|
||||
root = pytestconfig.rootpath
|
||||
_ = subprocess.run(["pip", "install", "-e", "."], shell=True, cwd=root, check=True, capture_output=True)
|
||||
yield
|
||||
_ = subprocess.run(
|
||||
["pip", "uninstall", "-y", "pytest_csv_params"], shell=True, cwd=root, check=True, capture_output=True
|
||||
)
|
29
tests/plugin/test_plugin.py
Normal file
29
tests/plugin/test_plugin.py
Normal file
@ -0,0 +1,29 @@
|
||||
"""
|
||||
Just try to call our plugin
|
||||
"""
|
||||
|
||||
|
||||
def test_plugin_test_multiplication(pytester, simple_test_csv, simple_fruit_test):
|
||||
"""
|
||||
Simple Roundtrip Smoke Test
|
||||
"""
|
||||
|
||||
csv_file = str(pytester.makefile(".csv", simple_test_csv).absolute())
|
||||
|
||||
pytester.makepyfile(simple_fruit_test(csv_file))
|
||||
|
||||
result = pytester.runpytest("-p", "no:bandit")
|
||||
result.assert_outcomes(passed=3, failed=1)
|
||||
|
||||
|
||||
def test_plugin_test_error(pytester, bad_test_csv, simple_fruit_test):
|
||||
"""
|
||||
Simple Error Behaviour Test
|
||||
"""
|
||||
|
||||
csv_file = str(pytester.makefile(".csv", bad_test_csv).absolute())
|
||||
|
||||
pytester.makepyfile(simple_fruit_test(csv_file))
|
||||
|
||||
result = pytester.runpytest("-p", "no:bandit")
|
||||
result.assert_outcomes(errors=1)
|
97
tests/test_parametrize.py
Normal file
97
tests/test_parametrize.py
Normal file
@ -0,0 +1,97 @@
|
||||
"""
|
||||
Test the Parametrization Feature
|
||||
"""
|
||||
from os.path import dirname, join
|
||||
|
||||
import pytest
|
||||
|
||||
from _ptcsvp.parametrize import add_parametrization
|
||||
from pytest_csv_params.exception import CsvParamsDataFileInvalid, CsvParamsDataFileNotFound
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
["csv_file", "id_col", "result", "ids", "expect_exception", "expect_message"],
|
||||
[
|
||||
("test0", "#ID", None, None, CsvParamsDataFileNotFound, None),
|
||||
(
|
||||
"test1",
|
||||
"#ID",
|
||||
(
|
||||
["Animal", "Color"],
|
||||
[
|
||||
["Cat", "Blue"],
|
||||
["Dog", "Green"],
|
||||
["Mouse", "Yellow"],
|
||||
["Bird", "Purple"],
|
||||
["Cow", "Red"],
|
||||
],
|
||||
),
|
||||
["A1", "A2", "A3", "A4", "A5"],
|
||||
None,
|
||||
None,
|
||||
),
|
||||
("test2", "#ID", None, None, CsvParamsDataFileInvalid, "Header and Data length mismatch"),
|
||||
("test3", "#ID", None, None, CsvParamsDataFileInvalid, "Header and Data length mismatch"),
|
||||
("test4", "#ID", None, None, CsvParamsDataFileInvalid, "Invalid data"),
|
||||
("test5", "#ID", None, None, CsvParamsDataFileInvalid, "Header and Data length mismatch"),
|
||||
("test6", "#ID", None, None, CsvParamsDataFileInvalid, "Cannot find ID column '#ID'"),
|
||||
("test7", "#ID", None, None, CsvParamsDataFileInvalid, "File does not contain a single data row"),
|
||||
("test8", "#ID", None, None, CsvParamsDataFileInvalid, "File does not contain a single data row"),
|
||||
("test9", "#ID", None, None, CsvParamsDataFileInvalid, "File seems only to have IDs"),
|
||||
("test0", "#ID", None, None, CsvParamsDataFileNotFound, None),
|
||||
(
|
||||
"test10",
|
||||
"#ID",
|
||||
(
|
||||
["Animal", "Color"],
|
||||
[
|
||||
["Cat", "Blue"],
|
||||
["Dog", "Green"],
|
||||
["Mouse", "Yellow"],
|
||||
["Bird", "Purple"],
|
||||
["Cow", "Red"],
|
||||
["Rat", "Black"],
|
||||
],
|
||||
),
|
||||
["A1", "A2", "A3", "A4", "A5", "A7"],
|
||||
None,
|
||||
None,
|
||||
),
|
||||
(
|
||||
"test11",
|
||||
None,
|
||||
(
|
||||
["Animal", "Color"],
|
||||
[
|
||||
["Cat", "Blue"],
|
||||
["Dog", "Green"],
|
||||
["Mouse", "Yellow"],
|
||||
["Bird", "Purple"],
|
||||
["Cow", "Red"],
|
||||
],
|
||||
),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_parametrization(
|
||||
csv_file, id_col, result, ids, expect_exception, expect_message
|
||||
): # pylint: disable=too-many-arguments
|
||||
"""
|
||||
Test the parametrization method
|
||||
"""
|
||||
data_file = join(dirname(__file__), "assets", f"{csv_file}.csv")
|
||||
if expect_exception:
|
||||
with pytest.raises(expect_exception) as raised_exception:
|
||||
add_parametrization(data_file=data_file, id_col=id_col, data_casts={"Number": int})
|
||||
if expect_message is not None:
|
||||
assert raised_exception.value.args[0] == expect_message
|
||||
else:
|
||||
parameterization = add_parametrization(data_file=data_file, id_col=id_col, data_casts={"Number": int})
|
||||
assert parameterization is not None
|
||||
assert isinstance(parameterization, type(pytest.mark.parametrize))
|
||||
assert parameterization.mark.args == parameterization.args
|
||||
assert parameterization.args == result
|
||||
assert parameterization.kwargs.get("ids", None) == ids
|
48
tests/test_read_csv.py
Normal file
48
tests/test_read_csv.py
Normal file
@ -0,0 +1,48 @@
|
||||
"""
|
||||
Test the reading of the CSV
|
||||
"""
|
||||
from os.path import dirname, join
|
||||
|
||||
import pytest
|
||||
|
||||
from _ptcsvp.parametrize import read_csv
|
||||
from pytest_csv_params.dialect import CsvParamsDefaultDialect
|
||||
from pytest_csv_params.exception import CsvParamsDataFileInvalid, CsvParamsDataFileNotFound
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
["csv_file", "base_dir", "expect_lines", "expect_exception", "expect_message"],
|
||||
[
|
||||
("test1.csv", join(dirname(__file__), "assets"), 6, None, None),
|
||||
(join(dirname(__file__), "assets", "test1.csv"), None, 6, None, None),
|
||||
("test2.csv", join(dirname(__file__), "assets"), 6, None, None),
|
||||
(join(dirname(__file__), "assets", "test2.csv"), None, 6, None, None),
|
||||
("test3.csv", join(dirname(__file__), "assets"), 6, None, None),
|
||||
(join(dirname(__file__), "assets", "test3.csv"), None, 6, None, None),
|
||||
("test4.csv", join(dirname(__file__), "assets"), -1, CsvParamsDataFileInvalid, "Invalid data"),
|
||||
(join(dirname(__file__), "assets", "test4.csv"), None, -1, CsvParamsDataFileInvalid, "Invalid data"),
|
||||
("test5.csv", join(dirname(__file__), "assets"), 6, None, None),
|
||||
(join(dirname(__file__), "assets", "test5.csv"), None, 6, None, None),
|
||||
("test-does-not-exist.csv", join(dirname(__file__), "assets"), -1, CsvParamsDataFileNotFound, None),
|
||||
(join(dirname(__file__), "assets", "does-not-exist.csv"), None, -1, CsvParamsDataFileNotFound, None),
|
||||
("test-does-not-exist.csv", join(dirname(__file__), "does-not-exist"), -1, CsvParamsDataFileNotFound, None),
|
||||
(join(dirname(__file__), "does-not-exist", "does-not-exist.csv"), None, -1, CsvParamsDataFileNotFound, None),
|
||||
("test1.csv", join(dirname(__file__), "does-not-exist"), -1, CsvParamsDataFileNotFound, None),
|
||||
(join(dirname(__file__), "does-not-exist", "test1.csv"), None, -1, CsvParamsDataFileNotFound, None),
|
||||
(None, join(dirname(__file__), "assets"), -1, CsvParamsDataFileInvalid, None),
|
||||
(None, None, -1, CsvParamsDataFileInvalid, None),
|
||||
],
|
||||
)
|
||||
def test_csv_reader(csv_file, base_dir, expect_lines, expect_exception, expect_message):
|
||||
"""
|
||||
Test behaviour of the CSV loading
|
||||
"""
|
||||
|
||||
if expect_exception is not None:
|
||||
with pytest.raises(expect_exception) as raised_exception:
|
||||
read_csv(base_dir, csv_file, CsvParamsDefaultDialect)
|
||||
if expect_message is not None:
|
||||
assert raised_exception.value.args[0] == expect_message
|
||||
else:
|
||||
csv_lines = read_csv(base_dir, csv_file, CsvParamsDefaultDialect)
|
||||
assert len(csv_lines) == expect_lines
|
118
tests/test_version_check.py
Normal file
118
tests/test_version_check.py
Normal file
@ -0,0 +1,118 @@
|
||||
"""
|
||||
We are checking the python version for the plugin.
|
||||
"""
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
from attr.exceptions import PythonTooOldError
|
||||
|
||||
from _ptcsvp.version import check_pytest_version, check_python_version
|
||||
|
||||
|
||||
def build_version(p_version):
|
||||
"""
|
||||
Build a Version
|
||||
"""
|
||||
elements = []
|
||||
for v_part in p_version.split("."):
|
||||
try:
|
||||
elements.append(int(v_part))
|
||||
except ValueError:
|
||||
elements.append(v_part)
|
||||
return tuple(elements)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
["p_version", "expect_error"],
|
||||
[
|
||||
("3.8", None),
|
||||
("3.8.1", None),
|
||||
("3.8.10", None),
|
||||
("3.8.10.ray.x", None),
|
||||
("3.9", None),
|
||||
("3.9.2", None),
|
||||
("3.9.21", None),
|
||||
("3.9.21.pre.7", None),
|
||||
("3.10", None),
|
||||
("3.10.31", None),
|
||||
("3.10.31.beta.7", None),
|
||||
("3.11", None),
|
||||
("3.11.12", None),
|
||||
("3.11.12.alpha.4", None),
|
||||
("3.12", None),
|
||||
("3.12.22", None),
|
||||
("3.12.22.final", None),
|
||||
("3.12.22.final.0", None),
|
||||
("2.7", (PythonTooOldError, "At least Python 3.8 required")),
|
||||
("2.7.1", (PythonTooOldError, "At least Python 3.8 required")),
|
||||
("2.7.9", (PythonTooOldError, "At least Python 3.8 required")),
|
||||
("2.7.9.final", (PythonTooOldError, "At least Python 3.8 required")),
|
||||
("2.7.9.final.6", (PythonTooOldError, "At least Python 3.8 required")),
|
||||
("3.7", (PythonTooOldError, "At least Python 3.8 required")),
|
||||
("3.7.1", (PythonTooOldError, "At least Python 3.8 required")),
|
||||
("3.7.final", (PythonTooOldError, "At least Python 3.8 required")),
|
||||
("3.7.final.6", (PythonTooOldError, "At least Python 3.8 required")),
|
||||
("3.7.final.6.777", (PythonTooOldError, "At least Python 3.8 required")),
|
||||
("3.7.3.final.6.777", (PythonTooOldError, "At least Python 3.8 required")),
|
||||
("3.7.3.7.final.6.777", (PythonTooOldError, "At least Python 3.8 required")),
|
||||
("3", (PythonTooOldError, "At least Python 3.8 required")),
|
||||
],
|
||||
)
|
||||
def test_python_version(mocker, p_version, expect_error):
|
||||
"""
|
||||
Test python versions
|
||||
"""
|
||||
mocker.patch.object(sys, "version_info", build_version(p_version))
|
||||
if expect_error is not None:
|
||||
with pytest.raises(expect_error[0]) as raised_exc:
|
||||
check_python_version()
|
||||
assert raised_exc.value.args[0] == expect_error[1]
|
||||
else:
|
||||
check_python_version()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
["p_version", "expect_error"],
|
||||
[
|
||||
("7.1", None),
|
||||
("7.1.1", None),
|
||||
("7.1.1.2", None),
|
||||
("7.1.1.2.3", None),
|
||||
("7.1.1.455555", None),
|
||||
("7.1.1.2-145", None),
|
||||
("7.1.1.090909090990", None),
|
||||
("7.2", None),
|
||||
("7.2.5", None),
|
||||
("7.2.5.6", None),
|
||||
("7.2.5.6.3333333", None),
|
||||
("7.2.5.6.333333333.4", None),
|
||||
("8.0", None),
|
||||
("8.0.1", None),
|
||||
("8.0.beta", None),
|
||||
("8.0.beta.3", None),
|
||||
("8.0.2.3", None),
|
||||
("7.0", (RuntimeError, "At least Pytest 7.1 required")),
|
||||
("7.0.1", (RuntimeError, "At least Pytest 7.1 required")),
|
||||
("7.0.111111", (RuntimeError, "At least Pytest 7.1 required")),
|
||||
("7.0.111111.extra", (RuntimeError, "At least Pytest 7.1 required")),
|
||||
("7.0.111111.extra.git-22", (RuntimeError, "At least Pytest 7.1 required")),
|
||||
("7", (RuntimeError, "At least Pytest 7.1 required")),
|
||||
("6", (RuntimeError, "At least Pytest 7.1 required")),
|
||||
("6.1", (RuntimeError, "At least Pytest 7.1 required")),
|
||||
("6.1.2", (RuntimeError, "At least Pytest 7.1 required")),
|
||||
("6.1.2.final", (RuntimeError, "At least Pytest 7.1 required")),
|
||||
("6.1.2.final.3", (RuntimeError, "At least Pytest 7.1 required")),
|
||||
],
|
||||
)
|
||||
def test_pytest_version(mocker, p_version, expect_error):
|
||||
"""
|
||||
Test pytest versions
|
||||
"""
|
||||
mocker.patch.object(pytest, "__version__", p_version)
|
||||
assert pytest.__version__ == p_version
|
||||
if expect_error is not None:
|
||||
with pytest.raises(expect_error[0]) as raised_exc:
|
||||
check_pytest_version()
|
||||
assert raised_exc.value.args[0] == expect_error[1]
|
||||
else:
|
||||
check_pytest_version()
|
Loading…
Reference in New Issue
Block a user