diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 777e7fced..a349a80fa 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -12,6 +12,31 @@ concurrency: cancel-in-progress: true jobs: + sanity: + name: Sanity (Ⓐ${{ matrix.ansible }}) + strategy: + matrix: + ansible: + - stable-2.15 + - stable-2.16 + - stable-2.17 + - stable-2.18 + - devel + + runs-on: ubuntu-latest + + steps: + # Run sanity tests inside a Docker container. + # The docker container has all the pinned dependencies that are + # required and all Python versions Ansible supports. + - name: Perform sanity testing + uses: ansible-community/ansible-test-gh-action@release/v1 + with: + ansible-core-version: ${{ matrix.ansible }} + testing-type: sanity + pull-request-change-detection: false + pre-test-cmd: rm -rf tests/fixtures tests/test_playbooks/fixtures + build: runs-on: ubuntu-20.04 container: ${{ matrix.container }} @@ -86,9 +111,6 @@ jobs: run: make test-other - name: Run dist tests run: make dist-test - - name: Run sanity tests - run: make SANITY_OPTS="--docker" sanity - if: matrix.ansible != 'v2.10.4' && matrix.ansible != 'stable-2.11' && matrix.ansible != 'stable-2.12' && matrix.ansible != 'stable-2.13' && matrix.ansible != 'stable-2.14' checkmode: runs-on: ubuntu-latest diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 7e3b9e13a..dc9865faf 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -6,6 +6,19 @@ redhat.satellite Release Notes This changelog describes changes after version 0.8.1. +v5.1.0 +====== + +Minor Changes +------------- + +- templates_import - Support configuring HTTP Proxy behaviour for template import + +Bugfixes +-------- + +- inventory - Drop fallback to Host API when Reports API fails, as this leads to possibly wrong data being used + v5.0.0 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index 00a644e15..b2a3e8bb0 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -928,3 +928,14 @@ releases: - drop-ansible-29.yaml - drop-python-pre-36.yaml release_date: '2024-11-22' + 5.1.0: + changes: + bugfixes: + - inventory - Drop fallback to Host API when Reports API fails, as this leads + to possibly wrong data being used + minor_changes: + - templates_import - Support configuring HTTP Proxy behaviour for template + import + fragments: + - drop-host-api-fallback.yml + release_date: '2024-12-06' diff --git a/changelogs/fragments/.git-keep b/changelogs/fragments/.gitkeep similarity index 100% rename from changelogs/fragments/.git-keep rename to changelogs/fragments/.gitkeep diff --git a/galaxy.yml b/galaxy.yml index ae673a3a9..f47283edd 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -94,6 +94,7 @@ authors: - "Yifat Makias " - "ab " - "achevalet " + - "adamlazik1 " - "alesc " - "bob <57952350+TheRedGreek@users.noreply.github.com>" - "calvingsmith <4283930+calvingsmith@users.noreply.github.com>" @@ -109,7 +110,7 @@ authors: - "russianguppie <46544650+russianguppie@users.noreply.github.com>" - "willtome " - "yuqo2450 <79540477+yuqo2450@users.noreply.github.com>" -version: "5.0.0" +version: "5.1.0" license: - "GPL-3.0-or-later" tags: diff --git a/generate_action_groups.py b/generate_action_groups.py index 46a11b0dd..ca61ae2f8 100644 --- a/generate_action_groups.py +++ b/generate_action_groups.py @@ -11,4 +11,4 @@ runtime['action_groups']['satellite'] = sorted(set(ALL_MODULES) - set(EXCLUDED_MODULES)) with open(META_RUNTIME, 'w') as runtime_file: - yaml.safe_dump(runtime, runtime_file, default_flow_style=False, explicit_start=True) + yaml.safe_dump(runtime, runtime_file, default_flow_style=False, explicit_start=True) diff --git a/plugins/inventory/foreman.py b/plugins/inventory/foreman.py index 4b4deb68a..59bbc7b46 100644 --- a/plugins/inventory/foreman.py +++ b/plugins/inventory/foreman.py @@ -474,13 +474,10 @@ def _get_hostname(self, properties, hostnames, strict=False): def _populate_report_api(self): self.groups = dict() self.hosts = dict() - try: - # We need a deep copy of the data, as we modify it below and this would also modify the cache - host_data = copy.deepcopy(self._post_request()) - except Exception as exc: - self.display.warning("Failed to use Reports API, falling back to Hosts API: {0}".format(exc)) - self._populate_host_api() - return + + # We need a deep copy of the data, as we modify it below and this would also modify the cache + host_data = copy.deepcopy(self._post_request()) + self.group_prefix = self.get_option('group_prefix') hostnames = self.get_option('hostnames') diff --git a/plugins/module_utils/foreman_helper.py b/plugins/module_utils/foreman_helper.py index b5b4a87b7..04525242d 100644 --- a/plugins/module_utils/foreman_helper.py +++ b/plugins/module_utils/foreman_helper.py @@ -13,7 +13,6 @@ import os import operator import re -import time import traceback from contextlib import contextmanager @@ -397,7 +396,6 @@ def __init__(self, **kwargs): self.fail_json(msg="The server URL needs to be either HTTPS or HTTP!") self.task_timeout = 60 - self.task_poll = 4 self._thin_default = False self.state = 'undefined' @@ -608,12 +606,12 @@ def connect(self): that are required by the module. """ - self.foremanapi = apypie.Api( + self.foremanapi = apypie.ForemanApi( uri=self._foremanapi_server_url, username=to_bytes(self._foremanapi_username), password=to_bytes(self._foremanapi_password), - api_version=2, verify_ssl=self._foremanapi_validate_certs, + task_timeout=self.task_timeout, ) _status = self.status() @@ -651,18 +649,6 @@ def status(self): return self.foremanapi.resource('home').call('status') - def _resource(self, resource): - if resource not in self.foremanapi.resources: - raise Exception("The server doesn't know about {0}, is the right plugin installed?".format(resource)) - return self.foremanapi.resource(resource) - - def _resource_call(self, resource, *args, **kwargs): - return self._resource(resource).call(*args, **kwargs) - - def _resource_prepare_params(self, resource, action, params): - api_action = self._resource(resource).action(action) - return api_action.prepare_params(params) - @_exception2fail_json(msg='Failed to show resource: {0}') def show_resource(self, resource, resource_id, params=None): """ @@ -676,16 +662,7 @@ def show_resource(self, resource, resource_id, params=None): :type params: Union[dict,None], optional """ - if params is None: - params = {} - else: - params = params.copy() - - params['id'] = resource_id - - params = self._resource_prepare_params(resource, 'show', params) - - return self._resource_call(resource, 'show', params) + return self.foremanapi.show(resource, resource_id, params) @_exception2fail_json(msg='Failed to list resource: {0}') def list_resource(self, resource, search=None, params=None): @@ -700,18 +677,7 @@ def list_resource(self, resource, search=None, params=None): :type params: Union[dict,None], optional """ - if params is None: - params = {} - else: - params = params.copy() - - if search is not None: - params['search'] = search - params['per_page'] = PER_PAGE - - params = self._resource_prepare_params(resource, 'index', params) - - return self._resource_call(resource, 'index', params)['results'] + return self.foremanapi.list(resource, search, params) def find_resource(self, resource, search, params=None, failsafe=False, thin=None): list_params = {} @@ -1024,9 +990,7 @@ def _validate_supported_payload(self, resource, action, payload): :return: The payload as it can be submitted to the API :rtype: dict """ - filtered_payload = self._resource_prepare_params(resource, action, payload) - # On Python 2 dict.keys() is just a list, but we need a set here. - unsupported_parameters = set(payload.keys()) - set(_recursive_dict_keys(filtered_payload)) + filtered_payload, unsupported_parameters = self.foremanapi.validate_payload(resource, action, payload) if unsupported_parameters: warn_msg = "The following parameters are not supported by your server when performing {0} on {1}: {2}. They were ignored." self.warn(warn_msg.format(action, resource, unsupported_parameters)) @@ -1050,14 +1014,12 @@ def _create_entity(self, resource, desired_entity, params, foreman_spec): """ payload = _flatten_entity(desired_entity, foreman_spec) self._validate_supported_payload(resource, 'create', payload) + self.set_changed() if not self.check_mode: - if params: - payload.update(params) - return self.resource_action(resource, 'create', payload) + return self.foremanapi.create(resource, payload, params) else: fake_entity = desired_entity.copy() fake_entity['id'] = -1 - self.set_changed() return fake_entity def _update_entity(self, resource, desired_entity, current_entity, params, foreman_spec): @@ -1111,16 +1073,14 @@ def _update_entity(self, resource, desired_entity, current_entity, params, forem if new_value != old_value: payload[key] = value if self._validate_supported_payload(resource, 'update', payload): + self.set_changed() payload['id'] = current_flat_entity['id'] if not self.check_mode: - if params: - payload.update(params) - return self.resource_action(resource, 'update', payload) + return self.foremanapi.update(resource, payload, params) else: # In check_mode we emulate the server updating the entity fake_entity = current_flat_entity.copy() fake_entity.update(payload) - self.set_changed() return fake_entity else: # Nothing needs changing @@ -1183,29 +1143,18 @@ def _delete_entity(self, resource, current_entity, params): :return: The new current state of the entity :rtype: Union[dict,None] """ - payload = {'id': current_entity['id']} - if params: - payload.update(params) - entity = self.resource_action(resource, 'destroy', payload) - - # this is a workaround for https://projects.theforeman.org/issues/26937 - if entity and isinstance(entity, dict) and 'error' in entity and 'message' in entity['error']: - self.fail_json(msg=entity['error']['message']) - - return None + self.set_changed() + if not self.check_mode: + return self.foremanapi.delete(resource, current_entity, params) + else: + return None def resource_action(self, resource, action, params, options=None, data=None, files=None, ignore_check_mode=False, record_change=True, ignore_task_errors=False): - resource_payload = self._resource_prepare_params(resource, action, params) - if options is None: - options = {} try: result = None if ignore_check_mode or not self.check_mode: - result = self._resource_call(resource, action, resource_payload, options=options, data=data, files=files) - is_foreman_task = isinstance(result, dict) and 'action' in result and 'state' in result and 'started_at' in result - if is_foreman_task: - result = self.wait_for_task(result, ignore_errors=ignore_task_errors) + result = self.foremanapi.resource_action(resource, action, params, options, data, files, ignore_task_errors) except Exception as e: msg = 'Error while performing {0} on {1}: {2}'.format( action, resource, to_native(e)) @@ -1216,18 +1165,7 @@ def resource_action(self, resource, action, params, options=None, data=None, fil return result def wait_for_task(self, task, ignore_errors=False): - duration = self.task_timeout - while task['state'] not in ['paused', 'stopped']: - duration -= self.task_poll - if duration <= 0: - self.fail_json(msg="Timeout waiting for Task {0}".format(task['id'])) - time.sleep(self.task_poll) - - resource_payload = self._resource_prepare_params('foreman_tasks', 'show', {'id': task['id']}) - task = self._resource_call('foreman_tasks', 'show', resource_payload) - if not ignore_errors and task['result'] != 'success': - self.fail_json(msg='Task {0}({1}) did not succeed. Task information: {2}'.format(task['action'], task['id'], task['humanized']['errors'])) - return task + return self.foremanapi.wait_for_task(task, ignore_errors) def fail_from_exception(self, exc, msg): fail = {'msg': msg} @@ -1759,15 +1697,6 @@ def _flatten_entity(entity, foreman_spec): return result -def _recursive_dict_keys(a_dict): - """Find all keys of a nested dictionary""" - keys = set(a_dict.keys()) - for _k, v in a_dict.items(): - if isinstance(v, dict): - keys.update(_recursive_dict_keys(v)) - return keys - - def _recursive_dict_without_none(a_dict, exclude=None): """ Remove all entries with `None` value from a dict, recursively. diff --git a/plugins/modules/templates_import.py b/plugins/modules/templates_import.py index 973034c5c..c23e6089c 100644 --- a/plugins/modules/templates_import.py +++ b/plugins/modules/templates_import.py @@ -90,6 +90,23 @@ - The directory within Git repo containing the templates. required: false type: str + http_proxy_policy: + description: + - HTTP proxy policy for template sync. + - You can choose no HTTP proxy, global HTTP proxy, or a custom HTTP proxy (C(selected)) + - If you choose 'selected', provide the C(http_proxy) parameter. + required: false + type: str + choices: + - none + - global + - selected + http_proxy: + description: + - HTTP proxy to use for template sync. + - Use this parameter together with C(http_proxy_policy=selected) + required: false + type: str attributes: check_mode: support: none @@ -156,9 +173,12 @@ def main(): force=dict(type='bool'), lock=dict(type='bool'), negate=dict(type='bool'), + http_proxy_policy=dict(choices=['global', 'none', 'selected']), + http_proxy=dict(type='entity'), ), supports_check_mode=False, required_plugins=[('templates', ['*'])], + required_if=[('http_proxy_policy', 'selected', ['http_proxy'])], ) with module.api_connection(): diff --git a/plugins/modules/user.py b/plugins/modules/user.py index 1cdb9397c..648fdb0b3 100644 --- a/plugins/modules/user.py +++ b/plugins/modules/user.py @@ -75,7 +75,7 @@ type: str default_organization: description: - - The organizxation that the user uses by default + - The organization that the user uses by default required: false type: str auth_source: diff --git a/roles/activation_keys/meta/main.yml b/roles/activation_keys/meta/main.yml new file mode 100644 index 000000000..4b6067764 --- /dev/null +++ b/roles/activation_keys/meta/main.yml @@ -0,0 +1,4 @@ +--- +galaxy_info: + description: Create and manage Activation Keys + standalone: false diff --git a/roles/auth_sources_ldap/meta/main.yml b/roles/auth_sources_ldap/meta/main.yml new file mode 100644 index 000000000..dd05c42d5 --- /dev/null +++ b/roles/auth_sources_ldap/meta/main.yml @@ -0,0 +1,4 @@ +--- +galaxy_info: + description: Create and manage LDAP authentication sources + standalone: false diff --git a/roles/compute_profiles/meta/main.yml b/roles/compute_profiles/meta/main.yml new file mode 100644 index 000000000..e03886ec5 --- /dev/null +++ b/roles/compute_profiles/meta/main.yml @@ -0,0 +1,4 @@ +--- +galaxy_info: + description: Create and manage Compute Profiles + standalone: false diff --git a/roles/compute_resources/meta/main.yml b/roles/compute_resources/meta/main.yml new file mode 100644 index 000000000..274db5f77 --- /dev/null +++ b/roles/compute_resources/meta/main.yml @@ -0,0 +1,4 @@ +--- +galaxy_info: + description: Create and manage Compute Resources + standalone: false diff --git a/roles/content_credentials/meta/main.yml b/roles/content_credentials/meta/main.yml new file mode 100644 index 000000000..4d654d589 --- /dev/null +++ b/roles/content_credentials/meta/main.yml @@ -0,0 +1,4 @@ +--- +galaxy_info: + description: Create and manage Content Credentials + standalone: false diff --git a/roles/content_rhel/meta/main.yml b/roles/content_rhel/meta/main.yml new file mode 100644 index 000000000..af0ac536b --- /dev/null +++ b/roles/content_rhel/meta/main.yml @@ -0,0 +1,4 @@ +--- +galaxy_info: + description: Configuration for everything needed to register and patch existing RHEL clients + standalone: false diff --git a/roles/content_view_publish/meta/main.yml b/roles/content_view_publish/meta/main.yml new file mode 100644 index 000000000..84d4718b6 --- /dev/null +++ b/roles/content_view_publish/meta/main.yml @@ -0,0 +1,4 @@ +--- +galaxy_info: + description: Publish a list of Content Views + standalone: false diff --git a/roles/content_view_version_cleanup/meta/main.yml b/roles/content_view_version_cleanup/meta/main.yml new file mode 100644 index 000000000..cfb8ae88d --- /dev/null +++ b/roles/content_view_version_cleanup/meta/main.yml @@ -0,0 +1,4 @@ +--- +galaxy_info: + description: Clean up unused Content View Versions + standalone: false diff --git a/roles/content_views/meta/main.yml b/roles/content_views/meta/main.yml new file mode 100644 index 000000000..54fee639c --- /dev/null +++ b/roles/content_views/meta/main.yml @@ -0,0 +1,4 @@ +--- +galaxy_info: + description: Create and manage Content Views + standalone: false diff --git a/roles/convert2rhel/meta/main.yml b/roles/convert2rhel/meta/main.yml new file mode 100644 index 000000000..9d428cd2d --- /dev/null +++ b/roles/convert2rhel/meta/main.yml @@ -0,0 +1,4 @@ +--- +galaxy_info: + description: Configure everything needed to register and convert CentOS clients to Red Hat Enterprise Linux + standalone: false diff --git a/roles/domains/meta/main.yml b/roles/domains/meta/main.yml new file mode 100644 index 000000000..cad3ead18 --- /dev/null +++ b/roles/domains/meta/main.yml @@ -0,0 +1,4 @@ +--- +galaxy_info: + description: Create and manage Domains + standalone: false diff --git a/roles/hostgroups/meta/main.yml b/roles/hostgroups/meta/main.yml new file mode 100644 index 000000000..3727a9ad7 --- /dev/null +++ b/roles/hostgroups/meta/main.yml @@ -0,0 +1,4 @@ +--- +galaxy_info: + description: Create and manage Hostgroups + standalone: false diff --git a/roles/lifecycle_environments/meta/main.yml b/roles/lifecycle_environments/meta/main.yml new file mode 100644 index 000000000..efd21e586 --- /dev/null +++ b/roles/lifecycle_environments/meta/main.yml @@ -0,0 +1,4 @@ +--- +galaxy_info: + description: Create and manage Lifecycle Environments + standalone: false diff --git a/roles/locations/meta/main.yml b/roles/locations/meta/main.yml new file mode 100644 index 000000000..160192a19 --- /dev/null +++ b/roles/locations/meta/main.yml @@ -0,0 +1,4 @@ +--- +galaxy_info: + description: Create and manage Locations + standalone: false diff --git a/roles/manifest/meta/main.yml b/roles/manifest/meta/main.yml new file mode 100644 index 000000000..3e4ad23bf --- /dev/null +++ b/roles/manifest/meta/main.yml @@ -0,0 +1,4 @@ +--- +galaxy_info: + description: Fetch a Manifest from the Red Hat Portal and upload it to Foreman + standalone: false diff --git a/roles/operatingsystems/meta/main.yml b/roles/operatingsystems/meta/main.yml new file mode 100644 index 000000000..43dbd41f5 --- /dev/null +++ b/roles/operatingsystems/meta/main.yml @@ -0,0 +1,4 @@ +--- +galaxy_info: + description: Create and manage Operating Systems + standalone: false diff --git a/roles/organizations/meta/main.yml b/roles/organizations/meta/main.yml new file mode 100644 index 000000000..17b1aa647 --- /dev/null +++ b/roles/organizations/meta/main.yml @@ -0,0 +1,4 @@ +--- +galaxy_info: + description: Create and manage Organizations + standalone: false diff --git a/roles/provisioning_templates/meta/main.yml b/roles/provisioning_templates/meta/main.yml new file mode 100644 index 000000000..2342bf250 --- /dev/null +++ b/roles/provisioning_templates/meta/main.yml @@ -0,0 +1,4 @@ +--- +galaxy_info: + description: Create and manage Provisioning Templates + standalone: false diff --git a/roles/repositories/meta/main.yml b/roles/repositories/meta/main.yml new file mode 100644 index 000000000..c05f3d2ad --- /dev/null +++ b/roles/repositories/meta/main.yml @@ -0,0 +1,4 @@ +--- +galaxy_info: + description: Define Products and Custom Repositories and enables Red Hat Repositories + standalone: false diff --git a/roles/settings/meta/main.yml b/roles/settings/meta/main.yml new file mode 100644 index 000000000..51429f83c --- /dev/null +++ b/roles/settings/meta/main.yml @@ -0,0 +1,4 @@ +--- +galaxy_info: + description: Manage Settings + standalone: false diff --git a/roles/subnets/meta/main.yml b/roles/subnets/meta/main.yml new file mode 100644 index 000000000..81a65fb8f --- /dev/null +++ b/roles/subnets/meta/main.yml @@ -0,0 +1,4 @@ +--- +galaxy_info: + description: Create and manage Subnets + standalone: false diff --git a/roles/sync_plans/meta/main.yml b/roles/sync_plans/meta/main.yml new file mode 100644 index 000000000..eebb27f43 --- /dev/null +++ b/roles/sync_plans/meta/main.yml @@ -0,0 +1,4 @@ +--- +galaxy_info: + description: Create and manage Sync Plans + standalone: false diff --git a/tests/config.yml b/tests/config.yml new file mode 100644 index 000000000..41f529264 --- /dev/null +++ b/tests/config.yml @@ -0,0 +1,3 @@ +--- +modules: + python_requires: ">=3.6" diff --git a/tests/test_playbooks/auth_source_ldap.yml b/tests/test_playbooks/auth_source_ldap.yml index 7c46fc42b..43f29ae2e 100644 --- a/tests/test_playbooks/auth_source_ldap.yml +++ b/tests/test_playbooks/auth_source_ldap.yml @@ -31,7 +31,8 @@ - include_tasks: tasks/auth_source_ldap.yml vars: auth_source_ldap_state: present - auth_source_ldap_account_password: changeme + # we only set this once at creation, as otherwise idempotency tests would fail + auth_source_ldap_account_password: "{{ default_auth_source_ldap_account_password }}" expected_change: true - include_tasks: tasks/auth_source_ldap.yml vars: diff --git a/tests/test_playbooks/tasks/templates_import.yml b/tests/test_playbooks/tasks/templates_import.yml index a930356b6..83678e82d 100644 --- a/tests/test_playbooks/tasks/templates_import.yml +++ b/tests/test_playbooks/tasks/templates_import.yml @@ -15,6 +15,8 @@ force: "{{ templates_import_force | default(omit) }}" lock: "{{ templates_import_lock | default(omit) }}" negate: "{{ templates_import_negate | default(omit) }}" + http_proxy_policy: "{{ templates_import_http_proxy_policy | default(omit) }}" + http_proxy: "{{ templates_import_http_proxy | default(omit) }}" locations: "{{ templates_import_locations | default(omit) }}" organizations: "{{ templates_import_organizations | default(omit) }}" register: result diff --git a/tests/test_playbooks/vars/server.yml.example b/tests/test_playbooks/vars/server.yml.example index ffe0231d5..32a7b64a5 100644 --- a/tests/test_playbooks/vars/server.yml.example +++ b/tests/test_playbooks/vars/server.yml.example @@ -35,6 +35,7 @@ auth_source_ldap_base_dn: dc=example,dc=com auth_source_ldap_attr_login: uid auth_source_ldap_groups_base: cn=groups,cn=accounts,dc=example,dc=com external_usergroup_name: "admins" +default_auth_source_ldap_account_password: changeme # Satellite branded params satellite_username: "{{ foreman_username }}" diff --git a/tests/test_recursive_dict_keys.py b/tests/test_recursive_dict_keys.py deleted file mode 100644 index 0a34667bc..000000000 --- a/tests/test_recursive_dict_keys.py +++ /dev/null @@ -1,7 +0,0 @@ -from plugins.module_utils.foreman_helper import _recursive_dict_keys - - -def test_recursive_dict_keys(): - a_dict = {'level1': 'has value', 'level2': {'real_level2': 'more value', 'level3': {'real_level3': 'nope'}}} - expected_keys = set(['level1', 'level2', 'level3', 'real_level2', 'real_level3']) - assert _recursive_dict_keys(a_dict) == expected_keys diff --git a/tests/vcr_python_wrapper.py b/tests/vcr_python_wrapper.py index 76a35fda1..136fc1923 100755 --- a/tests/vcr_python_wrapper.py +++ b/tests/vcr_python_wrapper.py @@ -27,7 +27,8 @@ def body_json_l2_matcher(r1, r2): body1 = json.loads(r1.body.decode('utf8')) body2 = json.loads(r2.body.decode('utf8')) if 'common_parameter' in body1 and 'common_parameter' in body2: - if body1['common_parameter'].get('parameter_type') == body2['common_parameter'].get('parameter_type') in ['hash', 'json', 'yaml']: + if (body1['common_parameter'].get('parameter_type') == body2['common_parameter'].get('parameter_type') + and body1['common_parameter'].get('parameter_type') in ['hash', 'json', 'yaml']): body1['common_parameter']['value'] = json.loads(body1['common_parameter'].get('value')) body2['common_parameter']['value'] = json.loads(body2['common_parameter'].get('value')) assert body1 == body2, "{} != {}".format(body1, body2) @@ -39,7 +40,7 @@ def body_json_l2_matcher(r1, r2): body2 = sorted(r2.body.replace(b'~', b'%7E').split(b'&')) assert len(body1) == len(body2), "the body lengths don't match" for i, v in enumerate(body1): - assert body1[i] == body2[i], "body contents at position {} dont't match: '{}' vs '{}'".format(i, body1[i], body2[i]) + assert body1[i] == body2[i], "body contents at position {} dont't match: '{}' vs '{}'".format(i, body1[i], body2[i]) # pylint:disable=all else: assert r1.body == r2.body, "{} != {}".format(r1.body, r2.body) diff --git a/vendor.py b/vendor.py index e6128d8c4..b0f19984a 100644 --- a/vendor.py +++ b/vendor.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python3 - import fileinput import os.path @@ -53,8 +51,10 @@ elif line in ['try:', 'if TYPE_CHECKING:'] or buffer_lines: buffer_lines.append(line) if "from typing" in line: - typing_imports.update([element.strip(',') for element in line.split('#')[0].strip().split(' ')[3:] if not element.strip(',') == 'TYPE_CHECKING']) - if ('pass' in line or 'TYPE_CHECKING =' in line or ('from apypie' in line and 'if TYPE_CHECKING:' in buffer_lines)) and ('from typing' in buffer_lines[1] or 'from apypie' in buffer_lines[1]): + typing_imports.update([element.strip(',') for element in line.split('#')[0].strip().split(' ')[3:] + if not element.strip(',') == 'TYPE_CHECKING']) + if (('pass' in line or 'TYPE_CHECKING =' in line or ('from apypie' in line and 'if TYPE_CHECKING:' in buffer_lines)) and + ('from typing' in buffer_lines[1] or 'from apypie' in buffer_lines[1])): buffer_lines.clear() elif "from typing" in line: typing_imports.update([element.strip(',') for element in line.split('#')[0].strip().split(' ')[3:] if not element.strip(',') == 'TYPE_CHECKING'])