Bug 2152655

Summary: python-bottle fails to build with Python 3.12: E AttributeError: 'TestConfDict' object has no attribute 'assertEquals'.
Product: [Fedora] Fedora Reporter: Tomáš Hrnčiar <thrnciar>
Component: python-bottleAssignee: fedepell <fede>
Status: CLOSED RAWHIDE QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: rawhideCC: aekoroglu, fede, mhroncok, thrnciar
Target Milestone: ---   
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2022-12-13 05:56:26 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On:    
Bug Blocks: 2135404    

Description Tomáš Hrnčiar 2022-12-12 15:54:59 UTC
python-bottle fails to build with Python 3.12.0a3.

=================================== FAILURES ===================================
_________________________ TestConfDict.test_load_dict __________________________

self = <test.test_config.TestConfDict testMethod=test_load_dict>

    def test_load_dict(self):
        c = ConfigDict()
        d = dict(a=dict(b=dict(foo=5, bar=6), baz=7))
        c.load_dict(d)
>       self.assertEquals(c['a.b.foo'], 5)
E       AttributeError: 'TestConfDict' object has no attribute 'assertEquals'. Did you mean: 'assertEqual'?

test/test_config.py:39: AttributeError
____________________________ TestConfDict.test_meta ____________________________

self = <test.test_config.TestConfDict testMethod=test_meta>

    def test_meta(self):
        c = ConfigDict()
        c.meta_set('bool', 'filter', bool)
        c.meta_set('int', 'filter', int)
        c['bool'] = 'I am so true!'
        c['int']  = '6'
        self.assertTrue(c['bool'] is True)
>       self.assertEquals(c['int'], 6)
E       AttributeError: 'TestConfDict' object has no attribute 'assertEquals'. Did you mean: 'assertEqual'?

test/test_config.py:32: AttributeError
___________________________ TestRequest.test_chunked ___________________________

self = <test.test_environ.TestRequest testMethod=test_chunked>

    def test_chunked(self):
>       self._test_chunked('1\r\nx\r\nff\r\n' + 'y'*255 + '\r\n0\r\n',
                           'x' + 'y'*255)

test/test_environ.py:307: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <test.test_environ.TestRequest testMethod=test_chunked>
body = '1\r\nx\r\nff\r\nyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy...yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy\r\n0\r\n'
expect = 'xyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy...yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'

    def _test_chunked(self, body, expect):
        e = {}
        wsgiref.util.setup_testing_defaults(e)
        e['wsgi.input'].write(tob(body))
        e['wsgi.input'].seek(0)
        e['HTTP_TRANSFER_ENCODING'] = 'chunked'
        if isinstance(expect, str):
>           self.assertEquals(tob(expect), BaseRequest(e).body.read())
E           AttributeError: 'TestRequest' object has no attribute 'assertEquals'. Did you mean: 'assertEqual'?

test/test_environ.py:302: AttributeError
_____________________ TestRequest.test_chunked_meta_fields _____________________

self = <test.test_environ.TestRequest testMethod=test_chunked_meta_fields>

    def test_chunked_meta_fields(self):
>       self._test_chunked('8 ; foo\r\nxxxxxxxx\r\n0\r\n','xxxxxxxx')

test/test_environ.py:313: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <test.test_environ.TestRequest testMethod=test_chunked_meta_fields>
body = '8 ; foo\r\nxxxxxxxx\r\n0\r\n', expect = 'xxxxxxxx'

    def _test_chunked(self, body, expect):
        e = {}
        wsgiref.util.setup_testing_defaults(e)
        e['wsgi.input'].write(tob(body))
        e['wsgi.input'].seek(0)
        e['HTTP_TRANSFER_ENCODING'] = 'chunked'
        if isinstance(expect, str):
>           self.assertEquals(tob(expect), BaseRequest(e).body.read())
E           AttributeError: 'TestRequest' object has no attribute 'assertEquals'. Did you mean: 'assertEqual'?

test/test_environ.py:302: AttributeError
________________________ TestResponse.test_content_type ________________________

self = <test.test_environ.TestResponse testMethod=test_content_type>

    def test_content_type(self):
        rs = BaseResponse()
        rs.content_type = 'test/some'
>       self.assertEquals('test/some', rs.headers.get('Content-Type'))
E       AttributeError: 'TestResponse' object has no attribute 'assertEquals'. Did you mean: 'assertEqual'?

test/test_environ.py:581: AttributeError
___________________________ TestPluginAPI.test_setup ___________________________

self = <test.test_plugins.TestPluginAPI testMethod=test_setup>

    def test_setup(self):
        class Plugin(object):
            def __call__(self, func): return func
            def setup(self, app): self.app = app
        plugin = self.app.install(Plugin())
>       self.assertEquals(getattr(plugin, 'app', None), self.app)
E       AttributeError: 'TestPluginAPI' object has no attribute 'assertEquals'. Did you mean: 'assertEqual'?

test/test_plugins.py:197: AttributeError
___________________ TestSimpleTemplate.test_htmlutils_quote ____________________

self = <test.test_stpl.TestSimpleTemplate testMethod=test_htmlutils_quote>

    def test_htmlutils_quote(self):
>       self.assertEquals('"&lt;&#039;&#13;&#10;&#9;&quot;\\&gt;"', html_quote('<\'\r\n\t"\\>'));
E       AttributeError: 'TestSimpleTemplate' object has no attribute 'assertEquals'. Did you mean: 'assertEqual'?

test/test_stpl.py:57: AttributeError
_________________________ TestRouteDecorator.test_name _________________________

self = <test.test_wsgi.TestRouteDecorator testMethod=test_name>

    def test_name(self):
        @bottle.route(name='foo')
        def test(x=5): return 'ok'
>       self.assertEquals('/test/6', bottle.url('foo', x=6))
E       AttributeError: 'TestRouteDecorator' object has no attribute 'assertEquals'. Did you mean: 'assertEqual'?

test/test_wsgi.py:260: AttributeError
=============================== warnings summary ===============================
bottle.py:37
  /builddir/build/BUILD/bottle-0.12.23/bottle.py:37: DeprecationWarning: 'cgi' is deprecated and slated for removal in Python 3.13
    import base64, cgi, email.utils, functools, hmac, itertools, mimetypes,\

test/test_importhook.py:4
  /builddir/build/BUILD/bottle-0.12.23/test/test_importhook.py:4: DeprecationWarning: the imp module is deprecated in favour of importlib and slated for removal in Python 3.12; see the module's documentation for alternative uses
    import imp

<frozen importlib._bootstrap>:1019
  <frozen importlib._bootstrap>:1019: ImportWarning: _ImportRedirect.find_spec() not found; falling back to find_module()

test/test_server.py:53
  /builddir/build/BUILD/bottle-0.12.23/test/test_server.py:53: SyntaxWarning: "is" with a literal. Did you mean "=="?
    if rv is 128: # Import error

test/test_server.py:57
  /builddir/build/BUILD/bottle-0.12.23/test/test_server.py:57: SyntaxWarning: "is" with a literal. Did you mean "=="?
    if rv is 3: # Port in use

test/test_configdict.py::TestConfigDict::test_attr_access
  /builddir/build/BUILD/bottle-0.12.23/test/test_configdict.py:30: DeprecationWarning: Attribute assignment is deprecated.
    c.test = 5

test/test_configdict.py::TestConfigDict::test_attr_access
  /builddir/build/BUILD/bottle-0.12.23/test/test_configdict.py:31: DeprecationWarning: Attribute access is deprecated.
    self.assertEqual(5, c.test)

test/test_configdict.py::TestConfigDict::test_attr_access
  /builddir/build/BUILD/bottle-0.12.23/test/test_configdict.py:34: DeprecationWarning: Attribute access is deprecated.
    self.assertEqual(6, c.test)

test/test_configdict.py::TestConfigDict::test_attr_access
  /builddir/build/BUILD/bottle-0.12.23/test/test_configdict.py:38: DeprecationWarning: Attribute access is deprecated.
    self.assertEqual(None, c.test)

test/test_configdict.py::TestConfigDict::test_call
  /builddir/build/BUILD/bottle-0.12.23/test/test_configdict.py:61: DeprecationWarning: Calling ConfDict is deprecated. Use the update() method.
    self.assertEqual(c, c(a=1))

test/test_configdict.py::TestConfigDict::test_call
  /builddir/build/BUILD/bottle-0.12.23/test/test_configdict.py:63: DeprecationWarning: Attribute access is deprecated.
    self.assertEqual(1, c.a)

test/test_configdict.py::TestConfigDict::test_isadict
  /builddir/build/BUILD/bottle-0.12.23/test/test_configdict.py:12: DeprecationWarning: Constructor does no longer accept parameters.
    d, m = dict(a=5), ConfigDict(a=5)

test/test_configdict.py::TestConfigDict::test_issue588
  /builddir/build/BUILD/bottle-0.12.23/test/test_configdict.py:70: DeprecationWarning: Accessing namespaces as dicts is discouraged. Only use flat item access: cfg["names"]["pace"]["key"] -> cfg["name.space.key"]
    self.assertEqual('c', c['a']['b'])

test/test_configdict.py::TestConfigDict::test_issue588
  <frozen _collections_abc>:887: DeprecationWarning: Accessing namespaces as dicts is discouraged. Only use flat item access: cfg["names"]["pace"]["key"] -> cfg["name.space.key"]

test/test_configdict.py::TestConfigDict::test_namespaces
test/test_configdict.py::TestConfigDict::test_namespaces
  /builddir/build/BUILD/bottle-0.12.23/test/test_configdict.py:43: DeprecationWarning: Attribute access is deprecated.
    self.assertEqual(ConfigDict.Namespace, c.Name.Space.__class__)

test/test_configdict.py::TestConfigDict::test_namespaces
test/test_configdict.py::TestConfigDict::test_namespaces
test/test_configdict.py::TestConfigDict::test_namespaces
test/test_configdict.py::TestConfigDict::test_namespaces
test/test_configdict.py::TestConfigDict::test_namespaces
  <frozen _collections_abc>:800: DeprecationWarning: Accessing namespaces as dicts is discouraged. Only use flat item access: cfg["names"]["pace"]["key"] -> cfg["name.space.key"]

test/test_configdict.py::TestConfigDict::test_namespaces
test/test_configdict.py::TestConfigDict::test_namespaces
  /builddir/build/BUILD/bottle-0.12.23/test/test_configdict.py:44: DeprecationWarning: Attribute access is deprecated.
    c.Name.Space.value = 5

test/test_configdict.py::TestConfigDict::test_namespaces
  /builddir/build/BUILD/bottle-0.12.23/test/test_configdict.py:44: DeprecationWarning: Attribute assignment is deprecated.
    c.Name.Space.value = 5

test/test_configdict.py::TestConfigDict::test_namespaces
test/test_configdict.py::TestConfigDict::test_namespaces
test/test_configdict.py::TestConfigDict::test_namespaces
  /builddir/build/BUILD/bottle-0.12.23/test/test_configdict.py:45: DeprecationWarning: Attribute access is deprecated.
    self.assertEqual(5, c.Name.Space.value)

test/test_configdict.py::TestConfigDict::test_namespaces
test/test_configdict.py::TestConfigDict::test_namespaces
  /builddir/build/BUILD/bottle-0.12.23/test/test_configdict.py:46: DeprecationWarning: Attribute access is deprecated.
    self.assertTrue('value' in c.Name.Space)

test/test_configdict.py::TestConfigDict::test_namespaces
  /builddir/build/BUILD/bottle-0.12.23/test/test_configdict.py:47: DeprecationWarning: Attribute access is deprecated.
    self.assertTrue('Space' in c.Name)

test/test_configdict.py::TestConfigDict::test_namespaces
  /builddir/build/BUILD/bottle-0.12.23/test/test_configdict.py:51: DeprecationWarning: Attribute assignment is deprecated.
    self.assertRaises(AttributeError, lambda: setattr(c, 'Name', 5))

test/test_configdict.py::TestConfigDict::test_namespaces
  /builddir/build/BUILD/bottle-0.12.23/test/test_configdict.py:53: DeprecationWarning: Attribute assignment is deprecated.
    self.assertRaises(AttributeError, lambda: setattr(c, 'keys', 5))

test/test_configdict.py::TestConfigDict::test_namespaces
  /builddir/build/BUILD/bottle-0.12.23/test/test_configdict.py:56: DeprecationWarning: Attribute access is deprecated.
    self.assertEqual(5, c.Name)

test/test_plugins.py: 15 warnings
  /builddir/build/BUILD/bottle-0.12.23/bottle.py:538: DeprecationWarning: Switch to Plugin API v2 and access the Route object directly.
    context = self if api > 1 else self._context

test/test_router.py::TestRouter::testFloatFilter
test/test_router.py::TestRouterInCGIMode::testFloatFilter
  /builddir/build/BUILD/bottle-0.12.23/bottle.py:391: RuntimeWarning: Route <GET /object/<id:float>> overwrites a previously defined route
    warnings.warn(msg % (method, rule), RuntimeWarning)

test/test_router.py::TestRouter::testParentheses
test/test_router.py::TestRouterInCGIMode::testParentheses
  /builddir/build/BUILD/bottle-0.12.23/bottle.py:391: RuntimeWarning: Route <GET /func2(:param#(foo|bar)#)> overwrites a previously defined route
    warnings.warn(msg % (method, rule), RuntimeWarning)

test/test_stpl.py::TestSimpleTemplate::test_coding_stress
test/test_stpl.py::TestSimpleTemplate::test_detect_pep263
test/test_stpl.py::TestSimpleTemplate::test_detect_pep263
  /builddir/build/BUILD/bottle-0.12.23/bottle.py:3618: DeprecationWarning: PEP263 encoding strings in templates are deprecated.
    line, comment = self.fix_backward_compatibility(line, comment)

test/test_stpl.py::TestSimpleTemplate::test_detect_pep263
  /builddir/build/BUILD/bottle-0.12.23/bottle.py:200: DeprecationWarning: Template encodings other than utf8 are no longer supported.
    value = obj.__dict__[self.func.__name__] = self.func(obj)

test/test_stpl.py::TestSimpleTemplate::test_escaped_codelines
test/test_stpl.py::TestSimpleTemplate::test_escaped_codelines
  /builddir/build/BUILD/bottle-0.12.23/bottle.py:3412: DeprecationWarning: Escape code lines with a backslash.
    code = parser.translate()

test/test_stpl.py::TestSimpleTemplate::test_file
test/test_stpl.py::TestSimpleTemplate::test_notfound
  /builddir/build/BUILD/bottle-0.12.23/bottle.py:3264: DeprecationWarning: The template lookup path list should not be empty.
    self.filename = self.search(self.name, self.lookup)

test/test_stpl.py::TestSimpleTemplate::test_file
  /builddir/build/BUILD/bottle-0.12.23/bottle.py:3264: DeprecationWarning: Absolute template path names are deprecated.
    self.filename = self.search(self.name, self.lookup)

test/test_stpl.py: 7 warnings
test/test_wsgi.py: 8 warnings
  /builddir/build/BUILD/bottle-0.12.23/bottle.py:3618: DeprecationWarning: The include and rebase keywords are functions now.
    line, comment = self.fix_backward_compatibility(line, comment)

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
=========================== short test summary info ============================
FAILED test/test_config.py::TestConfDict::test_load_dict - AttributeError: 'T...
FAILED test/test_config.py::TestConfDict::test_meta - AttributeError: 'TestCo...
FAILED test/test_environ.py::TestRequest::test_chunked - AttributeError: 'Tes...
FAILED test/test_environ.py::TestRequest::test_chunked_meta_fields - Attribut...
FAILED test/test_environ.py::TestResponse::test_content_type - AttributeError...
FAILED test/test_plugins.py::TestPluginAPI::test_setup - AttributeError: 'Tes...
FAILED test/test_stpl.py::TestSimpleTemplate::test_htmlutils_quote - Attribut...
FAILED test/test_wsgi.py::TestRouteDecorator::test_name - AttributeError: 'Te...
================== 8 failed, 307 passed, 76 warnings in 2.40s ==================

Removed many old deprecated unittest features.
You can use https://github.com/isidentical/teyit to automatically modernise your unit tests.
Undocumented and broken TestCase method assertDictContainsSubset (deprecated in Python 3.2).
Undocumented TestLoader.loadTestsFromModule parameter use_load_tests (deprecated and ignored since Python 3.2).
An alias of the TextTestResult class: _TextTestResult (deprecated in Python 3.2).

(Contributed by Serhiy Storchaka in bpo-45162.)


https://docs.python.org/3.12/whatsnew/3.12.html

For the build logs, see:
https://copr-be.cloud.fedoraproject.org/results/@python/python3.12/fedora-rawhide-x86_64/05124803-python-bottle/

For all our attempts to build python-bottle with Python 3.12, see:
https://copr.fedorainfracloud.org/coprs/g/python/python3.12/package/python-bottle/

Testing and mass rebuild of packages is happening in copr. You can follow these instructions to test locally in mock if your package builds with Python 3.12:
https://copr.fedorainfracloud.org/coprs/g/python/python3.12/

Let us know here if you have any questions.

Python 3.12 is planned to be included in Fedora 39. To make that update smoother, we're building Fedora packages with all pre-releases of Python 3.12.
A build failure prevents us from testing all dependent packages (transitive [Build]Requires), so if this package is required a lot, it's important for us to get it fixed soon.
We'd appreciate help from the people who know this package best, but if you don't want to work on this now, let us know so we can try to work around it on our side.

Comment 1 fedepell 2022-12-13 05:56:26 UTC
Thanks for the early warning.

Fixed with this update: https://bodhi.fedoraproject.org/updates/FEDORA-2022-6bf4c40cb0

As (please correct me if I'm wrong) for Rawhide/FC38 I cannot push manually a bug-connected update, I will now resolve the issue manually!

Cheers,
F.

Comment 2 Miro Hrončok 2022-12-13 09:47:28 UTC
Thanks for the fix!


> As (please correct me if I'm wrong) for Rawhide/FC38 I cannot push manually a bug-connected update...

When you include the bug reference in the changelog entry, bodhi will close the bugzilla.

https://fedora-infra.github.io/bodhi/6.0/user/automatic_updates.html#associate-bugs-to-automatic-updates