awscli2/python314.patch
Kseniia Nivnia 0889e2db6a
Update to 2.27.0
Resolves: RHEL-75536
Signed-off-by: Kseniia Nivnia <knivnia@redhat.com>
2025-07-24 15:30:41 +01:00

140 lines
5.6 KiB
Diff

diff --git a/awscli/arguments.py b/awscli/arguments.py
index 77639cf..3ab060b 100644
--- a/awscli/arguments.py
+++ b/awscli/arguments.py
@@ -451,7 +451,7 @@ class CLIArgument(BaseCLIArgument):
cli_name = self.cli_name
parser.add_argument(
cli_name,
- help=self.documentation,
+ help=self.documentation.replace("%", "%%"),
type=self.cli_type,
required=self.required,
)
@@ -602,7 +602,7 @@ class BooleanArgument(CLIArgument):
def add_to_parser(self, parser):
parser.add_argument(
self.cli_name,
- help=self.documentation,
+ help=self.documentation.replace("%", "%%"),
action=self._action,
default=self._default,
dest=self._destination,
diff --git a/awscli/customizations/logs/startlivetail.py b/awscli/customizations/logs/startlivetail.py
index cc5849b..bc71a3d 100644
--- a/awscli/customizations/logs/startlivetail.py
+++ b/awscli/customizations/logs/startlivetail.py
@@ -833,7 +833,7 @@ class InteractiveUI(BaseLiveTailUI):
await self._application.run_async()
def run(self):
- asyncio.get_event_loop().run_until_complete(self._run_ui())
+ asyncio.run(self._run_ui())
class PrintOnlyPrinter(BaseLiveTailPrinter):
diff --git a/awscli/customizations/wizard/app.py b/awscli/customizations/wizard/app.py
index c813b97..028fcaa 100644
--- a/awscli/customizations/wizard/app.py
+++ b/awscli/customizations/wizard/app.py
@@ -10,9 +10,9 @@
# 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 asyncio
import json
import os
-from asyncio import new_event_loop, set_event_loop
from collections.abc import MutableMapping
from prompt_toolkit.application import Application
@@ -77,14 +77,12 @@ class WizardApp(Application):
)
def run(self, pre_run=None, **kwargs):
- loop = new_event_loop()
- try:
- set_event_loop(loop)
+ def create_event_loop():
+ loop = asyncio.new_event_loop()
loop.set_exception_handler(self._handle_exception)
- f = self.run_async(pre_run=pre_run, set_exception_handler=False)
- return loop.run_until_complete(f)
- finally:
- loop.close()
+ return loop
+ f = self.run_async(pre_run=pre_run, set_exception_handler=False)
+ return asyncio.run(f, loop_factory=create_event_loop)
def _handle_exception(self, loop, context):
self.exit(exception=UnexpectedWizardException(context['exception']))
diff --git a/tests/__init__.py b/tests/__init__.py
index db70912..0ab2e4a 100644
--- a/tests/__init__.py
+++ b/tests/__init__.py
@@ -471,16 +471,9 @@ class PromptToolkitAppRunner:
# This is the function that will be passed to our thread to
# actually run the application
try:
- # When we run the app in a separate thread, there is no
- # default event loop. This ensures we create one as it is
- # likely the application will try to grab the default loop
- loop = asyncio.new_event_loop()
- asyncio.set_event_loop(loop)
app_run_context.return_value = target(*target_args)
except BaseException as e:
app_run_context.raised_exception = e
- finally:
- loop.close()
def _wait_until_app_is_done_updating(self):
self._wait_until_app_is_done_rendering()
diff --git a/tests/functional/test_utils.py b/tests/functional/test_utils.py
--- a/tests/functional/test_utils.py
+++ b/tests/functional/test_utils.py
@@ -18,7 +18,7 @@ class TestWriteException(unittest.TestCa
def test_write_exception(self):
error_message = "Some error message."
ex = Exception(error_message)
- with codecs.open(self.outfile, 'w+', encoding='utf-8') as outfile:
+ with open(self.outfile, 'w+', encoding='utf-8') as outfile:
write_exception(ex, outfile)
outfile.seek(0)
diff --git a/tests/unit/botocore/test_utils.py b/tests/unit/botocore/test_utils.py
--- a/tests/unit/botocore/test_utils.py
+++ b/tests/unit/botocore/test_utils.py
@@ -3646,20 +3646,28 @@ def test_lru_cache_weakref():
cls2 = ClassWithCachedMethod()
assert cls1.cached_fn.cache_info().currsize == 0
- assert getrefcount(cls1) == 2
- assert getrefcount(cls2) == 2
+ refcount1 = getrefcount(cls1)
+ refcount2 = getrefcount(cls2)
+ assert refcount1 in (1, 2)
+ assert refcount2 in (1, 2)
# "The count returned is generally one higher than you might expect, because
# it includes the (temporary) reference as an argument to getrefcount()."
# https://docs.python.org/3.8/library/sys.html#getrefcount
+ # However, as of 3.14: "The interpreter internally avoids some reference
+ # count modifications when loading objects onto the operands stack by
+ # borrowing references when possible. This can lead to smaller reference
+ # count values compared to previous Python versions."
+ # https://docs.python.org/3.14/whatsnew/3.14.html#whatsnew314-refcount
+
cls1.cached_fn(1, 1)
cls2.cached_fn(1, 1)
# The cache now has two entries, but the reference count remains the same as
# before.
assert cls1.cached_fn.cache_info().currsize == 2
- assert getrefcount(cls1) == 2
- assert getrefcount(cls2) == 2
+ assert getrefcount(cls1) == refcount1
+ assert getrefcount(cls2) == refcount2
# Deleting one of the objects does not interfere with the cache entries
# related to the other object.