Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Python 3.12 to supported versions #12793

Merged
merged 3 commits into from
Feb 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/pull_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.10', '3.11']
python-version: ['3.10', '3.11', '3.12']
steps:
- name: Checkout Robottelo
uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/weekly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.11]
python-version: [3.12]
steps:
- name: Checkout Robottelo
uses: actions/checkout@v4
Expand Down
7 changes: 6 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Version updates managed by dependabot

betelgeuse==1.11.0
broker[docker]==0.4.1
# broker[docker]==0.4.1 - Temporarily disabled, see below
cryptography==42.0.2
deepdiff==6.7.1
dynaconf[vault]==3.2.4
Expand Down Expand Up @@ -30,4 +30,9 @@ wrapanapi==3.6.0
# Get airgun, nailgun and upgrade from master
git+https://github.com/SatelliteQE/airgun.git@master#egg=airgun
git+https://github.com/SatelliteQE/nailgun.git@master#egg=nailgun
# Broker currently is unable to push to PyPi due to [1] and [2]
# In the meantime, we install directly from the repo
# [1] - https://github.com/ParallelSSH/ssh2-python/issues/193
# [2] - https://github.com/pypi/warehouse/issues/7136
Comment on lines +35 to +36
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think both of these issues have been resolved now, so can we keep this the way it is?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And the pypi issue is closed as a wontfix, so the issue is still affecting us. I have an idea about the latter, but we need this for now.

git+https://github.com/SatelliteQE/[email protected]#egg=broker
--editable .
8 changes: 4 additions & 4 deletions robottelo/cli/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,26 +132,26 @@ def delete(cls, options=None, timeout=None):
return cls.execute(cls._construct_command(options), ignore_stderr=True, timeout=timeout)

@classmethod
def delete_parameter(cls, options=None):
def delete_parameter(cls, options=None, timeout=None):
"""
Deletes parameter from record.
"""

cls.command_sub = 'delete-parameter'

result = cls.execute(cls._construct_command(options))
result = cls.execute(cls._construct_command(options), ignore_stderr=False, timeout=timeout)
Gauravtalreja1 marked this conversation as resolved.
Show resolved Hide resolved

return result

@classmethod
def dump(cls, options=None):
def dump(cls, options=None, timeout=None):
"""
Displays the content for existing partition table.
"""

cls.command_sub = 'dump'

result = cls.execute(cls._construct_command(options))
result = cls.execute(cls._construct_command(options), ignore_stderr=False, timeout=timeout)

return result

Expand Down
4 changes: 2 additions & 2 deletions robottelo/cli/subscription.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def refresh_manifest(cls, options=None, timeout=None):
return cls.execute(cls._construct_command(options), ignore_stderr=True, timeout=timeout)

@classmethod
def manifest_history(cls, options=None):
def manifest_history(cls, options=None, timeout=None):
"""Provided history for subscription manifest"""
cls.command_sub = 'manifest-history'
return cls.execute(cls._construct_command(options))
return cls.execute(cls._construct_command(options), ignore_stderr=True, timeout=timeout)
134 changes: 97 additions & 37 deletions tests/robottelo/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,8 @@ def test_add_operating_system(self, construct, execute):
assert 'add-operatingsystem' != Base.command_sub
assert execute.return_value == Base.add_operating_system(options)
assert 'add-operatingsystem' == Base.command_sub
construct.called_once_with(options)
execute.called_once_with(construct.return_value)
construct.assert_called_once_with(options)
execute.assert_called_once_with(construct.return_value)

@mock.patch('robottelo.cli.base.Base.execute')
@mock.patch('robottelo.cli.base.Base._construct_command')
Expand All @@ -159,8 +159,8 @@ def test_add_create_with_empty_result(self, construct, execute):
execute.return_value = []
assert execute.return_value == Base.create()
assert 'create' == Base.command_sub
construct.called_once_with({})
execute.called_once_with(construct.return_value, output_format='csv')
construct.assert_called_once_with({})
execute.assert_called_once_with(construct.return_value, output_format='csv', timeout=None)

@mock.patch('robottelo.cli.base.Base.info')
@mock.patch('robottelo.cli.base.Base.execute')
Expand All @@ -170,8 +170,8 @@ def test_add_create_with_result_dct_without_id(self, construct, execute, info):
execute.return_value = [{'not_id': 'foo'}]
assert execute.return_value == Base.create()
assert 'create' == Base.command_sub
construct.called_once_with({})
execute.called_once_with(construct.return_value, output_format='csv')
construct.assert_called_once_with({})
execute.assert_called_once_with(construct.return_value, output_format='csv', timeout=None)
assert not info.called

@mock.patch('robottelo.cli.base.Base.info')
Expand All @@ -185,9 +185,9 @@ def test_add_create_with_result_dct_with_id_not_required_org(self, construct, ex
Base.command_requires_org = False
assert execute.return_value == Base.create()
assert 'create' == Base.command_sub
construct.called_once_with({})
execute.called_once_with(construct.return_value, output_format='csv')
info.called_once_with({'id': 'foo'})
construct.assert_called_once_with({})
execute.assert_called_once_with(construct.return_value, output_format='csv', timeout=None)
info.assert_called_once_with({'id': 'foo'})

@mock.patch('robottelo.cli.base.Base.info')
@mock.patch('robottelo.cli.base.Base.execute')
Expand All @@ -200,9 +200,9 @@ def test_add_create_with_result_dct_with_id_required_org(self, construct, execut
Base.command_requires_org = True
assert execute.return_value == Base.create({'organization-id': 'org-id'})
assert 'create' == Base.command_sub
construct.called_once_with({})
execute.called_once_with(construct.return_value, output_format='csv')
info.called_once_with({'id': 'foo', 'organization-id': 'org-id'})
construct.assert_called_once_with({'organization-id': 'org-id'})
execute.assert_called_once_with(construct.return_value, output_format='csv', timeout=None)
info.assert_called_once_with({'id': 'foo', 'organization-id': 'org-id'})

@mock.patch('robottelo.cli.base.Base.execute')
@mock.patch('robottelo.cli.base.Base._construct_command')
Expand All @@ -215,17 +215,19 @@ def test_add_create_with_result_dct_id_required_org_error(self, construct, execu
with pytest.raises(CLIError):
Base.create()
assert 'create' == Base.command_sub
construct.called_once_with({})
execute.called_once_with(construct.return_value, output_format='csv')
construct.assert_called_once_with({})
execute.assert_called_once_with(construct.return_value, output_format='csv', timeout=None)

def assert_cmd_execution(
self, construct, execute, base_method, cmd_sub, ignore_stderr=False, **base_method_kwargs
):
"""Asssert Base class method successfully executed"""
assert execute.return_value == base_method(**base_method_kwargs)
assert cmd_sub == Base.command_sub
construct.called_once_with({})
execute.called_once_with(construct.return_value, ignore_stderr=ignore_stderr)
construct.assert_called_once_with(base_method_kwargs.get('options'))
execute.assert_called_once_with(
construct.return_value, ignore_stderr=ignore_stderr, timeout=None
)

@mock.patch('robottelo.cli.base.Base.execute')
@mock.patch('robottelo.cli.base.Base._construct_command')
Expand Down Expand Up @@ -308,16 +310,36 @@ def test_info_requires_organization_id(self, _): # noqa: PT019 - not a fixture
with pytest.raises(CLIError):
Base.info()

def assert_alt_cmd_execution(
self,
construct,
execute,
base_method,
cmd_sub,
call_kwargs,
command_kwarg=True,
**base_method_kwargs,
):
"""Asssert Base class method successfully executed"""
assert execute.return_value == base_method(**base_method_kwargs)
assert cmd_sub == Base.command_sub
construct.assert_called_once_with(base_method_kwargs.get('options'))
if command_kwarg:
execute.assert_called_once_with(command=construct.return_value, **call_kwargs)
else:
execute.assert_called_once_with(construct.return_value, **call_kwargs)

@mock.patch('robottelo.cli.base.hammer.parse_info')
@mock.patch('robottelo.cli.base.Base.execute')
@mock.patch('robottelo.cli.base.Base._construct_command')
def test_info_without_parsing_response(self, construct, execute, parse):
"""Check info method execution without parsing response"""
self.assert_cmd_execution(
self.assert_alt_cmd_execution(
construct,
execute,
Base.info,
'info',
call_kwargs={'output_format': 'json', 'return_raw_response': None},
output_format='json',
options={'organization-id': 1},
)
Expand All @@ -329,27 +351,24 @@ def test_info_without_parsing_response(self, construct, execute, parse):
def test_info_parsing_response(self, construct, execute, parse):
"""Check info method execution parsing response"""
parse.return_value = execute.return_value = 'some_response'
self.assert_cmd_execution(
construct, execute, Base.info, 'info', options={'organization-id': 1}
self.assert_alt_cmd_execution(
construct,
execute,
Base.info,
'info',
call_kwargs={'output_format': None, 'return_raw_response': None},
options={'organization-id': 1},
)
parse.called_once_with('some_response')

# @mock.patch('robottelo.cli.base.Base.command_requires_org')
# def test_list_requires_organization_id(self, _):
# """Check list raises CLIError with organization-id is not present in
# options
# """
# with pytest.raises(CLIError):
# Base.list()
parse.assert_called_once_with('some_response')

@mock.patch('robottelo.cli.base.Base.execute')
@mock.patch('robottelo.cli.base.Base._construct_command')
def test_list_with_default_per_page(self, construct, execute):
"""Check list method set per_page as 1000 by default"""
assert execute.return_value == Base.list(options={'organization-id': 1})
assert 'list' == Base.command_sub
construct.called_once_with({'per-page': 1000})
execute.called_once_with(construct.return_value, output_format='csv')
construct.assert_called_once_with({'organization-id': 1, 'per-page': 10000})
execute.assert_called_once_with(construct.return_value, output_format='csv')

@mock.patch('robottelo.cli.base.Base.execute')
@mock.patch('robottelo.cli.base.Base._construct_command')
Expand All @@ -358,39 +377,80 @@ def test_list_without_per_page(self, construct, execute):
list_with_per_page_false = partial(
Base.list, per_page=False, options={'organization-id': 1}
)
self.assert_cmd_execution(construct, execute, list_with_per_page_false, 'list')
self.assert_alt_cmd_execution(
construct,
execute,
list_with_per_page_false,
'list',
call_kwargs={'output_format': 'csv'},
command_kwarg=False,
options={'organization-id': 1},
)

@mock.patch('robottelo.cli.base.Base.execute')
@mock.patch('robottelo.cli.base.Base._construct_command')
def test_puppet_classes(self, construct, execute):
"""Check puppet_classes method execution"""
self.assert_cmd_execution(construct, execute, Base.puppetclasses, 'puppet-classes')
self.assert_alt_cmd_execution(
construct,
execute,
Base.puppetclasses,
'puppet-classes',
call_kwargs={'output_format': 'csv'},
command_kwarg=False,
)

@mock.patch('robottelo.cli.base.Base.execute')
@mock.patch('robottelo.cli.base.Base._construct_command')
def test_remove_operating_system(self, construct, execute):
"""Check remove_operating_system method execution"""
self.assert_cmd_execution(
construct, execute, Base.remove_operating_system, 'remove-operatingsystem'
self.assert_alt_cmd_execution(
construct,
execute,
Base.remove_operating_system,
'remove-operatingsystem',
call_kwargs={},
command_kwarg=False,
)

@mock.patch('robottelo.cli.base.Base.execute')
@mock.patch('robottelo.cli.base.Base._construct_command')
def test_sc_params(self, construct, execute):
"""Check sc_params method execution"""
self.assert_cmd_execution(construct, execute, Base.sc_params, 'sc-params')
self.assert_alt_cmd_execution(
construct,
execute,
Base.sc_params,
'sc-params',
call_kwargs={'output_format': 'csv'},
command_kwarg=False,
)

@mock.patch('robottelo.cli.base.Base.execute')
@mock.patch('robottelo.cli.base.Base._construct_command')
def test_set_parameter(self, construct, execute):
"""Check set_parameter method execution"""
self.assert_cmd_execution(construct, execute, Base.set_parameter, 'set-parameter')
self.assert_alt_cmd_execution(
construct,
execute,
Base.set_parameter,
'set-parameter',
call_kwargs={},
command_kwarg=False,
)

@mock.patch('robottelo.cli.base.Base.execute')
@mock.patch('robottelo.cli.base.Base._construct_command')
def test_update(self, construct, execute):
"""Check update method execution"""
self.assert_cmd_execution(construct, execute, Base.update, 'update')
self.assert_alt_cmd_execution(
construct,
execute,
Base.update,
'update',
call_kwargs={'output_format': 'csv', 'return_raw_response': None},
command_kwarg=False,
)


class CLIErrorTests(unittest.TestCase):
Expand Down
18 changes: 9 additions & 9 deletions tests/robottelo/test_cli_method_calls.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ def test_cli_org_method_called(mocker, command_sub):
options = {'foo': 'bar'}
assert execute.return_value == getattr(Org, command_sub.replace('-', '_'))(options)
assert command_sub == Org.command_sub
assert construct.called_once_with(options)
assert execute.called_once_with(construct.return_value)
construct.assert_called_once_with(options)
execute.assert_called_once_with(construct.return_value)


@pytest.mark.parametrize('command_sub', ['import-classes', 'refresh-features'])
Expand All @@ -54,11 +54,11 @@ def test_cli_proxy_method_called(mocker, command_sub):
options = {'foo': 'bar'}
assert execute.return_value == getattr(Proxy, command_sub.replace('-', '_'))(options)
assert command_sub == Proxy.command_sub
assert construct.called_once_with(options)
assert execute.called_once_with(construct.return_value)
construct.assert_called_once_with(options)
execute.assert_called_once_with(construct.return_value)


@pytest.mark.parametrize('command_sub', ['synchronize', 'remove-content', 'upload-content'])
@pytest.mark.parametrize('command_sub', ['remove-content', 'upload-content'])
def test_cli_repository_method_called(mocker, command_sub):
"""Check Repository methods are called and command_sub edited
This is a parametrized test called by Pytest for each of Repository methods
Expand All @@ -68,8 +68,8 @@ def test_cli_repository_method_called(mocker, command_sub):
options = {'foo': 'bar'}
assert execute.return_value == getattr(Repository, command_sub.replace('-', '_'))(options)
assert command_sub == Repository.command_sub
assert construct.called_once_with(options)
assert execute.called_once_with(construct.return_value)
construct.assert_called_once_with(options)
execute.assert_called_once_with(construct.return_value, output_format='csv', ignore_stderr=True)


@pytest.mark.parametrize('command_sub', ['info', 'create'])
Expand All @@ -94,5 +94,5 @@ def test_cli_subscription_method_called(mocker, command_sub):
options = {'foo': 'bar'}
assert execute.return_value == getattr(Subscription, command_sub.replace('-', '_'))(options)
assert command_sub == Subscription.command_sub
assert construct.called_once_with(options)
assert execute.called_once_with(construct.return_value)
construct.assert_called_once_with(options)
execute.assert_called_once_with(construct.return_value, ignore_stderr=True, timeout=None)
Loading