Skip to content

Commit

Permalink
Merge branch '6.13.z' into cherry-pick-6.13.z-e34528585ec1e991a8f5a3d…
Browse files Browse the repository at this point in the history
…3505d352c3aa0427e
  • Loading branch information
synkd authored Nov 5, 2024
2 parents 87409b6 + 8a049cf commit 04bbcfe
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 38 deletions.
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ repos:
- id: check-yaml
- id: debug-statements
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.6.9
rev: v0.7.2
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
Expand All @@ -28,6 +28,6 @@ repos:
types: [text]
require_serial: true
- repo: https://github.com/gitleaks/gitleaks
rev: v8.20.1
rev: v8.21.2
hooks:
- id: gitleaks
74 changes: 64 additions & 10 deletions pytest_plugins/requirements/req_updater.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
from functools import cached_property
import subprocess
import sys


class UsageError(Exception):
"""The UsageError raised when the package manager is different from uv or pip"""

pass


class ReqUpdater:
# Installed package name as key and its counterpart in requirements file as value
package_deviates = {
'Betelgeuse': 'betelgeuse',
'broker': 'broker[docker]',
'broker': 'broker[docker,podman,hussh]',
'dynaconf': 'dynaconf[vault]',
'Jinja2': 'jinja2',
'Sphinx': 'sphinx',
'pyyaml': 'PyYAML',
}

@cached_property
Expand All @@ -18,9 +26,9 @@ def installed_packages(self):
This also normalizes any package names that deviates in requirements file vs installed names
"""
installed_pkges = subprocess.run(
'pip list --format=freeze', capture_output=True, shell=True
).stdout.decode()
installer_args = [sys.executable, '-m', 'list', '--format=freeze']
installer_args[2:2] = self.packagae_manager.split(' ')
installed_pkges = subprocess.run(installer_args, capture_output=True).stdout.decode()
for pkg in self.package_deviates:
if pkg in installed_pkges:
# Replacing the installed package names with their names in requirements file
Expand Down Expand Up @@ -56,16 +64,62 @@ def opt_deviation(self):
"""Returns new and updates available packages in requirements-optional file"""
return set(self.optional_packages).difference(self.installed_packages)

@cached_property
def packagae_manager(self):
if (
subprocess.run(
[sys.executable, '-m', 'pip', '--version'],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
).returncode
== 0
):
_manager = 'pip'
elif (
subprocess.run(
[sys.executable, '-m', 'uv', '--version'],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
).returncode
== 0
):
_manager = 'uv pip'
else:
raise UsageError(
'The package manager is not identifiable for performing package updates.'
'Currently only pip and uv is supported. Please manually update the packages '
'and rerun pytest command.'
)
return _manager

def install_req_deviations(self):
"""Installs new and updates available packages in requirements file"""
if self.req_deviation:
subprocess.run(
f"pip install {' '.join(self.req_deviation)}", shell=True, stdout=subprocess.PIPE
)
lst_of_reqs = ' '.join(f"'{req}'" for req in self.req_deviation)
if (
subprocess.run(
f"{self.packagae_manager} install {lst_of_reqs}",
shell=True,
stdout=subprocess.PIPE,
).returncode
== 0
):
print('Mandatory requirements are updated.')
else:
print('ERROR: Some issue occurred with updating the required requirements')

def install_opt_deviations(self):
"""Installs new and updates available packages in requirements-optional file"""
if self.opt_deviation:
subprocess.run(
f"pip install {' '.join(self.opt_deviation)}", shell=True, stdout=subprocess.PIPE
)
lst_of_reqs = ' '.join(f"'{req}'" for req in self.opt_deviation)
if (
subprocess.run(
f"{self.packagae_manager} install {lst_of_reqs}",
shell=True,
stdout=subprocess.PIPE,
).returncode
== 0
):
print('Optional requirements are updated.')
else:
print('ERROR: Some issue occurred with updating the optional requirements')
36 changes: 23 additions & 13 deletions pytest_plugins/requirements/update_requirements.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@
updater = ReqUpdater()


def git_deviation_filter(deviation):
"""Packages installed from Git branch and the version cant be compared, so ignore them from reporting"""
git_packages = ['nailgun', 'airgun']
return all(git_pckg not in deviation for git_pckg in git_packages)


def pytest_addoption(parser):
"""Options to allow user to update the requirements"""
update_options = {
Expand All @@ -28,24 +34,28 @@ def pytest_report_header(config):
# Following will update the mandatory and optional requirements
# pytest tests/foreman --collect-only --update-all-reqs
"""
if updater.req_deviation:
print(f"Mandatory Requirements Mismatch: {' '.join(updater.req_deviation)}")
if config.getoption('update_required_reqs') or config.getoption('update_all_reqs'):
updater.install_req_deviations()
print('Mandatory requirements are installed to be up-to-date.')
req_deviations = updater.req_deviation
filtered_req_deviations = list(filter(git_deviation_filter, req_deviations))
if filtered_req_deviations:
print(f"Mandatory Requirements Mismatch: {' '.join(filtered_req_deviations)}")
else:
print('Mandatory Requirements are up to date.')

if updater.opt_deviation:
print(f"Optional Requirements Mismatch: {' '.join(updater.opt_deviation)}")
if config.getoption('update_all_reqs'):
updater.install_opt_deviations()
print('Optional requirements are installed to be up-to-date.')
if req_deviations and (
config.getoption('update_required_reqs') or config.getoption('update_all_reqs')
):
updater.install_req_deviations()

opt_deviations = updater.opt_deviation
filtered_opt_deviations = list(filter(git_deviation_filter, opt_deviations))
if filtered_opt_deviations:
print(f"Optional Requirements Mismatch: {' '.join(filtered_opt_deviations)}")
else:
print('Optional Requirements are up to date.')
if opt_deviations and config.getoption('update_all_reqs'):
updater.install_opt_deviations()

if updater.req_deviation or updater.opt_deviation:
if req_deviations or opt_deviations:
print(
"To update mismatched requirements, run the pytest command with "
"To update requirements, run the pytest with "
"'--update-required-reqs' OR '--update-all-reqs' option."
)
2 changes: 1 addition & 1 deletion requirements-optional.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ ruff==0.6.9

# For generating documentation.
sphinx==8.1.3
sphinx-autoapi==3.3.2
sphinx-autoapi==3.3.3

# For 'manage' interactive shell
manage==0.1.15
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ fauxfactory==3.1.1
jinja2==3.1.4
manifester==0.2.8
navmazing==1.2.2
productmd==1.40
productmd==1.41
pyotp==2.9.0
python-box==7.2.0
pytest==8.3.3
pytest-order==1.3.0
pytest-services==2.2.1
pytest-mock==3.14.0
pytest-reportportal==5.4.4
pytest-reportportal==5.4.5
pytest-xdist==3.6.1
pytest-fixturecollection==0.1.2
pytest-ibutsu==2.2.4
Expand Down
9 changes: 4 additions & 5 deletions robottelo/utils/io/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@ def get_local_file_data(path):
checksum = hashlib.sha256(file_content).hexdigest()

try:
tarobj = tarfile.open(path, mode='r')
host_counts = get_host_counts(tarobj)
tarobj.close()
extractable = True
json_files_parsable = True
with tarfile.open(path, mode='r') as tarobj:
host_counts = get_host_counts(tarobj)
extractable = True
json_files_parsable = True
except (tarfile.TarError, json.JSONDecodeError):
host_counts = {}
extractable = False
Expand Down
2 changes: 1 addition & 1 deletion tests/foreman/api/test_provisioningtemplate.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ def test_positive_end_to_end_crud(
# clone
template_origin = template.read_json()
# remove unique keys
unique_keys = ('updated_at', 'created_at', 'id', 'name')
unique_keys = ('updated_at', 'created_at', 'id', 'name', 'cloned_from_id')
template_origin = {
key: value for key, value in template_origin.items() if key not in unique_keys
}
Expand Down
7 changes: 3 additions & 4 deletions tests/robottelo/test_func_locker.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,9 @@ class TmpCountFile:
def __init__(self):
tmp_root_path = Path(func_locker.get_temp_dir()).joinpath(func_locker.TEMP_ROOT_DIR)
tmp_root_path.mkdir(parents=True, exist_ok=True)
self.file = tempfile.NamedTemporaryFile(delete=False, suffix='.counter', dir=tmp_root_path)
self.file_name = self.file.name
self.file.write(b'0')
self.file.close()
with tempfile.NamedTemporaryFile(delete=False, suffix='.counter', dir=tmp_root_path) as cf:
cf.write(b'0')
self.file_name = cf.name

def read(self):
with open(self.file_name) as cf:
Expand Down

0 comments on commit 04bbcfe

Please sign in to comment.