Merge "Keep CI up-to-date"

This commit is contained in:
Zuul 2023-05-19 20:35:12 +00:00 committed by Gerrit Code Review
commit e65935a938
21 changed files with 314 additions and 319 deletions

View File

@ -6,16 +6,16 @@
post-run: tests/ci/playbooks/fetch-html-and-json-reports.yaml post-run: tests/ci/playbooks/fetch-html-and-json-reports.yaml
timeout: 1800 timeout: 1800
- job:
name: rally-install-ubuntu-bionic
parent: rally-install-base
nodeset: ubuntu-bionic
- job: - job:
name: rally-install-ubuntu-focal name: rally-install-ubuntu-focal
parent: rally-install-base parent: rally-install-base
nodeset: ubuntu-focal nodeset: ubuntu-focal
- job:
name: rally-install-ubuntu-jammy
parent: rally-install-base
nodeset: ubuntu-jammy
- job: - job:
name: rally-install-centos-8s name: rally-install-centos-8s
parent: rally-install-base parent: rally-install-base
@ -24,4 +24,4 @@
- job: - job:
name: rally-install-centos-9s name: rally-install-centos-9s
parent: rally-install-base parent: rally-install-base
nodeset: centos-8-stream nodeset: centos-9-stream

View File

@ -6,7 +6,7 @@
post-run: tests/ci/playbooks/fetch-html-and-json-reports.yaml post-run: tests/ci/playbooks/fetch-html-and-json-reports.yaml
description: | description: |
Run test for rally project. Run test for rally project.
nodeset: ubuntu-bionic nodeset: ubuntu-jammy
- job: - job:
name: rally-tox-docs name: rally-tox-docs
@ -28,16 +28,6 @@
vars: vars:
tox_env: pep8 tox_env: pep8
- job:
name: rally-tox-functional-py38
parent: rally-tox-base
description: |
Run test for rally project.
Uses tox with the ``functional`` environment.
vars:
tox_env: functional-py38
- job: - job:
name: rally-tox-functional name: rally-tox-functional
parent: rally-tox-base parent: rally-tox-base
@ -67,6 +57,7 @@
Uses tox with the ``py36`` environment. Uses tox with the ``py36`` environment.
vars: vars:
tox_env: py36 tox_env: py36
nodeset: ubuntu-bionic
- job: - job:
name: rally-tox-py37 name: rally-tox-py37
@ -77,6 +68,7 @@
Uses tox with the ``py37`` environment. Uses tox with the ``py37`` environment.
vars: vars:
tox_env: py37 tox_env: py37
nodeset: ubuntu-bionic
- job: - job:
name: rally-tox-py38 name: rally-tox-py38
@ -85,9 +77,9 @@
Run unit test for rally project. Run unit test for rally project.
Uses tox with the ``py38`` environment. Uses tox with the ``py38`` environment.
nodeset: ubuntu-focal
vars: vars:
tox_env: py38 tox_env: py38
nodeset: ubuntu-focal
- job: - job:
name: rally-tox-py39 name: rally-tox-py39
@ -96,9 +88,19 @@
Run unit test for rally project. Run unit test for rally project.
Uses tox with the ``py39`` environment. Uses tox with the ``py39`` environment.
nodeset: ubuntu-focal
vars: vars:
tox_env: py39 tox_env: py39
nodeset: ubuntu-focal
- job:
name: rally-tox-py310
parent: rally-tox-base
description: |
Run unit test for rally project.
Uses tox with the ``py310`` environment.
vars:
tox_env: py310
- job: - job:
name: rally-tox-samples name: rally-tox-samples
@ -117,7 +119,6 @@
Run test for rally project. Run test for rally project.
Uses tox with the ``cover`` environment. Uses tox with the ``cover`` environment.
nodeset: ubuntu-bionic
vars: vars:
coverage_output_src: '{{ zuul.project.src_dir }}/cover/' coverage_output_src: '{{ zuul.project.src_dir }}/cover/'
zuul_executor_dest: '{{ zuul.executor.log_root }}/coverage/' zuul_executor_dest: '{{ zuul.executor.log_root }}/coverage/'

View File

@ -13,12 +13,12 @@
- rally-tox-py37 - rally-tox-py37
- rally-tox-py38 - rally-tox-py38
- rally-tox-py39 - rally-tox-py39
- rally-tox-py310
- rally-tox-samples - rally-tox-samples
- rally-tox-functional - rally-tox-functional
- rally-tox-functional-py38
- rally-tox-self - rally-tox-self
- rally-install-ubuntu-bionic
- rally-install-ubuntu-focal - rally-install-ubuntu-focal
- rally-install-ubuntu-jammy
- rally-install-centos-8s - rally-install-centos-8s
- rally-install-centos-9s - rally-install-centos-9s
- rally-docker-build - rally-docker-build
@ -31,10 +31,11 @@
- rally-tox-py37 - rally-tox-py37
- rally-tox-py38 - rally-tox-py38
- rally-tox-py39 - rally-tox-py39
- rally-tox-py310
- rally-tox-functional - rally-tox-functional
- rally-tox-self - rally-tox-self
- rally-install-ubuntu-bionic
- rally-install-ubuntu-focal - rally-install-ubuntu-focal
- rally-install-ubuntu-jammy
- rally-install-centos-8s - rally-install-centos-8s
- rally-install-centos-9s - rally-install-centos-9s
post: post:

View File

@ -27,11 +27,19 @@ Fixed
`Launchpad-bug #1956956 <https://launchpad.net/bugs/1956956>`_ `Launchpad-bug #1956956 <https://launchpad.net/bugs/1956956>`_
Changed Added
~~~~~
* Pin SQLAlchemy to <2.0.0
* CI for running unit and functional tests using python 3.10
* CI jobs that check Rally installation compatibility with CentOS 9 Stream and
Ubuntu Jammy
Removed
~~~~~~~ ~~~~~~~
Check ability to install Rally on Centos 8 Stream and Centos 9 Stream and * CI jobs with installation compatibility checks for CentOS 7, CentOS 8
stop checking Centos 7 and Centos 8 (CentOS 8 Stream is checked instead), Ubuntu Bionic.
[3.3.0] - 2021-06-16 [3.3.0] - 2021-06-16
-------------------- --------------------

View File

@ -616,11 +616,11 @@ def run(argv, categories):
rapi = api.API(config_args=argv[1:], skip_db_check=True) rapi = api.API(config_args=argv[1:], skip_db_check=True)
except exceptions.RallyException as e: except exceptions.RallyException as e:
print(e) print(e)
return(2) return 2
if CONF.category.name == "bash-completion": if CONF.category.name == "bash-completion":
print(_generate_bash_completion_script()) print(_generate_bash_completion_script())
return(0) return 0
fn = CONF.category.action_fn fn = CONF.category.action_fn
fn_args = [encodeutils.safe_decode(arg) fn_args = [encodeutils.safe_decode(arg)
@ -652,7 +652,7 @@ def run(argv, categories):
if arg[1].get("dest", "").endswith(missing): if arg[1].get("dest", "").endswith(missing):
print(" " + arg[0][0]) print(" " + arg[0][0])
break break
return(1) return 1
try: try:
validate_deprecated_args(argv, fn) validate_deprecated_args(argv, fn)

View File

@ -579,7 +579,7 @@ class TaskCommands(object):
print("Error: Invalid task status '%s'.\nAvailable statuses: %s" print("Error: Invalid task status '%s'.\nAvailable statuses: %s"
% (status, ", ".join(consts.TaskStatus)), % (status, ", ".join(consts.TaskStatus)),
file=sys.stderr) file=sys.stderr)
return(1) return 1
if not all_deployments: if not all_deployments:
filters["deployment"] = deployment filters["deployment"] = deployment

View File

@ -124,13 +124,13 @@ class ResultConsumer(object):
{"raw": results_chunk}) {"raw": results_chunk})
self.workload_data_count += 1 self.workload_data_count += 1
elif self.is_done.isSet(): elif self.is_done.is_set():
break break
else: else:
time.sleep(0.1) time.sleep(0.1)
def _consume_events(self): def _consume_events(self):
while not self.is_done.isSet() or self.runner.event_queue: while not self.is_done.is_set() or self.runner.event_queue:
if self.runner.event_queue: if self.runner.event_queue:
event = self.runner.event_queue.popleft() event = self.runner.event_queue.popleft()
self.hook_executor.on_event( self.hook_executor.on_event(
@ -201,7 +201,7 @@ class ResultConsumer(object):
runner.run method. runner.run method.
""" """
while not self.is_done.isSet(): while not self.is_done.is_set():
if self.is_task_in_aborting_status(self.task["uuid"], if self.is_task_in_aborting_status(self.task["uuid"],
check_soft=False): check_soft=False):
self.runner.abort() self.runner.abort()

View File

@ -63,7 +63,7 @@ class HookExecutor(object):
stopwatch = rutils.Stopwatch(stop_event=self._timer_stop_event) stopwatch = rutils.Stopwatch(stop_event=self._timer_stop_event)
stopwatch.start() stopwatch.start()
seconds_since_start = 0 seconds_since_start = 0
while not self._timer_stop_event.isSet(): while not self._timer_stop_event.is_set():
self.on_event(event_type="time", value=seconds_since_start) self.on_event(event_type="time", value=seconds_since_start)
seconds_since_start += 1 seconds_since_start += 1
stopwatch.sleep(seconds_since_start) stopwatch.sleep(seconds_since_start)

View File

@ -20,6 +20,8 @@ classifier =
Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
[files] [files]
packages = packages =

View File

@ -1,62 +1,33 @@
- hosts: all - hosts: all
name: Prepare host to install Rally name: Prepare host to install Rally
tasks: tasks:
- name: Check OS distro (CentOS) - name: Uninstall python3-pyyaml (CentOS 8 & 9)
when: ansible_distribution == "CentOS"
set_fact:
# in case of centos we do not care about minor versions
os_distro: '{{ ansible_distribution }} {{ ansible_distribution_major_version }}'
- name: Check OS distro (Ubuntu)
when: ansible_distribution == "Ubuntu"
set_fact:
os_distro: '{{ ansible_distribution }} {{ ansible_distribution_version }}'
- name: Install required packages (Centos-7)
when: os_distro == "CentOS 7"
shell:
cmd: |
sudo yum remove -y python-crypto || true
sudo yum remove -y python36-PyYAML || true
sudo yum update
sudo yum install -y yum-utils
sudo yum groupinstall -y development
sudo yum install -y https://repo.ius.io/ius-release-el7.rpm https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
sudo yum install -y python36u python36u-devel
- name: Uninstall required packages (Centos-8)
when: os_distro == "CentOS 8"
become: true become: true
shell: dnf remove -y python3-pyyaml package:
state: absent
name: python3-pyyaml
- name: Install required packages (Ubuntu-Bionic) - name: Install python3.8-dev (Ubuntu 20.04)
when: os_distro == "Ubuntu 18.04" become: true
shell: package:
chdir: '{{ zuul.project.src_dir }}' state: present
cmd: | name: python3.8-dev
# NOTE(pabelanger): We run apt-get update to ensure we dont have a stale when: ansible_distribution == "Ubuntu" and ansible_distribution_version == "20.04"
# package cache in the gate.
sudo apt update
sudo apt install --yes python3.6-dev
- name: Install required packages (Ubuntu-Focal) - name: Install python3.10-dev (Ubuntu 22.04)
when: os_distro == "Ubuntu 20.04" become: true
shell: package:
chdir: '{{ zuul.project.src_dir }}' state: present
cmd: | name: python3.10-dev
# NOTE(pabelanger): We run apt-get update to ensure we dont have a stale when: ansible_distribution == "Ubuntu" and ansible_distribution_version == "22.04"
# package cache in the gate.
sudo apt update
sudo apt install --yes python3.8-dev
- name: Install pip3 if needed - name: Install pip3 if needed
when: os_distro == "CentOS 7" or os_distro == "Ubuntu 18.04" or os_distro == "Ubuntu 20.04" become: true
shell: shell:
executable: /bin/bash executable: /bin/bash
chdir: '{{ zuul.project.src_dir }}' chdir: '{{ zuul.project.src_dir }}'
cmd: | cmd: |
set -e
python_version=`python3 --version` python_version=`python3 --version`
python_version=`echo $python_version |awk '{print $2}'` python_version=`echo $python_version |awk '{print $2}'`
echo $python_version echo $python_version
@ -66,19 +37,13 @@
pip_url=https://bootstrap.pypa.io/get-pip.py pip_url=https://bootstrap.pypa.io/get-pip.py
fi fi
curl $pip_url -o /tmp/get-pip.py curl $pip_url -o /tmp/get-pip.py
sudo python3 /tmp/get-pip.py python3 /tmp/get-pip.py
- name: Update pip3 if needed
when: os_distro == "CentOS 8"
become: true
shell: pip3 install --upgrade pip
- name: Install bindep - name: Install bindep
become: true become: true
shell: pip3 install --upgrade bindep PyYAML shell: pip3 install --upgrade bindep
- name: Prepare rally plugins stored at home dir - name: Prepare rally plugins stored at home dir
shell: shell: |
cmd: | mkdir --parents ~/.rally/plugins
mkdir --parents ~/.rally/plugins cp --recursive {{ zuul.project.src_dir }}/rally-jobs/plugins/* ~/.rally/plugins
cp --recursive {{ zuul.project.src_dir }}/rally-jobs/plugins/* ~/.rally/plugins

View File

@ -0,0 +1,4 @@
default_pip_url: "https://bootstrap.pypa.io/get-pip.py"
versioned_pip_url:
python3.6: "https://bootstrap.pypa.io/pip/3.6/get-pip.py"

View File

@ -0,0 +1,85 @@
# 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.
import argparse
import configparser
import re
PY_FACTORS_RE = re.compile("^(?!py$)(py|pypy|jython)([2-9][0-9]?[0-9]?)?$")
def _parse_env_name(env_name):
for factor in env_name.split("-"):
# copy-pasted from tox codebase with custom extra check
# https://github.com/tox-dev/tox/blob/6b76e18fcaa7c9610b642555bcb94aab1d37f2b3/src/tox/config/__init__.py#L658-L669
match = PY_FACTORS_RE.match(factor)
if match:
base_exe = {"py": "python"}.get(match.group(1), match.group(1))
if base_exe != "python":
raise ValueError("We do not support '%s' interpreter yet."
% base_exe)
version_s = match.group(2)
if not version_s:
version_info = ()
elif len(version_s) == 1:
version_info = (version_s,)
else:
version_info = (version_s[0], version_s[1:])
implied_version = ".".join(version_info)
implied_python = "{}{}".format(base_exe, implied_version)
return implied_python
def main():
parser = argparse.ArgumentParser()
parser.add_argument(
"--tox-cfg", metavar="<path>", type=str, required=True,
help="A path to tox.ini file to parse."
)
parser.add_argument(
"--tox-env", metavar="<env-name>", type=str, required=True,
help="Tox env name."
)
parser.add_argument(
"--default-python3-version", metavar="<python-interpreter>",
type=str, required=False, default="python3.10",
help="Default python3 interpreter to use for 'python3' case."
)
args = parser.parse_args()
tox_cfg = configparser.ConfigParser()
tox_cfg.read(args.tox_cfg)
python_version = None
# check python version specific to target tox env
env_section = "testenv:%s" % args.tox_env
if env_section in tox_cfg:
python_version = tox_cfg[env_section].get("basepython")
# try to determine python version based on env name like tox does
if python_version is None:
python_version = _parse_env_name(args.tox_env)
# check python version that is configured for all tox envs as default
if python_version is None:
python_version = tox_cfg["testenv"].get("basepython", "python3")
if python_version == "python3":
python_version = args.default_python3_version
print(python_version)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,35 @@
- name: Check required version of Python
args:
executable: python3
script: "find_python_for_tox_env.py --tox-cfg {{ zuul.project.src_dir }}/tox.ini --tox-env {{ tox_env }}"
changed_when: false
register: python_exec_from_tox
when: python_exec is not defined
- name: "Set python_exec var to {{ python_exec_from_tox }}"
set_fact:
python_exec: "{{ python_exec_from_tox.stdout.strip() }}"
when: python_exec_from_tox is defined and python_exec_from_tox.stdout.strip()
- name: Install the proper python version and pip
become: True
become_user: root
shell: |
set -e
apt-get update
apt-get install {{ python_exec }}-dev --yes
curl {{ versioned_pip_url.get(python_exec, default_pip_url) }} -o get-pip.py
{{ python_exec }} get-pip.py --force-reinstall
when: python_exec is defined
- name: Install python tox
become: True
become_user: root
shell: "{{ python_exec }} -m pip install tox"
- name: Install system deps
include_role:
name: bindep

View File

@ -0,0 +1 @@
- include_tasks: "{{ action }}.yaml"

View File

@ -0,0 +1,5 @@
---
- name: Run tox
args:
chdir: "{{ zuul.project.src_dir }}"
command: "tox -e {{ tox_env }}"

View File

@ -1,70 +1,6 @@
- hosts: all - hosts: all
name: Installs all required packages
tasks: tasks:
- name: Check required version of Python - include_role:
args: name: "rally-tox"
chdir: "{{ zuul.project.src_dir }}" vars:
shell: action: "install"
executable: /bin/sh
cmd: |
set -e
iniget(){
local xtrace
xtrace=$(set +o | grep xtrace)
set +o xtrace
local section=$1
local file="tox.ini"
local option="basepython"
local line
line=$(sed -ne "/^\[$section\]/,/^\[.*\]/ { /^$option[ \t]*=/ p; }" "$file")
echo ${line#*= python}
$xtrace
}
tox_testenv_python=$(iniget 'testenv:{{ tox_env }}')
if [ "$tox_testenv_python" != "" ]; then
echo $tox_testenv_python
else
echo $(iniget 'testenv')
fi
register: python_version
- name: Install the proper python version
become: True
become_user: root
shell:
executable: /bin/sh
cmd: |
set -e
apt-get update
apt-get install python{{ python_version.stdout }}-dev --yes
- name: Install the proper python pip version
become: True
become_user: root
shell:
executable: /bin/bash
cmd: |
set -e
pip_url="https://bootstrap.pypa.io/get-pip.py"
if [ "{{ python_version.stdout }}" = "3.6" ]; then
pip_url="https://bootstrap.pypa.io/pip/3.6/get-pip.py"
elif [ "{{ python_version.stdout }}" = "3" ]; then
pip_url="https://bootstrap.pypa.io/pip/3.6/get-pip.py"
fi
curl $pip_url -o get-pip.py
python{{ python_version.stdout }} get-pip.py --force-reinstall
- name: Install python tox
become: True
become_user: root
shell:
executable: /bin/bash
cmd: |
python{{ python_version.stdout }} -m pip install tox
roles:
- bindep

View File

@ -1,6 +1,6 @@
- hosts: all - hosts: all
tasks: tasks:
- name: Run tox - include_role:
args: name: "rally-tox"
chdir: "{{ zuul.project.src_dir }}" vars:
command: "tox -e{{ tox_env }}" action: "run"

View File

@ -24,7 +24,6 @@ Guidelines for writing new hacking checks
""" """
import functools
import re import re
import tokenize import tokenize
@ -77,22 +76,6 @@ re_datetime_alias = re.compile(r"^(from|import) datetime(?!\s+as\s+dt$)")
re_log_warn = re.compile(r"(.)*LOG\.(warn)\(\s*('|\"|_)") re_log_warn = re.compile(r"(.)*LOG\.(warn)\(\s*('|\"|_)")
def skip_ignored_lines(func):
@functools.wraps(func)
def wrapper(physical_line, logical_line, filename):
line = physical_line.strip()
if not line or line.startswith("#") or line.endswith("# noqa"):
return
try:
for res in func(physical_line, logical_line, filename):
yield res
except StopIteration:
return
return wrapper
def _parse_assert_mock_str(line): def _parse_assert_mock_str(line):
point = line.find(".assert_") point = line.find(".assert_")
@ -107,8 +90,7 @@ def _parse_assert_mock_str(line):
@core.flake8ext @core.flake8ext
@skip_ignored_lines def check_assert_methods_from_mock(logical_line, filename, noqa=False):
def check_assert_methods_from_mock(physical_line, logical_line, filename):
"""Ensure that ``assert_*`` methods from ``mock`` library is used correctly """Ensure that ``assert_*`` methods from ``mock`` library is used correctly
N301 - base error number N301 - base error number
@ -116,6 +98,8 @@ def check_assert_methods_from_mock(physical_line, logical_line, filename):
N303 - related to nonexistent "assert_called_once" N303 - related to nonexistent "assert_called_once"
N304 - related to nonexistent "called_once_with" N304 - related to nonexistent "called_once_with"
""" """
if noqa:
return
correct_names = ["assert_any_call", "assert_called_once_with", correct_names = ["assert_any_call", "assert_called_once_with",
"assert_called_with", "assert_has_calls", "assert_called_with", "assert_has_calls",
@ -161,12 +145,13 @@ def check_assert_methods_from_mock(physical_line, logical_line, filename):
@core.flake8ext @core.flake8ext
@skip_ignored_lines def check_import_of_logging(logical_line, filename, noqa=False):
def check_import_of_logging(physical_line, logical_line, filename):
"""Check correctness import of logging module """Check correctness import of logging module
N310 N310
""" """
if noqa:
return
excluded_files = ["./rally/common/logging.py", excluded_files = ["./rally/common/logging.py",
"./tests/unit/common/test_logging.py", "./tests/unit/common/test_logging.py",
@ -185,12 +170,13 @@ def check_import_of_logging(physical_line, logical_line, filename):
@core.flake8ext @core.flake8ext
@skip_ignored_lines def check_import_of_config(logical_line, filename, noqa=False):
def check_import_of_config(physical_line, logical_line, filename):
"""Check correctness import of config module """Check correctness import of config module
N311 N311
""" """
if noqa:
return
excluded_files = ["./rally/common/cfg.py"] excluded_files = ["./rally/common/cfg.py"]
@ -205,8 +191,7 @@ def check_import_of_config(physical_line, logical_line, filename):
@core.flake8ext @core.flake8ext
@skip_ignored_lines def no_use_conf_debug_check(logical_line, filename, noqa=False):
def no_use_conf_debug_check(physical_line, logical_line, filename):
"""Check for "cfg.CONF.debug" """Check for "cfg.CONF.debug"
Rally has two DEBUG level: Rally has two DEBUG level:
@ -216,6 +201,8 @@ def no_use_conf_debug_check(physical_line, logical_line, filename):
N312 N312
""" """
if noqa:
return
excluded_files = ["./rally/common/logging.py"] excluded_files = ["./rally/common/logging.py"]
point = logical_line.find("CONF.debug") point = logical_line.find("CONF.debug")
@ -226,36 +213,39 @@ def no_use_conf_debug_check(physical_line, logical_line, filename):
@core.flake8ext @core.flake8ext
@skip_ignored_lines def assert_true_instance(logical_line, noqa=False):
def assert_true_instance(physical_line, logical_line, filename):
"""Check for assertTrue(isinstance(a, b)) sentences """Check for assertTrue(isinstance(a, b)) sentences
N320 N320
""" """
if noqa:
return
if re_assert_true_instance.match(logical_line): if re_assert_true_instance.match(logical_line):
yield (0, "N320 assertTrue(isinstance(a, b)) sentences not allowed, " yield (0, "N320 assertTrue(isinstance(a, b)) sentences not allowed, "
"you should use assertIsInstance(a, b) instead.") "you should use assertIsInstance(a, b) instead.")
@core.flake8ext @core.flake8ext
@skip_ignored_lines def assert_equal_type(logical_line, noqa=False):
def assert_equal_type(physical_line, logical_line, filename):
"""Check for assertEqual(type(A), B) sentences """Check for assertEqual(type(A), B) sentences
N321 N321
""" """
if noqa:
return
if re_assert_equal_type.match(logical_line): if re_assert_equal_type.match(logical_line):
yield (0, "N321 assertEqual(type(A), B) sentences not allowed, " yield (0, "N321 assertEqual(type(A), B) sentences not allowed, "
"you should use assertIsInstance(a, b) instead.") "you should use assertIsInstance(a, b) instead.")
@core.flake8ext @core.flake8ext
@skip_ignored_lines def assert_equal_none(logical_line, noqa=False):
def assert_equal_none(physical_line, logical_line, filename):
"""Check for assertEqual(A, None) or assertEqual(None, A) sentences """Check for assertEqual(A, None) or assertEqual(None, A) sentences
N322 N322
""" """
if noqa:
return
res = (re_assert_equal_start_with_none.search(logical_line) res = (re_assert_equal_start_with_none.search(logical_line)
or re_assert_equal_end_with_none.search(logical_line)) or re_assert_equal_end_with_none.search(logical_line))
if res: if res:
@ -265,8 +255,7 @@ def assert_equal_none(physical_line, logical_line, filename):
@core.flake8ext @core.flake8ext
@skip_ignored_lines def assert_true_or_false_with_in(logical_line, noqa=False):
def assert_true_or_false_with_in(physical_line, logical_line, filename):
"""Check assertTrue/False(A in/not in B) with collection contents """Check assertTrue/False(A in/not in B) with collection contents
Check for assertTrue/False(A in B), assertTrue/False(A not in B), Check for assertTrue/False(A in B), assertTrue/False(A not in B),
@ -275,6 +264,8 @@ def assert_true_or_false_with_in(physical_line, logical_line, filename):
N323 N323
""" """
if noqa:
return
res = (re_assert_true_false_with_in_or_not_in.search(logical_line) res = (re_assert_true_false_with_in_or_not_in.search(logical_line)
or re_assert_true_false_with_in_or_not_in_spaces.search( or re_assert_true_false_with_in_or_not_in_spaces.search(
logical_line)) logical_line))
@ -285,8 +276,7 @@ def assert_true_or_false_with_in(physical_line, logical_line, filename):
@core.flake8ext @core.flake8ext
@skip_ignored_lines def assert_equal_in(logical_line, noqa=False):
def assert_equal_in(physical_line, logical_line, filename):
"""Check assertEqual(A in/not in B, True/False) with collection contents """Check assertEqual(A in/not in B, True/False) with collection contents
Check for assertEqual(A in B, True/False), assertEqual(True/False, A in B), Check for assertEqual(A in B, True/False), assertEqual(True/False, A in B),
@ -295,6 +285,8 @@ def assert_equal_in(physical_line, logical_line, filename):
N324 N324
""" """
if noqa:
return
res = (re_assert_equal_in_end_with_true_or_false.search(logical_line) res = (re_assert_equal_in_end_with_true_or_false.search(logical_line)
or re_assert_equal_in_start_with_true_or_false.search(logical_line)) or re_assert_equal_in_start_with_true_or_false.search(logical_line))
if res: if res:
@ -304,12 +296,13 @@ def assert_equal_in(physical_line, logical_line, filename):
@core.flake8ext @core.flake8ext
@skip_ignored_lines def assert_not_equal_none(logical_line, noqa=False):
def assert_not_equal_none(physical_line, logical_line, filename):
"""Check for assertNotEqual(A, None) or assertEqual(None, A) sentences """Check for assertNotEqual(A, None) or assertEqual(None, A) sentences
N325 N325
""" """
if noqa:
return
res = (re_assert_not_equal_start_with_none.search(logical_line) res = (re_assert_not_equal_start_with_none.search(logical_line)
or re_assert_not_equal_end_with_none.search(logical_line)) or re_assert_not_equal_end_with_none.search(logical_line))
if res: if res:
@ -319,8 +312,7 @@ def assert_not_equal_none(physical_line, logical_line, filename):
@core.flake8ext @core.flake8ext
@skip_ignored_lines def assert_equal_true_or_false(logical_line, noqa=False):
def assert_equal_true_or_false(physical_line, logical_line, filename):
"""Check for assertEqual(A, True/False) sentences """Check for assertEqual(A, True/False) sentences
Check for assertEqual(A, True/False) sentences or Check for assertEqual(A, True/False) sentences or
@ -328,6 +320,8 @@ def assert_equal_true_or_false(physical_line, logical_line, filename):
N326 N326
""" """
if noqa:
return
res = (re_assert_equal_end_with_true_or_false.search(logical_line) res = (re_assert_equal_end_with_true_or_false.search(logical_line)
or re_assert_equal_start_with_true_or_false.search(logical_line)) or re_assert_equal_start_with_true_or_false.search(logical_line))
if res: if res:
@ -337,9 +331,7 @@ def assert_equal_true_or_false(physical_line, logical_line, filename):
@core.flake8ext @core.flake8ext
@skip_ignored_lines def check_no_direct_rally_objects_import(logical_line, filename, noqa=False):
def check_no_direct_rally_objects_import(physical_line, logical_line,
filename):
"""Check if rally.common.objects are properly imported. """Check if rally.common.objects are properly imported.
If you import "from rally.common import objects" you are able to use If you import "from rally.common import objects" you are able to use
@ -347,10 +339,9 @@ def check_no_direct_rally_objects_import(physical_line, logical_line,
N340 N340
""" """
if filename == "./rally/common/objects/__init__.py": if noqa:
return return
if filename == "./rally/common/objects/__init__.py":
if filename == "./rally/common/objects/endpoint.py":
return return
if (logical_line.startswith("from rally.common.objects") if (logical_line.startswith("from rally.common.objects")
@ -361,8 +352,7 @@ def check_no_direct_rally_objects_import(physical_line, logical_line,
@core.flake8ext @core.flake8ext
@skip_ignored_lines def check_no_oslo_deprecated_import(logical_line, noqa=False):
def check_no_oslo_deprecated_import(physical_line, logical_line, filename):
"""Check if oslo.foo packages are not imported instead of oslo_foo ones. """Check if oslo.foo packages are not imported instead of oslo_foo ones.
Libraries from oslo.foo namespace are deprecated because of namespace Libraries from oslo.foo namespace are deprecated because of namespace
@ -370,6 +360,8 @@ def check_no_oslo_deprecated_import(physical_line, logical_line, filename):
N341 N341
""" """
if noqa:
return
if (logical_line.startswith("from oslo.") if (logical_line.startswith("from oslo.")
or logical_line.startswith("import oslo.")): or logical_line.startswith("import oslo.")):
yield (0, "N341: Import oslo module: `from oslo_xyz import ...`. " yield (0, "N341: Import oslo module: `from oslo_xyz import ...`. "
@ -378,12 +370,13 @@ def check_no_oslo_deprecated_import(physical_line, logical_line, filename):
@core.flake8ext @core.flake8ext
@skip_ignored_lines def check_quotes(logical_line, noqa=False):
def check_quotes(physical_line, logical_line, filename):
"""Check that single quotation marks are not used """Check that single quotation marks are not used
N350 N350
""" """
if noqa:
return
in_string = False in_string = False
in_multiline_string = False in_multiline_string = False
@ -432,12 +425,13 @@ def check_quotes(physical_line, logical_line, filename):
@core.flake8ext @core.flake8ext
@skip_ignored_lines def check_no_constructor_data_struct(logical_line, noqa=False):
def check_no_constructor_data_struct(physical_line, logical_line, filename):
"""Check that data structs (lists, dicts) are declared using literals """Check that data structs (lists, dicts) are declared using literals
N351 N351
""" """
if noqa:
return
match = re_no_construct_dict.search(logical_line) match = re_no_construct_dict.search(logical_line)
if match: if match:
@ -448,17 +442,12 @@ def check_no_constructor_data_struct(physical_line, logical_line, filename):
@core.flake8ext @core.flake8ext
def check_dict_formatting_in_string(logical_line, tokens): def check_dict_formatting_in_string(logical_line, tokens, noqa=False):
"""Check that strings do not use dict-formatting with a single replacement """Check that strings do not use dict-formatting with a single replacement
N352 N352
""" """
# NOTE(stpierre): Can't use @skip_ignored_lines here because it's if noqa:
# a stupid decorator that only works on functions that take
# (logical_line, filename) as arguments.
if (not logical_line
or logical_line.startswith("#")
or logical_line.endswith("# noqa")):
return return
current_string = "" current_string = ""
@ -516,40 +505,30 @@ def check_dict_formatting_in_string(logical_line, tokens):
@core.flake8ext @core.flake8ext
@skip_ignored_lines def check_raises(logical_line, filename, noqa=False):
def check_using_unicode(physical_line, logical_line, filename):
"""Check crosspython unicode usage
N353
"""
if re.search(r"\bunicode\(", logical_line):
yield (0, "N353 'unicode' function is absent in python3. Please "
"use 'str' instead.")
@core.flake8ext
def check_raises(physical_line, logical_line, filename):
"""Check raises usage """Check raises usage
N354 N354
""" """
if noqa:
return
ignored_files = ["./tests/unit/test_hacking.py", ignored_files = ["./tests/unit/test_hacking.py",
"./tests/hacking/checks.py"] "./tests/hacking/checks.py"]
if filename not in ignored_files: if filename not in ignored_files:
if re_raises.search(physical_line): if re_raises.search(logical_line):
yield (0, "N354 ':Please use ':raises Exception: conditions' " yield (0, "N354 ':Please use ':raises Exception: conditions' "
"in docstrings.") "in docstrings.")
@core.flake8ext @core.flake8ext
@skip_ignored_lines def check_old_type_class(logical_line, noqa=False):
def check_old_type_class(physical_line, logical_line, filename):
"""Use new-style Python classes """Use new-style Python classes
N355 N355
""" """
if noqa:
return
if re_old_type_class.search(logical_line): if re_old_type_class.search(logical_line):
yield (0, "N355 This class does not inherit from anything and thus " yield (0, "N355 This class does not inherit from anything and thus "
@ -558,23 +537,25 @@ def check_old_type_class(physical_line, logical_line, filename):
@core.flake8ext @core.flake8ext
@skip_ignored_lines def check_datetime_alias(logical_line, noqa=False):
def check_datetime_alias(physical_line, logical_line, filename):
"""Ensure using ``dt`` as alias for ``datetime`` """Ensure using ``dt`` as alias for ``datetime``
N356 N356
""" """
if noqa:
return
if re_datetime_alias.search(logical_line): if re_datetime_alias.search(logical_line):
yield 0, "N356 Please use ``dt`` as alias for ``datetime``." yield 0, "N356 Please use ``dt`` as alias for ``datetime``."
@core.flake8ext @core.flake8ext
@skip_ignored_lines def check_db_imports_in_cli(logical_line, filename, noqa=False):
def check_db_imports_in_cli(physical_line, logical_line, filename):
"""Ensure that CLI modules do not use ``rally.common.db`` """Ensure that CLI modules do not use ``rally.common.db``
N360 N360
""" """
if noqa:
return
if (not filename.startswith("./rally/cli") if (not filename.startswith("./rally/cli")
or filename == "./rally/cli/commands/db.py"): or filename == "./rally/cli/commands/db.py"):
return return
@ -584,8 +565,7 @@ def check_db_imports_in_cli(physical_line, logical_line, filename):
@core.flake8ext @core.flake8ext
@skip_ignored_lines def check_objects_imports_in_cli(logical_line, filename):
def check_objects_imports_in_cli(physical_line, logical_line, filename):
"""Ensure that CLI modules do not use ``rally.common.objects`` """Ensure that CLI modules do not use ``rally.common.objects``
N361 N361
@ -598,19 +578,19 @@ def check_objects_imports_in_cli(physical_line, logical_line, filename):
@core.flake8ext @core.flake8ext
@skip_ignored_lines def check_log_warn(logical_line):
def check_log_warn(physical_line, logical_line, filename):
if re_log_warn.search(logical_line): if re_log_warn.search(logical_line):
yield 0, "N313 LOG.warn is deprecated, please use LOG.warning" yield 0, "N313 LOG.warn is deprecated, please use LOG.warning"
@core.flake8ext @core.flake8ext
@skip_ignored_lines def check_opts_import_path(logical_line, filename, noqa=False):
def check_opts_import_path(physical_line, logical_line, filename):
"""Ensure that we load opts from correct paths only """Ensure that we load opts from correct paths only
N342 N342
""" """
if noqa:
return
excluded_files = ["./rally/task/engine.py", excluded_files = ["./rally/task/engine.py",
"./rally/task/context.py", "./rally/task/context.py",
"./rally/task/scenario.py", "./rally/task/scenario.py",

View File

@ -705,7 +705,7 @@ class ResultConsumerTestCase(test.TestCase):
runner = mock.MagicMock(result_queue=False) runner = mock.MagicMock(result_queue=False)
is_done = mock.MagicMock() is_done = mock.MagicMock()
is_done.isSet.side_effect = (False, True) is_done.is_set.side_effect = (False, True)
task = mock.MagicMock() task = mock.MagicMock()
mock_task_get_status.return_value = consts.TaskStatus.ABORTED mock_task_get_status.return_value = consts.TaskStatus.ABORTED
@ -923,7 +923,7 @@ class ResultConsumerTestCase(test.TestCase):
consts.TaskStatus.ABORTING) consts.TaskStatus.ABORTING)
mock_is_done = mock.MagicMock() mock_is_done = mock.MagicMock()
mock_event.return_value = mock_is_done mock_event.return_value = mock_is_done
mock_is_done.isSet.return_value = False mock_is_done.is_set.return_value = False
ctx_manager = mock.MagicMock() ctx_manager = mock.MagicMock()
res = engine.ResultConsumer(workload_cfg, task=task, subtask=subtask, res = engine.ResultConsumer(workload_cfg, task=task, subtask=subtask,
@ -954,7 +954,7 @@ class ResultConsumerTestCase(test.TestCase):
mock_event.return_value = mock_is_done mock_event.return_value = mock_is_done
ctx_manager = mock.MagicMock() ctx_manager = mock.MagicMock()
mock_is_done.isSet.side_effect = [False, False, False, False, True] mock_is_done.is_set.side_effect = [False, False, False, False, True]
res = engine.ResultConsumer(workload_cfg, task=task, subtask=subtask, res = engine.ResultConsumer(workload_cfg, task=task, subtask=subtask,
workload=workload, runner=runner, workload=workload, runner=runner,

View File

@ -10,6 +10,7 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import inspect
import io import io
import tokenize import tokenize
@ -23,12 +24,23 @@ from tests.unit import test
class HackingTestCase(test.TestCase): class HackingTestCase(test.TestCase):
def _assert_good_samples(self, checker, samples, module_file="f"): def _assert_good_samples(self, checker, samples, module_file="f"):
spec = inspect.getfullargspec(checker)
base_args = {}
if "filename" in spec.args:
base_args["filename"] = module_file
for s in samples: for s in samples:
self.assertEqual([], list(checker(s, s, module_file)), s) args = {"logical_line": s, **base_args}
self.assertEqual([], list(checker(*args)), s)
def _assert_bad_samples(self, checker, samples, module_file="f"): def _assert_bad_samples(self, checker, samples, module_file="f"):
spec = inspect.getfullargspec(checker)
base_args = {}
if "filename" in spec.args:
base_args["filename"] = module_file
for s in samples: for s in samples:
self.assertEqual(1, len(list(checker(s, s, module_file))), s) args = {"logical_line": s, **base_args}
self.assertEqual(1, len(list(checker(**args))), s)
def test__parse_assert_mock_str(self): def test__parse_assert_mock_str(self):
pos, method, obj = checks._parse_assert_mock_str( pos, method, obj = checks._parse_assert_mock_str(
@ -43,21 +55,6 @@ class HackingTestCase(test.TestCase):
self.assertIsNone(method) self.assertIsNone(method)
self.assertIsNone(obj) self.assertIsNone(obj)
@ddt.data(
{"line": "fdafadfdas # noqa", "result": []},
{"line": " # fdafadfdas", "result": []},
{"line": " ", "result": []},
{"line": "otherstuff", "result": [42]}
)
@ddt.unpack
def test_skip_ignored_lines(self, line, result):
@checks.skip_ignored_lines
def any_gen(physical_line, logical_line, file_name):
yield 42
self.assertEqual(result, list(any_gen(line, line, "f")))
def test_correct_usage_of_assert_from_mock(self): def test_correct_usage_of_assert_from_mock(self):
correct_method_names = ["assert_any_call", "assert_called_once_with", correct_method_names = ["assert_any_call", "assert_called_once_with",
"assert_called_with", "assert_has_calls"] "assert_called_with", "assert_has_calls"]
@ -71,7 +68,7 @@ class HackingTestCase(test.TestCase):
fake_method = "rtfm.assert_something()" fake_method = "rtfm.assert_something()"
actual_number, actual_msg = next(checks.check_assert_methods_from_mock( actual_number, actual_msg = next(checks.check_assert_methods_from_mock(
fake_method, fake_method, "./tests/fake/test")) fake_method, "./tests/fake/test"))
self.assertEqual(4, actual_number) self.assertEqual(4, actual_number)
self.assertTrue(actual_msg.startswith("N301")) self.assertTrue(actual_msg.startswith("N301"))
@ -79,7 +76,7 @@ class HackingTestCase(test.TestCase):
fake_method = "rtfm.assert_called()" fake_method = "rtfm.assert_called()"
actual_number, actual_msg = next(checks.check_assert_methods_from_mock( actual_number, actual_msg = next(checks.check_assert_methods_from_mock(
fake_method, fake_method, "./tests/fake/test")) fake_method, "./tests/fake/test", False))
self.assertEqual(4, actual_number) self.assertEqual(4, actual_number)
self.assertTrue(actual_msg.startswith("N302")) self.assertTrue(actual_msg.startswith("N302"))
@ -87,7 +84,7 @@ class HackingTestCase(test.TestCase):
fake_method = "rtfm.assert_called_once()" fake_method = "rtfm.assert_called_once()"
actual_number, actual_msg = next(checks.check_assert_methods_from_mock( actual_number, actual_msg = next(checks.check_assert_methods_from_mock(
fake_method, fake_method, "./tests/fake/test")) fake_method, "./tests/fake/test", False))
self.assertEqual(4, actual_number) self.assertEqual(4, actual_number)
self.assertTrue(actual_msg.startswith("N303")) self.assertTrue(actual_msg.startswith("N303"))
@ -100,16 +97,16 @@ class HackingTestCase(test.TestCase):
"import rally.common.logging"] "import rally.common.logging"]
for bad in bad_imports: for bad in bad_imports:
checkres = checks.check_import_of_logging(bad, bad, "fakefile") checkres = checks.check_import_of_logging(bad, "fakefile")
self.assertIsNotNone(next(checkres)) self.assertIsNotNone(next(checkres))
for bad in bad_imports: for bad in bad_imports:
checkres = checks.check_import_of_logging( checkres = checks.check_import_of_logging(
bad, bad, "./rally/common/logging.py") bad, "./rally/common/logging.py")
self.assertEqual([], list(checkres)) self.assertEqual([], list(checkres))
for good in good_imports: for good in good_imports:
checkres = checks.check_import_of_logging(good, good, "fakefile") checkres = checks.check_import_of_logging(good, "fakefile")
self.assertEqual([], list(checkres)) self.assertEqual([], list(checkres))
def test_no_use_conf_debug_check(self): def test_no_use_conf_debug_check(self):
@ -134,8 +131,7 @@ class HackingTestCase(test.TestCase):
) )
@ddt.unpack @ddt.unpack
def test_assert_true_instance(self, line, result): def test_assert_true_instance(self, line, result):
self.assertEqual( self.assertEqual(result, len(list(checks.assert_true_instance(line))))
result, len(list(checks.assert_true_instance(line, line, "f"))))
@ddt.data( @ddt.data(
{ {
@ -149,8 +145,7 @@ class HackingTestCase(test.TestCase):
) )
@ddt.unpack @ddt.unpack
def test_assert_equal_type(self, line, result): def test_assert_equal_type(self, line, result):
self.assertEqual(result, self.assertEqual(result, len(list(checks.assert_equal_type(line))))
len(list(checks.assert_equal_type(line, line, "f"))))
@ddt.data( @ddt.data(
{"line": "self.assertEqual(A, None)", "result": 1}, {"line": "self.assertEqual(A, None)", "result": 1},
@ -160,8 +155,7 @@ class HackingTestCase(test.TestCase):
@ddt.unpack @ddt.unpack
def test_assert_equal_none(self, line, result): def test_assert_equal_none(self, line, result):
self.assertEqual(result, self.assertEqual(result, len(list(checks.assert_equal_none(line))))
len(list(checks.assert_equal_none(line, line, "f"))))
@ddt.data( @ddt.data(
{"line": "self.assertNotEqual(A, None)", "result": 1}, {"line": "self.assertNotEqual(A, None)", "result": 1},
@ -171,9 +165,7 @@ class HackingTestCase(test.TestCase):
@ddt.unpack @ddt.unpack
def test_assert_not_equal_none(self, line, result): def test_assert_not_equal_none(self, line, result):
self.assertEqual(result, self.assertEqual(result, len(list(checks.assert_not_equal_none(line))))
len(list(checks.assert_not_equal_none(line,
line, "f"))))
def test_assert_true_or_false_with_in_or_not_in(self): def test_assert_true_or_false_with_in_or_not_in(self):
good_lines = [ good_lines = [
@ -334,16 +326,6 @@ class HackingTestCase(test.TestCase):
[], [],
list(checks.check_dict_formatting_in_string(sample, tokens))) list(checks.check_dict_formatting_in_string(sample, tokens)))
@ddt.data(
"text = unicode('sometext')",
"text = process(unicode('sometext'))"
)
def test_check_using_unicode(self, line):
checkres = checks.check_using_unicode(line, line, "fakefile")
self.assertIsNotNone(next(checkres))
self.assertEqual([], list(checkres))
def test_check_raises(self): def test_check_raises(self):
self._assert_bad_samples( self._assert_bad_samples(
checks.check_raises, checks.check_raises,
@ -357,21 +339,17 @@ class HackingTestCase(test.TestCase):
def test_check_db_imports_of_cli(self): def test_check_db_imports_of_cli(self):
line = "from rally.common import db" line = "from rally.common import db"
next(checks.check_db_imports_in_cli( next(checks.check_db_imports_in_cli(line, "./rally/cli/filename"))
line, line, "./rally/cli/filename"))
checkres = checks.check_db_imports_in_cli( checkres = checks.check_db_imports_in_cli(line, "./filename")
line, line, "./filename")
self.assertRaises(StopIteration, next, checkres) self.assertRaises(StopIteration, next, checkres)
def test_check_objects_imports_of_cli(self): def test_check_objects_imports_of_cli(self):
line = "from rally.common import objects" line = "from rally.common import objects"
next(checks.check_objects_imports_in_cli( next(checks.check_objects_imports_in_cli(line, "./rally/cli/filename"))
line, line, "./rally/cli/filename"))
checkres = checks.check_objects_imports_in_cli( checkres = checks.check_objects_imports_in_cli(line, "./filename")
line, line, "./filename")
self.assertRaises(StopIteration, next, checkres) self.assertRaises(StopIteration, next, checkres)
@ddt.data( @ddt.data(
@ -379,7 +357,7 @@ class HackingTestCase(test.TestCase):
"class Oldstyle:" "class Oldstyle:"
) )
def test_check_old_type_class(self, line): def test_check_old_type_class(self, line):
checkres = checks.check_old_type_class(line, line, "fakefile") checkres = checks.check_old_type_class(line)
self.assertIsNotNone(next(checkres)) self.assertIsNotNone(next(checkres))
self.assertEqual([], list(checkres)) self.assertEqual([], list(checkres))
@ -390,12 +368,12 @@ class HackingTestCase(test.TestCase):
"from datetime import datetime as dtime"] "from datetime import datetime as dtime"]
for line in lines: for line in lines:
checkres = checks.check_datetime_alias(line, line, "fakefile") checkres = checks.check_datetime_alias(line)
self.assertIsNotNone(next(checkres)) self.assertIsNotNone(next(checkres))
self.assertEqual([], list(checkres)) self.assertEqual([], list(checkres))
line = "import datetime as dt" line = "import datetime as dt"
checkres = checks.check_datetime_alias(line, line, "fakefile") checks.check_datetime_alias(line)
def test_check_log_warn(self): def test_check_log_warn(self):
bad_samples = ["LOG.warn('foo')", "LOG.warn(_('bar'))"] bad_samples = ["LOG.warn('foo')", "LOG.warn(_('bar'))"]

18
tox.ini
View File

@ -6,7 +6,6 @@ envlist = py36,py37,py38,pep8,samples
[testenv] [testenv]
extras = {env:RALLY_EXTRAS:} extras = {env:RALLY_EXTRAS:}
setenv = VIRTUAL_ENV={envdir} setenv = VIRTUAL_ENV={envdir}
HOME={homedir}
LANG=en_US.UTF-8 LANG=en_US.UTF-8
LANGUAGE=en_US:en LANGUAGE=en_US:en
LC_ALL=C LC_ALL=C
@ -15,6 +14,7 @@ setenv = VIRTUAL_ENV={envdir}
allowlist_externals = find allowlist_externals = find
rm rm
make make
mkdir
deps = -r{toxinidir}/requirements.txt deps = -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt -r{toxinidir}/test-requirements.txt
-c{toxinidir}/upper-constraints.txt -c{toxinidir}/upper-constraints.txt
@ -23,7 +23,7 @@ commands =
find . -type f -name "*.pyc" -delete find . -type f -name "*.pyc" -delete
python {toxinidir}/tests/ci/pytest_launcher.py tests/unit --posargs={posargs} python {toxinidir}/tests/ci/pytest_launcher.py tests/unit --posargs={posargs}
distribute = false distribute = false
basepython = python3.6 basepython = python3
passenv = passenv =
PYTEST_REPORT PYTEST_REPORT
http_proxy http_proxy
@ -32,6 +32,7 @@ passenv =
HTTPS_PROXY HTTPS_PROXY
no_proxy no_proxy
NO_PROXY NO_PROXY
HOME
[testenv:pep8] [testenv:pep8]
commands = flake8 commands = flake8
@ -66,15 +67,6 @@ commands =
find . -type f -name "*.pyc" -delete find . -type f -name "*.pyc" -delete
python {toxinidir}/tests/ci/pytest_launcher.py tests/functional --posargs={posargs} python {toxinidir}/tests/ci/pytest_launcher.py tests/functional --posargs={posargs}
[testenv:functional-py38]
deps = -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
stestr
basepython = python3.8
commands =
find . -type f -name "*.pyc" -delete
python {toxinidir}/tests/ci/pytest_launcher.py tests/functional --posargs={posargs}
[testenv:cover] [testenv:cover]
commands = {toxinidir}/tests/ci/cover.sh {posargs} commands = {toxinidir}/tests/ci/cover.sh {posargs}
allowlist_externals = {toxinidir}/tests/ci/cover.sh allowlist_externals = {toxinidir}/tests/ci/cover.sh
@ -126,7 +118,6 @@ extension =
N350 = checks:check_quotes N350 = checks:check_quotes
N351 = checks:check_no_constructor_data_struct N351 = checks:check_no_constructor_data_struct
N352 = checks:check_dict_formatting_in_string N352 = checks:check_dict_formatting_in_string
N353 = checks:check_using_unicode
N354 = checks:check_raises N354 = checks:check_raises
N355 = checks:check_old_type_class N355 = checks:check_old_type_class
N356 = checks:check_datetime_alias N356 = checks:check_datetime_alias
@ -177,5 +168,8 @@ filterwarnings =
ignore:Using or importing the ABCs:DeprecationWarning:unittest2.* ignore:Using or importing the ABCs:DeprecationWarning:unittest2.*
# python 3.8 # python 3.8
ignore:::.*netaddr.strategy.* ignore:::.*netaddr.strategy.*
# python 3.10
ignore:The distutils package is deprecated and slated for removal in Python 3.12. Use setuptools or check PEP 632 for potential alternatives:DeprecationWarning:
ignore:pkg_resources is deprecated as an API:DeprecationWarning:
# pytest-cov # pytest-cov
ignore:The --rsyncdir command line argument and rsyncdirs config variable are deprecated.:DeprecationWarning: ignore:The --rsyncdir command line argument and rsyncdirs config variable are deprecated.:DeprecationWarning: