diff --git a/0001-add-external-links-to-the-leapp-report.txt.patch b/0001-add-external-links-to-the-leapp-report.txt.patch new file mode 100644 index 0000000..61d0649 --- /dev/null +++ b/0001-add-external-links-to-the-leapp-report.txt.patch @@ -0,0 +1,77 @@ +From ea71f9b27a7c969d8023099cf151564dd8e5aae3 Mon Sep 17 00:00:00 2001 +From: PeterMocary +Date: Wed, 6 Sep 2023 15:31:17 +0200 +Subject: [PATCH 1/5] add external links to the leapp-report.txt + +--- + leapp/utils/report.py | 40 +++++++++++++++++++++++++++++----------- + 1 file changed, 29 insertions(+), 11 deletions(-) + +diff --git a/leapp/utils/report.py b/leapp/utils/report.py +index 2db0e55..bbf8f28 100644 +--- a/leapp/utils/report.py ++++ b/leapp/utils/report.py +@@ -8,6 +8,7 @@ import six + from leapp.reporting import ( + _DEPRECATION_FLAGS, + _UPCOMING_DEPRECATION_FLAGS, ++ ExternalLink, + Groups, + Remediation, + Severity, +@@ -115,6 +116,31 @@ def importance(message): + return SEVERITY_LEVELS.get(message['severity'], 99) + + ++def _report_detail_to_string(report_detail): ++ detail = u'' ++ external_links = report_detail[ExternalLink.name] if ExternalLink.name in report_detail.keys() else None ++ remediation = Remediation.from_dict(report_detail) ++ ++ if external_links: ++ external_links_text = u'Related links:' ++ for link in external_links: ++ external_links_text += u'\n - {}: {}'.format(link['title'], link['url']) ++ detail += external_links_text ++ ++ if remediation: ++ # NOTE(ivasilev) Decoding is necessary in case of python2 as remediation is an encoded string, ++ # while io.open expects "true text" input. For python3 repr will return proper py3 str, no ++ # decoding will be needed. ++ # This hassle and clumsiness makes me sad, so suggestions are welcome. ++ remediation_text = '\nRemediation: {}\n'.format(remediation) ++ if isinstance(remediation_text, six.binary_type): ++ # This will be true for py2 where repr returns an encoded string ++ remediation_text = remediation_text.decode('utf-8') ++ detail += remediation_text ++ ++ return detail ++ ++ + def generate_report_file(messages_to_report, context, path, report_schema='1.1.0'): + # NOTE(ivasilev) Int conversion should not break as only specific formats of report_schema versions are allowed + report_schema_tuple = tuple(int(x) for x in report_schema.split('.')) +@@ -130,17 +156,9 @@ def generate_report_file(messages_to_report, context, path, report_schema='1.1.0 + f.write(u'Risk Factor: {} {}\n'.format(message['severity'], flag)) + f.write(u'Title: {}\n'.format(message['title'])) + f.write(u'Summary: {}\n'.format(message['summary'])) +- remediation = Remediation.from_dict(message.get('detail', {})) +- if remediation: +- # NOTE(ivasilev) Decoding is necessary in case of python2 as remediation is an encoded string, +- # while io.open expects "true text" input. For python3 repr will return proper py3 str, no +- # decoding will be needed. +- # This hassle and clumsiness makes me sad, so suggestions are welcome. +- remediation_text = 'Remediation: {}\n'.format(remediation) +- if isinstance(remediation_text, six.binary_type): +- # This will be true for py2 where repr returns an encoded string +- remediation_text = remediation_text.decode('utf-8') +- f.write(remediation_text) ++ report_detail = message.get('detail', {}) ++ detail = _report_detail_to_string(report_detail) ++ f.write(detail) + if report_schema_tuple > (1, 0, 0): + # report-schema 1.0.0 doesn't have a stable report key + f.write(u'Key: {}\n'.format(message['key'])) +-- +2.43.0 + diff --git a/0002-Report-txt-fix-printing-of-non-ascii-details-844.patch b/0002-Report-txt-fix-printing-of-non-ascii-details-844.patch new file mode 100644 index 0000000..afec650 --- /dev/null +++ b/0002-Report-txt-fix-printing-of-non-ascii-details-844.patch @@ -0,0 +1,83 @@ +From 0eac9d86df3167f173d7ba3b98a6108ae3fb1d61 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Stod=C5=AFlka?= +Date: Wed, 11 Oct 2023 18:51:23 +0200 +Subject: [PATCH 2/5] Report txt: fix printing of non-ascii details (#844) + +Previous commit introduced couple of issues regarding details of +reports that could lead to situations like: +* remediation instructions has not been printed when non-ascii + characters have been present +* possible unwanted empty line when remediation has been specified + but relative symlinks hasn't +* if the URL title contained non-ascii character, it has been broken + too (on py2) + +This should handle all mentioned problems when generating the txt +file. +--- + leapp/utils/report.py | 28 +++++++++++++++++++--------- + 1 file changed, 19 insertions(+), 9 deletions(-) + +diff --git a/leapp/utils/report.py b/leapp/utils/report.py +index bbf8f28..1ea0122 100644 +--- a/leapp/utils/report.py ++++ b/leapp/utils/report.py +@@ -116,15 +116,29 @@ def importance(message): + return SEVERITY_LEVELS.get(message['severity'], 99) + + ++def _treat_str(text): ++ """ ++ Ensure the given text is decoded. ++ ++ This is problem in case of Py2 when non-asci characters are present. ++ """ ++ return text.decode('utf-8') if isinstance(text, six.binary_type) else text ++ ++ + def _report_detail_to_string(report_detail): + detail = u'' + external_links = report_detail[ExternalLink.name] if ExternalLink.name in report_detail.keys() else None + remediation = Remediation.from_dict(report_detail) + + if external_links: +- external_links_text = u'Related links:' ++ external_links_text = u'Related links:\n' + for link in external_links: +- external_links_text += u'\n - {}: {}'.format(link['title'], link['url']) ++ # Note(pstodulk): IRI could contain unicode characters. Even when it's ++ # still unexpected , let's reather treat it as well. ++ external_links_text += u' - {}: {}\n'.format( ++ _treat_str(link['title']), ++ _treat_str(link['url']) ++ ) + detail += external_links_text + + if remediation: +@@ -132,11 +146,8 @@ def _report_detail_to_string(report_detail): + # while io.open expects "true text" input. For python3 repr will return proper py3 str, no + # decoding will be needed. + # This hassle and clumsiness makes me sad, so suggestions are welcome. +- remediation_text = '\nRemediation: {}\n'.format(remediation) +- if isinstance(remediation_text, six.binary_type): +- # This will be true for py2 where repr returns an encoded string +- remediation_text = remediation_text.decode('utf-8') +- detail += remediation_text ++ remediation_text = 'Remediation: {}\n'.format(remediation) ++ detail += _treat_str(remediation_text) + + return detail + +@@ -156,8 +167,7 @@ def generate_report_file(messages_to_report, context, path, report_schema='1.1.0 + f.write(u'Risk Factor: {} {}\n'.format(message['severity'], flag)) + f.write(u'Title: {}\n'.format(message['title'])) + f.write(u'Summary: {}\n'.format(message['summary'])) +- report_detail = message.get('detail', {}) +- detail = _report_detail_to_string(report_detail) ++ detail = _report_detail_to_string(message.get('detail', {})) + f.write(detail) + if report_schema_tuple > (1, 0, 0): + # report-schema 1.0.0 doesn't have a stable report key +-- +2.43.0 + diff --git a/0003-Recommend-descriptive-variable-name-for-discarded-va.patch b/0003-Recommend-descriptive-variable-name-for-discarded-va.patch new file mode 100644 index 0000000..319ff18 --- /dev/null +++ b/0003-Recommend-descriptive-variable-name-for-discarded-va.patch @@ -0,0 +1,65 @@ +From 84f642e8398e5fce24a55bc0bec408ce11b5998d Mon Sep 17 00:00:00 2001 +From: Toshio Kuratomi +Date: Tue, 17 Oct 2023 05:09:24 -0700 +Subject: [PATCH 3/5] Recommend descriptive variable name for discarded values. + +* We tell people not to use `_`. Now we advise them on what to use instead. +* Also fix link syntax in the contribution guide. +--- + docs/source/contributing.md | 6 +++--- + docs/source/python-coding-guidelines.md | 11 ++++++++++- + 2 files changed, 13 insertions(+), 4 deletions(-) + +diff --git a/docs/source/contributing.md b/docs/source/contributing.md +index fe69ca0..f0422ee 100644 +--- a/docs/source/contributing.md ++++ b/docs/source/contributing.md +@@ -3,7 +3,7 @@ + First, thank you for taking your time to contribute to the project. + + The following is a set of guidelines for contributing effectively to the Leapp-related repositories +-hosted under the `OS and Application Modernization Group organization `_ ++hosted under the [OS and Application Modernization Group organization](https://github.com/oamg/) + on GitHub. + + ## Code style guidelines +@@ -32,7 +32,7 @@ Before you submit your pull request, consider the following guidelines: + ``git checkout -b bug/my-fix-branch master`` + + * Include documentation that either describe a change to a behavior or the changed capability to an end user. +-* Commit your changes with message conforming to the `Git Commit Messages`_ guidelines. ++* Commit your changes with message conforming to the [Git Commit Messages](#git-commit-messages) guidelines. + * Include tests for the capability you have implemented. + * Make sure your tests pass. We use Jenkins CI for our automated testing. + * Push your branch to GitHub: +@@ -65,7 +65,7 @@ Before you submit your pull request, consider the following guidelines: + * Use the present tense ("Add feature" not "Added feature") + * Use the imperative mood ("Move cursor to..." not "Moves cursor to...") + * If you are fixing a GitHub issue, include something like 'Closes issue #xyz' +-* For more best practices, read `How to Write a Git Commit Message `_ ++* For more best practices, read [How to Write a Git Commit Message](https://chris.beams.io/posts/git-commit/) + + ## Contact + +diff --git a/docs/source/python-coding-guidelines.md b/docs/source/python-coding-guidelines.md +index d30f986..3a15579 100644 +--- a/docs/source/python-coding-guidelines.md ++++ b/docs/source/python-coding-guidelines.md +@@ -175,4 +175,13 @@ class MyActor(Actor): + ### 13. Underscore usage + + For leapp and leapp-repository the `_` and `P_` is reserved for localization. Please don't use it for anything else like +-variable-to-be-discarded. ++variable-to-be-discarded. Instead, use a variable name prefixed with `dummy_`. What comes after ++the prefix should describe the data that is being discarded, like so: ++ ++``` python ++dummy_scheme, netloc, path, dummy_params, query, fragment = urlparse("scheme://netloc/path;parameters?query#fragment") ++``` ++ ++Using an informative variable name for discarded values is helpful when a future developer modifies ++the code and needs the discarded information. They can quickly see that the information is already ++available; they just need to rename the variable and start using it. +-- +2.43.0 + diff --git a/0004-Python-3.12-compat-and-refactor-of-path-determinatio.patch b/0004-Python-3.12-compat-and-refactor-of-path-determinatio.patch new file mode 100644 index 0000000..4f9c0c6 --- /dev/null +++ b/0004-Python-3.12-compat-and-refactor-of-path-determinatio.patch @@ -0,0 +1,61 @@ +From 034aee0abcbb03d62c8d0bd0269e635a71afa34a Mon Sep 17 00:00:00 2001 +From: Toshio Kuratomi +Date: Tue, 17 Oct 2023 04:33:42 -0700 +Subject: [PATCH 4/5] Python-3.12 compat and refactor of path determination. + +In `stdlib._call()`, we lookup whether the command to call is present +on the user's PATH. Two changes are made to this functionality: + +* Simplify the lookup of PATH now that we have a local variable with all the + information we need. +* Add compat code to use `shutil.which()` on Python3 (while still using + `distutils.spawn.find_executable()` on Python2). As noted in pstodulk's comment, `which()` + will be needed when the code runs on Python-3.12. +--- + leapp/libraries/stdlib/call.py | 20 +++++++++++--------- + 1 file changed, 11 insertions(+), 9 deletions(-) + +diff --git a/leapp/libraries/stdlib/call.py b/leapp/libraries/stdlib/call.py +index 363fd27..b80f860 100644 +--- a/leapp/libraries/stdlib/call.py ++++ b/leapp/libraries/stdlib/call.py +@@ -1,10 +1,17 @@ + from __future__ import print_function + +-from distutils.spawn import find_executable + import codecs + import errno + import os + import sys ++try: ++ # shutil.which is available in Python 3.3 and above. ++ from shutil import which ++except ImportError: ++ # (pstodulk): find_executable() is from the distutils module which was ++ # removed in Python 3.12. We can get rid of this fallback when we drop ++ # support for Python 2. https://peps.python.org/pep-0632/ ++ from distutils.spawn import find_executable as which + + from leapp.compat import string_types + from leapp.libraries.stdlib.eventloop import POLL_HUP, POLL_IN, POLL_OUT, POLL_PRI, EventLoop +@@ -134,14 +141,9 @@ def _call(command, callback_raw=lambda fd, value: None, callback_linebuffered=la + raise TypeError('env parameter has to be a dictionary') + environ.update(env) + +- _path = (env or {}).get('PATH', None) +- # NOTE(pstodulk): the find_executable function is from the distutils +- # module which is deprecated and it is going to be removed in Python 3.12. +- # In future, we should use the shutil.which function, however that one is +- # not available for Python2. We are going to address the problem in future +- # (e.g. when we drop support for Python 2). +- # https://peps.python.org/pep-0632/ +- if not find_executable(command[0], _path): ++ _path = environ.get('PATH', None) ++ ++ if not which(command[0], path=_path): + raise OSError(errno.ENOENT, os.strerror(errno.ENOENT), command[0]) + + # Create a separate pipe for stdout/stderr +-- +2.43.0 + diff --git a/0005-Fix-stdlib.run-documentation.patch b/0005-Fix-stdlib.run-documentation.patch new file mode 100644 index 0000000..69205f0 --- /dev/null +++ b/0005-Fix-stdlib.run-documentation.patch @@ -0,0 +1,26 @@ +From 1cdd1898ba2cee253e6557b846dc54ca77a862f2 Mon Sep 17 00:00:00 2001 +From: Toshio Kuratomi +Date: Wed, 10 Jan 2024 18:32:29 -0800 +Subject: [PATCH 5/5] Fix stdlib.run() documentation + +CalledProcessError() is raised on non-zero exit when checked==True, not when checked==False. +--- + leapp/libraries/stdlib/__init__.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/leapp/libraries/stdlib/__init__.py b/leapp/libraries/stdlib/__init__.py +index 77a2f7a..89e59b2 100644 +--- a/leapp/libraries/stdlib/__init__.py ++++ b/leapp/libraries/stdlib/__init__.py +@@ -168,7 +168,7 @@ def run(args, split=False, callback_raw=_console_logging_handler, callback_lineb + :return: {'stdout' : stdout, 'stderr': stderr, 'signal': signal, 'exit_code': exit_code, 'pid': pid} + :rtype: dict + :raises: OSError if an executable is missing or has wrong permissions +- :raises: CalledProcessError if the cmd has non-zero exit code and `checked` is False ++ :raises: CalledProcessError if the cmd has non-zero exit code and `checked` is True + :raises: TypeError if any input parameters have an invalid type + :raises: valueError if any of input parameters have an invalid value + """ +-- +2.43.0 + diff --git a/leapp.spec b/leapp.spec index 449119b..7071226 100644 --- a/leapp.spec +++ b/leapp.spec @@ -37,7 +37,7 @@ Name: leapp Version: 0.16.0 -Release: 2%{?dist} +Release: 3%{?dist} Summary: OS & Application modernization framework License: ASL 2.0 @@ -66,6 +66,12 @@ Requires: leapp-repository # PATCHES HERE # Patch0001: filename.patch +Patch0001: 0001-add-external-links-to-the-leapp-report.txt.patch +Patch0002: 0002-Report-txt-fix-printing-of-non-ascii-details-844.patch +Patch0003: 0003-Recommend-descriptive-variable-name-for-discarded-va.patch +Patch0004: 0004-Python-3.12-compat-and-refactor-of-path-determinatio.patch +Patch0005: 0005-Fix-stdlib.run-documentation.patch + %description Leapp utility provides the possibility to use the Leapp framework via CLI. The utility itself does not define any subcommands but "help". All leapp @@ -159,6 +165,11 @@ Requires: findutils # APPLY REGISTERED PATCHES HERE # %%patch0001 -p1 +%patch0001 -p1 +%patch0002 -p1 +%patch0003 -p1 +%patch0004 -p1 +%patch0005 -p1 ################################################## @@ -242,6 +253,10 @@ install -m 0644 -p man/leapp.1 %{buildroot}%{_mandir}/man1/ # no files here %changelog +* Fri Jan 12 2024 Petr Stodulka - 0.16.0-3 +- Add external links to the text version of the generated report file +- Resolves: RHEL-21451 + * Wed Aug 23 2023 Petr Stodulka - 0.16.0-2 - Bump leapp-framework to 5.0 - Resolves: #2223312