New Upstream Release - pytest-salt
Ready changes
Summary
Merged new upstream version: 2020.1.27 (was: 2019.6.13).
Resulting package
Built on 2022-03-16T18:28 (took 1m47s)
The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:
apt install -t fresh-releases python3-pytestsalt
Lintian Result
Diff
diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 7775df2..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,63 +0,0 @@
-# Byte-compiled / optimized / DLL files
-__pycache__/
-*.py[cod]
-
-# C extensions
-*.so
-
-# Distribution / packaging
-.Python
-env/
-build/
-develop-eggs/
-dist/
-downloads/
-eggs/
-.eggs/
-lib/
-lib64/
-parts/
-sdist/
-var/
-*.egg-info/
-.installed.cfg
-*.egg
-
-# 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/
-.coverage
-.coverage.*
-.cache
-nosetests.xml
-coverage.xml
-*,cover
-
-# Translations
-*.mo
-*.pot
-
-# Django stuff:
-*.log
-
-# Sphinx documentation
-docs/_build/
-
-# PyBuilder
-target/
-
-# Ignore pyenv python version file
-.python-version
-
-# Ignore local vimrc file
-.lvimrc
diff --git a/.pylintrc b/.pylintrc
deleted file mode 100644
index 6103723..0000000
--- a/.pylintrc
+++ /dev/null
@@ -1,469 +0,0 @@
-[MASTER]
-
-# Specify a configuration file.
-#rcfile=
-
-# Python code to execute, usually for sys.path manipulation such as
-# pygtk.require().
-#init-hook=
-
-# Profiled execution.
-profile=no
-
-# Add files or directories to the blacklist. They should be base names, not
-# paths.
-ignore=CVS
-
-# Pickle collected data for later comparisons.
-persistent=yes
-
-# List of plugins (as comma separated values of python modules names) to load,
-# usually to register additional checkers.
-load-plugins=saltpylint.pep8,
- saltpylint.pep263,
- saltpylint.strings,
- saltpylint.fileperms,
- saltpylint.smartup,
-
-# Use multiple processes to speed up Pylint.
-jobs=1
-
-# Allow loading of arbitrary C extensions. Extensions are imported into the
-# active Python interpreter and may run arbitrary code.
-unsafe-load-any-extension=no
-
-# 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-whitelist=
-
-# Fileperms Lint Plugin Settings
-fileperms-default=0o644
-fileperms-ignore-paths=setup.py
-
-[MESSAGES CONTROL]
-
-# Only show warnings with the listed confidence levels. Leave empty to show
-# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED
-confidence=
-
-# 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. See also the "--disable" option for examples.
-#enable=
-
-# 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 reenable 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=
-disable=R,
- I0011,
- I0012,
- I0013,
- E1101,
- E1103,
- C0102,
- C0103,
- C0111,
- C0203,
- C0204,
- C0301,
- C0302,
- C0330,
- W0110,
- W0122,
- W0142,
- W0201,
- W0212,
- W0404,
- W0511,
- W0603,
- W0612,
- W0613,
- W0621,
- W0622,
- W0631,
- W0704,
- W1202,
- W1307,
- F0220,
- F0401,
- E8501,
- E8116,
- E8121,
- E8122,
- E8123,
- E8124,
- E8125,
- E8126,
- E8127,
- E8128,
- E8129,
- E8131,
- E8265,
- E8266,
- E8402,
- E8731,
- locally-disabled,
- repr-flag-used-in-string,
- un-indexed-curly-braces-error,
- un-indexed-curly-braces-warning
-
-# Disabled:
-# R* [refactoring suggestions & reports]
-# I0011 (locally-disabling)
-# I0012 (locally-enabling)
-# I0013 (file-ignored)
-# E1101 (no-member) [pylint isn't smart enough]
-# E1103 (maybe-no-member)
-# C0102 (blacklisted-name) [because it activates C0103 too]
-# C0103 (invalid-name)
-# C0111 (missing-docstring)
-# C0203 (bad-mcs-method-argument)
-# C0204 (bad-mcs-classmethod-argument)
-# C0301 (line-too-long)
-# C0302 (too-many-lines)
-# C0330 (bad-continuation)
-# W0110 (deprecated-lambda)
-# W0122 (exec-statement)
-# W0142 (star-args)
-# W0201 (attribute-defined-outside-init) [done in several places in the codebase]
-# W0212 (protected-access)
-# W0404 (reimported) [done intentionally for legit reasons]
-# W0511 (fixme) [several outstanding instances currently in the codebase]
-# W0603 (global-statement)
-# W0612 (unused-variable) [unused return values]
-# W0613 (unused-argument)
-# W0621 (redefined-outer-name)
-# W0622 (redefined-builtin) [many parameter names shadow builtins]
-# W0631 (undefined-loop-variable) [~3 instances, seem to be okay]
-# W0704 (pointless-except) [misnomer; "ignores the exception" rather than "pointless"]
-# F0220 (unresolved-interface)
-# F0401 (import-error)
-# W1202 (logging-format-interpolation) Use % formatting in logging functions but pass the % parameters as arguments
-# W1307 (invalid-format-index) Using invalid lookup key '%s' in format specifier "0['%s']"
-#
-# E8116 PEP8 E116: unexpected indentation (comment)
-# E812* All PEP8 E12*
-# E8265 PEP8 E265 - block comment should start with "# "
-# E8266 PEP8 E266 - too many leading '#' for block comment
-# E8501 PEP8 line too long
-# E8402 module level import not at top of file
-# E8731 do not assign a lambda expression, use a def
-#
-# E1322(repr-flag-used-in-string)
-
-[REPORTS]
-
-# Set the output format. Available formats are text, parseable, colorized, msvs
-# (visual studio) and html. You can also give a reporter class, eg
-# mypackage.mymodule.MyReporterClass.
-output-format=text
-
-# Put messages in a separate file for each module / package specified on the
-# command line instead of printing them on stdout. Reports (if any) will be
-# written in a file name "pylint_global.[txt|html]".
-files-output=no
-
-# Tells whether to display a full report or only the messages
-reports=yes
-
-# Python expression which should return a note less than 10 (10 is the highest
-# note). You have access to the variables errors warning, statement which
-# respectively contain the number of errors / warnings messages and the total
-# number of statements analyzed. This is used by the global evaluation report
-# (RP0004).
-evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
-
-# Add a comment according to your evaluation note. This is used by the global
-# evaluation report (RP0004).
-comment=no
-
-# 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=
-
-
-[LOGGING]
-
-# Logging modules to check that the string format arguments are in logging
-# function parameter format
-logging-modules=logging
-
-
-[SPELLING]
-
-# Spelling dictionary name. Available dictionaries: none. To make it working
-# install python-enchant package.
-spelling-dict=
-
-# List of comma separated words that should not be checked.
-spelling-ignore-words=
-
-# A path to a file that contains private dictionary; one word per line.
-spelling-private-dict-file=
-
-# Tells whether to store unknown words to indicated private dictionary in
-# --spelling-private-dict-file option instead of raising a message.
-spelling-store-unknown-words=no
-
-
-[SIMILARITIES]
-
-# Minimum lines number of a similarity.
-min-similarity-lines=4
-
-# Ignore comments when computing similarities.
-ignore-comments=yes
-
-# Ignore docstrings when computing similarities.
-ignore-docstrings=yes
-
-# Ignore imports when computing similarities.
-ignore-imports=no
-
-
-[VARIABLES]
-
-# Tells whether we should check for unused import in __init__ files.
-init-import=no
-
-# A regular expression matching the name of dummy variables (i.e. expectedly
-# not used).
-dummy-variables-rgx=_$|dummy
-
-# List of additional names supposed to be defined in builtins. Remember that
-# you should avoid to define new builtins when possible.
-additional-builtins=__opts__,__virtual__,__salt_system_encoding__
-
-# 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
-
-
-[MISCELLANEOUS]
-
-# List of note tags to take in consideration, separated by a comma.
-notes=FIXME,XXX,TODO
-
-
-[BASIC]
-
-# List of builtins function names that should not be used, separated by a comma
-bad-functions=map,filter,input
-
-# Good variable names which should always be accepted, separated by a comma
-good-names=i,j,k,ex,Run,_,log,pytest_plugins,__opts__
-
-# Bad variable names which should always be refused, separated by a comma
-bad-names=foo,bar,baz,toto,tutu,tata
-
-# Colon-delimited sets of names that determine each other's naming style when
-# the name regexes allow several styles.
-name-group=
-
-# Include a hint for the correct naming format with invalid-name
-include-naming-hint=no
-
-# Regular expression matching correct function names
-function-rgx=[a-z_][a-z0-9_]{2,60}$
-
-# Naming hint for function names
-function-name-hint=[a-z_][a-z0-9_]{2,60}$
-
-# Regular expression matching correct variable names
-variable-rgx=[a-z_][a-z0-9_]{2,60}$
-
-# Naming hint for variable names
-variable-name-hint=[a-z_][a-z0-9_]{2,60}$
-
-# Regular expression matching correct constant names
-const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
-
-# Naming hint for constant names
-const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$
-
-# Regular expression matching correct attribute names
-attr-rgx=[a-z_][a-z0-9_]{2,60}$
-
-# Naming hint for attribute names
-attr-name-hint=[a-z_][a-z0-9_]{2,60}$
-
-# Regular expression matching correct argument names
-argument-rgx=[a-z_][a-z0-9_]{2,60}$
-
-# Naming hint for argument names
-argument-name-hint=[a-z_][a-z0-9_]{2,60}$
-
-# Regular expression matching correct class attribute names
-class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,60}|(__.*__))$
-
-# Naming hint for class attribute names
-class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,60}|(__.*__))$
-
-# Regular expression matching correct inline iteration names
-inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
-
-# Naming hint for inline iteration names
-inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$
-
-# Regular expression matching correct class names
-class-rgx=[A-Z_][a-zA-Z0-9]+$
-
-# Naming hint for class names
-class-name-hint=[A-Z_][a-zA-Z0-9]+$
-
-# Regular expression matching correct module names
-module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
-
-# Naming hint for module names
-module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
-
-# Regular expression matching correct method names
-method-rgx=[a-z_][a-z0-9_]{2,60}$
-
-# Naming hint for method names
-method-name-hint=[a-z_][a-z0-9_]{2,60}$
-
-# Regular expression which should only match function or class names that do
-# not require a docstring.
-no-docstring-rgx=__.*__
-
-# Minimum line length for functions/classes that require docstrings, shorter
-# ones are exempt.
-docstring-min-length=-1
-
-
-[FORMAT]
-
-# Maximum number of characters on a single line.
-max-line-length=120
-
-# Regexp for a line that is allowed to be longer than the limit.
-ignore-long-lines=^\s*(# )?<?https?://\S+>?$
-
-# 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
-
-# List of optional constructs for which whitespace checking is disabled
-no-space-check=trailing-comma,dict-separator
-
-# Maximum number of lines in a module
-max-module-lines=1000
-
-# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
-# tab).
-indent-string=' '
-
-# Number of spaces of indent required inside a hanging or continued line.
-indent-after-paren=4
-
-# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
-expected-line-ending-format=LF
-
-
-[TYPECHECK]
-
-# Tells whether missing members accessed in mixin class should be ignored. A
-# mixin class is detected if its name ends with "mixin" (case insensitive).
-ignore-mixin-members=yes
-
-# 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
-ignored-modules=
-
-# List of classes names for which member attributes should not be checked
-# (useful for classes with attributes dynamically set).
-ignored-classes=
-
-# When zope mode is activated, add a predefined set of Zope acquired attributes
-# to generated-members.
-zope=no
-
-# List of members which are set dynamically and missed by pylint inference
-# system, and so shouldn't trigger E0201 when accessed. Python regular
-# expressions are accepted.
-generated-members=
-
-
-[IMPORTS]
-
-# Deprecated modules which should not be used, separated by a comma
-deprecated-modules=regsub,TERMIOS,Bastion,rexec
-
-# Create a graph of every (i.e. internal and external) dependencies in the
-# given file (report RP0402 must not be disabled)
-import-graph=
-
-# Create a graph of external dependencies in the given file (report RP0402 must
-# not be disabled)
-ext-import-graph=
-
-# Create a graph of internal dependencies in the given file (report RP0402 must
-# not be disabled)
-int-import-graph=
-
-
-[DESIGN]
-
-# Maximum number of arguments for function / method
-max-args=5
-
-# Argument names that match this expression will be ignored. Default to name
-# with leading underscore
-ignored-argument-names=_.*
-
-# Maximum number of locals for function / method body
-max-locals=15
-
-# Maximum number of return / yield for function / method body
-max-returns=6
-
-# Maximum number of branch for function / method body
-max-branches=12
-
-# Maximum number of statements in function / method body
-max-statements=50
-
-# Maximum number of parents for a class (see R0901).
-max-parents=7
-
-# Maximum number of attributes for a class (see R0902).
-max-attributes=7
-
-# Minimum number of public methods for a class (see R0903).
-min-public-methods=2
-
-# Maximum number of public methods for a class (see R0904).
-max-public-methods=20
-
-
-[CLASSES]
-
-# List of method names used to declare (i.e. assign) instance attributes.
-defining-attr-methods=__init__,__new__,setUp
-
-# 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=mcs
-
-# List of member names, which should be excluded from the protected access
-# warning.
-exclude-protected=_asdict,_fields,_replace,_source,_make
-
-
-[EXCEPTIONS]
-
-# Exceptions that will emit a warning when being caught. Defaults to
-# "Exception"
-overgeneral-exceptions=Exception
diff --git a/.testing.pylintrc b/.testing.pylintrc
deleted file mode 100644
index 1cb63d0..0000000
--- a/.testing.pylintrc
+++ /dev/null
@@ -1,469 +0,0 @@
-[MASTER]
-
-# Specify a configuration file.
-#rcfile=
-
-# Python code to execute, usually for sys.path manipulation such as
-# pygtk.require().
-#init-hook=
-
-# Profiled execution.
-profile=no
-
-# Add files or directories to the blacklist. They should be base names, not
-# paths.
-ignore=CVS
-
-# Pickle collected data for later comparisons.
-persistent=no
-
-# List of plugins (as comma separated values of python modules names) to load,
-# usually to register additional checkers.
-load-plugins=saltpylint.pep8,
- saltpylint.pep263,
- saltpylint.strings,
- saltpylint.fileperms,
- saltpylint.smartup,
-
-# Use multiple processes to speed up Pylint.
-jobs=1
-
-# Allow loading of arbitrary C extensions. Extensions are imported into the
-# active Python interpreter and may run arbitrary code.
-unsafe-load-any-extension=no
-
-# 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-whitelist=
-
-# Fileperms Lint Plugin Settings
-fileperms-default=0o644
-fileperms-ignore-paths=setup.py
-
-[MESSAGES CONTROL]
-
-# Only show warnings with the listed confidence levels. Leave empty to show
-# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED
-confidence=
-
-# 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. See also the "--disable" option for examples.
-#enable=
-
-# 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 reenable 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=
-disable=R,
- I0011,
- I0012,
- I0013,
- E1101,
- E1103,
- C0102,
- C0103,
- C0111,
- C0203,
- C0204,
- C0301,
- C0302,
- C0330,
- W0110,
- W0122,
- W0142,
- W0201,
- W0212,
- W0404,
- W0511,
- W0603,
- W0612,
- W0613,
- W0621,
- W0622,
- W0631,
- W0704,
- W1202,
- W1307,
- F0220,
- F0401,
- E8501,
- E8116,
- E8121,
- E8122,
- E8123,
- E8124,
- E8125,
- E8126,
- E8127,
- E8128,
- E8129,
- E8131,
- E8265,
- E8266,
- E8402,
- E8731,
- locally-disabled,
- repr-flag-used-in-string,
- un-indexed-curly-braces-error,
- un-indexed-curly-braces-warning
-
-# Disabled:
-# R* [refactoring suggestions & reports]
-# I0011 (locally-disabling)
-# I0012 (locally-enabling)
-# I0013 (file-ignored)
-# E1101 (no-member) [pylint isn't smart enough]
-# E1103 (maybe-no-member)
-# C0102 (blacklisted-name) [because it activates C0103 too]
-# C0103 (invalid-name)
-# C0111 (missing-docstring)
-# C0203 (bad-mcs-method-argument)
-# C0204 (bad-mcs-classmethod-argument)
-# C0301 (line-too-long)
-# C0302 (too-many-lines)
-# C0330 (bad-continuation)
-# W0110 (deprecated-lambda)
-# W0122 (exec-statement)
-# W0142 (star-args)
-# W0201 (attribute-defined-outside-init) [done in several places in the codebase]
-# W0212 (protected-access)
-# W0404 (reimported) [done intentionally for legit reasons]
-# W0511 (fixme) [several outstanding instances currently in the codebase]
-# W0603 (global-statement)
-# W0612 (unused-variable) [unused return values]
-# W0613 (unused-argument)
-# W0621 (redefined-outer-name)
-# W0622 (redefined-builtin) [many parameter names shadow builtins]
-# W0631 (undefined-loop-variable) [~3 instances, seem to be okay]
-# W0704 (pointless-except) [misnomer; "ignores the exception" rather than "pointless"]
-# F0220 (unresolved-interface)
-# F0401 (import-error)
-# W1202 (logging-format-interpolation) Use % formatting in logging functions but pass the % parameters as arguments
-# W1307 (invalid-format-index) Using invalid lookup key '%s' in format specifier "0['%s']"
-#
-# E8116 PEP8 E116: unexpected indentation (comment)
-# E812* All PEP8 E12*
-# E8265 PEP8 E265 - block comment should start with "# "
-# E8266 PEP8 E266 - too many leading '#' for block comment
-# E8501 PEP8 line too long
-# E8402 module level import not at top of file
-# E8731 do not assign a lambda expression, use a def
-#
-# E1322(repr-flag-used-in-string)
-
-[REPORTS]
-
-# Set the output format. Available formats are text, parseable, colorized, msvs
-# (visual studio) and html. You can also give a reporter class, eg
-# mypackage.mymodule.MyReporterClass.
-output-format=text
-
-# Put messages in a separate file for each module / package specified on the
-# command line instead of printing them on stdout. Reports (if any) will be
-# written in a file name "pylint_global.[txt|html]".
-files-output=no
-
-# Tells whether to display a full report or only the messages
-reports=no
-
-# Python expression which should return a note less than 10 (10 is the highest
-# note). You have access to the variables errors warning, statement which
-# respectively contain the number of errors / warnings messages and the total
-# number of statements analyzed. This is used by the global evaluation report
-# (RP0004).
-evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
-
-# Add a comment according to your evaluation note. This is used by the global
-# evaluation report (RP0004).
-comment=no
-
-# 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=
-msg-template='{path}:{line}: [{msg_id}({symbol}), {obj}] {msg}'
-
-[LOGGING]
-
-# Logging modules to check that the string format arguments are in logging
-# function parameter format
-logging-modules=logging
-
-
-[SPELLING]
-
-# Spelling dictionary name. Available dictionaries: none. To make it working
-# install python-enchant package.
-spelling-dict=
-
-# List of comma separated words that should not be checked.
-spelling-ignore-words=
-
-# A path to a file that contains private dictionary; one word per line.
-spelling-private-dict-file=
-
-# Tells whether to store unknown words to indicated private dictionary in
-# --spelling-private-dict-file option instead of raising a message.
-spelling-store-unknown-words=no
-
-
-[SIMILARITIES]
-
-# Minimum lines number of a similarity.
-min-similarity-lines=4
-
-# Ignore comments when computing similarities.
-ignore-comments=yes
-
-# Ignore docstrings when computing similarities.
-ignore-docstrings=yes
-
-# Ignore imports when computing similarities.
-ignore-imports=no
-
-
-[VARIABLES]
-
-# Tells whether we should check for unused import in __init__ files.
-init-import=no
-
-# A regular expression matching the name of dummy variables (i.e. expectedly
-# not used).
-dummy-variables-rgx=_$|dummy
-
-# List of additional names supposed to be defined in builtins. Remember that
-# you should avoid to define new builtins when possible.
-additional-builtins=__opts__,__virtual__,__salt_system_encoding__
-
-# 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
-
-
-[MISCELLANEOUS]
-
-# List of note tags to take in consideration, separated by a comma.
-notes=FIXME,XXX,TODO
-
-
-[BASIC]
-
-# List of builtins function names that should not be used, separated by a comma
-bad-functions=map,filter,input
-
-# Good variable names which should always be accepted, separated by a comma
-good-names=i,j,k,ex,Run,_,log,pytest_plugins
-
-# Bad variable names which should always be refused, separated by a comma
-bad-names=foo,bar,baz,toto,tutu,tata
-
-# Colon-delimited sets of names that determine each other's naming style when
-# the name regexes allow several styles.
-name-group=
-
-# Include a hint for the correct naming format with invalid-name
-include-naming-hint=no
-
-# Regular expression matching correct function names
-function-rgx=[a-z_][a-z0-9_]{2,60}$
-
-# Naming hint for function names
-function-name-hint=[a-z_][a-z0-9_]{2,60}$
-
-# Regular expression matching correct variable names
-variable-rgx=[a-z_][a-z0-9_]{2,60}$
-
-# Naming hint for variable names
-variable-name-hint=[a-z_][a-z0-9_]{2,60}$
-
-# Regular expression matching correct constant names
-const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
-
-# Naming hint for constant names
-const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$
-
-# Regular expression matching correct attribute names
-attr-rgx=[a-z_][a-z0-9_]{2,60}$
-
-# Naming hint for attribute names
-attr-name-hint=[a-z_][a-z0-9_]{2,60}$
-
-# Regular expression matching correct argument names
-argument-rgx=[a-z_][a-z0-9_]{2,60}$
-
-# Naming hint for argument names
-argument-name-hint=[a-z_][a-z0-9_]{2,60}$
-
-# Regular expression matching correct class attribute names
-class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,60}|(__.*__))$
-
-# Naming hint for class attribute names
-class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,60}|(__.*__))$
-
-# Regular expression matching correct inline iteration names
-inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
-
-# Naming hint for inline iteration names
-inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$
-
-# Regular expression matching correct class names
-class-rgx=[A-Z_][a-zA-Z0-9]+$
-
-# Naming hint for class names
-class-name-hint=[A-Z_][a-zA-Z0-9]+$
-
-# Regular expression matching correct module names
-module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
-
-# Naming hint for module names
-module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
-
-# Regular expression matching correct method names
-method-rgx=[a-z_][a-z0-9_]{2,60}$
-
-# Naming hint for method names
-method-name-hint=[a-z_][a-z0-9_]{2,60}$
-
-# Regular expression which should only match function or class names that do
-# not require a docstring.
-no-docstring-rgx=__.*__
-
-# Minimum line length for functions/classes that require docstrings, shorter
-# ones are exempt.
-docstring-min-length=-1
-
-
-[FORMAT]
-
-# Maximum number of characters on a single line.
-max-line-length=120
-
-# Regexp for a line that is allowed to be longer than the limit.
-ignore-long-lines=^\s*(# )?<?https?://\S+>?$
-
-# 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
-
-# List of optional constructs for which whitespace checking is disabled
-no-space-check=trailing-comma,dict-separator
-
-# Maximum number of lines in a module
-max-module-lines=1000
-
-# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
-# tab).
-indent-string=' '
-
-# Number of spaces of indent required inside a hanging or continued line.
-indent-after-paren=4
-
-# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
-expected-line-ending-format=LF
-
-
-[TYPECHECK]
-
-# Tells whether missing members accessed in mixin class should be ignored. A
-# mixin class is detected if its name ends with "mixin" (case insensitive).
-ignore-mixin-members=yes
-
-# 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
-ignored-modules=
-
-# List of classes names for which member attributes should not be checked
-# (useful for classes with attributes dynamically set).
-ignored-classes=
-
-# When zope mode is activated, add a predefined set of Zope acquired attributes
-# to generated-members.
-zope=no
-
-# List of members which are set dynamically and missed by pylint inference
-# system, and so shouldn't trigger E0201 when accessed. Python regular
-# expressions are accepted.
-generated-members=
-
-
-[IMPORTS]
-
-# Deprecated modules which should not be used, separated by a comma
-deprecated-modules=regsub,TERMIOS,Bastion,rexec
-
-# Create a graph of every (i.e. internal and external) dependencies in the
-# given file (report RP0402 must not be disabled)
-import-graph=
-
-# Create a graph of external dependencies in the given file (report RP0402 must
-# not be disabled)
-ext-import-graph=
-
-# Create a graph of internal dependencies in the given file (report RP0402 must
-# not be disabled)
-int-import-graph=
-
-
-[DESIGN]
-
-# Maximum number of arguments for function / method
-max-args=5
-
-# Argument names that match this expression will be ignored. Default to name
-# with leading underscore
-ignored-argument-names=_.*
-
-# Maximum number of locals for function / method body
-max-locals=15
-
-# Maximum number of return / yield for function / method body
-max-returns=6
-
-# Maximum number of branch for function / method body
-max-branches=12
-
-# Maximum number of statements in function / method body
-max-statements=50
-
-# Maximum number of parents for a class (see R0901).
-max-parents=7
-
-# Maximum number of attributes for a class (see R0902).
-max-attributes=7
-
-# Minimum number of public methods for a class (see R0903).
-min-public-methods=2
-
-# Maximum number of public methods for a class (see R0904).
-max-public-methods=20
-
-
-[CLASSES]
-
-# List of method names used to declare (i.e. assign) instance attributes.
-defining-attr-methods=__init__,__new__,setUp
-
-# 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=mcs
-
-# List of member names, which should be excluded from the protected access
-# warning.
-exclude-protected=_asdict,_fields,_replace,_source,_make
-
-
-[EXCEPTIONS]
-
-# Exceptions that will emit a warning when being caught. Defaults to
-# "Exception"
-overgeneral-exceptions=Exception
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index 5efafb6..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "{}"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright 2015-2018 SaltStack Team
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
diff --git a/MANIFEST.in b/MANIFEST.in
index fc8090f..b4db1f1 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,2 +1,3 @@
include versioneer.py
include pytestsalt/_version.py
+include pytestsalt/salt/coverage/sitecustomize.py
diff --git a/PKG-INFO b/PKG-INFO
index 73c164e..844f234 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.2
Name: pytest-salt
-Version: 2019.6.13
+Version: 2020.1.27
Summary: Pytest Salt Plugin
Home-page: https://github.com/saltstack/pytest-salt
Author: Pedro Algarvio
diff --git a/debian/changelog b/debian/changelog
index b63e49b..ca8a084 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+pytest-salt (2020.1.27-1) UNRELEASED; urgency=low
+
+ * New upstream release.
+
+ -- Debian Janitor <janitor@jelmer.uk> Wed, 16 Mar 2022 18:26:33 -0000
+
pytest-salt (2019.6.13-1) unstable; urgency=medium
* New upstream version
diff --git a/pytest_salt.egg-info/PKG-INFO b/pytest_salt.egg-info/PKG-INFO
index 73c164e..844f234 100644
--- a/pytest_salt.egg-info/PKG-INFO
+++ b/pytest_salt.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.2
Name: pytest-salt
-Version: 2019.6.13
+Version: 2020.1.27
Summary: Pytest Salt Plugin
Home-page: https://github.com/saltstack/pytest-salt
Author: Pedro Algarvio
diff --git a/pytest_salt.egg-info/SOURCES.txt b/pytest_salt.egg-info/SOURCES.txt
index 1dbf06b..15cc651 100644
--- a/pytest_salt.egg-info/SOURCES.txt
+++ b/pytest_salt.egg-info/SOURCES.txt
@@ -1,12 +1,7 @@
-.gitignore
-.pylintrc
-.testing.pylintrc
-LICENSE
MANIFEST.in
README.rst
setup.cfg
setup.py
-tox.ini
versioneer.py
pytest_salt.egg-info/PKG-INFO
pytest_salt.egg-info/SOURCES.txt
@@ -25,6 +20,7 @@ pytestsalt/fixtures/ports.py
pytestsalt/fixtures/stats.py
pytestsalt/salt/__init__.py
pytestsalt/salt/loader.py
+pytestsalt/salt/coverage/sitecustomize.py
pytestsalt/salt/engines/__init__.py
pytestsalt/salt/engines/pytest_engine.py
pytestsalt/salt/log_handlers/__init__.py
@@ -33,8 +29,4 @@ pytestsalt/utils/__init__.py
pytestsalt/utils/cli_scripts.py
pytestsalt/utils/compat.py
pytestsalt/utils/log_server_asyncio.py
-pytestsalt/utils/log_server_tornado.py
-tests/conftest.py
-tests/test_salt_call.py
-tests/test_salt_master.py
-tests/test_salt_minion.py
\ No newline at end of file
+pytestsalt/utils/log_server_tornado.py
\ No newline at end of file
diff --git a/pytestsalt/_version.py b/pytestsalt/_version.py
index 762b06f..f34e548 100644
--- a/pytestsalt/_version.py
+++ b/pytestsalt/_version.py
@@ -9,11 +9,11 @@ import json
version_json = '''
{
- "date": "2019-06-12T13:32:25+0100",
+ "date": "2020-01-27T20:17:50+0000",
"dirty": false,
"error": null,
- "full-revisionid": "5d8883b10459d2ec7fe65566a1d773b936bec649",
- "version": "2019.6.13"
+ "full-revisionid": "58f5e95c05fa41df9f471772664839226610d5af",
+ "version": "2020.1.27"
}
''' # END VERSION_JSON
diff --git a/pytestsalt/fixtures/config.py b/pytestsalt/fixtures/config.py
index a211532..88dc0c4 100644
--- a/pytestsalt/fixtures/config.py
+++ b/pytestsalt/fixtures/config.py
@@ -783,12 +783,16 @@ def apply_master_config(default_options,
if 'engines_dirs' not in default_options:
default_options['engines_dirs'] = []
- default_options['engines_dirs'].insert(0, engines_dir)
+ if engines_dir not in default_options['engines']:
+ default_options['engines_dirs'].insert(0, engines_dir)
+
default_options['pytest_engine_port'] = engine_port
if 'log_handlers_dirs' not in default_options:
default_options['log_handlers_dirs'] = []
- default_options['log_handlers_dirs'].insert(0, log_handlers_dir)
+
+ if log_handlers_dir not in default_options['log_handlers_dirs']:
+ default_options['log_handlers_dirs'].insert(0, log_handlers_dir)
default_options['pytest_log_host'] = 'localhost'
default_options['pytest_log_port'] = log_server_port
@@ -800,9 +804,9 @@ def apply_master_config(default_options,
# Apply it!
dictupdate.update(default_options, direct_overrides, merge_lists=True)
- log.info('Writing to configuration file %s. Configuration:\n%s',
- config_file,
- pprint.pformat(default_options))
+ log.debug('Writing to configuration file %s. Configuration:\n%s',
+ config_file,
+ pprint.pformat(default_options))
# Write down the computed configuration into the config file
with compat.fopen(config_file, 'w') as wfh:
@@ -1146,7 +1150,9 @@ def apply_minion_config(default_options,
if 'log_handlers_dirs' not in default_options:
default_options['log_handlers_dirs'] = []
- default_options['log_handlers_dirs'].insert(0, log_handlers_dir)
+
+ if log_handlers_dir not in default_options['log_handlers_dirs']:
+ default_options['log_handlers_dirs'].insert(0, log_handlers_dir)
default_options['pytest_log_host'] = 'localhost'
default_options['pytest_log_port'] = log_server_port
@@ -1158,9 +1164,9 @@ def apply_minion_config(default_options,
# Apply it!
dictupdate.update(default_options, direct_overrides, merge_lists=True)
- log.info('Writing to configuration file %s. Configuration:\n%s',
- config_file,
- pprint.pformat(default_options))
+ log.debug('Writing to configuration file %s. Configuration:\n%s',
+ config_file,
+ pprint.pformat(default_options))
# Write down the computed configuration into the config file
with compat.fopen(config_file, 'w') as wfh:
@@ -1261,7 +1267,9 @@ def apply_proxy_config(default_options,
if 'log_handlers_dirs' not in default_options:
default_options['log_handlers_dirs'] = []
- default_options['log_handlers_dirs'].insert(0, log_handlers_dir)
+
+ if log_handlers_dir not in default_options['log_handlers_dirs']:
+ default_options['log_handlers_dirs'].insert(0, log_handlers_dir)
default_options['pytest_log_host'] = 'localhost'
default_options['pytest_log_port'] = log_server_port
@@ -1273,9 +1281,9 @@ def apply_proxy_config(default_options,
# Apply it!
dictupdate.update(default_options, direct_overrides, merge_lists=True)
- log.info('Writing to configuration file %s. Configuration:\n%s',
- config_file,
- pprint.pformat(default_options))
+ log.debug('Writing to configuration file %s. Configuration:\n%s',
+ config_file,
+ pprint.pformat(default_options))
# Write down the computed configuration into the config file
with compat.fopen(config_file, 'w') as wfh:
@@ -1499,9 +1507,9 @@ def apply_syndic_config(syndic_default_options,
syndic_master_config_file = syndic_conf_dir.join('master').realpath().strpath
# Write down the master computed configuration into the config file
- log.info('Writing to configuration file %s. Configuration:\n%s',
- syndic_master_config_file,
- pprint.pformat(master_config))
+ log.debug('Writing to configuration file %s. Configuration:\n%s',
+ syndic_master_config_file,
+ pprint.pformat(master_config))
with compat.fopen(syndic_master_config_file, 'w') as wfh:
yamlserialize.safe_dump(master_config, wfh, default_flow_style=False)
diff --git a/pytestsalt/fixtures/daemons.py b/pytestsalt/fixtures/daemons.py
index 3c9cc7c..71e6173 100644
--- a/pytestsalt/fixtures/daemons.py
+++ b/pytestsalt/fixtures/daemons.py
@@ -1580,14 +1580,9 @@ class SaltMinion(SaltDaemonScriptBase):
return script_args
def get_check_events(self):
- if sys.platform.startswith('win'):
- return super(SaltMinion, self).get_check_events()
return set(['salt/{}/{}/start'.format(self.config['__role'], self.config['id'])])
def get_check_ports(self):
- if sys.platform.startswith('win'):
- return set([self.config['tcp_pub_port'],
- self.config['tcp_pull_port']])
return super(SaltMinion, self).get_check_ports()
@@ -1605,14 +1600,9 @@ class SaltProxy(SaltDaemonScriptBase):
return script_args
def get_check_events(self):
- if sys.platform.startswith('win'):
- return super(SaltProxy, self).get_check_events()
return set(['salt/{}/{}/start'.format(self.config['__role'], self.config['id'])])
def get_check_ports(self):
- if sys.platform.startswith('win'):
- return set([self.config['tcp_pub_port'],
- self.config['tcp_pull_port']])
return super(SaltProxy, self).get_check_ports()
@@ -1625,14 +1615,9 @@ class SaltMaster(SaltDaemonScriptBase):
return ['-l', 'quiet']
def get_check_events(self):
- if sys.platform.startswith('win'):
- return super(SaltMaster, self).get_check_events()
return set(['salt/{}/{}/start'.format(self.config['__role'], self.config['id'])])
def get_check_ports(self):
- if sys.platform.startswith('win'):
- return set([self.config['ret_port'],
- self.config['publish_port']])
return super(SaltMaster, self).get_check_ports()
diff --git a/pytestsalt/fixtures/stats.py b/pytestsalt/fixtures/stats.py
index 821846d..cedb149 100644
--- a/pytestsalt/fixtures/stats.py
+++ b/pytestsalt/fixtures/stats.py
@@ -25,6 +25,13 @@ IS_WINDOWS = sys.platform.startswith('win')
class SaltTerminalReporter(TerminalReporter):
def __init__(self, config):
TerminalReporter.__init__(self, config)
+ self._session = None
+ self._show_sys_stats = config.getoption('--sys-stats') is True
+ self._sys_stats_no_children = config.getoption('--sys-stats-no-children') is True
+ if config.getoption('--sys-stats-uss-mem') is True:
+ self._sys_stats_mem_type = 'uss'
+ else:
+ self._sys_stats_mem_type = 'rss'
@pytest.hookimpl(trylast=True)
def pytest_sessionstart(self, session):
@@ -35,39 +42,76 @@ class SaltTerminalReporter(TerminalReporter):
TerminalReporter.pytest_runtest_logreport(self, report)
if self.verbosity <= 0:
return
+
if report.when != 'call':
return
- if self.config.getoption('--sys-stats') is False:
+
+ if self._show_sys_stats is False:
return
if self.verbosity > 1:
self.ensure_newline()
self.section('Processes Statistics', sep='-', bold=True)
left_padding = len(max(['System'] + list(self._session.stats_processes), key=len))
- template = ' ...{} {} - CPU: {:6.2f} % MEM: {:6.2f} %'
- if not IS_WINDOWS:
- template += ' SWAP: {:6.2f} %'
+ template = ' ...{dots} {name} - CPU: {cpu:6.2f} % MEM: {mem:6.2f} % (Virtual Memory)'
+
+ stats = {
+ 'name': 'System',
+ 'dots': '.' * (left_padding - len('System')),
+ 'cpu': psutil.cpu_percent(),
+ 'mem': psutil.virtual_memory().percent
+ }
+
+ swap = psutil.swap_memory().percent
+ if swap > 0:
+ template += ' SWAP: {swap:6.2f} %'
+ stats['swap'] = swap
+
template += '\n'
- self.write(
- template.format(
- '.' * (left_padding - len('System')),
- 'System',
- psutil.cpu_percent(),
- psutil.virtual_memory().percent,
- psutil.swap_memory().percent
- )
- )
+ self.write(template.format(**stats))
+
+ template = ' ...{dots} {name} - CPU: {cpu:6.2f} % MEM: {mem:6.2f} % ({m_type})'
+ children_template = template + ' MEM SUM: {c_mem} % ({m_type}) CHILD PROCS: {c_count}\n'
+ no_children_template = template + '\n'
+
for name, psproc in self._session.stats_processes.items():
- with psproc.oneshot():
- cpu = psproc.cpu_percent()
- mem = psproc.memory_percent('vms')
- dots = '.' * (left_padding - len(name))
- if not IS_WINDOWS:
- swap = psproc.memory_percent('swap')
- formatted = template.format(dots, name, cpu, mem, swap)
- else:
- formatted = template.format(dots, name, cpu, mem)
- self.write(formatted)
+ template = no_children_template
+ dots = '.' * (left_padding - len(name))
+ pids = []
+ try:
+ with psproc.oneshot():
+ stats = {
+ 'name': name,
+ 'dots': dots,
+ 'cpu': psproc.cpu_percent(),
+ 'mem': psproc.memory_percent(self._sys_stats_mem_type),
+ 'm_type': self._sys_stats_mem_type.upper()
+ }
+ if self._sys_stats_no_children is False:
+ pids.append(psproc.pid)
+ children = psproc.children(recursive=True)
+ if children:
+ template = children_template
+ stats['c_count'] = 0
+ c_mem = stats['mem']
+ for child in children:
+ if child.pid in pids:
+ continue
+ pids.append(child.pid)
+ if not psutil.pid_exists(child.pid):
+ continue
+ try:
+ c_mem += child.memory_percent(self._sys_stats_mem_type)
+ stats['c_count'] += 1
+ except (psutil.AccessDenied, psutil.NoSuchProcess):
+ continue
+ if stats['c_count']:
+ stats['c_mem'] = '{:6.2f}'.format(c_mem)
+ else:
+ template = no_children_template
+ self.write(template.format(**stats))
+ except psutil.NoSuchProcess:
+ continue
def _get_progress_information_message(self):
msg = TerminalReporter._get_progress_information_message(self)
@@ -99,6 +143,19 @@ def pytest_addoption(parser):
action='store_true',
help='Print System CPU and MEM statistics after each test execution.'
)
+ output_options_group.addoption(
+ '--sys-stats-no-children',
+ default=False,
+ action='store_true',
+ help='Don\'t include child processes memory statistics.'
+ )
+ output_options_group.addoption(
+ '--sys-stats-uss-mem',
+ default=False,
+ action='store_true',
+ help='Use the USS("Unique Set Size", memory unique to a process which would be freed if the process was '
+ 'terminated) memory instead which is more expensive to calculate.'
+ )
@pytest.mark.trylast
diff --git a/pytestsalt/salt/coverage/sitecustomize.py b/pytestsalt/salt/coverage/sitecustomize.py
new file mode 100644
index 0000000..e8500dd
--- /dev/null
+++ b/pytestsalt/salt/coverage/sitecustomize.py
@@ -0,0 +1,6 @@
+# -*- coding: utf-8 -*-
+try:
+ import coverage
+ coverage.process_startup()
+except ImportError:
+ pass
diff --git a/pytestsalt/salt/engines/pytest_engine.py b/pytestsalt/salt/engines/pytest_engine.py
index 7ee9b05..f17b7cc 100644
--- a/pytestsalt/salt/engines/pytest_engine.py
+++ b/pytestsalt/salt/engines/pytest_engine.py
@@ -22,6 +22,10 @@ try:
HAS_SALT_ASYNC = True
except ImportError:
HAS_SALT_ASYNC = False
+try:
+ import salt.ext.six as six
+except ImportError:
+ import six
# Import 3rd-party libs
from tornado import gen
@@ -104,13 +108,40 @@ class PyTestEngine(object):
# 30 seconds should be more than enough to fire these events every second in order
# for pytest-salt to pickup that the master is running
timeout = 30
+ event_bus = None
+ call_destroy = False
+ try:
+ with salt.utils.event.get_master_event(self.opts,
+ self.sock_dir,
+ listen=False) as event_bus:
+ yield self._fire_master_started_event(event_bus,
+ load,
+ master_start_event_tag,
+ timeout)
+ except AttributeError as exc:
+ if '__enter__' not in str(exc):
+ six.reraise(*sys.exc_info())
+ call_destroy = True
+ event_bus = salt.utils.event.get_master_event(self.opts,
+ self.sock_dir,
+ listen=False)
+ yield self._fire_master_started_event(event_bus,
+ load,
+ master_start_event_tag,
+ timeout)
+ finally:
+ if call_destroy and event_bus is not None:
+ event_bus.destroy()
+
+ @gen.coroutine
+ def _fire_master_started_event(self, event_bus, load, tag, timeout):
while True:
if self.stop_sending_events_file and not os.path.exists(self.stop_sending_events_file):
log.info('The stop sending events file "marker" is done. Stop sending events...')
break
timeout -= 1
try:
- event_bus.fire_event(load, master_start_event_tag, timeout=500)
+ event_bus.fire_event(load, tag, timeout=500)
if timeout <= 0:
break
yield gen.sleep(1)
diff --git a/pytestsalt/salt/log_handlers/pytest_log_handler.py b/pytestsalt/salt/log_handlers/pytest_log_handler.py
index a7788a8..80a745f 100644
--- a/pytestsalt/salt/log_handlers/pytest_log_handler.py
+++ b/pytestsalt/salt/log_handlers/pytest_log_handler.py
@@ -18,7 +18,6 @@ from multiprocessing import Queue
import msgpack
# Import Salt libs
-import salt.log.setup
# pylint: disable=no-member,invalid-name
try:
import salt.utils.stringutils
@@ -40,6 +39,9 @@ log = logging.getLogger(__name__)
def __virtual__():
+ if 'log_forwarding_consumer' in __opts__:
+ # New Salt Logging in place. This handler is not needed
+ return False, "New Salt Logging in place. Not loading."
if 'pytest_log_port' not in __opts__:
return False, "'pytest_log_port' not in options"
return True
@@ -83,9 +85,12 @@ def setup_handlers():
# start dropping. This will contain a memory leak in case `process_queue`
# can't process fast enough of in case it can't deliver the log records at all.
queue_size = 10000000
+
+ # Late Imports Because of Salt's logging refactoring
+ from salt.log.setup import SaltLogQueueHandler, LOG_LEVELS
queue = Queue(queue_size)
- handler = salt.log.setup.SaltLogQueueHandler(queue)
- level = salt.log.setup.LOG_LEVELS[(__opts__.get('pytest_log_level') or 'error').lower()]
+ handler = SaltLogQueueHandler(queue)
+ level = LOG_LEVELS[(__opts__.get('pytest_log_level') or 'error').lower()]
handler.setLevel(level)
pytest_log_prefix = os.environ.get('PYTEST_LOG_PREFIX') or __opts__['pytest_log_prefix']
process_queue_thread = threading.Thread(target=process_queue,
@@ -106,7 +111,7 @@ def process_queue(host, port, prefix, queue):
sock.close()
return
- log.warning('Sending log records to Remote log server')
+ log.debug('Sending log records to Remote log server')
while True:
try:
record = queue.get()
diff --git a/pytestsalt/utils/__init__.py b/pytestsalt/utils/__init__.py
index 1a3680a..6b63a58 100644
--- a/pytestsalt/utils/__init__.py
+++ b/pytestsalt/utils/__init__.py
@@ -15,11 +15,13 @@ import json
import time
import errno
import atexit
+import pprint
import signal
import socket
import logging
import subprocess
import threading
+import weakref
from operator import itemgetter
from collections import namedtuple
@@ -34,12 +36,6 @@ except ImportError:
log = logging.getLogger(__name__)
-if sys.platform.startswith('win'):
- SIGINT = SIGTERM = signal.CTRL_BREAK_EVENT # pylint: disable=no-member
-else:
- SIGINT = signal.SIGINT
- SIGTERM = signal.SIGTERM
-
def set_proc_title(title):
if HAS_SETPROCTITLE is False:
@@ -71,7 +67,53 @@ def collect_child_processes(pid):
return children
+def _get_cmdline(proc):
+ # pylint: disable=protected-access
+ try:
+ return proc._cmdline
+ except AttributeError:
+ # Cache the cmdline since that will be inaccessible once the process is terminated
+ # and we use it in log calls
+ try:
+ cmdline = proc.cmdline()
+ except (psutil.NoSuchProcess, psutil.AccessDenied):
+ # OSX is more restrictive about the above information
+ cmdline = None
+ except OSError:
+ # On Windows we've seen something like:
+ # File " c: ... \lib\site-packages\pytestsalt\utils\__init__.py", line 182, in terminate_process
+ # terminate_process_list(process_list, kill=slow_stop is False, slow_stop=slow_stop)
+ # File " c: ... \lib\site-packages\pytestsalt\utils\__init__.py", line 130, in terminate_process_list
+ # _terminate_process_list(process_list, kill=kill, slow_stop=slow_stop)
+ # File " c: ... \lib\site-packages\pytestsalt\utils\__init__.py", line 78, in _terminate_process_list
+ # cmdline = process.cmdline()
+ # File " c: ... \lib\site-packages\psutil\__init__.py", line 786, in cmdline
+ # return self._proc.cmdline()
+ # File " c: ... \lib\site-packages\psutil\_pswindows.py", line 667, in wrapper
+ # return fun(self, *args, **kwargs)
+ # File " c: ... \lib\site-packages\psutil\_pswindows.py", line 745, in cmdline
+ # ret = cext.proc_cmdline(self.pid, use_peb=True)
+ # OSError: [WinError 299] Only part of a ReadProcessMemory or WriteProcessMemory request was completed: 'originated from ReadProcessMemory(ProcessParameters)
+
+ # Late import
+ cmdline = None
+ if not cmdline:
+ try:
+ cmdline = proc.as_dict()
+ except psutil.NoSuchProcess:
+ cmdline = '<could not be retrived; dead process: {}>'.format(proc)
+ except (psutil.AccessDenied, OSError):
+ cmdline = weakref.proxy(proc)
+ proc._cmdline = cmdline
+ return proc._cmdline
+ # pylint: enable=protected-access
+
+
def _terminate_process_list(process_list, kill=False, slow_stop=False):
+ log.info(
+ 'Terminating process list:\n%s',
+ pprint.pformat([_get_cmdline(proc) for proc in process_list])
+ )
for process in process_list[:]: # Iterate over copy of the list
if not psutil.pid_exists(process.pid):
process_list.remove(process)
@@ -80,22 +122,15 @@ def _terminate_process_list(process_list, kill=False, slow_stop=False):
if not kill and process.status() == psutil.STATUS_ZOMBIE:
# Zombie processes will exit once child processes also exit
continue
- try:
- cmdline = process.cmdline()
- except psutil.AccessDenied:
- # OSX is more restrictive about the above information
- cmdline = None
- if not cmdline:
- cmdline = process.as_dict()
if kill:
- log.info('Killing process(%s): %s', process.pid, cmdline)
+ log.info('Killing process(%s): %s', process.pid, _get_cmdline(process))
process.kill()
else:
- log.info('Terminating process(%s): %s', process.pid, cmdline)
+ log.info('Terminating process(%s): %s', process.pid, _get_cmdline(process))
try:
if slow_stop:
# Allow coverage data to be written down to disk
- process.send_signal(SIGTERM)
+ process.send_signal(signal.SIGTERM)
try:
process.wait(2)
except psutil.TimeoutExpired:
@@ -120,19 +155,17 @@ def terminate_process_list(process_list, kill=False, slow_stop=False):
# Try to terminate processes with the provided kill and slow_stop parameters
log.info('Terminating process list. 1st step. kill: %s, slow stop: %s', kill, slow_stop)
- # Cache the cmdline since that will be inaccessible once the process is terminated
- for proc in process_list:
- try:
- cmdline = proc.cmdline()
- except (psutil.NoSuchProcess, psutil.AccessDenied):
- # OSX is more restrictive about the above information
- cmdline = None
- if not cmdline:
- try:
- cmdline = proc
- except (psutil.NoSuchProcess, psutil.AccessDenied):
- cmdline = '<could not be retrived; dead process: {}>'.format(proc)
- proc._cmdline = cmdline
+ # Remove duplicates from the process list
+ seen_pids = []
+ start_count = len(process_list)
+ for proc in process_list[:]:
+ if proc.pid in seen_pids:
+ process_list.remove(proc)
+ seen_pids.append(proc.pid)
+ end_count = len(process_list)
+ if end_count < start_count:
+ log.debug('Removed %d duplicates from the initial process list', start_count - end_count)
+
_terminate_process_list(process_list, kill=kill, slow_stop=slow_stop)
psutil.wait_procs(process_list, timeout=15, callback=on_process_terminated)
@@ -153,14 +186,16 @@ def terminate_process_list(process_list, kill=False, slow_stop=False):
log.warning('Some processes failed to properly terminate: %s', process_list)
-def terminate_process(pid=None, process=None, children=None, kill_children=False, slow_stop=False):
+def terminate_process(pid=None, process=None, children=None, kill_children=None, slow_stop=False):
'''
Try to terminate/kill the started processe
'''
children = children or []
process_list = []
- # Always kill children if kill the parent process.
- kill_children = True if slow_stop is False else kill_children
+
+ if kill_children is None:
+ # Always kill children if kill the parent process and kill_children was not set
+ kill_children = True if slow_stop is False else kill_children
if pid and not process:
try:
@@ -172,11 +207,7 @@ def terminate_process(pid=None, process=None, children=None, kill_children=False
if kill_children:
if process:
- if not children:
- children = collect_child_processes(process.pid)
- else:
- # Let's collect children again since there might be new ones
- children.extend(collect_child_processes(pid))
+ children.extend(collect_child_processes(pid))
if children:
process_list.extend(children)
@@ -260,12 +291,11 @@ def start_daemon(request,
log.info('[%s] pytest %s(%s) stopped', daemon_log_prefix, daemon_name, daemon_id)
request.addfinalizer(stop_daemon)
- return process
+ break
else:
terminate_process(process.pid, kill_children=True, slow_stop=slow_stop)
continue
- else: # pylint: disable=useless-else-on-loop
- # Wrong, we have a return, its not useless
+ else:
if process is not None:
terminate_process(process.pid, kill_children=True, slow_stop=slow_stop)
fail_method(
@@ -275,6 +305,7 @@ def start_daemon(request,
attempts-1
)
)
+ return process
class SaltScriptBase(object):
@@ -306,7 +337,7 @@ class SaltScriptBase(object):
self.cli_script_name = cli_script_name
if self.cli_display_name is None:
self.cli_display_name = '{}({})'.format(self.__class__.__name__,
- self.cli_script_name)
+ self.cli_script_name)
self.slow_stop = slow_stop
self.environ = environ or os.environ.copy()
self.cwd = cwd or os.getcwd()
@@ -476,15 +507,13 @@ class SaltDaemonScriptBase(SaltScriptBase):
'''
Blocking call to wait for the daemon to start listening
'''
- # Late import
- import salt.ext.six as six
if self._connectable.is_set():
return True
expire = time.time() + timeout
check_ports = self.get_check_ports()
if check_ports:
- log.debug(
+ log.info(
'[%s][%s] Checking the following ports to assure running status: %s',
self.log_prefix,
self.cli_display_name,
@@ -492,80 +521,66 @@ class SaltDaemonScriptBase(SaltScriptBase):
)
check_events = self.get_check_events()
if check_events:
- log.debug(
+ log.info(
'[%s][%s] Checking the following event tags to assure running status: %s',
self.log_prefix,
self.cli_display_name,
check_events
)
log.debug('Wait until running expire: %s Timeout: %s Current Time: %s', expire, timeout, time.time())
- event_listener = EventListener(
- self.event_listener_config_dir or self.config_dir,
- self.log_prefix
- )
- try:
- while True:
- if self._running.is_set() is False:
- # No longer running, break
- log.warning('No longer running!')
- break
-
- if time.time() > expire:
- # Timeout, break
- log.debug('Expired at %s(was set to %s)', time.time(), expire)
- break
-
- if not check_ports and not check_events:
- self._connectable.set()
- break
-
- if check_events:
- for tag in event_listener.wait_for_events(check_events, timeout=timeout - 0.5):
- check_events.remove(tag)
-
- if not check_events:
- stop_sending_events_file = self.config.get('pytest_stop_sending_events_file')
- if stop_sending_events_file and os.path.exists(stop_sending_events_file):
- log.warning('Removing pytest_stop_sending_events_file: %s', stop_sending_events_file)
- os.unlink(stop_sending_events_file)
-
- for port in set(check_ports):
- if isinstance(port, int):
- log.debug('[%s][%s] Checking connectable status on port: %s',
- self.log_prefix,
- self.cli_display_name,
- port)
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- conn = sock.connect_ex(('localhost', port))
- try:
- if conn == 0:
- log.debug('[%s][%s] Port %s is connectable!',
- self.log_prefix,
- self.cli_display_name,
- port)
- check_ports.remove(port)
- sock.shutdown(socket.SHUT_RDWR)
- except socket.error:
- continue
- finally:
- sock.close()
- del sock
- elif isinstance(port, six.string_types):
- salt_run = self.get_salt_run_fixture()
- minions_joined = salt_run.run('manage.joined')
- if minions_joined.exitcode == 0:
- if minions_joined.json and port in minions_joined.json:
- check_ports.remove(port)
- log.warning('Removed ID %r Still left: %r', port, check_ports)
- elif minions_joined.json is None:
- log.debug('salt-run manage.join did not return any valid JSON: %s', minions_joined)
- time.sleep(0.5)
- except KeyboardInterrupt:
- return self._connectable.is_set()
- finally:
- event_listener.terminate()
+ with EventListener(self.event_listener_config_dir or self.config_dir, self.log_prefix) as event_listener:
+ try:
+ while True:
+ if self._running.is_set() is False:
+ # No longer running, break
+ log.warning('No longer running!')
+ break
+
+ if time.time() > expire:
+ # Timeout, break
+ log.warning('Wait until running expired at %s(was set to %s)', time.time(), expire)
+ break
+
+ if not check_ports and not check_events:
+ self._connectable.set()
+ break
+
+ if check_events:
+ for tag in event_listener.wait_for_events(check_events, timeout=timeout - 0.5):
+ check_events.remove(tag)
+
+ if not check_events:
+ stop_sending_events_file = self.config.get('pytest_stop_sending_events_file')
+ if stop_sending_events_file and os.path.exists(stop_sending_events_file):
+ log.info('Removing pytest_stop_sending_events_file: %s', stop_sending_events_file)
+ os.unlink(stop_sending_events_file)
+
+ for port in set(check_ports):
+ if isinstance(port, int):
+ log.debug('[%s][%s] Checking connectable status on port: %s',
+ self.log_prefix,
+ self.cli_display_name,
+ port)
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ conn = sock.connect_ex(('localhost', port))
+ try:
+ if conn == 0:
+ log.debug('[%s][%s] Port %s is connectable!',
+ self.log_prefix,
+ self.cli_display_name,
+ port)
+ check_ports.remove(port)
+ sock.shutdown(socket.SHUT_RDWR)
+ except socket.error:
+ continue
+ finally:
+ sock.close()
+ del sock
+ time.sleep(0.5)
+ except KeyboardInterrupt:
+ pass
if self._connectable.is_set():
- log.debug('[%s][%s] All ports checked. Running!', self.log_prefix, self.cli_display_name)
+ log.info('[%s][%s] All ports checked. Running!', self.log_prefix, self.cli_display_name)
return self._connectable.is_set()
@@ -579,8 +594,8 @@ class ShellResult(namedtuple('Result', ('exitcode', 'stdout', 'stderr', 'json'))
'''
__slots__ = ()
- def __new__(cls, exitcode, stdout, stderr, json):
- return super(ShellResult, cls).__new__(cls, exitcode, stdout, stderr, json)
+ def __new__(cls, exitcode, stdout, stderr, _json):
+ return super(ShellResult, cls).__new__(cls, exitcode, stdout, stderr, _json)
# These are copied from the namedtuple verbose output in order to quiet down PyLint
exitcode = property(itemgetter(0), doc='Alias for field number 0')
@@ -695,8 +710,8 @@ class SaltCliScriptBase(SaltScriptBase):
args,
kwargs,
'[{}][{}] Timed out after {} seconds!'.format(self.log_prefix,
- self.cli_display_name,
- timeout)
+ self.cli_display_name,
+ timeout)
)
)
except (SystemExit, KeyboardInterrupt):
@@ -729,145 +744,7 @@ class SaltCliScriptBase(SaltScriptBase):
return stdout, stderr, json_out
-class SaltRunEventListener(SaltCliScriptBase):
- '''
- Class which runs 'salt-run state.event *' to match agaist a provided set of event tags
- '''
-
- EVENT_MATCH_RE = re.compile(r'^(?P<tag>[\w/-]+)(?:[\s]+)(?P<data>[\S\W]+)$')
-
- def get_base_script_args(self):
- return SaltScriptBase.get_base_script_args(self)
-
- def get_script_args(self): # pylint: disable=no-self-use
- '''
- Returns any additional arguments to pass to the CLI script
- '''
- return ['state.event']
-
- def run(self, tags=(), timeout=10): # pylint: disable=arguments-differ
- '''
- Run the given command synchronously
- '''
- log.info('%s checking for tags: %s', self.__class__.__name__, tags)
- # Late import
- import salt.ext.six as six
- exitcode = 0
- timeout_expire = time.time() + timeout
- environ = self.environ.copy()
- environ['PYTEST_LOG_PREFIX'] = '{}[EventListen]'.format(self.log_prefix)
- environ['PYTHONUNBUFFERED'] = '1'
- proc_args = [
- self.get_script_path(self.cli_script_name)
- ] + self.get_base_script_args() + self.get_script_args()
-
- if sys.platform.startswith('win'):
- # Windows needs the python executable to come first
- proc_args.insert(0, sys.executable)
-
- log.info('[%s][%s] Running \'%s\' in CWD: %s...',
- self.log_prefix, self.cli_display_name, ' '.join(proc_args), self.cwd)
-
- to_match_events = set(tags)
- matched_events = {}
-
- terminal = self.init_terminal(proc_args,
- cwd=self.cwd,
- env=environ,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
-
- # Consume the output
- stdout = six.b('')
- stderr = six.b('')
-
- process_output = six.b('')
- events_processed = 0
- try:
- while True:
- time.sleep(0.5)
- if terminal.stdout is not None:
- try:
- out = terminal.recv(4096)
- except IOError:
- out = six.b('')
- if out:
- stdout += out
- process_output += out
- if terminal.stderr is not None:
- try:
- err = terminal.recv_err(4096)
- except IOError:
- err = ''
- if err:
- stderr += err
- if out is None and err is None:
- if to_match_events:
- exitcode = 1
- log.warning('[%s][%s] Premature exit?! Failed to find all of the required event tags. '
- 'Total events processed: %s',
- self.log_prefix,
- self.cli_display_name,
- events_processed)
- break
-
- if process_output:
- lines = process_output.split(b'}\n')
- if lines[-1] != b'':
- process_output = lines.pop()
- else:
- process_output = six.b('')
- lines.pop()
- for line in lines:
- match = self.EVENT_MATCH_RE.match(line.decode(__salt_system_encoding__)) # pylint: disable=undefined-variable
- if match:
- events_processed += 1
- tag, data = match.groups()
- if tag in to_match_events:
- matched_events[tag] = json.loads(data + '}')
- to_match_events.remove(tag)
-
- log.info('[%s][%s] Events processed so far: %d',
- self.log_prefix,
- self.cli_display_name,
- events_processed)
-
- if not to_match_events:
- log.debug('[%s][%s] ALL EVENT TAGS FOUND!!!', self.log_prefix, self.cli_display_name)
- break
-
- if timeout_expire < time.time():
- log.warning('[%s][%s] Failed to find all of the required event tags. Total events processed: %s',
- self.log_prefix,
- self.cli_display_name,
- events_processed)
- exitcode = 1
- break
- except (SystemExit, KeyboardInterrupt):
- pass
- finally:
- self.terminate()
-
- if six.PY3:
- # pylint: disable=undefined-variable
- stdout = stdout.decode(__salt_system_encoding__)
- stderr = stderr.decode(__salt_system_encoding__)
- # pylint: enable=undefined-variable
-
- if to_match_events:
- stop_sending_events_file = self.config.get('pytest_stop_sending_events_file')
- if stop_sending_events_file and os.path.exists(stop_sending_events_file):
- log.warning('Removing pytest_stop_sending_events_file: %s', stop_sending_events_file)
- os.unlink(stop_sending_events_file)
-
- json_out = {
- 'matched': matched_events,
- 'unmatched': to_match_events
- }
- return ShellResult(exitcode, stdout, stderr, json_out)
-
-
-class EventListener:
+class EventListener(object):
DEFAULT_TIMEOUT = 60
@@ -888,6 +765,8 @@ class EventListener:
events_to_match = set(check_events)
events_processed = 0
max_timeout = time.time() + timeout
+ last_log = 0
+ log_freq = 10
while True:
if not events_to_match:
log.info('%s ALL EVENT TAGS FOUND!!!', self.log_prefix)
@@ -895,42 +774,50 @@ class EventListener:
if time.time() > max_timeout:
log.warning(
- '%s Failed to find all of the required event tags. '
- 'Total events processed: %s',
+ '%s Failed to find all of the required event tags(%s). '
+ 'Total events processed: %s. Total events found: %s.',
self.log_prefix,
- events_processed
+ check_events,
+ events_processed,
+ len(matched_events)
)
return matched_events
- event = self.listener.get_event(full=True, auto_reconnect=True)
+ event = self._listener.get_event(full=True, auto_reconnect=True)
if event is None:
continue
tag = event['tag']
- log.warning('Got event: %s', event)
+ log.info('Got event: %s', event)
if tag in events_to_match:
matched_events.add(tag)
events_to_match.remove(tag)
events_processed += 1
- log.info('%s Events processed so far: %d',
- self.log_prefix,
- events_processed)
+ if time.time() - last_log > log_freq:
+ log.debug('%s Events processed so far: %d',
+ self.log_prefix,
+ events_processed)
+ last_log = time.time()
def terminate(self):
- listener = self.listener
- self._listener = None
- listener.destroy()
+ if self._listener is not None:
+ listener = self._listener
+ self._listener = None
+ listener.destroy()
- @property
- def listener(self):
+ def __enter__(self):
if self._listener is None:
# Late import
import salt.config
import salt.utils.event
opts = salt.config.master_config(os.path.join(self.config_dir, 'master'))
self._listener = salt.utils.event.get_event('master', opts=opts, listen=True)
- return self._listener
+ atexit.register(self.terminate)
+ return self
+
+ def __exit__(self, *args):
+ self.terminate()
@pytest.mark.trylast
diff --git a/pytestsalt/utils/log_server_tornado.py b/pytestsalt/utils/log_server_tornado.py
index 7346a39..adc16f1 100644
--- a/pytestsalt/utils/log_server_tornado.py
+++ b/pytestsalt/utils/log_server_tornado.py
@@ -13,10 +13,17 @@ import threading
# Import 3rd-party libs
import msgpack
-from tornado import gen
-from tornado.ioloop import IOLoop
-from tornado.tcpserver import TCPServer
-from tornado.iostream import StreamClosedError
+
+try:
+ from salt.ext.tornado import gen
+ from salt.ext.tornado.ioloop import IOLoop
+ from salt.ext.tornado.tcpserver import TCPServer
+ from salt.ext.tornado.iostream import StreamClosedError
+except ImportError:
+ from tornado import gen
+ from tornado.ioloop import IOLoop
+ from tornado.tcpserver import TCPServer
+ from tornado.iostream import StreamClosedError
log = logging.getLogger(__name__)
diff --git a/tests/conftest.py b/tests/conftest.py
deleted file mode 100644
index 53cfa95..0000000
--- a/tests/conftest.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Import python libs
-import logging
-
-if not hasattr(logging, 'TRACE'):
- logging.TRACE = 5
- logging.addLevelName(logging.TRACE, 'TRACE')
-if not hasattr(logging, 'GARBAGE'):
- logging.GARBAGE = 1
- logging.addLevelName(logging.GARBAGE, 'GARBAGE')
-
-
-pytest_plugins = 'pytester', 'tornado'
-
-
-def pytest_configure(config):
- config._inicache['log_format'] = '%(asctime)s,%(msecs)04.0f [%(name)-5s:%(lineno)-4d][%(processName)-8s][%(levelname)-8s] %(message)s'
diff --git a/tests/test_salt_call.py b/tests/test_salt_call.py
deleted file mode 100644
index 3b9f7df..0000000
--- a/tests/test_salt_call.py
+++ /dev/null
@@ -1,39 +0,0 @@
-# -*- coding: utf-8 -*-
-'''
- :codeauthor: :email:`Pedro Algarvio (pedro@algarvio.me)`
- :copyright: Copyright 2015 by the SaltStack Team, see AUTHORS for more details.
- :license: Apache 2.0, see LICENSE for more details.
-
-
- test_salt_minion.py
- ~~~~~~~~~~~~~~~~~~~
-
- Test the pytest salt plugin salt minion
-'''
-
-# Import python libs
-from __future__ import absolute_import
-
-
-# Import pytest libs
-import pytest
-
-
-def test_ping(salt_call):
- assert salt_call.run_sync('test.ping', timeout=10).exitcode == 0
-
-
-@pytest.mark.gen_test
-def test_ping_async(salt_call):
- result = yield salt_call.run('test.ping', timeout=10)
- assert result.exitcode == 0
-
-
-def test_sync(salt_call):
- assert salt_call.run_sync('saltutil.sync_all', timeout=10).exitcode == 0
-
-
-@pytest.mark.gen_test
-def test_sync_async(salt_call):
- result = yield salt_call.run('saltutil.sync_all', timeout=10)
- assert result.exitcode == 0
diff --git a/tests/test_salt_master.py b/tests/test_salt_master.py
deleted file mode 100644
index c44be5a..0000000
--- a/tests/test_salt_master.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-'''
- :codeauthor: :email:`Pedro Algarvio (pedro@algarvio.me)`
- :copyright: Copyright 2015 by the SaltStack Team, see AUTHORS for more details.
- :license: Apache 2.0, see LICENSE for more details.
-
-
- test_salt_master.py
- ~~~~~~~~~~~~~~~~~~~
-
- Test the pytest salt plugin salt master
-'''
-
-# Import python libs
-from __future__ import absolute_import
-
-
-def test_salt_master_running(salt_master):
- assert salt_master.is_alive()
diff --git a/tests/test_salt_minion.py b/tests/test_salt_minion.py
deleted file mode 100644
index 9405729..0000000
--- a/tests/test_salt_minion.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-'''
- :codeauthor: :email:`Pedro Algarvio (pedro@algarvio.me)`
- :copyright: Copyright 2015 by the SaltStack Team, see AUTHORS for more details.
- :license: Apache 2.0, see LICENSE for more details.
-
-
- test_salt_minion.py
- ~~~~~~~~~~~~~~~~~~~
-
- Test the pytest salt plugin salt minion
-'''
-
-# Import python libs
-from __future__ import absolute_import
-
-
-def test_salt_minion_running(salt_minion):
- assert salt_minion.is_alive()
diff --git a/tox.ini b/tox.ini
deleted file mode 100644
index 22d8b2a..0000000
--- a/tox.ini
+++ /dev/null
@@ -1,10 +0,0 @@
-# For more information about tox, see https://tox.readthedocs.org/en/latest/
-[tox]
-#envlist = py27,py33,py34,py35
-envlist = py27
-
-[testenv]
-deps =
- pytest
- /home/vampas/projects/SaltStack/salt/develop/dist/salt-2015.8.0-590-g3b5d967.tar.gz
-commands = py.test {posargs:tests}
Debdiff
[The following lists of changes regard files as different if they have different names, permissions or owners.]
Files in second set of .debs but not in first
-rw-r--r-- root/root /usr/lib/python3/dist-packages/pytest_salt-2020.1.27.egg-info/PKG-INFO -rw-r--r-- root/root /usr/lib/python3/dist-packages/pytest_salt-2020.1.27.egg-info/dependency_links.txt -rw-r--r-- root/root /usr/lib/python3/dist-packages/pytest_salt-2020.1.27.egg-info/entry_points.txt -rw-r--r-- root/root /usr/lib/python3/dist-packages/pytest_salt-2020.1.27.egg-info/requires.txt -rw-r--r-- root/root /usr/lib/python3/dist-packages/pytest_salt-2020.1.27.egg-info/top_level.txt
Files in first set of .debs but not in second
-rw-r--r-- root/root /usr/lib/python3/dist-packages/pytest_salt-2019.6.13.egg-info/PKG-INFO -rw-r--r-- root/root /usr/lib/python3/dist-packages/pytest_salt-2019.6.13.egg-info/dependency_links.txt -rw-r--r-- root/root /usr/lib/python3/dist-packages/pytest_salt-2019.6.13.egg-info/entry_points.txt -rw-r--r-- root/root /usr/lib/python3/dist-packages/pytest_salt-2019.6.13.egg-info/requires.txt -rw-r--r-- root/root /usr/lib/python3/dist-packages/pytest_salt-2019.6.13.egg-info/top_level.txt
No differences were encountered in the control files