diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 13ba4e3ce..cf519b475 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -36,8 +36,7 @@ repos: - id: black # By default, this ignores pyi files, though black supports them types: [text] - # Not all Python files are Blacked, yet - files: ^(setup.py|pybind11|tests/extra|tools).*\.pyi?$ + files: \.pyi?$ # Changes tabs to spaces - repo: https://github.com/Lucas-C/pre-commit-hooks diff --git a/docs/benchmark.py b/docs/benchmark.py index 023477212..33d78fb4e 100644 --- a/docs/benchmark.py +++ b/docs/benchmark.py @@ -14,7 +14,7 @@ def generate_dummy_code_pybind11(nclasses=10): for cl in range(nclasses): decl += "class cl%03i;\n" % cl - decl += '\n' + decl += "\n" for cl in range(nclasses): decl += "class cl%03i {\n" % cl @@ -22,18 +22,17 @@ def generate_dummy_code_pybind11(nclasses=10): bindings += ' py::class_(m, "cl%03i")\n' % (cl, cl) for fn in range(nfns): ret = random.randint(0, nclasses - 1) - params = [random.randint(0, nclasses - 1) for i in range(nargs)] + params = [random.randint(0, nclasses - 1) for i in range(nargs)] decl += " cl%03i *fn_%03i(" % (ret, fn) decl += ", ".join("cl%03i *" % p for p in params) decl += ");\n" - bindings += ' .def("fn_%03i", &cl%03i::fn_%03i)\n' % \ - (fn, cl, fn) + bindings += ' .def("fn_%03i", &cl%03i::fn_%03i)\n' % (fn, cl, fn) decl += "};\n\n" - bindings += ' ;\n' + bindings += " ;\n" result = "#include \n\n" result += "namespace py = pybind11;\n\n" - result += decl + '\n' + result += decl + "\n" result += "PYBIND11_MODULE(example, m) {\n" result += bindings result += "}" @@ -46,7 +45,7 @@ def generate_dummy_code_boost(nclasses=10): for cl in range(nclasses): decl += "class cl%03i;\n" % cl - decl += '\n' + decl += "\n" for cl in range(nclasses): decl += "class cl%03i {\n" % cl @@ -54,18 +53,20 @@ def generate_dummy_code_boost(nclasses=10): bindings += ' py::class_("cl%03i")\n' % (cl, cl) for fn in range(nfns): ret = random.randint(0, nclasses - 1) - params = [random.randint(0, nclasses - 1) for i in range(nargs)] + params = [random.randint(0, nclasses - 1) for i in range(nargs)] decl += " cl%03i *fn_%03i(" % (ret, fn) decl += ", ".join("cl%03i *" % p for p in params) decl += ");\n" - bindings += ' .def("fn_%03i", &cl%03i::fn_%03i, py::return_value_policy())\n' % \ - (fn, cl, fn) + bindings += ( + ' .def("fn_%03i", &cl%03i::fn_%03i, py::return_value_policy())\n' + % (fn, cl, fn) + ) decl += "};\n\n" - bindings += ' ;\n' + bindings += " ;\n" result = "#include \n\n" result += "namespace py = boost::python;\n\n" - result += decl + '\n' + result += decl + "\n" result += "BOOST_PYTHON_MODULE(example) {\n" result += bindings result += "}" @@ -73,17 +74,19 @@ def generate_dummy_code_boost(nclasses=10): for codegen in [generate_dummy_code_pybind11, generate_dummy_code_boost]: - print ("{") + print("{") for i in range(0, 10): nclasses = 2 ** i with open("test.cpp", "w") as f: f.write(codegen(nclasses)) n1 = dt.datetime.now() - os.system("g++ -Os -shared -rdynamic -undefined dynamic_lookup " + os.system( + "g++ -Os -shared -rdynamic -undefined dynamic_lookup " "-fvisibility=hidden -std=c++14 test.cpp -I include " - "-I /System/Library/Frameworks/Python.framework/Headers -o test.so") + "-I /System/Library/Frameworks/Python.framework/Headers -o test.so" + ) n2 = dt.datetime.now() elapsed = (n2 - n1).total_seconds() - size = os.stat('test.so').st_size + size = os.stat("test.so").st_size print(" {%i, %f, %i}," % (nclasses * nfns, elapsed, size)) - print ("}") + print("}") diff --git a/docs/conf.py b/docs/conf.py index 831cf6f58..dca362e2f 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -21,40 +21,44 @@ import subprocess # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.insert(0, os.path.abspath('.')) +# sys.path.insert(0, os.path.abspath('.')) # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' +# needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = ['breathe', 'sphinxcontrib.rsvgconverter', 'sphinxcontrib.moderncmakedomain'] +extensions = [ + "breathe", + "sphinxcontrib.rsvgconverter", + "sphinxcontrib.moderncmakedomain", +] -breathe_projects = {'pybind11': '.build/doxygenxml/'} -breathe_default_project = 'pybind11' -breathe_domain_by_extension = {'h': 'cpp'} +breathe_projects = {"pybind11": ".build/doxygenxml/"} +breathe_default_project = "pybind11" +breathe_domain_by_extension = {"h": "cpp"} # Add any paths that contain templates here, relative to this directory. -templates_path = ['.templates'] +templates_path = [".templates"] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # source_suffix = ['.rst', '.md'] -source_suffix = '.rst' +source_suffix = ".rst" # The encoding of source files. -#source_encoding = 'utf-8-sig' +# source_encoding = 'utf-8-sig' # The master toctree document. -master_doc = 'index' +master_doc = "index" # General information about the project. -project = 'pybind11' -copyright = '2017, Wenzel Jakob' -author = 'Wenzel Jakob' +project = "pybind11" +copyright = "2017, Wenzel Jakob" +author = "Wenzel Jakob" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -78,37 +82,37 @@ language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: -#today = '' +# today = '' # Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' +# today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. -exclude_patterns = ['.build', 'release.rst'] +exclude_patterns = [".build", "release.rst"] # The reST default role (used for this markup: `text`) to use for all # documents. -default_role = 'any' +default_role = "any" # If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True +# add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). -#add_module_names = True +# add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. -#show_authors = False +# show_authors = False # The name of the Pygments (syntax highlighting) style to use. -#pygments_style = 'monokai' +# pygments_style = 'monokai' # A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] +# modindex_common_prefix = [] # If true, keep warnings as "system message" paragraphs in the built documents. -#keep_warnings = False +# keep_warnings = False # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = False @@ -119,144 +123,137 @@ todo_include_todos = False # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -on_rtd = os.environ.get('READTHEDOCS', None) == 'True' +on_rtd = os.environ.get("READTHEDOCS", None) == "True" if not on_rtd: # only import and set the theme if we're building docs locally import sphinx_rtd_theme - html_theme = 'sphinx_rtd_theme' + + html_theme = "sphinx_rtd_theme" html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] - html_context = { - 'css_files': [ - '_static/theme_overrides.css' - ] - } + html_context = {"css_files": ["_static/theme_overrides.css"]} else: html_context = { - 'css_files': [ - '//media.readthedocs.org/css/sphinx_rtd_theme.css', - '//media.readthedocs.org/css/readthedocs-doc-embed.css', - '_static/theme_overrides.css' + "css_files": [ + "//media.readthedocs.org/css/sphinx_rtd_theme.css", + "//media.readthedocs.org/css/readthedocs-doc-embed.css", + "_static/theme_overrides.css", ] } # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. -#html_theme_options = {} +# html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] +# html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". -#html_title = None +# html_title = None # A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None +# html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. -#html_logo = None +# html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. -#html_favicon = None +# html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ["_static"] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. -#html_extra_path = [] +# html_extra_path = [] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' +# html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. -#html_use_smartypants = True +# html_use_smartypants = True # Custom sidebar templates, maps document names to template names. -#html_sidebars = {} +# html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. -#html_additional_pages = {} +# html_additional_pages = {} # If false, no module index is generated. -#html_domain_indices = True +# html_domain_indices = True # If false, no index is generated. -#html_use_index = True +# html_use_index = True # If true, the index is split into individual pages for each letter. -#html_split_index = False +# html_split_index = False # If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True +# html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True +# html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True +# html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. -#html_use_opensearch = '' +# html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None +# html_file_suffix = None # Language to be used for generating the HTML full-text search index. # Sphinx supports the following languages: # 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja' # 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr' -#html_search_language = 'en' +# html_search_language = 'en' # A dictionary with options for the search language support, empty by default. # Now only 'ja' uses this config value -#html_search_options = {'type': 'default'} +# html_search_options = {'type': 'default'} # The name of a javascript file (relative to the configuration directory) that # implements a search results scorer. If empty, the default will be used. -#html_search_scorer = 'scorer.js' +# html_search_scorer = 'scorer.js' # Output file base name for HTML help builder. -htmlhelp_basename = 'pybind11doc' +htmlhelp_basename = "pybind11doc" # -- Options for LaTeX output --------------------------------------------- latex_elements = { -# The paper size ('letterpaper' or 'a4paper'). -#'papersize': 'letterpaper', - -# The font size ('10pt', '11pt' or '12pt'). -#'pointsize': '10pt', - -# Additional stuff for the LaTeX preamble. -'preamble': r''' + # The paper size ('letterpaper' or 'a4paper'). + # 'papersize': 'letterpaper', + # The font size ('10pt', '11pt' or '12pt'). + # 'pointsize': '10pt', + # Additional stuff for the LaTeX preamble. + "preamble": r""" \DeclareUnicodeCharacter{00A0}{} \DeclareUnicodeCharacter{2194}{<->} -''', - -# Latex figure (float) alignment -#'figure_align': 'htbp', +""", + # Latex figure (float) alignment + # 'figure_align': 'htbp', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, 'pybind11.tex', 'pybind11 Documentation', - 'Wenzel Jakob', 'manual'), + (master_doc, "pybind11.tex", "pybind11 Documentation", "Wenzel Jakob", "manual"), ] # The name of an image file (relative to this directory) to place at the top of @@ -265,32 +262,29 @@ latex_documents = [ # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. -#latex_use_parts = False +# latex_use_parts = False # If true, show page references after internal links. -#latex_show_pagerefs = False +# latex_show_pagerefs = False # If true, show URL addresses after external links. -#latex_show_urls = False +# latex_show_urls = False # Documents to append as an appendix to all manuals. -#latex_appendices = [] +# latex_appendices = [] # If false, no module index is generated. -#latex_domain_indices = True +# latex_domain_indices = True # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, 'pybind11', 'pybind11 Documentation', - [author], 1) -] +man_pages = [(master_doc, "pybind11", "pybind11 Documentation", [author], 1)] # If true, show URL addresses after external links. -#man_show_urls = False +# man_show_urls = False # -- Options for Texinfo output ------------------------------------------- @@ -299,35 +293,41 @@ man_pages = [ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'pybind11', 'pybind11 Documentation', - author, 'pybind11', 'One line description of project.', - 'Miscellaneous'), + ( + master_doc, + "pybind11", + "pybind11 Documentation", + author, + "pybind11", + "One line description of project.", + "Miscellaneous", + ), ] # Documents to append as an appendix to all manuals. -#texinfo_appendices = [] +# texinfo_appendices = [] # If false, no module index is generated. -#texinfo_domain_indices = True +# texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' +# texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. -#texinfo_no_detailmenu = False +# texinfo_no_detailmenu = False -primary_domain = 'cpp' -highlight_language = 'cpp' +primary_domain = "cpp" +highlight_language = "cpp" def generate_doxygen_xml(app): - build_dir = os.path.join(app.confdir, '.build') + build_dir = os.path.join(app.confdir, ".build") if not os.path.exists(build_dir): os.mkdir(build_dir) try: - subprocess.call(['doxygen', '--version']) - retcode = subprocess.call(['doxygen'], cwd=app.confdir) + subprocess.call(["doxygen", "--version"]) + retcode = subprocess.call(["doxygen"], cwd=app.confdir) if retcode < 0: sys.stderr.write("doxygen error code: {}\n".format(-retcode)) except OSError as e: diff --git a/tests/conftest.py b/tests/conftest.py index a2350d041..362eb8069 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -18,9 +18,9 @@ import env # Early diagnostic for failed imports import pybind11_tests # noqa: F401 -_unicode_marker = re.compile(r'u(\'[^\']*\')') -_long_marker = re.compile(r'([0-9])L') -_hexadecimal = re.compile(r'0x[0-9a-fA-F]+') +_unicode_marker = re.compile(r"u(\'[^\']*\')") +_long_marker = re.compile(r"([0-9])L") +_hexadecimal = re.compile(r"0x[0-9a-fA-F]+") # Avoid collecting Python3 only files collect_ignore = [] @@ -30,7 +30,7 @@ if env.PY2: def _strip_and_dedent(s): """For triple-quote strings""" - return textwrap.dedent(s.lstrip('\n').rstrip()) + return textwrap.dedent(s.lstrip("\n").rstrip()) def _split_and_sort(s): @@ -40,11 +40,14 @@ def _split_and_sort(s): def _make_explanation(a, b): """Explanation for a failed assert -- the a and b arguments are List[str]""" - return ["--- actual / +++ expected"] + [line.strip('\n') for line in difflib.ndiff(a, b)] + return ["--- actual / +++ expected"] + [ + line.strip("\n") for line in difflib.ndiff(a, b) + ] class Output(object): """Basic output post-processing and comparison""" + def __init__(self, string): self.string = string self.explanation = [] @@ -54,7 +57,11 @@ class Output(object): def __eq__(self, other): # Ignore constructor/destructor output which is prefixed with "###" - a = [line for line in self.string.strip().splitlines() if not line.startswith("###")] + a = [ + line + for line in self.string.strip().splitlines() + if not line.startswith("###") + ] b = _strip_and_dedent(other).splitlines() if a == b: return True @@ -65,6 +72,7 @@ class Output(object): class Unordered(Output): """Custom comparison for output without strict line ordering""" + def __eq__(self, other): a = _split_and_sort(self.string) b = _split_and_sort(other) @@ -175,7 +183,7 @@ def msg(): # noinspection PyUnusedLocal def pytest_assertrepr_compare(op, left, right): """Hook to insert custom failure explanation""" - if hasattr(left, 'explanation'): + if hasattr(left, "explanation"): return left.explanation @@ -189,8 +197,8 @@ def suppress(exception): def gc_collect(): - ''' Run the garbage collector twice (needed when running - reference counting tests with PyPy) ''' + """Run the garbage collector twice (needed when running + reference counting tests with PyPy)""" gc.collect() gc.collect() diff --git a/tests/test_buffers.py b/tests/test_buffers.py index d6ca0776b..f0f370844 100644 --- a/tests/test_buffers.py +++ b/tests/test_buffers.py @@ -46,8 +46,8 @@ def test_to_python(): mat[3, 2] = 7.0 assert mat[2, 3] == 4 assert mat[3, 2] == 7 - assert struct.unpack_from('f', mat, (3 * 4 + 2) * 4) == (7, ) - assert struct.unpack_from('f', mat, (2 * 4 + 3) * 4) == (4, ) + assert struct.unpack_from("f", mat, (3 * 4 + 2) * 4) == (7,) + assert struct.unpack_from("f", mat, (2 * 4 + 3) * 4) == (4,) mat2 = np.array(mat, copy=False) assert mat2.shape == (5, 4) @@ -83,31 +83,31 @@ def test_pointer_to_member_fn(): for cls in [m.Buffer, m.ConstBuffer, m.DerivedBuffer]: buf = cls() buf.value = 0x12345678 - value = struct.unpack('i', bytearray(buf))[0] + value = struct.unpack("i", bytearray(buf))[0] assert value == 0x12345678 def test_readonly_buffer(): buf = m.BufferReadOnly(0x64) view = memoryview(buf) - assert view[0] == b'd' if env.PY2 else 0x64 + assert view[0] == b"d" if env.PY2 else 0x64 assert view.readonly def test_selective_readonly_buffer(): buf = m.BufferReadOnlySelect() - memoryview(buf)[0] = b'd' if env.PY2 else 0x64 + memoryview(buf)[0] = b"d" if env.PY2 else 0x64 assert buf.value == 0x64 - io.BytesIO(b'A').readinto(buf) - assert buf.value == ord(b'A') + io.BytesIO(b"A").readinto(buf) + assert buf.value == ord(b"A") buf.readonly = True with pytest.raises(TypeError): - memoryview(buf)[0] = b'\0' if env.PY2 else 0 + memoryview(buf)[0] = b"\0" if env.PY2 else 0 with pytest.raises(TypeError): - io.BytesIO(b'1').readinto(buf) + io.BytesIO(b"1").readinto(buf) def test_ctypes_array_1d(): diff --git a/tests/test_builtin_casters.py b/tests/test_builtin_casters.py index 08d38bc15..bd7996b62 100644 --- a/tests/test_builtin_casters.py +++ b/tests/test_builtin_casters.py @@ -37,79 +37,85 @@ def test_unicode_conversion(): with pytest.raises(UnicodeDecodeError): m.bad_utf8_u8string() - assert m.u8_Z() == 'Z' - assert m.u8_eacute() == u'Ă©' - assert m.u16_ibang() == u'“' - assert m.u32_mathbfA() == u'𝐀' - assert m.wchar_heart() == u'♄' + assert m.u8_Z() == "Z" + assert m.u8_eacute() == u"Ă©" + assert m.u16_ibang() == u"“" + assert m.u32_mathbfA() == u"𝐀" + assert m.wchar_heart() == u"♄" if hasattr(m, "has_u8string"): - assert m.u8_char8_Z() == 'Z' + assert m.u8_char8_Z() == "Z" def test_single_char_arguments(): """Tests failures for passing invalid inputs to char-accepting functions""" + def toobig_message(r): return "Character code point not in range({0:#x})".format(r) + toolong_message = "Expected a character, but multi-character string found" - assert m.ord_char(u'a') == 0x61 # simple ASCII - assert m.ord_char_lv(u'b') == 0x62 - assert m.ord_char(u'Ă©') == 0xE9 # requires 2 bytes in utf-8, but can be stuffed in a char + assert m.ord_char(u"a") == 0x61 # simple ASCII + assert m.ord_char_lv(u"b") == 0x62 + assert ( + m.ord_char(u"Ă©") == 0xE9 + ) # requires 2 bytes in utf-8, but can be stuffed in a char with pytest.raises(ValueError) as excinfo: - assert m.ord_char(u'Ā') == 0x100 # requires 2 bytes, doesn't fit in a char + assert m.ord_char(u"Ā") == 0x100 # requires 2 bytes, doesn't fit in a char assert str(excinfo.value) == toobig_message(0x100) with pytest.raises(ValueError) as excinfo: - assert m.ord_char(u'ab') + assert m.ord_char(u"ab") assert str(excinfo.value) == toolong_message - assert m.ord_char16(u'a') == 0x61 - assert m.ord_char16(u'Ă©') == 0xE9 - assert m.ord_char16_lv(u'ĂȘ') == 0xEA - assert m.ord_char16(u'Ā') == 0x100 - assert m.ord_char16(u'“') == 0x203d - assert m.ord_char16(u'♄') == 0x2665 - assert m.ord_char16_lv(u'♡') == 0x2661 + assert m.ord_char16(u"a") == 0x61 + assert m.ord_char16(u"Ă©") == 0xE9 + assert m.ord_char16_lv(u"ĂȘ") == 0xEA + assert m.ord_char16(u"Ā") == 0x100 + assert m.ord_char16(u"“") == 0x203D + assert m.ord_char16(u"♄") == 0x2665 + assert m.ord_char16_lv(u"♡") == 0x2661 with pytest.raises(ValueError) as excinfo: - assert m.ord_char16(u'🎂') == 0x1F382 # requires surrogate pair + assert m.ord_char16(u"🎂") == 0x1F382 # requires surrogate pair assert str(excinfo.value) == toobig_message(0x10000) with pytest.raises(ValueError) as excinfo: - assert m.ord_char16(u'aa') + assert m.ord_char16(u"aa") assert str(excinfo.value) == toolong_message - assert m.ord_char32(u'a') == 0x61 - assert m.ord_char32(u'Ă©') == 0xE9 - assert m.ord_char32(u'Ā') == 0x100 - assert m.ord_char32(u'“') == 0x203d - assert m.ord_char32(u'♄') == 0x2665 - assert m.ord_char32(u'🎂') == 0x1F382 + assert m.ord_char32(u"a") == 0x61 + assert m.ord_char32(u"Ă©") == 0xE9 + assert m.ord_char32(u"Ā") == 0x100 + assert m.ord_char32(u"“") == 0x203D + assert m.ord_char32(u"♄") == 0x2665 + assert m.ord_char32(u"🎂") == 0x1F382 with pytest.raises(ValueError) as excinfo: - assert m.ord_char32(u'aa') + assert m.ord_char32(u"aa") assert str(excinfo.value) == toolong_message - assert m.ord_wchar(u'a') == 0x61 - assert m.ord_wchar(u'Ă©') == 0xE9 - assert m.ord_wchar(u'Ā') == 0x100 - assert m.ord_wchar(u'“') == 0x203d - assert m.ord_wchar(u'♄') == 0x2665 + assert m.ord_wchar(u"a") == 0x61 + assert m.ord_wchar(u"Ă©") == 0xE9 + assert m.ord_wchar(u"Ā") == 0x100 + assert m.ord_wchar(u"“") == 0x203D + assert m.ord_wchar(u"♄") == 0x2665 if m.wchar_size == 2: with pytest.raises(ValueError) as excinfo: - assert m.ord_wchar(u'🎂') == 0x1F382 # requires surrogate pair + assert m.ord_wchar(u"🎂") == 0x1F382 # requires surrogate pair assert str(excinfo.value) == toobig_message(0x10000) else: - assert m.ord_wchar(u'🎂') == 0x1F382 + assert m.ord_wchar(u"🎂") == 0x1F382 with pytest.raises(ValueError) as excinfo: - assert m.ord_wchar(u'aa') + assert m.ord_wchar(u"aa") assert str(excinfo.value) == toolong_message if hasattr(m, "has_u8string"): - assert m.ord_char8(u'a') == 0x61 # simple ASCII - assert m.ord_char8_lv(u'b') == 0x62 - assert m.ord_char8(u'Ă©') == 0xE9 # requires 2 bytes in utf-8, but can be stuffed in a char + assert m.ord_char8(u"a") == 0x61 # simple ASCII + assert m.ord_char8_lv(u"b") == 0x62 + assert ( + m.ord_char8(u"Ă©") == 0xE9 + ) # requires 2 bytes in utf-8, but can be stuffed in a char with pytest.raises(ValueError) as excinfo: - assert m.ord_char8(u'Ā') == 0x100 # requires 2 bytes, doesn't fit in a char + assert m.ord_char8(u"Ā") == 0x100 # requires 2 bytes, doesn't fit in a char assert str(excinfo.value) == toobig_message(0x100) with pytest.raises(ValueError) as excinfo: - assert m.ord_char8(u'ab') + assert m.ord_char8(u"ab") assert str(excinfo.value) == toolong_message @@ -129,19 +135,19 @@ def test_bytes_to_string(): assert m.strlen(to_bytes("a\x00b")) == 1 # C-string limitation # passing in a utf8 encoded string should work - assert m.string_length(u'đŸ’©'.encode("utf8")) == 4 + assert m.string_length(u"đŸ’©".encode("utf8")) == 4 @pytest.mark.skipif(not hasattr(m, "has_string_view"), reason="no ") def test_string_view(capture): """Tests support for C++17 string_view arguments and return values""" assert m.string_view_chars("Hi") == [72, 105] - assert m.string_view_chars("Hi 🎂") == [72, 105, 32, 0xf0, 0x9f, 0x8e, 0x82] - assert m.string_view16_chars(u"Hi 🎂") == [72, 105, 32, 0xd83c, 0xdf82] + assert m.string_view_chars("Hi 🎂") == [72, 105, 32, 0xF0, 0x9F, 0x8E, 0x82] + assert m.string_view16_chars(u"Hi 🎂") == [72, 105, 32, 0xD83C, 0xDF82] assert m.string_view32_chars(u"Hi 🎂") == [72, 105, 32, 127874] if hasattr(m, "has_u8string"): assert m.string_view8_chars("Hi") == [72, 105] - assert m.string_view8_chars(u"Hi 🎂") == [72, 105, 32, 0xf0, 0x9f, 0x8e, 0x82] + assert m.string_view8_chars(u"Hi 🎂") == [72, 105, 32, 0xF0, 0x9F, 0x8E, 0x82] assert m.string_view_return() == u"utf8 secret 🎂" assert m.string_view16_return() == u"utf16 secret 🎂" @@ -154,40 +160,52 @@ def test_string_view(capture): m.string_view_print("utf8 🎂") m.string_view16_print(u"utf16 🎂") m.string_view32_print(u"utf32 🎂") - assert capture == u""" + assert ( + capture + == u""" Hi 2 utf8 🎂 9 utf16 🎂 8 utf32 🎂 7 """ + ) if hasattr(m, "has_u8string"): with capture: m.string_view8_print("Hi") m.string_view8_print(u"utf8 🎂") - assert capture == u""" + assert ( + capture + == u""" Hi 2 utf8 🎂 9 """ + ) with capture: m.string_view_print("Hi, ascii") m.string_view_print("Hi, utf8 🎂") m.string_view16_print(u"Hi, utf16 🎂") m.string_view32_print(u"Hi, utf32 🎂") - assert capture == u""" + assert ( + capture + == u""" Hi, ascii 9 Hi, utf8 🎂 13 Hi, utf16 🎂 12 Hi, utf32 🎂 11 """ + ) if hasattr(m, "has_u8string"): with capture: m.string_view8_print("Hi, ascii") m.string_view8_print(u"Hi, utf8 🎂") - assert capture == u""" + assert ( + capture + == u""" Hi, ascii 9 Hi, utf8 🎂 13 """ + ) def test_integer_casting(): @@ -199,8 +217,14 @@ def test_integer_casting(): if env.PY2: assert m.i32_str(long(-1)) == "-1" # noqa: F821 undefined name 'long' assert m.i64_str(long(-1)) == "-1" # noqa: F821 undefined name 'long' - assert m.i64_str(long(-999999999999)) == "-999999999999" # noqa: F821 undefined name - assert m.u64_str(long(999999999999)) == "999999999999" # noqa: F821 undefined name 'long' + assert ( + m.i64_str(long(-999999999999)) # noqa: F821 undefined name 'long' + == "-999999999999" + ) + assert ( + m.u64_str(long(999999999999)) # noqa: F821 undefined name 'long' + == "999999999999" + ) else: assert m.i64_str(-999999999999) == "-999999999999" assert m.u64_str(999999999999) == "999999999999" @@ -236,16 +260,22 @@ def test_tuple(doc): assert m.tuple_passthrough([True, "test", 5]) == (5, "test", True) assert m.empty_tuple() == () - assert doc(m.pair_passthrough) == """ + assert ( + doc(m.pair_passthrough) + == """ pair_passthrough(arg0: Tuple[bool, str]) -> Tuple[str, bool] Return a pair in reversed order """ - assert doc(m.tuple_passthrough) == """ + ) + assert ( + doc(m.tuple_passthrough) + == """ tuple_passthrough(arg0: Tuple[bool, str, int]) -> Tuple[int, str, bool] Return a triple in reversed order """ + ) assert m.rvalue_pair() == ("rvalue", "rvalue") assert m.lvalue_pair() == ("lvalue", "lvalue") @@ -372,7 +402,7 @@ def test_numpy_bool(): assert convert(np.bool_(False)) is False assert noconvert(np.bool_(True)) is True assert noconvert(np.bool_(False)) is False - cant_convert(np.zeros(2, dtype='int')) + cant_convert(np.zeros(2, dtype="int")) def test_int_long(): @@ -382,7 +412,8 @@ def test_int_long(): long.""" import sys - must_be_long = type(getattr(sys, 'maxint', 1) + 1) + + must_be_long = type(getattr(sys, "maxint", 1) + 1) assert isinstance(m.int_cast(), int) assert isinstance(m.long_cast(), int) assert isinstance(m.longlong_cast(), must_be_long) diff --git a/tests/test_call_policies.py b/tests/test_call_policies.py index ec005c132..e0413d145 100644 --- a/tests/test_call_policies.py +++ b/tests/test_call_policies.py @@ -16,10 +16,13 @@ def test_keep_alive_argument(capture): with capture: p.addChild(m.Child()) assert ConstructorStats.detail_reg_inst() == n_inst + 1 - assert capture == """ + assert ( + capture + == """ Allocating child. Releasing child. """ + ) with capture: del p assert ConstructorStats.detail_reg_inst() == n_inst @@ -35,10 +38,13 @@ def test_keep_alive_argument(capture): with capture: del p assert ConstructorStats.detail_reg_inst() == n_inst - assert capture == """ + assert ( + capture + == """ Releasing parent. Releasing child. """ + ) def test_keep_alive_return_value(capture): @@ -49,10 +55,13 @@ def test_keep_alive_return_value(capture): with capture: p.returnChild() assert ConstructorStats.detail_reg_inst() == n_inst + 1 - assert capture == """ + assert ( + capture + == """ Allocating child. Releasing child. """ + ) with capture: del p assert ConstructorStats.detail_reg_inst() == n_inst @@ -68,10 +77,13 @@ def test_keep_alive_return_value(capture): with capture: del p assert ConstructorStats.detail_reg_inst() == n_inst - assert capture == """ + assert ( + capture + == """ Releasing parent. Releasing child. """ + ) # https://foss.heptapod.net/pypy/pypy/-/issues/2447 @@ -82,14 +94,17 @@ def test_alive_gc(capture): p.addChildKeepAlive(m.Child()) assert ConstructorStats.detail_reg_inst() == n_inst + 2 lst = [p] - lst.append(lst) # creates a circular reference + lst.append(lst) # creates a circular reference with capture: del p, lst assert ConstructorStats.detail_reg_inst() == n_inst - assert capture == """ + assert ( + capture + == """ Releasing parent. Releasing child. """ + ) def test_alive_gc_derived(capture): @@ -101,14 +116,17 @@ def test_alive_gc_derived(capture): p.addChildKeepAlive(m.Child()) assert ConstructorStats.detail_reg_inst() == n_inst + 2 lst = [p] - lst.append(lst) # creates a circular reference + lst.append(lst) # creates a circular reference with capture: del p, lst assert ConstructorStats.detail_reg_inst() == n_inst - assert capture == """ + assert ( + capture + == """ Releasing parent. Releasing child. """ + ) def test_alive_gc_multi_derived(capture): @@ -123,15 +141,18 @@ def test_alive_gc_multi_derived(capture): # +3 rather than +2 because Derived corresponds to two registered instances assert ConstructorStats.detail_reg_inst() == n_inst + 3 lst = [p] - lst.append(lst) # creates a circular reference + lst.append(lst) # creates a circular reference with capture: del p, lst assert ConstructorStats.detail_reg_inst() == n_inst - assert capture == """ + assert ( + capture + == """ Releasing parent. Releasing child. Releasing child. """ + ) def test_return_none(capture): @@ -167,17 +188,23 @@ def test_keep_alive_constructor(capture): with capture: p = m.Parent(m.Child()) assert ConstructorStats.detail_reg_inst() == n_inst + 2 - assert capture == """ + assert ( + capture + == """ Allocating child. Allocating parent. """ + ) with capture: del p assert ConstructorStats.detail_reg_inst() == n_inst - assert capture == """ + assert ( + capture + == """ Releasing parent. Releasing child. """ + ) def test_call_guard(): diff --git a/tests/test_callbacks.py b/tests/test_callbacks.py index d5d0e045d..039b877ce 100644 --- a/tests/test_callbacks.py +++ b/tests/test_callbacks.py @@ -42,17 +42,19 @@ def test_bound_method_callback(): def test_keyword_args_and_generalized_unpacking(): - def f(*args, **kwargs): return args, kwargs assert m.test_tuple_unpacking(f) == (("positional", 1, 2, 3, 4, 5, 6), {}) - assert m.test_dict_unpacking(f) == (("positional", 1), {"key": "value", "a": 1, "b": 2}) + assert m.test_dict_unpacking(f) == ( + ("positional", 1), + {"key": "value", "a": 1, "b": 2}, + ) assert m.test_keyword_args(f) == ((), {"x": 10, "y": 20}) assert m.test_unpacking_and_keywords1(f) == ((1, 2), {"c": 3, "d": 4}) assert m.test_unpacking_and_keywords2(f) == ( ("positional", 1, 2, 3, 4, 5), - {"key": "value", "a": 1, "b": 2, "c": 3, "d": 4, "e": 5} + {"key": "value", "a": 1, "b": 2, "c": 3, "d": 4, "e": 5}, ) with pytest.raises(TypeError) as excinfo: @@ -83,12 +85,18 @@ def test_lambda_closure_cleanup(): def test_cpp_function_roundtrip(): """Test if passing a function pointer from C++ -> Python -> C++ yields the original pointer""" - assert m.test_dummy_function(m.dummy_function) == "matches dummy_function: eval(1) = 2" - assert (m.test_dummy_function(m.roundtrip(m.dummy_function)) == - "matches dummy_function: eval(1) = 2") + assert ( + m.test_dummy_function(m.dummy_function) == "matches dummy_function: eval(1) = 2" + ) + assert ( + m.test_dummy_function(m.roundtrip(m.dummy_function)) + == "matches dummy_function: eval(1) = 2" + ) assert m.roundtrip(None, expect_none=True) is None - assert (m.test_dummy_function(lambda x: x + 2) == - "can't convert to function pointer: eval(1) = 3") + assert ( + m.test_dummy_function(lambda x: x + 2) + == "can't convert to function pointer: eval(1) = 3" + ) with pytest.raises(TypeError) as excinfo: m.test_dummy_function(m.dummy_function2) @@ -96,8 +104,10 @@ def test_cpp_function_roundtrip(): with pytest.raises(TypeError) as excinfo: m.test_dummy_function(lambda x, y: x + y) - assert any(s in str(excinfo.value) for s in ("missing 1 required positional argument", - "takes exactly 2 arguments")) + assert any( + s in str(excinfo.value) + for s in ("missing 1 required positional argument", "takes exactly 2 arguments") + ) def test_function_signatures(doc): @@ -127,6 +137,7 @@ def test_async_callbacks(): m.test_async_callback(gen_f(), work) # wait until work is done from time import sleep + sleep(0.5) assert sum(res) == sum([x + 3 for x in work]) diff --git a/tests/test_chrono.py b/tests/test_chrono.py index ae24b7dda..e9e24e082 100644 --- a/tests/test_chrono.py +++ b/tests/test_chrono.py @@ -80,22 +80,28 @@ SKIP_TZ_ENV_ON_WIN = pytest.mark.skipif( ) -@pytest.mark.parametrize("time1", [ - datetime.datetime.today().time(), - datetime.time(0, 0, 0), - datetime.time(0, 0, 0, 1), - datetime.time(0, 28, 45, 109827), - datetime.time(0, 59, 59, 999999), - datetime.time(1, 0, 0), - datetime.time(5, 59, 59, 0), - datetime.time(5, 59, 59, 1), -]) -@pytest.mark.parametrize("tz", [ - None, - pytest.param("Europe/Brussels", marks=SKIP_TZ_ENV_ON_WIN), - pytest.param("Asia/Pyongyang", marks=SKIP_TZ_ENV_ON_WIN), - pytest.param("America/New_York", marks=SKIP_TZ_ENV_ON_WIN), -]) +@pytest.mark.parametrize( + "time1", + [ + datetime.datetime.today().time(), + datetime.time(0, 0, 0), + datetime.time(0, 0, 0, 1), + datetime.time(0, 28, 45, 109827), + datetime.time(0, 59, 59, 999999), + datetime.time(1, 0, 0), + datetime.time(5, 59, 59, 0), + datetime.time(5, 59, 59, 1), + ], +) +@pytest.mark.parametrize( + "tz", + [ + None, + pytest.param("Europe/Brussels", marks=SKIP_TZ_ENV_ON_WIN), + pytest.param("Asia/Pyongyang", marks=SKIP_TZ_ENV_ON_WIN), + pytest.param("America/New_York", marks=SKIP_TZ_ENV_ON_WIN), + ], +) def test_chrono_system_clock_roundtrip_time(time1, tz, monkeypatch): if tz is not None: monkeypatch.setenv("TZ", "/usr/share/zoneinfo/{}".format(tz)) @@ -199,7 +205,7 @@ def test_floating_point_duration(): def test_nano_timepoint(): time = datetime.datetime.now() time1 = m.test_nano_timepoint(time, datetime.timedelta(seconds=60)) - assert(time1 == time + datetime.timedelta(seconds=60)) + assert time1 == time + datetime.timedelta(seconds=60) def test_chrono_different_resolutions(): diff --git a/tests/test_class.py b/tests/test_class.py index 10e4dd79b..c34ee8a12 100644 --- a/tests/test_class.py +++ b/tests/test_class.py @@ -31,8 +31,10 @@ def test_type(): with pytest.raises(RuntimeError) as execinfo: m.check_type(0) - assert 'pybind11::detail::get_type_info: unable to find type info' in str(execinfo.value) - assert 'Invalid' in str(execinfo.value) + assert "pybind11::detail::get_type_info: unable to find type info" in str( + execinfo.value + ) + assert "Invalid" in str(execinfo.value) # Currently not supported # See https://github.com/pybind/pybind11/issues/2486 @@ -73,18 +75,24 @@ def test_docstrings(doc): assert UserType.get_value.__name__ == "get_value" assert UserType.get_value.__module__ == "pybind11_tests" - assert doc(UserType.get_value) == """ + assert ( + doc(UserType.get_value) + == """ get_value(self: m.UserType) -> int Get value using a method """ + ) assert doc(UserType.value) == "Get/set value using a property" - assert doc(m.NoConstructor.new_instance) == """ + assert ( + doc(m.NoConstructor.new_instance) + == """ new_instance() -> m.class_.NoConstructor Return an instance """ + ) def test_qualname(doc): @@ -93,51 +101,69 @@ def test_qualname(doc): assert m.NestBase.__qualname__ == "NestBase" assert m.NestBase.Nested.__qualname__ == "NestBase.Nested" - assert doc(m.NestBase.__init__) == """ + assert ( + doc(m.NestBase.__init__) + == """ __init__(self: m.class_.NestBase) -> None """ - assert doc(m.NestBase.g) == """ + ) + assert ( + doc(m.NestBase.g) + == """ g(self: m.class_.NestBase, arg0: m.class_.NestBase.Nested) -> None """ - assert doc(m.NestBase.Nested.__init__) == """ + ) + assert ( + doc(m.NestBase.Nested.__init__) + == """ __init__(self: m.class_.NestBase.Nested) -> None """ - assert doc(m.NestBase.Nested.fn) == """ + ) + assert ( + doc(m.NestBase.Nested.fn) + == """ fn(self: m.class_.NestBase.Nested, arg0: int, arg1: m.class_.NestBase, arg2: m.class_.NestBase.Nested) -> None """ # noqa: E501 line too long - assert doc(m.NestBase.Nested.fa) == """ + ) + assert ( + doc(m.NestBase.Nested.fa) + == """ fa(self: m.class_.NestBase.Nested, a: int, b: m.class_.NestBase, c: m.class_.NestBase.Nested) -> None """ # noqa: E501 line too long + ) assert m.NestBase.__module__ == "pybind11_tests.class_" assert m.NestBase.Nested.__module__ == "pybind11_tests.class_" def test_inheritance(msg): - roger = m.Rabbit('Rabbit') + roger = m.Rabbit("Rabbit") assert roger.name() + " is a " + roger.species() == "Rabbit is a parrot" assert m.pet_name_species(roger) == "Rabbit is a parrot" - polly = m.Pet('Polly', 'parrot') + polly = m.Pet("Polly", "parrot") assert polly.name() + " is a " + polly.species() == "Polly is a parrot" assert m.pet_name_species(polly) == "Polly is a parrot" - molly = m.Dog('Molly') + molly = m.Dog("Molly") assert molly.name() + " is a " + molly.species() == "Molly is a dog" assert m.pet_name_species(molly) == "Molly is a dog" - fred = m.Hamster('Fred') + fred = m.Hamster("Fred") assert fred.name() + " is a " + fred.species() == "Fred is a rodent" assert m.dog_bark(molly) == "Woof!" with pytest.raises(TypeError) as excinfo: m.dog_bark(polly) - assert msg(excinfo.value) == """ + assert ( + msg(excinfo.value) + == """ dog_bark(): incompatible function arguments. The following argument types are supported: 1. (arg0: m.class_.Dog) -> str Invoked with: """ + ) with pytest.raises(TypeError) as excinfo: m.Chimera("lion", "goat") @@ -150,6 +176,7 @@ def test_inheritance_init(msg): class Python(m.Pet): def __init__(self): pass + with pytest.raises(TypeError) as exc_info: Python() expected = "m.class_.Pet.__init__() must be called when overriding __init__" @@ -191,13 +218,19 @@ def test_mismatched_holder(): with pytest.raises(RuntimeError) as excinfo: m.mismatched_holder_1() - assert re.match('generic_type: type ".*MismatchDerived1" does not have a non-default ' - 'holder type while its base ".*MismatchBase1" does', str(excinfo.value)) + assert re.match( + 'generic_type: type ".*MismatchDerived1" does not have a non-default ' + 'holder type while its base ".*MismatchBase1" does', + str(excinfo.value), + ) with pytest.raises(RuntimeError) as excinfo: m.mismatched_holder_2() - assert re.match('generic_type: type ".*MismatchDerived2" has a non-default holder type ' - 'while its base ".*MismatchBase2" does not', str(excinfo.value)) + assert re.match( + 'generic_type: type ".*MismatchDerived2" has a non-default holder type ' + 'while its base ".*MismatchBase2" does not', + str(excinfo.value), + ) def test_override_static(): @@ -229,20 +262,20 @@ def test_operator_new_delete(capture): a = m.HasOpNewDel() b = m.HasOpNewDelSize() d = m.HasOpNewDelBoth() - assert capture == """ + assert ( + capture + == """ A new 8 B new 4 D new 32 """ + ) sz_alias = str(m.AliasedHasOpNewDelSize.size_alias) sz_noalias = str(m.AliasedHasOpNewDelSize.size_noalias) with capture: c = m.AliasedHasOpNewDelSize() c2 = SubAliased() - assert capture == ( - "C new " + sz_noalias + "\n" + - "C new " + sz_alias + "\n" - ) + assert capture == ("C new " + sz_noalias + "\n" + "C new " + sz_alias + "\n") with capture: del a @@ -251,21 +284,21 @@ def test_operator_new_delete(capture): pytest.gc_collect() del d pytest.gc_collect() - assert capture == """ + assert ( + capture + == """ A delete B delete 4 D delete """ + ) with capture: del c pytest.gc_collect() del c2 pytest.gc_collect() - assert capture == ( - "C delete " + sz_noalias + "\n" + - "C delete " + sz_alias + "\n" - ) + assert capture == ("C delete " + sz_noalias + "\n" + "C delete " + sz_alias + "\n") def test_bind_protected_functions(): @@ -325,19 +358,23 @@ def test_reentrant_implicit_conversion_failure(msg): # ensure that there is no runaway reentrant implicit conversion (#1035) with pytest.raises(TypeError) as excinfo: m.BogusImplicitConversion(0) - assert msg(excinfo.value) == ''' + assert ( + msg(excinfo.value) + == """ __init__(): incompatible constructor arguments. The following argument types are supported: 1. m.class_.BogusImplicitConversion(arg0: m.class_.BogusImplicitConversion) Invoked with: 0 - ''' + """ + ) def test_error_after_conversions(): with pytest.raises(TypeError) as exc_info: m.test_error_after_conversions("hello") assert str(exc_info.value).startswith( - "Unable to convert function return value to a Python type!") + "Unable to convert function return value to a Python type!" + ) def test_aligned(): @@ -350,8 +387,10 @@ def test_aligned(): @pytest.mark.xfail("env.PYPY") def test_final(): with pytest.raises(TypeError) as exc_info: + class PyFinalChild(m.IsFinal): pass + assert str(exc_info.value).endswith("is not an acceptable base type") @@ -359,8 +398,10 @@ def test_final(): @pytest.mark.xfail("env.PYPY") def test_non_final_final(): with pytest.raises(TypeError) as exc_info: + class PyNonFinalFinalChild(m.IsNonFinalFinal): pass + assert str(exc_info.value).endswith("is not an acceptable base type") @@ -396,11 +437,14 @@ def test_base_and_derived_nested_scope(): @pytest.mark.skip("See https://github.com/pybind/pybind11/pull/2564") def test_register_duplicate_class(): import types + module_scope = types.ModuleType("module_scope") with pytest.raises(RuntimeError) as exc_info: m.register_duplicate_class_name(module_scope) - expected = ('generic_type: cannot initialize type "Duplicate": ' - 'an object with that name is already defined') + expected = ( + 'generic_type: cannot initialize type "Duplicate": ' + "an object with that name is already defined" + ) assert str(exc_info.value) == expected with pytest.raises(RuntimeError) as exc_info: m.register_duplicate_class_type(module_scope) @@ -409,10 +453,13 @@ def test_register_duplicate_class(): class ClassScope: pass + with pytest.raises(RuntimeError) as exc_info: m.register_duplicate_nested_class_name(ClassScope) - expected = ('generic_type: cannot initialize type "DuplicateNested": ' - 'an object with that name is already defined') + expected = ( + 'generic_type: cannot initialize type "DuplicateNested": ' + "an object with that name is already defined" + ) assert str(exc_info.value) == expected with pytest.raises(RuntimeError) as exc_info: m.register_duplicate_nested_class_type(ClassScope) diff --git a/tests/test_copy_move.py b/tests/test_copy_move.py index 6b53993a9..7e3cc168c 100644 --- a/tests/test_copy_move.py +++ b/tests/test_copy_move.py @@ -19,7 +19,11 @@ def test_move_and_copy_casts(): """Cast some values in C++ via custom type casters and count the number of moves/copies.""" cstats = m.move_and_copy_cstats() - c_m, c_mc, c_c = cstats["MoveOnlyInt"], cstats["MoveOrCopyInt"], cstats["CopyOnlyInt"] + c_m, c_mc, c_c = ( + cstats["MoveOnlyInt"], + cstats["MoveOrCopyInt"], + cstats["CopyOnlyInt"], + ) # The type move constructions/assignments below each get incremented: the move assignment comes # from the type_caster load; the move construction happens when extracting that via a cast or @@ -43,7 +47,11 @@ def test_move_and_copy_loads(): moves/copies.""" cstats = m.move_and_copy_cstats() - c_m, c_mc, c_c = cstats["MoveOnlyInt"], cstats["MoveOrCopyInt"], cstats["CopyOnlyInt"] + c_m, c_mc, c_c = ( + cstats["MoveOnlyInt"], + cstats["MoveOrCopyInt"], + cstats["CopyOnlyInt"], + ) assert m.move_only(10) == 10 # 1 move, c_m assert m.move_or_copy(11) == 11 # 1 move, c_mc @@ -66,12 +74,16 @@ def test_move_and_copy_loads(): assert c_m.alive() + c_mc.alive() + c_c.alive() == 0 -@pytest.mark.skipif(not m.has_optional, reason='no ') +@pytest.mark.skipif(not m.has_optional, reason="no ") def test_move_and_copy_load_optional(): """Tests move/copy loads of std::optional arguments""" cstats = m.move_and_copy_cstats() - c_m, c_mc, c_c = cstats["MoveOnlyInt"], cstats["MoveOrCopyInt"], cstats["CopyOnlyInt"] + c_m, c_mc, c_c = ( + cstats["MoveOnlyInt"], + cstats["MoveOrCopyInt"], + cstats["CopyOnlyInt"], + ) # The extra move/copy constructions below come from the std::optional move (which has to move # its arguments): diff --git a/tests/test_custom_type_casters.py b/tests/test_custom_type_casters.py index 9475c4516..bb74d54eb 100644 --- a/tests/test_custom_type_casters.py +++ b/tests/test_custom_type_casters.py @@ -5,65 +5,91 @@ from pybind11_tests import custom_type_casters as m def test_noconvert_args(msg): a = m.ArgInspector() - assert msg(a.f("hi")) == """ + assert ( + msg(a.f("hi")) + == """ loading ArgInspector1 argument WITH conversion allowed. Argument value = hi """ - assert msg(a.g("this is a", "this is b")) == """ + ) + assert ( + msg(a.g("this is a", "this is b")) + == """ loading ArgInspector1 argument WITHOUT conversion allowed. Argument value = this is a loading ArgInspector1 argument WITH conversion allowed. Argument value = this is b 13 loading ArgInspector2 argument WITH conversion allowed. Argument value = (default arg inspector 2) """ # noqa: E501 line too long - assert msg(a.g("this is a", "this is b", 42)) == """ + ) + assert ( + msg(a.g("this is a", "this is b", 42)) + == """ loading ArgInspector1 argument WITHOUT conversion allowed. Argument value = this is a loading ArgInspector1 argument WITH conversion allowed. Argument value = this is b 42 loading ArgInspector2 argument WITH conversion allowed. Argument value = (default arg inspector 2) """ # noqa: E501 line too long - assert msg(a.g("this is a", "this is b", 42, "this is d")) == """ + ) + assert ( + msg(a.g("this is a", "this is b", 42, "this is d")) + == """ loading ArgInspector1 argument WITHOUT conversion allowed. Argument value = this is a loading ArgInspector1 argument WITH conversion allowed. Argument value = this is b 42 loading ArgInspector2 argument WITH conversion allowed. Argument value = this is d """ - assert (a.h("arg 1") == - "loading ArgInspector2 argument WITHOUT conversion allowed. Argument value = arg 1") - assert msg(m.arg_inspect_func("A1", "A2")) == """ + ) + assert ( + a.h("arg 1") + == "loading ArgInspector2 argument WITHOUT conversion allowed. Argument value = arg 1" + ) + assert ( + msg(m.arg_inspect_func("A1", "A2")) + == """ loading ArgInspector2 argument WITH conversion allowed. Argument value = A1 loading ArgInspector1 argument WITHOUT conversion allowed. Argument value = A2 """ + ) assert m.floats_preferred(4) == 2.0 assert m.floats_only(4.0) == 2.0 with pytest.raises(TypeError) as excinfo: m.floats_only(4) - assert msg(excinfo.value) == """ + assert ( + msg(excinfo.value) + == """ floats_only(): incompatible function arguments. The following argument types are supported: 1. (f: float) -> float Invoked with: 4 """ + ) assert m.ints_preferred(4) == 2 assert m.ints_preferred(True) == 0 with pytest.raises(TypeError) as excinfo: m.ints_preferred(4.0) - assert msg(excinfo.value) == """ + assert ( + msg(excinfo.value) + == """ ints_preferred(): incompatible function arguments. The following argument types are supported: 1. (i: int) -> int Invoked with: 4.0 """ # noqa: E501 line too long + ) assert m.ints_only(4) == 2 with pytest.raises(TypeError) as excinfo: m.ints_only(4.0) - assert msg(excinfo.value) == """ + assert ( + msg(excinfo.value) + == """ ints_only(): incompatible function arguments. The following argument types are supported: 1. (i: int) -> int Invoked with: 4.0 """ + ) def test_custom_caster_destruction(): diff --git a/tests/test_docstring_options.py b/tests/test_docstring_options.py index 80ade0f15..87d80d2df 100644 --- a/tests/test_docstring_options.py +++ b/tests/test_docstring_options.py @@ -18,10 +18,10 @@ def test_docstring_options(): assert m.test_overloaded3.__doc__ == "Overload docstr" # options.enable_function_signatures() - assert m.test_function3.__doc__ .startswith("test_function3(a: int, b: int) -> None") + assert m.test_function3.__doc__.startswith("test_function3(a: int, b: int) -> None") - assert m.test_function4.__doc__ .startswith("test_function4(a: int, b: int) -> None") - assert m.test_function4.__doc__ .endswith("A custom docstring\n") + assert m.test_function4.__doc__.startswith("test_function4(a: int, b: int) -> None") + assert m.test_function4.__doc__.endswith("A custom docstring\n") # options.disable_function_signatures() # options.disable_user_defined_docstrings() @@ -31,8 +31,8 @@ def test_docstring_options(): assert m.test_function6.__doc__ == "A custom docstring" # RAII destructor - assert m.test_function7.__doc__ .startswith("test_function7(a: int, b: int) -> None") - assert m.test_function7.__doc__ .endswith("A custom docstring\n") + assert m.test_function7.__doc__.startswith("test_function7(a: int, b: int) -> None") + assert m.test_function7.__doc__.endswith("A custom docstring\n") # Suppression of user-defined docstrings for non-function objects assert not m.DocstringTestFoo.__doc__ diff --git a/tests/test_eigen.py b/tests/test_eigen.py index ac6847147..a131dc15d 100644 --- a/tests/test_eigen.py +++ b/tests/test_eigen.py @@ -6,11 +6,15 @@ np = pytest.importorskip("numpy") m = pytest.importorskip("pybind11_tests.eigen") -ref = np.array([[ 0., 3, 0, 0, 0, 11], - [22, 0, 0, 0, 17, 11], - [ 7, 5, 0, 1, 0, 11], - [ 0, 0, 0, 0, 0, 11], - [ 0, 0, 14, 0, 8, 11]]) +ref = np.array( + [ + [0.0, 3, 0, 0, 0, 11], + [22, 0, 0, 0, 17, 11], + [7, 5, 0, 1, 0, 11], + [0, 0, 0, 0, 0, 11], + [0, 0, 14, 0, 8, 11], + ] +) def assert_equal_ref(mat): @@ -40,28 +44,37 @@ def test_dense(): def test_partially_fixed(): - ref2 = np.array([[0., 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]]) + ref2 = np.array([[0.0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]]) np.testing.assert_array_equal(m.partial_copy_four_rm_r(ref2), ref2) np.testing.assert_array_equal(m.partial_copy_four_rm_c(ref2), ref2) np.testing.assert_array_equal(m.partial_copy_four_rm_r(ref2[:, 1]), ref2[:, [1]]) np.testing.assert_array_equal(m.partial_copy_four_rm_c(ref2[0, :]), ref2[[0], :]) - np.testing.assert_array_equal(m.partial_copy_four_rm_r(ref2[:, (0, 2)]), ref2[:, (0, 2)]) np.testing.assert_array_equal( - m.partial_copy_four_rm_c(ref2[(3, 1, 2), :]), ref2[(3, 1, 2), :]) + m.partial_copy_four_rm_r(ref2[:, (0, 2)]), ref2[:, (0, 2)] + ) + np.testing.assert_array_equal( + m.partial_copy_four_rm_c(ref2[(3, 1, 2), :]), ref2[(3, 1, 2), :] + ) np.testing.assert_array_equal(m.partial_copy_four_cm_r(ref2), ref2) np.testing.assert_array_equal(m.partial_copy_four_cm_c(ref2), ref2) np.testing.assert_array_equal(m.partial_copy_four_cm_r(ref2[:, 1]), ref2[:, [1]]) np.testing.assert_array_equal(m.partial_copy_four_cm_c(ref2[0, :]), ref2[[0], :]) - np.testing.assert_array_equal(m.partial_copy_four_cm_r(ref2[:, (0, 2)]), ref2[:, (0, 2)]) np.testing.assert_array_equal( - m.partial_copy_four_cm_c(ref2[(3, 1, 2), :]), ref2[(3, 1, 2), :]) + m.partial_copy_four_cm_r(ref2[:, (0, 2)]), ref2[:, (0, 2)] + ) + np.testing.assert_array_equal( + m.partial_copy_four_cm_c(ref2[(3, 1, 2), :]), ref2[(3, 1, 2), :] + ) # TypeError should be raise for a shape mismatch - functions = [m.partial_copy_four_rm_r, m.partial_copy_four_rm_c, - m.partial_copy_four_cm_r, m.partial_copy_four_cm_c] - matrix_with_wrong_shape = [[1, 2], - [3, 4]] + functions = [ + m.partial_copy_four_rm_r, + m.partial_copy_four_rm_c, + m.partial_copy_four_cm_r, + m.partial_copy_four_cm_c, + ] + matrix_with_wrong_shape = [[1, 2], [3, 4]] for f in functions: with pytest.raises(TypeError) as excinfo: f(matrix_with_wrong_shape) @@ -69,7 +82,7 @@ def test_partially_fixed(): def test_mutator_descriptors(): - zr = np.arange(30, dtype='float32').reshape(5, 6) # row-major + zr = np.arange(30, dtype="float32").reshape(5, 6) # row-major zc = zr.reshape(6, 5).transpose() # column-major m.fixed_mutator_r(zr) @@ -78,18 +91,21 @@ def test_mutator_descriptors(): m.fixed_mutator_a(zc) with pytest.raises(TypeError) as excinfo: m.fixed_mutator_r(zc) - assert ('(arg0: numpy.ndarray[numpy.float32[5, 6],' - ' flags.writeable, flags.c_contiguous]) -> None' - in str(excinfo.value)) + assert ( + "(arg0: numpy.ndarray[numpy.float32[5, 6]," + " flags.writeable, flags.c_contiguous]) -> None" in str(excinfo.value) + ) with pytest.raises(TypeError) as excinfo: m.fixed_mutator_c(zr) - assert ('(arg0: numpy.ndarray[numpy.float32[5, 6],' - ' flags.writeable, flags.f_contiguous]) -> None' - in str(excinfo.value)) + assert ( + "(arg0: numpy.ndarray[numpy.float32[5, 6]," + " flags.writeable, flags.f_contiguous]) -> None" in str(excinfo.value) + ) with pytest.raises(TypeError) as excinfo: - m.fixed_mutator_a(np.array([[1, 2], [3, 4]], dtype='float32')) - assert ('(arg0: numpy.ndarray[numpy.float32[5, 6], flags.writeable]) -> None' - in str(excinfo.value)) + m.fixed_mutator_a(np.array([[1, 2], [3, 4]], dtype="float32")) + assert "(arg0: numpy.ndarray[numpy.float32[5, 6], flags.writeable]) -> None" in str( + excinfo.value + ) zr.flags.writeable = False with pytest.raises(TypeError): m.fixed_mutator_r(zr) @@ -98,26 +114,26 @@ def test_mutator_descriptors(): def test_cpp_casting(): - assert m.cpp_copy(m.fixed_r()) == 22. - assert m.cpp_copy(m.fixed_c()) == 22. - z = np.array([[5., 6], [7, 8]]) - assert m.cpp_copy(z) == 7. - assert m.cpp_copy(m.get_cm_ref()) == 21. - assert m.cpp_copy(m.get_rm_ref()) == 21. - assert m.cpp_ref_c(m.get_cm_ref()) == 21. - assert m.cpp_ref_r(m.get_rm_ref()) == 21. + assert m.cpp_copy(m.fixed_r()) == 22.0 + assert m.cpp_copy(m.fixed_c()) == 22.0 + z = np.array([[5.0, 6], [7, 8]]) + assert m.cpp_copy(z) == 7.0 + assert m.cpp_copy(m.get_cm_ref()) == 21.0 + assert m.cpp_copy(m.get_rm_ref()) == 21.0 + assert m.cpp_ref_c(m.get_cm_ref()) == 21.0 + assert m.cpp_ref_r(m.get_rm_ref()) == 21.0 with pytest.raises(RuntimeError) as excinfo: # Can't reference m.fixed_c: it contains floats, m.cpp_ref_any wants doubles m.cpp_ref_any(m.fixed_c()) - assert 'Unable to cast Python instance' in str(excinfo.value) + assert "Unable to cast Python instance" in str(excinfo.value) with pytest.raises(RuntimeError) as excinfo: # Can't reference m.fixed_r: it contains floats, m.cpp_ref_any wants doubles m.cpp_ref_any(m.fixed_r()) - assert 'Unable to cast Python instance' in str(excinfo.value) - assert m.cpp_ref_any(m.ReturnTester.create()) == 1. + assert "Unable to cast Python instance" in str(excinfo.value) + assert m.cpp_ref_any(m.ReturnTester.create()) == 1.0 - assert m.cpp_ref_any(m.get_cm_ref()) == 21. - assert m.cpp_ref_any(m.get_cm_ref()) == 21. + assert m.cpp_ref_any(m.get_cm_ref()) == 21.0 + assert m.cpp_ref_any(m.get_cm_ref()) == 21.0 def test_pass_readonly_array(): @@ -149,7 +165,7 @@ def test_nonunit_stride_from_python(): # Mutator: m.double_threer(second_row) m.double_threec(second_col) - np.testing.assert_array_equal(counting_mat, [[0., 2, 2], [6, 16, 10], [6, 14, 8]]) + np.testing.assert_array_equal(counting_mat, [[0.0, 2, 2], [6, 16, 10], [6, 14, 8]]) def test_negative_stride_from_python(msg): @@ -178,26 +194,36 @@ def test_negative_stride_from_python(msg): # Mutator: with pytest.raises(TypeError) as excinfo: m.double_threer(second_row) - assert msg(excinfo.value) == """ + assert ( + msg(excinfo.value) + == """ double_threer(): incompatible function arguments. The following argument types are supported: 1. (arg0: numpy.ndarray[numpy.float32[1, 3], flags.writeable]) -> None - Invoked with: """ + repr(np.array([ 5., 4., 3.], dtype='float32')) # noqa: E501 line too long + Invoked with: """ # noqa: E501 line too long + + repr(np.array([5.0, 4.0, 3.0], dtype="float32")) + ) with pytest.raises(TypeError) as excinfo: m.double_threec(second_col) - assert msg(excinfo.value) == """ + assert ( + msg(excinfo.value) + == """ double_threec(): incompatible function arguments. The following argument types are supported: 1. (arg0: numpy.ndarray[numpy.float32[3, 1], flags.writeable]) -> None - Invoked with: """ + repr(np.array([ 7., 4., 1.], dtype='float32')) # noqa: E501 line too long + Invoked with: """ # noqa: E501 line too long + + repr(np.array([7.0, 4.0, 1.0], dtype="float32")) + ) def test_nonunit_stride_to_python(): assert np.all(m.diagonal(ref) == ref.diagonal()) assert np.all(m.diagonal_1(ref) == ref.diagonal(1)) for i in range(-5, 7): - assert np.all(m.diagonal_n(ref, i) == ref.diagonal(i)), "m.diagonal_n({})".format(i) + assert np.all( + m.diagonal_n(ref, i) == ref.diagonal(i) + ), "m.diagonal_n({})".format(i) assert np.all(m.block(ref, 2, 1, 3, 3) == ref[2:5, 1:4]) assert np.all(m.block(ref, 1, 4, 4, 2) == ref[1:, 4:]) @@ -207,8 +233,10 @@ def test_nonunit_stride_to_python(): def test_eigen_ref_to_python(): chols = [m.cholesky1, m.cholesky2, m.cholesky3, m.cholesky4] for i, chol in enumerate(chols, start=1): - mymat = chol(np.array([[1., 2, 4], [2, 13, 23], [4, 23, 77]])) - assert np.all(mymat == np.array([[1, 0, 0], [2, 3, 0], [4, 5, 6]])), "cholesky{}".format(i) + mymat = chol(np.array([[1.0, 2, 4], [2, 13, 23], [4, 23, 77]])) + assert np.all( + mymat == np.array([[1, 0, 0], [2, 3, 0], [4, 5, 6]]) + ), "cholesky{}".format(i) def assign_both(a1, a2, r, c, v): @@ -325,8 +353,12 @@ def test_eigen_return_references(): np.testing.assert_array_equal(a_block1, master[3:5, 3:5]) np.testing.assert_array_equal(a_block2, master[2:5, 2:4]) np.testing.assert_array_equal(a_block3, master[6:10, 7:10]) - np.testing.assert_array_equal(a_corn1, master[0::master.shape[0] - 1, 0::master.shape[1] - 1]) - np.testing.assert_array_equal(a_corn2, master[0::master.shape[0] - 1, 0::master.shape[1] - 1]) + np.testing.assert_array_equal( + a_corn1, master[0 :: master.shape[0] - 1, 0 :: master.shape[1] - 1] + ) + np.testing.assert_array_equal( + a_corn2, master[0 :: master.shape[0] - 1, 0 :: master.shape[1] - 1] + ) np.testing.assert_array_equal(a_copy1, c1want) np.testing.assert_array_equal(a_copy2, c2want) @@ -355,16 +387,28 @@ def test_eigen_keepalive(): cstats = ConstructorStats.get(m.ReturnTester) assert cstats.alive() == 1 unsafe = [a.ref(), a.ref_const(), a.block(1, 2, 3, 4)] - copies = [a.copy_get(), a.copy_view(), a.copy_ref(), a.copy_ref_const(), - a.copy_block(4, 3, 2, 1)] + copies = [ + a.copy_get(), + a.copy_view(), + a.copy_ref(), + a.copy_ref_const(), + a.copy_block(4, 3, 2, 1), + ] del a assert cstats.alive() == 0 del unsafe del copies - for meth in [m.ReturnTester.get, m.ReturnTester.get_ptr, m.ReturnTester.view, - m.ReturnTester.view_ptr, m.ReturnTester.ref_safe, m.ReturnTester.ref_const_safe, - m.ReturnTester.corners, m.ReturnTester.corners_const]: + for meth in [ + m.ReturnTester.get, + m.ReturnTester.get_ptr, + m.ReturnTester.view, + m.ReturnTester.view_ptr, + m.ReturnTester.ref_safe, + m.ReturnTester.ref_const_safe, + m.ReturnTester.corners, + m.ReturnTester.corners_const, + ]: assert_keeps_alive(m.ReturnTester, meth) for meth in [m.ReturnTester.block_safe, m.ReturnTester.block_const]: @@ -374,18 +418,18 @@ def test_eigen_keepalive(): def test_eigen_ref_mutators(): """Tests Eigen's ability to mutate numpy values""" - orig = np.array([[1., 2, 3], [4, 5, 6], [7, 8, 9]]) + orig = np.array([[1.0, 2, 3], [4, 5, 6], [7, 8, 9]]) zr = np.array(orig) - zc = np.array(orig, order='F') + zc = np.array(orig, order="F") m.add_rm(zr, 1, 0, 100) - assert np.all(zr == np.array([[1., 2, 3], [104, 5, 6], [7, 8, 9]])) + assert np.all(zr == np.array([[1.0, 2, 3], [104, 5, 6], [7, 8, 9]])) m.add_cm(zc, 1, 0, 200) - assert np.all(zc == np.array([[1., 2, 3], [204, 5, 6], [7, 8, 9]])) + assert np.all(zc == np.array([[1.0, 2, 3], [204, 5, 6], [7, 8, 9]])) m.add_any(zr, 1, 0, 20) - assert np.all(zr == np.array([[1., 2, 3], [124, 5, 6], [7, 8, 9]])) + assert np.all(zr == np.array([[1.0, 2, 3], [124, 5, 6], [7, 8, 9]])) m.add_any(zc, 1, 0, 10) - assert np.all(zc == np.array([[1., 2, 3], [214, 5, 6], [7, 8, 9]])) + assert np.all(zc == np.array([[1.0, 2, 3], [214, 5, 6], [7, 8, 9]])) # Can't reference a col-major array with a row-major Ref, and vice versa: with pytest.raises(TypeError): @@ -406,8 +450,8 @@ def test_eigen_ref_mutators(): cornersr = zr[0::2, 0::2] cornersc = zc[0::2, 0::2] - assert np.all(cornersr == np.array([[1., 3], [7, 9]])) - assert np.all(cornersc == np.array([[1., 3], [7, 9]])) + assert np.all(cornersr == np.array([[1.0, 3], [7, 9]])) + assert np.all(cornersc == np.array([[1.0, 3], [7, 9]])) with pytest.raises(TypeError): m.add_rm(cornersr, 0, 1, 25) @@ -419,8 +463,8 @@ def test_eigen_ref_mutators(): m.add_cm(cornersc, 0, 1, 25) m.add_any(cornersr, 0, 1, 25) m.add_any(cornersc, 0, 1, 44) - assert np.all(zr == np.array([[1., 2, 28], [4, 5, 6], [7, 8, 9]])) - assert np.all(zc == np.array([[1., 2, 47], [4, 5, 6], [7, 8, 9]])) + assert np.all(zr == np.array([[1.0, 2, 28], [4, 5, 6], [7, 8, 9]])) + assert np.all(zc == np.array([[1.0, 2, 47], [4, 5, 6], [7, 8, 9]])) # You shouldn't be allowed to pass a non-writeable array to a mutating Eigen method: zro = zr[0:4, 0:4] @@ -458,7 +502,7 @@ def test_numpy_ref_mutators(): assert not zrro.flags.owndata and not zrro.flags.writeable zc[1, 2] = 99 - expect = np.array([[11., 12, 13], [21, 22, 99], [31, 32, 33]]) + expect = np.array([[11.0, 12, 13], [21, 22, 99], [31, 32, 33]]) # We should have just changed zc, of course, but also zcro and the original eigen matrix assert np.all(zc == expect) assert np.all(zcro == expect) @@ -506,18 +550,20 @@ def test_both_ref_mutators(): assert np.all(z == z3) assert np.all(z == z4) assert np.all(z == z5) - expect = np.array([[0., 22, 20], [31, 37, 33], [41, 42, 38]]) + expect = np.array([[0.0, 22, 20], [31, 37, 33], [41, 42, 38]]) assert np.all(z == expect) - y = np.array(range(100), dtype='float64').reshape(10, 10) + y = np.array(range(100), dtype="float64").reshape(10, 10) y2 = m.incr_matrix_any(y, 10) # np -> eigen -> np - y3 = m.incr_matrix_any(y2[0::2, 0::2], -33) # np -> eigen -> np slice -> np -> eigen -> np + y3 = m.incr_matrix_any( + y2[0::2, 0::2], -33 + ) # np -> eigen -> np slice -> np -> eigen -> np y4 = m.even_rows(y3) # numpy -> eigen slice -> (... y3) y5 = m.even_cols(y4) # numpy -> eigen slice -> (... y4) y6 = m.incr_matrix_any(y5, 1000) # numpy -> eigen -> (... y5) # Apply same mutations using just numpy: - yexpect = np.array(range(100), dtype='float64').reshape(10, 10) + yexpect = np.array(range(100), dtype="float64").reshape(10, 10) yexpect += 10 yexpect[0::2, 0::2] -= 33 yexpect[0::4, 0::4] += 1000 @@ -532,10 +578,14 @@ def test_both_ref_mutators(): def test_nocopy_wrapper(): # get_elem requires a column-contiguous matrix reference, but should be # callable with other types of matrix (via copying): - int_matrix_colmajor = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], order='F') - dbl_matrix_colmajor = np.array(int_matrix_colmajor, dtype='double', order='F', copy=True) - int_matrix_rowmajor = np.array(int_matrix_colmajor, order='C', copy=True) - dbl_matrix_rowmajor = np.array(int_matrix_rowmajor, dtype='double', order='C', copy=True) + int_matrix_colmajor = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], order="F") + dbl_matrix_colmajor = np.array( + int_matrix_colmajor, dtype="double", order="F", copy=True + ) + int_matrix_rowmajor = np.array(int_matrix_colmajor, order="C", copy=True) + dbl_matrix_rowmajor = np.array( + int_matrix_rowmajor, dtype="double", order="C", copy=True + ) # All should be callable via get_elem: assert m.get_elem(int_matrix_colmajor) == 8 @@ -546,32 +596,38 @@ def test_nocopy_wrapper(): # All but the second should fail with m.get_elem_nocopy: with pytest.raises(TypeError) as excinfo: m.get_elem_nocopy(int_matrix_colmajor) - assert ('get_elem_nocopy(): incompatible function arguments.' in str(excinfo.value) and - ', flags.f_contiguous' in str(excinfo.value)) + assert "get_elem_nocopy(): incompatible function arguments." in str( + excinfo.value + ) and ", flags.f_contiguous" in str(excinfo.value) assert m.get_elem_nocopy(dbl_matrix_colmajor) == 8 with pytest.raises(TypeError) as excinfo: m.get_elem_nocopy(int_matrix_rowmajor) - assert ('get_elem_nocopy(): incompatible function arguments.' in str(excinfo.value) and - ', flags.f_contiguous' in str(excinfo.value)) + assert "get_elem_nocopy(): incompatible function arguments." in str( + excinfo.value + ) and ", flags.f_contiguous" in str(excinfo.value) with pytest.raises(TypeError) as excinfo: m.get_elem_nocopy(dbl_matrix_rowmajor) - assert ('get_elem_nocopy(): incompatible function arguments.' in str(excinfo.value) and - ', flags.f_contiguous' in str(excinfo.value)) + assert "get_elem_nocopy(): incompatible function arguments." in str( + excinfo.value + ) and ", flags.f_contiguous" in str(excinfo.value) # For the row-major test, we take a long matrix in row-major, so only the third is allowed: with pytest.raises(TypeError) as excinfo: m.get_elem_rm_nocopy(int_matrix_colmajor) - assert ('get_elem_rm_nocopy(): incompatible function arguments.' in str(excinfo.value) and - ', flags.c_contiguous' in str(excinfo.value)) + assert "get_elem_rm_nocopy(): incompatible function arguments." in str( + excinfo.value + ) and ", flags.c_contiguous" in str(excinfo.value) with pytest.raises(TypeError) as excinfo: m.get_elem_rm_nocopy(dbl_matrix_colmajor) - assert ('get_elem_rm_nocopy(): incompatible function arguments.' in str(excinfo.value) and - ', flags.c_contiguous' in str(excinfo.value)) + assert "get_elem_rm_nocopy(): incompatible function arguments." in str( + excinfo.value + ) and ", flags.c_contiguous" in str(excinfo.value) assert m.get_elem_rm_nocopy(int_matrix_rowmajor) == 8 with pytest.raises(TypeError) as excinfo: m.get_elem_rm_nocopy(dbl_matrix_rowmajor) - assert ('get_elem_rm_nocopy(): incompatible function arguments.' in str(excinfo.value) and - ', flags.c_contiguous' in str(excinfo.value)) + assert "get_elem_rm_nocopy(): incompatible function arguments." in str( + excinfo.value + ) and ", flags.c_contiguous" in str(excinfo.value) def test_eigen_ref_life_support(): @@ -589,12 +645,9 @@ def test_eigen_ref_life_support(): def test_special_matrix_objects(): - assert np.all(m.incr_diag(7) == np.diag([1., 2, 3, 4, 5, 6, 7])) + assert np.all(m.incr_diag(7) == np.diag([1.0, 2, 3, 4, 5, 6, 7])) - asymm = np.array([[ 1., 2, 3, 4], - [ 5, 6, 7, 8], - [ 9, 10, 11, 12], - [13, 14, 15, 16]]) + asymm = np.array([[1.0, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]) symm_lower = np.array(asymm) symm_upper = np.array(asymm) for i in range(4): @@ -607,41 +660,51 @@ def test_special_matrix_objects(): def test_dense_signature(doc): - assert doc(m.double_col) == """ + assert ( + doc(m.double_col) + == """ double_col(arg0: numpy.ndarray[numpy.float32[m, 1]]) -> numpy.ndarray[numpy.float32[m, 1]] """ - assert doc(m.double_row) == """ + ) + assert ( + doc(m.double_row) + == """ double_row(arg0: numpy.ndarray[numpy.float32[1, n]]) -> numpy.ndarray[numpy.float32[1, n]] """ - assert doc(m.double_complex) == (""" + ) + assert doc(m.double_complex) == ( + """ double_complex(arg0: numpy.ndarray[numpy.complex64[m, 1]])""" - """ -> numpy.ndarray[numpy.complex64[m, 1]] - """) - assert doc(m.double_mat_rm) == (""" + """ -> numpy.ndarray[numpy.complex64[m, 1]] + """ + ) + assert doc(m.double_mat_rm) == ( + """ double_mat_rm(arg0: numpy.ndarray[numpy.float32[m, n]])""" - """ -> numpy.ndarray[numpy.float32[m, n]] - """) + """ -> numpy.ndarray[numpy.float32[m, n]] + """ + ) def test_named_arguments(): a = np.array([[1.0, 2], [3, 4], [5, 6]]) b = np.ones((2, 1)) - assert np.all(m.matrix_multiply(a, b) == np.array([[3.], [7], [11]])) - assert np.all(m.matrix_multiply(A=a, B=b) == np.array([[3.], [7], [11]])) - assert np.all(m.matrix_multiply(B=b, A=a) == np.array([[3.], [7], [11]])) + assert np.all(m.matrix_multiply(a, b) == np.array([[3.0], [7], [11]])) + assert np.all(m.matrix_multiply(A=a, B=b) == np.array([[3.0], [7], [11]])) + assert np.all(m.matrix_multiply(B=b, A=a) == np.array([[3.0], [7], [11]])) with pytest.raises(ValueError) as excinfo: m.matrix_multiply(b, a) - assert str(excinfo.value) == 'Nonconformable matrices!' + assert str(excinfo.value) == "Nonconformable matrices!" with pytest.raises(ValueError) as excinfo: m.matrix_multiply(A=b, B=a) - assert str(excinfo.value) == 'Nonconformable matrices!' + assert str(excinfo.value) == "Nonconformable matrices!" with pytest.raises(ValueError) as excinfo: m.matrix_multiply(B=a, A=b) - assert str(excinfo.value) == 'Nonconformable matrices!' + assert str(excinfo.value) == "Nonconformable matrices!" def test_sparse(): @@ -656,21 +719,31 @@ def test_sparse(): def test_sparse_signature(doc): pytest.importorskip("scipy") - assert doc(m.sparse_copy_r) == """ + assert ( + doc(m.sparse_copy_r) + == """ sparse_copy_r(arg0: scipy.sparse.csr_matrix[numpy.float32]) -> scipy.sparse.csr_matrix[numpy.float32] """ # noqa: E501 line too long - assert doc(m.sparse_copy_c) == """ + ) + assert ( + doc(m.sparse_copy_c) + == """ sparse_copy_c(arg0: scipy.sparse.csc_matrix[numpy.float32]) -> scipy.sparse.csc_matrix[numpy.float32] """ # noqa: E501 line too long + ) def test_issue738(): """Ignore strides on a length-1 dimension (even if they would be incompatible length > 1)""" - assert np.all(m.iss738_f1(np.array([[1., 2, 3]])) == np.array([[1., 102, 203]])) - assert np.all(m.iss738_f1(np.array([[1.], [2], [3]])) == np.array([[1.], [12], [23]])) + assert np.all(m.iss738_f1(np.array([[1.0, 2, 3]])) == np.array([[1.0, 102, 203]])) + assert np.all( + m.iss738_f1(np.array([[1.0], [2], [3]])) == np.array([[1.0], [12], [23]]) + ) - assert np.all(m.iss738_f2(np.array([[1., 2, 3]])) == np.array([[1., 102, 203]])) - assert np.all(m.iss738_f2(np.array([[1.], [2], [3]])) == np.array([[1.], [12], [23]])) + assert np.all(m.iss738_f2(np.array([[1.0, 2, 3]])) == np.array([[1.0, 102, 203]])) + assert np.all( + m.iss738_f2(np.array([[1.0], [2], [3]])) == np.array([[1.0], [12], [23]]) + ) def test_issue1105(): diff --git a/tests/test_enum.py b/tests/test_enum.py index 46cb37946..385fbbc9e 100644 --- a/tests/test_enum.py +++ b/tests/test_enum.py @@ -24,18 +24,24 @@ def test_unscoped_enum(): assert m.UnscopedEnum.EOne.name == "EOne" # __members__ property - assert m.UnscopedEnum.__members__ == \ - {"EOne": m.UnscopedEnum.EOne, "ETwo": m.UnscopedEnum.ETwo, "EThree": m.UnscopedEnum.EThree} + assert m.UnscopedEnum.__members__ == { + "EOne": m.UnscopedEnum.EOne, + "ETwo": m.UnscopedEnum.ETwo, + "EThree": m.UnscopedEnum.EThree, + } # __members__ readonly with pytest.raises(AttributeError): m.UnscopedEnum.__members__ = {} # __members__ returns a copy foo = m.UnscopedEnum.__members__ foo["bar"] = "baz" - assert m.UnscopedEnum.__members__ == \ - {"EOne": m.UnscopedEnum.EOne, "ETwo": m.UnscopedEnum.ETwo, "EThree": m.UnscopedEnum.EThree} + assert m.UnscopedEnum.__members__ == { + "EOne": m.UnscopedEnum.EOne, + "ETwo": m.UnscopedEnum.ETwo, + "EThree": m.UnscopedEnum.EThree, + } - for docstring_line in '''An unscoped enumeration + for docstring_line in """An unscoped enumeration Members: @@ -43,7 +49,9 @@ Members: ETwo : Docstring for ETwo - EThree : Docstring for EThree'''.split('\n'): + EThree : Docstring for EThree""".split( + "\n" + ): assert docstring_line in m.UnscopedEnum.__doc__ # Unscoped enums will accept ==/!= int comparisons @@ -53,10 +61,10 @@ Members: assert y != 3 assert 3 != y # Compare with None - assert (y != None) # noqa: E711 + assert y != None # noqa: E711 assert not (y == None) # noqa: E711 # Compare with an object - assert (y != object()) + assert y != object() assert not (y == object()) # Compare with string assert y != "2" @@ -119,10 +127,10 @@ def test_scoped_enum(): assert z != 3 assert 3 != z # Compare with None - assert (z != None) # noqa: E711 + assert z != None # noqa: E711 assert not (z == None) # noqa: E711 # Compare with an object - assert (z != object()) + assert z != object() assert not (z == object()) # Scoped enums will *NOT* accept >, <, >= and <= int comparisons (Will throw exceptions) with pytest.raises(TypeError): diff --git a/tests/test_eval_call.py b/tests/test_eval_call.py index d42a0a6d3..373b67bac 100644 --- a/tests/test_eval_call.py +++ b/tests/test_eval_call.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- # This file is called from 'test_eval.py' -if 'call_test2' in locals(): +if "call_test2" in locals(): call_test2(y) # noqa: F821 undefined name diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py index 7d7088d00..95eac7092 100644 --- a/tests/test_exceptions.py +++ b/tests/test_exceptions.py @@ -54,27 +54,27 @@ def test_python_alreadyset_in_destructor(monkeypatch, capsys): hooked = False triggered = [False] # mutable, so Python 2.7 closure can modify it - if hasattr(sys, 'unraisablehook'): # Python 3.8+ + if hasattr(sys, "unraisablehook"): # Python 3.8+ hooked = True default_hook = sys.unraisablehook def hook(unraisable_hook_args): exc_type, exc_value, exc_tb, err_msg, obj = unraisable_hook_args - if obj == 'already_set demo': + if obj == "already_set demo": triggered[0] = True default_hook(unraisable_hook_args) return # Use monkeypatch so pytest can apply and remove the patch as appropriate - monkeypatch.setattr(sys, 'unraisablehook', hook) + monkeypatch.setattr(sys, "unraisablehook", hook) - assert m.python_alreadyset_in_destructor('already_set demo') is True + assert m.python_alreadyset_in_destructor("already_set demo") is True if hooked: assert triggered[0] is True _, captured_stderr = capsys.readouterr() # Error message is different in Python 2 and 3, check for words that appear in both - assert 'ignored' in captured_stderr and 'already_set demo' in captured_stderr + assert "ignored" in captured_stderr and "already_set demo" in captured_stderr def test_exception_matches(): @@ -107,7 +107,9 @@ def test_custom(msg): # Can we fall-through to the default handler? with pytest.raises(RuntimeError) as excinfo: m.throws_logic_error() - assert msg(excinfo.value) == "this error should fall through to the standard handler" + assert ( + msg(excinfo.value) == "this error should fall through to the standard handler" + ) # OverFlow error translation. with pytest.raises(OverflowError) as excinfo: @@ -166,7 +168,13 @@ def test_nested_throws(capture): # C++ -> Python -> C++ -> Python with capture: m.try_catch( - m.MyException5, pycatch, m.MyException, m.try_catch, m.MyException, throw_myex5) + m.MyException5, + pycatch, + m.MyException, + m.try_catch, + m.MyException, + throw_myex5, + ) assert str(capture).startswith("MyException5: nested error 5") # C++ -> Python -> C++ @@ -182,7 +190,6 @@ def test_nested_throws(capture): # This can often happen if you wrap a pybind11 class in a Python wrapper def test_invalid_repr(): - class MyRepr(object): def __repr__(self): raise AttributeError("Example error") diff --git a/tests/test_factory_constructors.py b/tests/test_factory_constructors.py index b141c13de..ffcce6fd4 100644 --- a/tests/test_factory_constructors.py +++ b/tests/test_factory_constructors.py @@ -12,7 +12,10 @@ from pybind11_tests import ConstructorStats def test_init_factory_basic(): """Tests py::init_factory() wrapper around various ways of returning the object""" - cstats = [ConstructorStats.get(c) for c in [m.TestFactory1, m.TestFactory2, m.TestFactory3]] + cstats = [ + ConstructorStats.get(c) + for c in [m.TestFactory1, m.TestFactory2, m.TestFactory3] + ] cstats[0].alive() # force gc n_inst = ConstructorStats.detail_reg_inst() @@ -41,12 +44,12 @@ def test_init_factory_basic(): z3 = m.TestFactory3("bye") assert z3.value == "bye" - for null_ptr_kind in [tag.null_ptr, - tag.null_unique_ptr, - tag.null_shared_ptr]: + for null_ptr_kind in [tag.null_ptr, tag.null_unique_ptr, tag.null_shared_ptr]: with pytest.raises(TypeError) as excinfo: m.TestFactory3(null_ptr_kind) - assert str(excinfo.value) == "pybind11::init(): factory function returned nullptr" + assert ( + str(excinfo.value) == "pybind11::init(): factory function returned nullptr" + ) assert [i.alive() for i in cstats] == [3, 3, 3] assert ConstructorStats.detail_reg_inst() == n_inst + 9 @@ -61,7 +64,7 @@ def test_init_factory_basic(): assert [i.values() for i in cstats] == [ ["3", "hi!"], ["7", "hi again"], - ["42", "bye"] + ["42", "bye"], ] assert [i.default_constructions for i in cstats] == [1, 1, 1] @@ -69,7 +72,9 @@ def test_init_factory_basic(): def test_init_factory_signature(msg): with pytest.raises(TypeError) as excinfo: m.TestFactory1("invalid", "constructor", "arguments") - assert msg(excinfo.value) == """ + assert ( + msg(excinfo.value) + == """ __init__(): incompatible constructor arguments. The following argument types are supported: 1. m.factory_constructors.TestFactory1(arg0: m.factory_constructors.tag.unique_ptr_tag, arg1: int) 2. m.factory_constructors.TestFactory1(arg0: str) @@ -78,8 +83,11 @@ def test_init_factory_signature(msg): Invoked with: 'invalid', 'constructor', 'arguments' """ # noqa: E501 line too long + ) - assert msg(m.TestFactory1.__init__.__doc__) == """ + assert ( + msg(m.TestFactory1.__init__.__doc__) + == """ __init__(*args, **kwargs) Overloaded function. @@ -91,12 +99,16 @@ def test_init_factory_signature(msg): 4. __init__(self: m.factory_constructors.TestFactory1, arg0: handle, arg1: int, arg2: handle) -> None """ # noqa: E501 line too long + ) def test_init_factory_casting(): """Tests py::init_factory() wrapper with various upcasting and downcasting returns""" - cstats = [ConstructorStats.get(c) for c in [m.TestFactory3, m.TestFactory4, m.TestFactory5]] + cstats = [ + ConstructorStats.get(c) + for c in [m.TestFactory3, m.TestFactory4, m.TestFactory5] + ] cstats[0].alive() # force gc n_inst = ConstructorStats.detail_reg_inst() @@ -134,7 +146,7 @@ def test_init_factory_casting(): assert [i.values() for i in cstats] == [ ["4", "5", "6", "7", "8"], ["4", "5", "8"], - ["6", "7"] + ["6", "7"], ] @@ -204,7 +216,7 @@ def test_init_factory_alias(): assert [i.values() for i in cstats] == [ ["1", "8", "3", "4", "5", "6", "123", "10", "47"], - ["hi there", "3", "4", "6", "move", "123", "why hello!", "move", "47"] + ["hi there", "3", "4", "6", "move", "123", "why hello!", "move", "47"], ] @@ -268,9 +280,11 @@ def test_init_factory_dual(): assert not g1.has_alias() with pytest.raises(TypeError) as excinfo: PythFactory7(tag.shared_ptr, tag.invalid_base, 14) - assert (str(excinfo.value) == - "pybind11::init(): construction failed: returned holder-wrapped instance is not an " - "alias instance") + assert ( + str(excinfo.value) + == "pybind11::init(): construction failed: returned holder-wrapped instance is not an " + "alias instance" + ) assert [i.alive() for i in cstats] == [13, 7] assert ConstructorStats.detail_reg_inst() == n_inst + 13 @@ -284,7 +298,7 @@ def test_init_factory_dual(): assert [i.values() for i in cstats] == [ ["1", "2", "3", "4", "5", "6", "7", "8", "9", "100", "11", "12", "13", "14"], - ["2", "4", "6", "8", "9", "100", "12"] + ["2", "4", "6", "8", "9", "100", "12"], ] @@ -294,7 +308,7 @@ def test_no_placement_new(capture): with capture: a = m.NoPlacementNew(123) - found = re.search(r'^operator new called, returning (\d+)\n$', str(capture)) + found = re.search(r"^operator new called, returning (\d+)\n$", str(capture)) assert found assert a.i == 123 with capture: @@ -305,7 +319,7 @@ def test_no_placement_new(capture): with capture: b = m.NoPlacementNew() - found = re.search(r'^operator new called, returning (\d+)\n$', str(capture)) + found = re.search(r"^operator new called, returning (\d+)\n$", str(capture)) assert found assert b.i == 100 with capture: @@ -333,7 +347,7 @@ def create_and_destroy(*args): def strip_comments(s): - return re.sub(r'\s+#.*', '', s) + return re.sub(r"\s+#.*", "", s) def test_reallocation_a(capture, msg): @@ -345,7 +359,9 @@ def test_reallocation_a(capture, msg): with capture: create_and_destroy(1) - assert msg(capture) == """ + assert ( + msg(capture) + == """ noisy new noisy placement new NoisyAlloc(int 1) @@ -353,12 +369,14 @@ def test_reallocation_a(capture, msg): ~NoisyAlloc() noisy delete """ + ) def test_reallocation_b(capture, msg): with capture: create_and_destroy(1.5) - assert msg(capture) == strip_comments(""" + assert msg(capture) == strip_comments( + """ noisy new # allocation required to attempt first overload noisy delete # have to dealloc before considering factory init overload noisy new # pointer factory calling "new", part 1: allocation @@ -366,51 +384,59 @@ def test_reallocation_b(capture, msg): --- ~NoisyAlloc() # Destructor noisy delete # operator delete - """) + """ + ) def test_reallocation_c(capture, msg): with capture: create_and_destroy(2, 3) - assert msg(capture) == strip_comments(""" + assert msg(capture) == strip_comments( + """ noisy new # pointer factory calling "new", allocation NoisyAlloc(int 2) # constructor --- ~NoisyAlloc() # Destructor noisy delete # operator delete - """) + """ + ) def test_reallocation_d(capture, msg): with capture: create_and_destroy(2.5, 3) - assert msg(capture) == strip_comments(""" + assert msg(capture) == strip_comments( + """ NoisyAlloc(double 2.5) # construction (local func variable: operator_new not called) noisy new # return-by-value "new" part 1: allocation ~NoisyAlloc() # moved-away local func variable destruction --- ~NoisyAlloc() # Destructor noisy delete # operator delete - """) + """ + ) def test_reallocation_e(capture, msg): with capture: create_and_destroy(3.5, 4.5) - assert msg(capture) == strip_comments(""" + assert msg(capture) == strip_comments( + """ noisy new # preallocation needed before invoking placement-new overload noisy placement new # Placement new NoisyAlloc(double 3.5) # construction --- ~NoisyAlloc() # Destructor noisy delete # operator delete - """) + """ + ) def test_reallocation_f(capture, msg): with capture: create_and_destroy(4, 0.5) - assert msg(capture) == strip_comments(""" + assert msg(capture) == strip_comments( + """ noisy new # preallocation needed before invoking placement-new overload noisy delete # deallocation of preallocated storage noisy new # Factory pointer allocation @@ -418,13 +444,15 @@ def test_reallocation_f(capture, msg): --- ~NoisyAlloc() # Destructor noisy delete # operator delete - """) + """ + ) def test_reallocation_g(capture, msg): with capture: create_and_destroy(5, "hi") - assert msg(capture) == strip_comments(""" + assert msg(capture) == strip_comments( + """ noisy new # preallocation needed before invoking first placement new noisy delete # delete before considering new-style constructor noisy new # preallocation for second placement new @@ -433,13 +461,15 @@ def test_reallocation_g(capture, msg): --- ~NoisyAlloc() # Destructor noisy delete # operator delete - """) + """ + ) @pytest.mark.skipif("env.PY2") def test_invalid_self(): """Tests invocation of the pybind-registered base class with an invalid `self` argument. You can only actually do this on Python 3: Python 2 raises an exception itself if you try.""" + class NotPybindDerived(object): pass @@ -463,16 +493,26 @@ def test_invalid_self(): a = m.TestFactory2(tag.pointer, 1) m.TestFactory6.__init__(a, tag.alias, 1) elif bad == 3: - m.TestFactory6.__init__(NotPybindDerived.__new__(NotPybindDerived), tag.base, 1) + m.TestFactory6.__init__( + NotPybindDerived.__new__(NotPybindDerived), tag.base, 1 + ) elif bad == 4: - m.TestFactory6.__init__(NotPybindDerived.__new__(NotPybindDerived), tag.alias, 1) + m.TestFactory6.__init__( + NotPybindDerived.__new__(NotPybindDerived), tag.alias, 1 + ) for arg in (1, 2): with pytest.raises(TypeError) as excinfo: BrokenTF1(arg) - assert str(excinfo.value) == "__init__(self, ...) called with invalid `self` argument" + assert ( + str(excinfo.value) + == "__init__(self, ...) called with invalid `self` argument" + ) for arg in (1, 2, 3, 4): with pytest.raises(TypeError) as excinfo: BrokenTF6(arg) - assert str(excinfo.value) == "__init__(self, ...) called with invalid `self` argument" + assert ( + str(excinfo.value) + == "__init__(self, ...) called with invalid `self` argument" + ) diff --git a/tests/test_gil_scoped.py b/tests/test_gil_scoped.py index b2169d98b..0a1d62747 100644 --- a/tests/test_gil_scoped.py +++ b/tests/test_gil_scoped.py @@ -21,6 +21,7 @@ def _run_in_process(target, *args, **kwargs): def _python_to_cpp_to_python(): """Calls different C++ functions that come back to Python.""" + class ExtendedVirtClass(m.VirtClass): def virtual_func(self): pass @@ -74,7 +75,9 @@ def test_python_to_cpp_to_python_from_thread_multiple_sequential(): It runs in a separate process to be able to stop and assert if it deadlocks. """ - assert _run_in_process(_python_to_cpp_to_python_from_threads, 8, parallel=False) == 0 + assert ( + _run_in_process(_python_to_cpp_to_python_from_threads, 8, parallel=False) == 0 + ) # TODO: FIXME on macOS Python 3.9 diff --git a/tests/test_iostream.py b/tests/test_iostream.py index 7ac4fcece..506db42ec 100644 --- a/tests/test_iostream.py +++ b/tests/test_iostream.py @@ -18,6 +18,7 @@ try: # Python 3.4 from contextlib import redirect_stdout except ImportError: + @contextmanager def redirect_stdout(target): original = sys.stdout @@ -25,10 +26,12 @@ except ImportError: yield sys.stdout = original + try: # Python 3.5 from contextlib import redirect_stderr except ImportError: + @contextmanager def redirect_stderr(target): original = sys.stderr @@ -42,16 +45,16 @@ def test_captured(capsys): m.captured_output(msg) stdout, stderr = capsys.readouterr() assert stdout == msg - assert stderr == '' + assert stderr == "" m.captured_output_default(msg) stdout, stderr = capsys.readouterr() assert stdout == msg - assert stderr == '' + assert stderr == "" m.captured_err(msg) stdout, stderr = capsys.readouterr() - assert stdout == '' + assert stdout == "" assert stderr == msg @@ -63,7 +66,7 @@ def test_captured_large_string(capsys): m.captured_output_default(msg) stdout, stderr = capsys.readouterr() assert stdout == msg - assert stderr == '' + assert stderr == "" def test_guard_capture(capsys): @@ -71,7 +74,7 @@ def test_guard_capture(capsys): m.guard_output(msg) stdout, stderr = capsys.readouterr() assert stdout == msg - assert stderr == '' + assert stderr == "" def test_series_captured(capture): @@ -88,7 +91,7 @@ def test_flush(capfd): with m.ostream_redirect(): m.noisy_function(msg, flush=False) stdout, stderr = capfd.readouterr() - assert stdout == '' + assert stdout == "" m.noisy_function(msg2, flush=True) stdout, stderr = capfd.readouterr() @@ -107,15 +110,15 @@ def test_not_captured(capfd): m.raw_output(msg) stdout, stderr = capfd.readouterr() assert stdout == msg - assert stderr == '' - assert stream.getvalue() == '' + assert stderr == "" + assert stream.getvalue() == "" stream = StringIO() with redirect_stdout(stream): m.captured_output(msg) stdout, stderr = capfd.readouterr() - assert stdout == '' - assert stderr == '' + assert stdout == "" + assert stderr == "" assert stream.getvalue() == msg @@ -125,16 +128,16 @@ def test_err(capfd): with redirect_stderr(stream): m.raw_err(msg) stdout, stderr = capfd.readouterr() - assert stdout == '' + assert stdout == "" assert stderr == msg - assert stream.getvalue() == '' + assert stream.getvalue() == "" stream = StringIO() with redirect_stderr(stream): m.captured_err(msg) stdout, stderr = capfd.readouterr() - assert stdout == '' - assert stderr == '' + assert stdout == "" + assert stderr == "" assert stream.getvalue() == msg @@ -146,8 +149,8 @@ def test_multi_captured(capfd): m.captured_output("c") m.raw_output("d") stdout, stderr = capfd.readouterr() - assert stdout == 'bd' - assert stream.getvalue() == 'ac' + assert stdout == "bd" + assert stream.getvalue() == "ac" def test_dual(capsys): @@ -164,14 +167,14 @@ def test_redirect(capfd): m.raw_output(msg) stdout, stderr = capfd.readouterr() assert stdout == msg - assert stream.getvalue() == '' + assert stream.getvalue() == "" stream = StringIO() with redirect_stdout(stream): with m.ostream_redirect(): m.raw_output(msg) stdout, stderr = capfd.readouterr() - assert stdout == '' + assert stdout == "" assert stream.getvalue() == msg stream = StringIO() @@ -179,7 +182,7 @@ def test_redirect(capfd): m.raw_output(msg) stdout, stderr = capfd.readouterr() assert stdout == msg - assert stream.getvalue() == '' + assert stream.getvalue() == "" def test_redirect_err(capfd): @@ -193,7 +196,7 @@ def test_redirect_err(capfd): m.raw_err(msg2) stdout, stderr = capfd.readouterr() assert stdout == msg - assert stderr == '' + assert stderr == "" assert stream.getvalue() == msg2 @@ -209,7 +212,7 @@ def test_redirect_both(capfd): m.raw_output(msg) m.raw_err(msg2) stdout, stderr = capfd.readouterr() - assert stdout == '' - assert stderr == '' + assert stdout == "" + assert stderr == "" assert stream.getvalue() == msg assert stream2.getvalue() == msg2 diff --git a/tests/test_kwargs_and_defaults.py b/tests/test_kwargs_and_defaults.py index 2a81dbdc5..12fe705b4 100644 --- a/tests/test_kwargs_and_defaults.py +++ b/tests/test_kwargs_and_defaults.py @@ -15,11 +15,17 @@ def test_function_signatures(doc): assert doc(m.kw_func_udl) == "kw_func_udl(x: int, y: int = 300) -> str" assert doc(m.kw_func_udl_z) == "kw_func_udl_z(x: int, y: int = 0) -> str" assert doc(m.args_function) == "args_function(*args) -> tuple" - assert doc(m.args_kwargs_function) == "args_kwargs_function(*args, **kwargs) -> tuple" - assert doc(m.KWClass.foo0) == \ - "foo0(self: m.kwargs_and_defaults.KWClass, arg0: int, arg1: float) -> None" - assert doc(m.KWClass.foo1) == \ - "foo1(self: m.kwargs_and_defaults.KWClass, x: int, y: float) -> None" + assert ( + doc(m.args_kwargs_function) == "args_kwargs_function(*args, **kwargs) -> tuple" + ) + assert ( + doc(m.KWClass.foo0) + == "foo0(self: m.kwargs_and_defaults.KWClass, arg0: int, arg1: float) -> None" + ) + assert ( + doc(m.KWClass.foo1) + == "foo1(self: m.kwargs_and_defaults.KWClass, x: int, y: float) -> None" + ) def test_named_arguments(msg): @@ -40,7 +46,9 @@ def test_named_arguments(msg): # noinspection PyArgumentList m.kw_func2(x=5, y=10, z=12) assert excinfo.match( - r'(?s)^kw_func2\(\): incompatible.*Invoked with: kwargs: ((x=5|y=10|z=12)(, |$))' + '{3}$') + r"(?s)^kw_func2\(\): incompatible.*Invoked with: kwargs: ((x=5|y=10|z=12)(, |$))" + + "{3}$" + ) assert m.kw_func4() == "{13 17}" assert m.kw_func4(myList=[1, 2, 3]) == "{1 2 3}" @@ -50,11 +58,11 @@ def test_named_arguments(msg): def test_arg_and_kwargs(): - args = 'arg1_value', 'arg2_value', 3 + args = "arg1_value", "arg2_value", 3 assert m.args_function(*args) == args - args = 'a1', 'a2' - kwargs = dict(arg3='a3', arg4=4) + args = "a1", "a2" + kwargs = dict(arg3="a3", arg4=4) assert m.args_kwargs_function(*args, **kwargs) == (args, kwargs) @@ -68,47 +76,71 @@ def test_mixed_args_and_kwargs(msg): assert mpa(1, 2.5) == (1, 2.5, ()) with pytest.raises(TypeError) as excinfo: assert mpa(1) - assert msg(excinfo.value) == """ + assert ( + msg(excinfo.value) + == """ mixed_plus_args(): incompatible function arguments. The following argument types are supported: 1. (arg0: int, arg1: float, *args) -> tuple Invoked with: 1 """ # noqa: E501 line too long + ) with pytest.raises(TypeError) as excinfo: assert mpa() - assert msg(excinfo.value) == """ + assert ( + msg(excinfo.value) + == """ mixed_plus_args(): incompatible function arguments. The following argument types are supported: 1. (arg0: int, arg1: float, *args) -> tuple Invoked with: """ # noqa: E501 line too long + ) - assert mpk(-2, 3.5, pi=3.14159, e=2.71828) == (-2, 3.5, {'e': 2.71828, 'pi': 3.14159}) + assert mpk(-2, 3.5, pi=3.14159, e=2.71828) == ( + -2, + 3.5, + {"e": 2.71828, "pi": 3.14159}, + ) assert mpak(7, 7.7, 7.77, 7.777, 7.7777, minusseven=-7) == ( - 7, 7.7, (7.77, 7.777, 7.7777), {'minusseven': -7}) + 7, + 7.7, + (7.77, 7.777, 7.7777), + {"minusseven": -7}, + ) assert mpakd() == (1, 3.14159, (), {}) assert mpakd(3) == (3, 3.14159, (), {}) assert mpakd(j=2.71828) == (1, 2.71828, (), {}) - assert mpakd(k=42) == (1, 3.14159, (), {'k': 42}) + assert mpakd(k=42) == (1, 3.14159, (), {"k": 42}) assert mpakd(1, 1, 2, 3, 5, 8, then=13, followedby=21) == ( - 1, 1, (2, 3, 5, 8), {'then': 13, 'followedby': 21}) + 1, + 1, + (2, 3, 5, 8), + {"then": 13, "followedby": 21}, + ) # Arguments specified both positionally and via kwargs should fail: with pytest.raises(TypeError) as excinfo: assert mpakd(1, i=1) - assert msg(excinfo.value) == """ + assert ( + msg(excinfo.value) + == """ mixed_plus_args_kwargs_defaults(): incompatible function arguments. The following argument types are supported: 1. (i: int = 1, j: float = 3.14159, *args, **kwargs) -> tuple Invoked with: 1; kwargs: i=1 """ # noqa: E501 line too long + ) with pytest.raises(TypeError) as excinfo: assert mpakd(1, 2, j=1) - assert msg(excinfo.value) == """ + assert ( + msg(excinfo.value) + == """ mixed_plus_args_kwargs_defaults(): incompatible function arguments. The following argument types are supported: 1. (i: int = 1, j: float = 3.14159, *args, **kwargs) -> tuple Invoked with: 1, 2; kwargs: j=1 """ # noqa: E501 line too long + ) def test_keyword_only_args(msg): @@ -134,9 +166,9 @@ def test_keyword_only_args(msg): assert m.kw_only_mixed(j=2, i=3) == (3, 2) assert m.kw_only_mixed(i=2, j=3) == (2, 3) - assert m.kw_only_plus_more(4, 5, k=6, extra=7) == (4, 5, 6, {'extra': 7}) - assert m.kw_only_plus_more(3, k=5, j=4, extra=6) == (3, 4, 5, {'extra': 6}) - assert m.kw_only_plus_more(2, k=3, extra=4) == (2, -1, 3, {'extra': 4}) + assert m.kw_only_plus_more(4, 5, k=6, extra=7) == (4, 5, 6, {"extra": 7}) + assert m.kw_only_plus_more(3, k=5, j=4, extra=6) == (3, 4, 5, {"extra": 6}) + assert m.kw_only_plus_more(2, k=3, extra=4) == (2, -1, 3, {"extra": 4}) with pytest.raises(TypeError) as excinfo: assert m.kw_only_mixed(i=1) == (1,) @@ -144,9 +176,12 @@ def test_keyword_only_args(msg): with pytest.raises(RuntimeError) as excinfo: m.register_invalid_kw_only(m) - assert msg(excinfo.value) == """ + assert ( + msg(excinfo.value) + == """ arg(): cannot specify an unnamed argument after an kw_only() annotation """ + ) def test_positional_only_args(msg): @@ -194,7 +229,10 @@ def test_signatures(): assert "kw_only_mixed(i: int, *, j: int) -> tuple\n" == m.kw_only_mixed.__doc__ assert "pos_only_all(i: int, j: int, /) -> tuple\n" == m.pos_only_all.__doc__ assert "pos_only_mix(i: int, /, j: int) -> tuple\n" == m.pos_only_mix.__doc__ - assert "pos_kw_only_mix(i: int, /, j: int, *, k: int) -> tuple\n" == m.pos_kw_only_mix.__doc__ + assert ( + "pos_kw_only_mix(i: int, /, j: int, *, k: int) -> tuple\n" + == m.pos_kw_only_mix.__doc__ + ) @pytest.mark.xfail("env.PYPY and env.PY2", reason="PyPy2 doesn't double count") @@ -219,11 +257,18 @@ def test_args_refcount(): assert m.args_function(-1, myval) == (-1, myval) assert refcount(myval) == expected - assert m.mixed_plus_args_kwargs(5, 6.0, myval, a=myval) == (5, 6.0, (myval,), {"a": myval}) + assert m.mixed_plus_args_kwargs(5, 6.0, myval, a=myval) == ( + 5, + 6.0, + (myval,), + {"a": myval}, + ) assert refcount(myval) == expected - assert m.args_kwargs_function(7, 8, myval, a=1, b=myval) == \ - ((7, 8, myval), {"a": 1, "b": myval}) + assert m.args_kwargs_function(7, 8, myval, a=1, b=myval) == ( + (7, 8, myval), + {"a": 1, "b": myval}, + ) assert refcount(myval) == expected exp3 = refcount(myval, myval, myval) diff --git a/tests/test_local_bindings.py b/tests/test_local_bindings.py index ebc4873e2..d23c46752 100644 --- a/tests/test_local_bindings.py +++ b/tests/test_local_bindings.py @@ -36,8 +36,8 @@ def test_local_bindings(): assert i2.get() == 11 assert i2.get2() == 12 - assert not hasattr(i1, 'get2') - assert not hasattr(i2, 'get3') + assert not hasattr(i1, "get2") + assert not hasattr(i2, "get3") # Loading within the local module assert m.local_value(i1) == 5 @@ -55,7 +55,9 @@ def test_nonlocal_failure(): with pytest.raises(RuntimeError) as excinfo: cm.register_nonlocal() - assert str(excinfo.value) == 'generic_type: type "NonLocalType" is already registered!' + assert ( + str(excinfo.value) == 'generic_type: type "NonLocalType" is already registered!' + ) def test_duplicate_local(): @@ -63,9 +65,12 @@ def test_duplicate_local(): with pytest.raises(RuntimeError) as excinfo: m.register_local_external() import pybind11_tests + assert str(excinfo.value) == ( 'generic_type: type "LocalExternal" is already registered!' - if hasattr(pybind11_tests, 'class_') else 'test_class not enabled') + if hasattr(pybind11_tests, "class_") + else "test_class not enabled" + ) def test_stl_bind_local(): @@ -98,8 +103,8 @@ def test_stl_bind_local(): d1["b"] = v1[1] d2["c"] = v2[0] d2["d"] = v2[1] - assert {i: d1[i].get() for i in d1} == {'a': 0, 'b': 1} - assert {i: d2[i].get() for i in d2} == {'c': 2, 'd': 3} + assert {i: d1[i].get() for i in d1} == {"a": 0, "b": 1} + assert {i: d2[i].get() for i in d2} == {"c": 2, "d": 3} def test_stl_bind_global(): @@ -107,15 +112,21 @@ def test_stl_bind_global(): with pytest.raises(RuntimeError) as excinfo: cm.register_nonlocal_map() - assert str(excinfo.value) == 'generic_type: type "NonLocalMap" is already registered!' + assert ( + str(excinfo.value) == 'generic_type: type "NonLocalMap" is already registered!' + ) with pytest.raises(RuntimeError) as excinfo: cm.register_nonlocal_vec() - assert str(excinfo.value) == 'generic_type: type "NonLocalVec" is already registered!' + assert ( + str(excinfo.value) == 'generic_type: type "NonLocalVec" is already registered!' + ) with pytest.raises(RuntimeError) as excinfo: cm.register_nonlocal_map2() - assert str(excinfo.value) == 'generic_type: type "NonLocalMap2" is already registered!' + assert ( + str(excinfo.value) == 'generic_type: type "NonLocalMap2" is already registered!' + ) def test_mixed_local_global(): @@ -123,6 +134,7 @@ def test_mixed_local_global(): type can be registered even if the type is already registered globally. With the module, casting will go to the local type; outside the module casting goes to the global type.""" import pybind11_cross_module_tests as cm + m.register_mixed_global() m.register_mixed_local() @@ -145,13 +157,26 @@ def test_mixed_local_global(): a.append(cm.get_mixed_gl(11)) a.append(cm.get_mixed_lg(12)) - assert [x.get() for x in a] == \ - [101, 1002, 103, 1004, 105, 1006, 207, 2008, 109, 1010, 211, 2012] + assert [x.get() for x in a] == [ + 101, + 1002, + 103, + 1004, + 105, + 1006, + 207, + 2008, + 109, + 1010, + 211, + 2012, + ] def test_internal_locals_differ(): """Makes sure the internal local type map differs across the two modules""" import pybind11_cross_module_tests as cm + assert m.local_cpp_types_addr() != cm.local_cpp_types_addr() @@ -169,12 +194,15 @@ def test_stl_caster_vs_stl_bind(msg): assert m.load_vector_via_caster(v2) == 6 with pytest.raises(TypeError) as excinfo: cm.load_vector_via_binding(v2) == 6 - assert msg(excinfo.value) == """ + assert ( + msg(excinfo.value) + == """ load_vector_via_binding(): incompatible function arguments. The following argument types are supported: 1. (arg0: pybind11_cross_module_tests.VectorInt) -> int Invoked with: [1, 2, 3] """ # noqa: E501 line too long + ) def test_cross_module_calls(): diff --git a/tests/test_methods_and_attributes.py b/tests/test_methods_and_attributes.py index d5793296b..3e0e6cf05 100644 --- a/tests/test_methods_and_attributes.py +++ b/tests/test_methods_and_attributes.py @@ -40,17 +40,17 @@ def test_methods_and_attributes(): assert instance1.overloaded(0) == "(int)" assert instance1.overloaded(1, 1.0) == "(int, float)" assert instance1.overloaded(2.0, 2) == "(float, int)" - assert instance1.overloaded(3, 3) == "(int, int)" - assert instance1.overloaded(4., 4.) == "(float, float)" + assert instance1.overloaded(3, 3) == "(int, int)" + assert instance1.overloaded(4.0, 4.0) == "(float, float)" assert instance1.overloaded_const(-3) == "(int) const" assert instance1.overloaded_const(5, 5.0) == "(int, float) const" assert instance1.overloaded_const(6.0, 6) == "(float, int) const" - assert instance1.overloaded_const(7, 7) == "(int, int) const" - assert instance1.overloaded_const(8., 8.) == "(float, float) const" + assert instance1.overloaded_const(7, 7) == "(int, int) const" + assert instance1.overloaded_const(8.0, 8.0) == "(float, float) const" assert instance1.overloaded_float(1, 1) == "(float, float)" - assert instance1.overloaded_float(1, 1.) == "(float, float)" - assert instance1.overloaded_float(1., 1) == "(float, float)" - assert instance1.overloaded_float(1., 1.) == "(float, float)" + assert instance1.overloaded_float(1, 1.0) == "(float, float)" + assert instance1.overloaded_float(1.0, 1) == "(float, float)" + assert instance1.overloaded_float(1.0, 1.0) == "(float, float)" assert instance1.value == 320 instance1.value = 100 @@ -193,7 +193,10 @@ def test_metaclass_override(): assert type(m.MetaclassOverride).__name__ == "type" assert m.MetaclassOverride.readonly == 1 - assert type(m.MetaclassOverride.__dict__["readonly"]).__name__ == "pybind11_static_property" + assert ( + type(m.MetaclassOverride.__dict__["readonly"]).__name__ + == "pybind11_static_property" + ) # Regular `type` replaces the property instead of calling `__set__()` m.MetaclassOverride.readonly = 2 @@ -206,22 +209,26 @@ def test_no_mixed_overloads(): with pytest.raises(RuntimeError) as excinfo: m.ExampleMandA.add_mixed_overloads1() - assert (str(excinfo.value) == - "overloading a method with both static and instance methods is not supported; " + - ("compile in debug mode for more details" if not debug_enabled else - "error while attempting to bind static method ExampleMandA.overload_mixed1" - "(arg0: float) -> str") - ) + assert str( + excinfo.value + ) == "overloading a method with both static and instance methods is not supported; " + ( + "compile in debug mode for more details" + if not debug_enabled + else "error while attempting to bind static method ExampleMandA.overload_mixed1" + "(arg0: float) -> str" + ) with pytest.raises(RuntimeError) as excinfo: m.ExampleMandA.add_mixed_overloads2() - assert (str(excinfo.value) == - "overloading a method with both static and instance methods is not supported; " + - ("compile in debug mode for more details" if not debug_enabled else - "error while attempting to bind instance method ExampleMandA.overload_mixed2" - "(self: pybind11_tests.methods_and_attributes.ExampleMandA, arg0: int, arg1: int)" - " -> str") - ) + assert str( + excinfo.value + ) == "overloading a method with both static and instance methods is not supported; " + ( + "compile in debug mode for more details" + if not debug_enabled + else "error while attempting to bind instance method ExampleMandA.overload_mixed2" + "(self: pybind11_tests.methods_and_attributes.ExampleMandA, arg0: int, arg1: int)" + " -> str" + ) @pytest.mark.parametrize("access", ["ro", "rw", "static_ro", "static_rw"]) @@ -333,8 +340,8 @@ def test_bad_arg_default(msg): assert msg(excinfo.value) == ( "arg(): could not convert default argument 'a: UnregisteredType' in function " "'should_fail' into a Python object (type not registered yet?)" - if debug_enabled else - "arg(): could not convert default argument into a Python object (type not registered " + if debug_enabled + else "arg(): could not convert default argument into a Python object (type not registered " "yet?). Compile in debug mode for more information." ) @@ -343,8 +350,8 @@ def test_bad_arg_default(msg): assert msg(excinfo.value) == ( "arg(): could not convert default argument 'UnregisteredType' in function " "'should_fail' into a Python object (type not registered yet?)" - if debug_enabled else - "arg(): could not convert default argument into a Python object (type not registered " + if debug_enabled + else "arg(): could not convert default argument into a Python object (type not registered " "yet?). Compile in debug mode for more information." ) @@ -381,12 +388,15 @@ def test_accepts_none(msg): # The first one still raises because you can't pass None as a lvalue reference arg: with pytest.raises(TypeError) as excinfo: assert m.ok_none1(None) == -1 - assert msg(excinfo.value) == """ + assert ( + msg(excinfo.value) + == """ ok_none1(): incompatible function arguments. The following argument types are supported: 1. (arg0: m.methods_and_attributes.NoneTester) -> int Invoked with: None """ + ) # The rest take the argument as pointer or holder, and accept None: assert m.ok_none2(None) == -1 @@ -402,13 +412,16 @@ def test_str_issue(msg): with pytest.raises(TypeError) as excinfo: str(m.StrIssue("no", "such", "constructor")) - assert msg(excinfo.value) == """ + assert ( + msg(excinfo.value) + == """ __init__(): incompatible constructor arguments. The following argument types are supported: 1. m.methods_and_attributes.StrIssue(arg0: int) 2. m.methods_and_attributes.StrIssue() Invoked with: 'no', 'such', 'constructor' """ + ) def test_unregistered_base_implementations(): @@ -441,7 +454,7 @@ def test_ref_qualified(): def test_overload_ordering(): - 'Check to see if the normal overload order (first defined) and prepend overload order works' + "Check to see if the normal overload order (first defined) and prepend overload order works" assert m.overload_order("string") == 1 assert m.overload_order(0) == 4 @@ -449,8 +462,14 @@ def test_overload_ordering(): uni_name = type(u"").__name__ assert "1. overload_order(arg0: int) -> int" in m.overload_order.__doc__ - assert "2. overload_order(arg0: {}) -> int".format(uni_name) in m.overload_order.__doc__ - assert "3. overload_order(arg0: {}) -> int".format(uni_name) in m.overload_order.__doc__ + assert ( + "2. overload_order(arg0: {}) -> int".format(uni_name) + in m.overload_order.__doc__ + ) + assert ( + "3. overload_order(arg0: {}) -> int".format(uni_name) + in m.overload_order.__doc__ + ) assert "4. overload_order(arg0: int) -> int" in m.overload_order.__doc__ with pytest.raises(TypeError) as err: diff --git a/tests/test_modules.py b/tests/test_modules.py index 7e2100524..5630ccf9b 100644 --- a/tests/test_modules.py +++ b/tests/test_modules.py @@ -6,9 +6,13 @@ from pybind11_tests import ConstructorStats def test_nested_modules(): import pybind11_tests + assert pybind11_tests.__name__ == "pybind11_tests" assert pybind11_tests.modules.__name__ == "pybind11_tests.modules" - assert pybind11_tests.modules.subsubmodule.__name__ == "pybind11_tests.modules.subsubmodule" + assert ( + pybind11_tests.modules.subsubmodule.__name__ + == "pybind11_tests.modules.subsubmodule" + ) assert m.__name__ == "pybind11_tests.modules" assert ms.__name__ == "pybind11_tests.modules.subsubmodule" @@ -35,7 +39,7 @@ def test_reference_internal(): del b assert astats.alive() == 0 assert bstats.alive() == 0 - assert astats.values() == ['1', '2', '42', '43'] + assert astats.values() == ["1", "2", "42", "43"] assert bstats.values() == [] assert astats.default_constructions == 0 assert bstats.default_constructions == 1 @@ -54,7 +58,7 @@ def test_importing(): from collections import OrderedDict assert OD is OrderedDict - assert str(OD([(1, 'a'), (2, 'b')])) == "OrderedDict([(1, 'a'), (2, 'b')])" + assert str(OD([(1, "a"), (2, "b")])) == "OrderedDict([(1, 'a'), (2, 'b')])" def test_pydoc(): diff --git a/tests/test_multiple_inheritance.py b/tests/test_multiple_inheritance.py index 7a0259d21..e6a7f9762 100644 --- a/tests/test_multiple_inheritance.py +++ b/tests/test_multiple_inheritance.py @@ -57,7 +57,6 @@ def test_multiple_inheritance_mix2(): @pytest.mark.skipif("env.PYPY and env.PY2") @pytest.mark.xfail("env.PYPY and not env.PY2") def test_multiple_inheritance_python(): - class MI1(m.Base1, m.Base2): def __init__(self, i, j): m.Base1.__init__(self, i) @@ -163,7 +162,6 @@ def test_multiple_inheritance_python(): def test_multiple_inheritance_python_many_bases(): - class MIMany14(m.BaseN1, m.BaseN2, m.BaseN3, m.BaseN4): def __init__(self): m.BaseN1.__init__(self, 1) @@ -178,8 +176,16 @@ def test_multiple_inheritance_python_many_bases(): m.BaseN7.__init__(self, 7) m.BaseN8.__init__(self, 8) - class MIMany916(m.BaseN9, m.BaseN10, m.BaseN11, m.BaseN12, m.BaseN13, m.BaseN14, m.BaseN15, - m.BaseN16): + class MIMany916( + m.BaseN9, + m.BaseN10, + m.BaseN11, + m.BaseN12, + m.BaseN13, + m.BaseN14, + m.BaseN15, + m.BaseN16, + ): def __init__(self): m.BaseN9.__init__(self, 9) m.BaseN10.__init__(self, 10) @@ -225,7 +231,6 @@ def test_multiple_inheritance_python_many_bases(): def test_multiple_inheritance_virtbase(): - class MITypePy(m.Base12a): def __init__(self, i, j): m.Base12a.__init__(self, i, j) @@ -238,7 +243,7 @@ def test_multiple_inheritance_virtbase(): def test_mi_static_properties(): """Mixing bases with and without static properties should be possible - and the result should be independent of base definition order""" + and the result should be independent of base definition order""" for d in (m.VanillaStaticMix1(), m.VanillaStaticMix2()): assert d.vanilla() == "Vanilla" diff --git a/tests/test_numpy_array.py b/tests/test_numpy_array.py index e3e7c5f57..02f3ecfc0 100644 --- a/tests/test_numpy_array.py +++ b/tests/test_numpy_array.py @@ -19,33 +19,36 @@ def test_dtypes(): print(check) assert check.numpy == check.pybind11, check if check.numpy.num != check.pybind11.num: - print("NOTE: typenum mismatch for {}: {} != {}".format( - check, check.numpy.num, check.pybind11.num)) + print( + "NOTE: typenum mismatch for {}: {} != {}".format( + check, check.numpy.num, check.pybind11.num + ) + ) -@pytest.fixture(scope='function') +@pytest.fixture(scope="function") def arr(): - return np.array([[1, 2, 3], [4, 5, 6]], '=u2') + return np.array([[1, 2, 3], [4, 5, 6]], "=u2") def test_array_attributes(): - a = np.array(0, 'f8') + a = np.array(0, "f8") assert m.ndim(a) == 0 assert all(m.shape(a) == []) assert all(m.strides(a) == []) with pytest.raises(IndexError) as excinfo: m.shape(a, 0) - assert str(excinfo.value) == 'invalid axis: 0 (ndim = 0)' + assert str(excinfo.value) == "invalid axis: 0 (ndim = 0)" with pytest.raises(IndexError) as excinfo: m.strides(a, 0) - assert str(excinfo.value) == 'invalid axis: 0 (ndim = 0)' + assert str(excinfo.value) == "invalid axis: 0 (ndim = 0)" assert m.writeable(a) assert m.size(a) == 1 assert m.itemsize(a) == 8 assert m.nbytes(a) == 8 assert m.owndata(a) - a = np.array([[1, 2, 3], [4, 5, 6]], 'u2').view() + a = np.array([[1, 2, 3], [4, 5, 6]], "u2").view() a.flags.writeable = False assert m.ndim(a) == 2 assert all(m.shape(a) == [2, 3]) @@ -56,10 +59,10 @@ def test_array_attributes(): assert m.strides(a, 1) == 2 with pytest.raises(IndexError) as excinfo: m.shape(a, 2) - assert str(excinfo.value) == 'invalid axis: 2 (ndim = 2)' + assert str(excinfo.value) == "invalid axis: 2 (ndim = 2)" with pytest.raises(IndexError) as excinfo: m.strides(a, 2) - assert str(excinfo.value) == 'invalid axis: 2 (ndim = 2)' + assert str(excinfo.value) == "invalid axis: 2 (ndim = 2)" assert not m.writeable(a) assert m.size(a) == 6 assert m.itemsize(a) == 2 @@ -67,7 +70,9 @@ def test_array_attributes(): assert not m.owndata(a) -@pytest.mark.parametrize('args, ret', [([], 0), ([0], 0), ([1], 3), ([0, 1], 1), ([1, 2], 5)]) +@pytest.mark.parametrize( + "args, ret", [([], 0), ([0], 0), ([1], 3), ([0, 1], 1), ([1, 2], 5)] +) def test_index_offset(arr, args, ret): assert m.index_at(arr, *args) == ret assert m.index_at_t(arr, *args) == ret @@ -76,31 +81,46 @@ def test_index_offset(arr, args, ret): def test_dim_check_fail(arr): - for func in (m.index_at, m.index_at_t, m.offset_at, m.offset_at_t, m.data, m.data_t, - m.mutate_data, m.mutate_data_t): + for func in ( + m.index_at, + m.index_at_t, + m.offset_at, + m.offset_at_t, + m.data, + m.data_t, + m.mutate_data, + m.mutate_data_t, + ): with pytest.raises(IndexError) as excinfo: func(arr, 1, 2, 3) - assert str(excinfo.value) == 'too many indices for an array: 3 (ndim = 2)' + assert str(excinfo.value) == "too many indices for an array: 3 (ndim = 2)" -@pytest.mark.parametrize('args, ret', - [([], [1, 2, 3, 4, 5, 6]), - ([1], [4, 5, 6]), - ([0, 1], [2, 3, 4, 5, 6]), - ([1, 2], [6])]) +@pytest.mark.parametrize( + "args, ret", + [ + ([], [1, 2, 3, 4, 5, 6]), + ([1], [4, 5, 6]), + ([0, 1], [2, 3, 4, 5, 6]), + ([1, 2], [6]), + ], +) def test_data(arr, args, ret): from sys import byteorder + assert all(m.data_t(arr, *args) == ret) - assert all(m.data(arr, *args)[(0 if byteorder == 'little' else 1)::2] == ret) - assert all(m.data(arr, *args)[(1 if byteorder == 'little' else 0)::2] == 0) + assert all(m.data(arr, *args)[(0 if byteorder == "little" else 1) :: 2] == ret) + assert all(m.data(arr, *args)[(1 if byteorder == "little" else 0) :: 2] == 0) -@pytest.mark.parametrize('dim', [0, 1, 3]) +@pytest.mark.parametrize("dim", [0, 1, 3]) def test_at_fail(arr, dim): for func in m.at_t, m.mutate_at_t: with pytest.raises(IndexError) as excinfo: func(arr, *([0] * dim)) - assert str(excinfo.value) == 'index dimension mismatch: {} (ndim = 2)'.format(dim) + assert str(excinfo.value) == "index dimension mismatch: {} (ndim = 2)".format( + dim + ) def test_at(arr): @@ -113,10 +133,14 @@ def test_at(arr): def test_mutate_readonly(arr): arr.flags.writeable = False - for func, args in (m.mutate_data, ()), (m.mutate_data_t, ()), (m.mutate_at_t, (0, 0)): + for func, args in ( + (m.mutate_data, ()), + (m.mutate_data_t, ()), + (m.mutate_at_t, (0, 0)), + ): with pytest.raises(ValueError) as excinfo: func(arr, *args) - assert str(excinfo.value) == 'array is not writeable' + assert str(excinfo.value) == "array is not writeable" def test_mutate_data(arr): @@ -134,14 +158,22 @@ def test_mutate_data(arr): def test_bounds_check(arr): - for func in (m.index_at, m.index_at_t, m.data, m.data_t, - m.mutate_data, m.mutate_data_t, m.at_t, m.mutate_at_t): + for func in ( + m.index_at, + m.index_at_t, + m.data, + m.data_t, + m.mutate_data, + m.mutate_data_t, + m.at_t, + m.mutate_at_t, + ): with pytest.raises(IndexError) as excinfo: func(arr, 2, 0) - assert str(excinfo.value) == 'index 2 is out of bounds for axis 0 with size 2' + assert str(excinfo.value) == "index 2 is out of bounds for axis 0 with size 2" with pytest.raises(IndexError) as excinfo: func(arr, 0, 4) - assert str(excinfo.value) == 'index 4 is out of bounds for axis 1 with size 3' + assert str(excinfo.value) == "index 4 is out of bounds for axis 1 with size 3" def test_make_c_f_array(): @@ -163,10 +195,11 @@ def test_make_empty_shaped_array(): def test_wrap(): def assert_references(a, b, base=None): from distutils.version import LooseVersion + if base is None: base = a assert a is not b - assert a.__array_interface__['data'][0] == b.__array_interface__['data'][0] + assert a.__array_interface__["data"][0] == b.__array_interface__["data"][0] assert a.shape == b.shape assert a.strides == b.strides assert a.flags.c_contiguous == b.flags.c_contiguous @@ -189,12 +222,12 @@ def test_wrap(): a2 = m.wrap(a1) assert_references(a1, a2) - a1 = np.array([[1, 2], [3, 4]], dtype=np.float32, order='F') + a1 = np.array([[1, 2], [3, 4]], dtype=np.float32, order="F") assert a1.flags.owndata and a1.base is None a2 = m.wrap(a1) assert_references(a1, a2) - a1 = np.array([[1, 2], [3, 4]], dtype=np.float32, order='C') + a1 = np.array([[1, 2], [3, 4]], dtype=np.float32, order="C") a1.flags.writeable = False a2 = m.wrap(a1) assert_references(a1, a2) @@ -224,11 +257,14 @@ def test_numpy_view(capture): assert np.all(ac_view_1 == np.array([1, 2], dtype=np.int32)) del ac pytest.gc_collect() - assert capture == """ + assert ( + capture + == """ ArrayClass() ArrayClass::numpy_view() ArrayClass::numpy_view() """ + ) ac_view_1[0] = 4 ac_view_1[1] = 3 assert ac_view_2[0] == 4 @@ -238,9 +274,12 @@ def test_numpy_view(capture): del ac_view_2 pytest.gc_collect() pytest.gc_collect() - assert capture == """ + assert ( + capture + == """ ~ArrayClass() """ + ) def test_cast_numpy_int64_to_uint64(): @@ -271,20 +310,22 @@ def test_constructors(): def test_overload_resolution(msg): # Exact overload matches: - assert m.overloaded(np.array([1], dtype='float64')) == 'double' - assert m.overloaded(np.array([1], dtype='float32')) == 'float' - assert m.overloaded(np.array([1], dtype='ushort')) == 'unsigned short' - assert m.overloaded(np.array([1], dtype='intc')) == 'int' - assert m.overloaded(np.array([1], dtype='longlong')) == 'long long' - assert m.overloaded(np.array([1], dtype='complex')) == 'double complex' - assert m.overloaded(np.array([1], dtype='csingle')) == 'float complex' + assert m.overloaded(np.array([1], dtype="float64")) == "double" + assert m.overloaded(np.array([1], dtype="float32")) == "float" + assert m.overloaded(np.array([1], dtype="ushort")) == "unsigned short" + assert m.overloaded(np.array([1], dtype="intc")) == "int" + assert m.overloaded(np.array([1], dtype="longlong")) == "long long" + assert m.overloaded(np.array([1], dtype="complex")) == "double complex" + assert m.overloaded(np.array([1], dtype="csingle")) == "float complex" # No exact match, should call first convertible version: - assert m.overloaded(np.array([1], dtype='uint8')) == 'double' + assert m.overloaded(np.array([1], dtype="uint8")) == "double" with pytest.raises(TypeError) as excinfo: m.overloaded("not an array") - assert msg(excinfo.value) == """ + assert ( + msg(excinfo.value) + == """ overloaded(): incompatible function arguments. The following argument types are supported: 1. (arg0: numpy.ndarray[numpy.float64]) -> str 2. (arg0: numpy.ndarray[numpy.float32]) -> str @@ -296,15 +337,16 @@ def test_overload_resolution(msg): Invoked with: 'not an array' """ + ) - assert m.overloaded2(np.array([1], dtype='float64')) == 'double' - assert m.overloaded2(np.array([1], dtype='float32')) == 'float' - assert m.overloaded2(np.array([1], dtype='complex64')) == 'float complex' - assert m.overloaded2(np.array([1], dtype='complex128')) == 'double complex' - assert m.overloaded2(np.array([1], dtype='float32')) == 'float' + assert m.overloaded2(np.array([1], dtype="float64")) == "double" + assert m.overloaded2(np.array([1], dtype="float32")) == "float" + assert m.overloaded2(np.array([1], dtype="complex64")) == "float complex" + assert m.overloaded2(np.array([1], dtype="complex128")) == "double complex" + assert m.overloaded2(np.array([1], dtype="float32")) == "float" - assert m.overloaded3(np.array([1], dtype='float64')) == 'double' - assert m.overloaded3(np.array([1], dtype='intc')) == 'int' + assert m.overloaded3(np.array([1], dtype="float64")) == "double" + assert m.overloaded3(np.array([1], dtype="intc")) == "int" expected_exc = """ overloaded3(): incompatible function arguments. The following argument types are supported: 1. (arg0: numpy.ndarray[numpy.int32]) -> str @@ -313,47 +355,49 @@ def test_overload_resolution(msg): Invoked with: """ with pytest.raises(TypeError) as excinfo: - m.overloaded3(np.array([1], dtype='uintc')) - assert msg(excinfo.value) == expected_exc + repr(np.array([1], dtype='uint32')) + m.overloaded3(np.array([1], dtype="uintc")) + assert msg(excinfo.value) == expected_exc + repr(np.array([1], dtype="uint32")) with pytest.raises(TypeError) as excinfo: - m.overloaded3(np.array([1], dtype='float32')) - assert msg(excinfo.value) == expected_exc + repr(np.array([1.], dtype='float32')) + m.overloaded3(np.array([1], dtype="float32")) + assert msg(excinfo.value) == expected_exc + repr(np.array([1.0], dtype="float32")) with pytest.raises(TypeError) as excinfo: - m.overloaded3(np.array([1], dtype='complex')) - assert msg(excinfo.value) == expected_exc + repr(np.array([1. + 0.j])) + m.overloaded3(np.array([1], dtype="complex")) + assert msg(excinfo.value) == expected_exc + repr(np.array([1.0 + 0.0j])) # Exact matches: - assert m.overloaded4(np.array([1], dtype='double')) == 'double' - assert m.overloaded4(np.array([1], dtype='longlong')) == 'long long' + assert m.overloaded4(np.array([1], dtype="double")) == "double" + assert m.overloaded4(np.array([1], dtype="longlong")) == "long long" # Non-exact matches requiring conversion. Since float to integer isn't a # save conversion, it should go to the double overload, but short can go to # either (and so should end up on the first-registered, the long long). - assert m.overloaded4(np.array([1], dtype='float32')) == 'double' - assert m.overloaded4(np.array([1], dtype='short')) == 'long long' + assert m.overloaded4(np.array([1], dtype="float32")) == "double" + assert m.overloaded4(np.array([1], dtype="short")) == "long long" - assert m.overloaded5(np.array([1], dtype='double')) == 'double' - assert m.overloaded5(np.array([1], dtype='uintc')) == 'unsigned int' - assert m.overloaded5(np.array([1], dtype='float32')) == 'unsigned int' + assert m.overloaded5(np.array([1], dtype="double")) == "double" + assert m.overloaded5(np.array([1], dtype="uintc")) == "unsigned int" + assert m.overloaded5(np.array([1], dtype="float32")) == "unsigned int" def test_greedy_string_overload(): """Tests fix for #685 - ndarray shouldn't go to std::string overload""" assert m.issue685("abc") == "string" - assert m.issue685(np.array([97, 98, 99], dtype='b')) == "array" + assert m.issue685(np.array([97, 98, 99], dtype="b")) == "array" assert m.issue685(123) == "other" def test_array_unchecked_fixed_dims(msg): - z1 = np.array([[1, 2], [3, 4]], dtype='float64') + z1 = np.array([[1, 2], [3, 4]], dtype="float64") m.proxy_add2(z1, 10) assert np.all(z1 == [[11, 12], [13, 14]]) with pytest.raises(ValueError) as excinfo: - m.proxy_add2(np.array([1., 2, 3]), 5.0) - assert msg(excinfo.value) == "array has incorrect number of dimensions: 1; expected 2" + m.proxy_add2(np.array([1.0, 2, 3]), 5.0) + assert ( + msg(excinfo.value) == "array has incorrect number of dimensions: 1; expected 2" + ) - expect_c = np.ndarray(shape=(3, 3, 3), buffer=np.array(range(3, 30)), dtype='int') + expect_c = np.ndarray(shape=(3, 3, 3), buffer=np.array(range(3, 30)), dtype="int") assert np.all(m.proxy_init3(3.0) == expect_c) expect_f = np.transpose(expect_c) assert np.all(m.proxy_init3F(3.0) == expect_f) @@ -369,11 +413,11 @@ def test_array_unchecked_fixed_dims(msg): def test_array_unchecked_dyn_dims(msg): - z1 = np.array([[1, 2], [3, 4]], dtype='float64') + z1 = np.array([[1, 2], [3, 4]], dtype="float64") m.proxy_add2_dyn(z1, 10) assert np.all(z1 == [[11, 12], [13, 14]]) - expect_c = np.ndarray(shape=(3, 3, 3), buffer=np.array(range(3, 30)), dtype='int') + expect_c = np.ndarray(shape=(3, 3, 3), buffer=np.array(range(3, 30)), dtype="int") assert np.all(m.proxy_init3_dyn(3.0) == expect_c) assert m.proxy_auxiliaries2_dyn(z1) == [11, 11, True, 2, 8, 2, 2, 4, 32] @@ -383,15 +427,15 @@ def test_array_unchecked_dyn_dims(msg): def test_array_failure(): with pytest.raises(ValueError) as excinfo: m.array_fail_test() - assert str(excinfo.value) == 'cannot create a pybind11::array from a nullptr' + assert str(excinfo.value) == "cannot create a pybind11::array from a nullptr" with pytest.raises(ValueError) as excinfo: m.array_t_fail_test() - assert str(excinfo.value) == 'cannot create a pybind11::array_t from a nullptr' + assert str(excinfo.value) == "cannot create a pybind11::array_t from a nullptr" with pytest.raises(ValueError) as excinfo: m.array_fail_test_negative_size() - assert str(excinfo.value) == 'negative dimensions are not allowed' + assert str(excinfo.value) == "negative dimensions are not allowed" def test_initializer_list(): @@ -402,35 +446,35 @@ def test_initializer_list(): def test_array_resize(msg): - a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9], dtype='float64') + a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9], dtype="float64") m.array_reshape2(a) - assert(a.size == 9) - assert(np.all(a == [[1, 2, 3], [4, 5, 6], [7, 8, 9]])) + assert a.size == 9 + assert np.all(a == [[1, 2, 3], [4, 5, 6], [7, 8, 9]]) # total size change should succced with refcheck off m.array_resize3(a, 4, False) - assert(a.size == 64) + assert a.size == 64 # ... and fail with refcheck on try: m.array_resize3(a, 3, True) except ValueError as e: - assert(str(e).startswith("cannot resize an array")) + assert str(e).startswith("cannot resize an array") # transposed array doesn't own data b = a.transpose() try: m.array_resize3(b, 3, False) except ValueError as e: - assert(str(e).startswith("cannot resize this array: it does not own its data")) + assert str(e).startswith("cannot resize this array: it does not own its data") # ... but reshape should be fine m.array_reshape2(b) - assert(b.shape == (8, 8)) + assert b.shape == (8, 8) @pytest.mark.xfail("env.PYPY") def test_array_create_and_resize(msg): a = m.create_and_resize(2) - assert(a.size == 4) - assert(np.all(a == 42.)) + assert a.size == 4 + assert np.all(a == 42.0) def test_index_using_ellipsis(): @@ -439,16 +483,16 @@ def test_index_using_ellipsis(): @pytest.mark.parametrize("forcecast", [False, True]) -@pytest.mark.parametrize("contiguity", [None, 'C', 'F']) +@pytest.mark.parametrize("contiguity", [None, "C", "F"]) @pytest.mark.parametrize("noconvert", [False, True]) @pytest.mark.filterwarnings( "ignore:Casting complex values to real discards the imaginary part:numpy.ComplexWarning" ) def test_argument_conversions(forcecast, contiguity, noconvert): function_name = "accept_double" - if contiguity == 'C': + if contiguity == "C": function_name += "_c_style" - elif contiguity == 'F': + elif contiguity == "F": function_name += "_f_style" if forcecast: function_name += "_forcecast" @@ -456,37 +500,39 @@ def test_argument_conversions(forcecast, contiguity, noconvert): function_name += "_noconvert" function = getattr(m, function_name) - for dtype in [np.dtype('float32'), np.dtype('float64'), np.dtype('complex128')]: - for order in ['C', 'F']: + for dtype in [np.dtype("float32"), np.dtype("float64"), np.dtype("complex128")]: + for order in ["C", "F"]: for shape in [(2, 2), (1, 3, 1, 1), (1, 1, 1), (0,)]: if not noconvert: # If noconvert is not passed, only complex128 needs to be truncated and # "cannot be safely obtained". So without `forcecast`, the argument shouldn't # be accepted. - should_raise = dtype.name == 'complex128' and not forcecast + should_raise = dtype.name == "complex128" and not forcecast else: # If noconvert is passed, only float64 and the matching order is accepted. # If at most one dimension has a size greater than 1, the array is also # trivially contiguous. trivially_contiguous = sum(1 for d in shape if d > 1) <= 1 - should_raise = ( - dtype.name != 'float64' or - (contiguity is not None and - contiguity != order and - not trivially_contiguous) + should_raise = dtype.name != "float64" or ( + contiguity is not None + and contiguity != order + and not trivially_contiguous ) array = np.zeros(shape, dtype=dtype, order=order) if not should_raise: function(array) else: - with pytest.raises(TypeError, match="incompatible function arguments"): + with pytest.raises( + TypeError, match="incompatible function arguments" + ): function(array) @pytest.mark.xfail("env.PYPY") def test_dtype_refcount_leak(): from sys import getrefcount + dtype = np.dtype(np.float_) a = np.array([1], dtype=dtype) before = getrefcount(dtype) diff --git a/tests/test_numpy_dtypes.py b/tests/test_numpy_dtypes.py index b9f3bd26e..f56b776a4 100644 --- a/tests/test_numpy_dtypes.py +++ b/tests/test_numpy_dtypes.py @@ -10,57 +10,71 @@ from pybind11_tests import numpy_dtypes as m np = pytest.importorskip("numpy") -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def simple_dtype(): - ld = np.dtype('longdouble') - return np.dtype({'names': ['bool_', 'uint_', 'float_', 'ldbl_'], - 'formats': ['?', 'u4', 'f4', 'f{}'.format(ld.itemsize)], - 'offsets': [0, 4, 8, (16 if ld.alignment > 4 else 12)]}) + ld = np.dtype("longdouble") + return np.dtype( + { + "names": ["bool_", "uint_", "float_", "ldbl_"], + "formats": ["?", "u4", "f4", "f{}".format(ld.itemsize)], + "offsets": [0, 4, 8, (16 if ld.alignment > 4 else 12)], + } + ) -@pytest.fixture(scope='module') +@pytest.fixture(scope="module") def packed_dtype(): - return np.dtype([('bool_', '?'), ('uint_', 'u4'), ('float_', 'f4'), ('ldbl_', 'g')]) + return np.dtype([("bool_", "?"), ("uint_", "u4"), ("float_", "f4"), ("ldbl_", "g")]) def dt_fmt(): from sys import byteorder - e = '<' if byteorder == 'little' else '>' - return ("{{'names':['bool_','uint_','float_','ldbl_']," - " 'formats':['?','" + e + "u4','" + e + "f4','" + e + "f{}']," - " 'offsets':[0,4,8,{}], 'itemsize':{}}}") + + e = "<" if byteorder == "little" else ">" + return ( + "{{'names':['bool_','uint_','float_','ldbl_']," + " 'formats':['?','" + e + "u4','" + e + "f4','" + e + "f{}']," + " 'offsets':[0,4,8,{}], 'itemsize':{}}}" + ) def simple_dtype_fmt(): - ld = np.dtype('longdouble') + ld = np.dtype("longdouble") simple_ld_off = 12 + 4 * (ld.alignment > 4) return dt_fmt().format(ld.itemsize, simple_ld_off, simple_ld_off + ld.itemsize) def packed_dtype_fmt(): from sys import byteorder + return "[('bool_', '?'), ('uint_', '{e}u4'), ('float_', '{e}f4'), ('ldbl_', '{e}f{}')]".format( - np.dtype('longdouble').itemsize, e='<' if byteorder == 'little' else '>') + np.dtype("longdouble").itemsize, e="<" if byteorder == "little" else ">" + ) def partial_ld_offset(): - return 12 + 4 * (np.dtype('uint64').alignment > 4) + 8 + 8 * ( - np.dtype('longdouble').alignment > 8) + return ( + 12 + + 4 * (np.dtype("uint64").alignment > 4) + + 8 + + 8 * (np.dtype("longdouble").alignment > 8) + ) def partial_dtype_fmt(): - ld = np.dtype('longdouble') + ld = np.dtype("longdouble") partial_ld_off = partial_ld_offset() return dt_fmt().format(ld.itemsize, partial_ld_off, partial_ld_off + ld.itemsize) def partial_nested_fmt(): - ld = np.dtype('longdouble') + ld = np.dtype("longdouble") partial_nested_off = 8 + 8 * (ld.alignment > 8) partial_ld_off = partial_ld_offset() partial_nested_size = partial_nested_off * 2 + partial_ld_off + ld.itemsize return "{{'names':['a'], 'formats':[{}], 'offsets':[{}], 'itemsize':{}}}".format( - partial_dtype_fmt(), partial_nested_off, partial_nested_size) + partial_dtype_fmt(), partial_nested_off, partial_nested_size + ) def assert_equal(actual, expected_data, expected_dtype): @@ -70,15 +84,19 @@ def assert_equal(actual, expected_data, expected_dtype): def test_format_descriptors(): with pytest.raises(RuntimeError) as excinfo: m.get_format_unbound() - assert re.match('^NumPy type info missing for .*UnboundStruct.*$', str(excinfo.value)) + assert re.match( + "^NumPy type info missing for .*UnboundStruct.*$", str(excinfo.value) + ) - ld = np.dtype('longdouble') - ldbl_fmt = ('4x' if ld.alignment > 4 else '') + ld.char + ld = np.dtype("longdouble") + ldbl_fmt = ("4x" if ld.alignment > 4 else "") + ld.char ss_fmt = "^T{?:bool_:3xI:uint_:f:float_:" + ldbl_fmt + ":ldbl_:}" - dbl = np.dtype('double') - partial_fmt = ("^T{?:bool_:3xI:uint_:f:float_:" + - str(4 * (dbl.alignment > 4) + dbl.itemsize + 8 * (ld.alignment > 8)) + - "xg:ldbl_:}") + dbl = np.dtype("double") + partial_fmt = ( + "^T{?:bool_:3xI:uint_:f:float_:" + + str(4 * (dbl.alignment > 4) + dbl.itemsize + 8 * (ld.alignment > 8)) + + "xg:ldbl_:}" + ) nested_extra = str(max(8, ld.alignment)) assert m.print_format_descriptors() == [ ss_fmt, @@ -88,14 +106,15 @@ def test_format_descriptors(): "^T{" + nested_extra + "x" + partial_fmt + ":a:" + nested_extra + "x}", "^T{3s:a:3s:b:}", "^T{(3)4s:a:(2)i:b:(3)B:c:1x(4, 2)f:d:}", - '^T{q:e1:B:e2:}', - '^T{Zf:cflt:Zd:cdbl:}' + "^T{q:e1:B:e2:}", + "^T{Zf:cflt:Zd:cdbl:}", ] def test_dtype(simple_dtype): from sys import byteorder - e = '<' if byteorder == 'little' else '>' + + e = "<" if byteorder == "little" else ">" assert m.print_dtypes() == [ simple_dtype_fmt(), @@ -104,30 +123,60 @@ def test_dtype(simple_dtype): partial_dtype_fmt(), partial_nested_fmt(), "[('a', 'S3'), ('b', 'S3')]", - ("{{'names':['a','b','c','d'], " + - "'formats':[('S4', (3,)),('" + e + "i4', (2,)),('u1', (3,)),('" + e + "f4', (4, 2))], " + - "'offsets':[0,12,20,24], 'itemsize':56}}").format(e=e), + ( + "{{'names':['a','b','c','d'], " + + "'formats':[('S4', (3,)),('" + + e + + "i4', (2,)),('u1', (3,)),('" + + e + + "f4', (4, 2))], " + + "'offsets':[0,12,20,24], 'itemsize':56}}" + ).format(e=e), "[('e1', '" + e + "i8'), ('e2', 'u1')]", "[('x', 'i1'), ('y', '" + e + "u8')]", - "[('cflt', '" + e + "c8'), ('cdbl', '" + e + "c16')]" + "[('cflt', '" + e + "c8'), ('cdbl', '" + e + "c16')]", ] - d1 = np.dtype({'names': ['a', 'b'], 'formats': ['int32', 'float64'], - 'offsets': [1, 10], 'itemsize': 20}) - d2 = np.dtype([('a', 'i4'), ('b', 'f4')]) - assert m.test_dtype_ctors() == [np.dtype('int32'), np.dtype('float64'), - np.dtype('bool'), d1, d1, np.dtype('uint32'), d2] + d1 = np.dtype( + { + "names": ["a", "b"], + "formats": ["int32", "float64"], + "offsets": [1, 10], + "itemsize": 20, + } + ) + d2 = np.dtype([("a", "i4"), ("b", "f4")]) + assert m.test_dtype_ctors() == [ + np.dtype("int32"), + np.dtype("float64"), + np.dtype("bool"), + d1, + d1, + np.dtype("uint32"), + d2, + ] - assert m.test_dtype_methods() == [np.dtype('int32'), simple_dtype, False, True, - np.dtype('int32').itemsize, simple_dtype.itemsize] + assert m.test_dtype_methods() == [ + np.dtype("int32"), + simple_dtype, + False, + True, + np.dtype("int32").itemsize, + simple_dtype.itemsize, + ] - assert m.trailing_padding_dtype() == m.buffer_to_dtype(np.zeros(1, m.trailing_padding_dtype())) + assert m.trailing_padding_dtype() == m.buffer_to_dtype( + np.zeros(1, m.trailing_padding_dtype()) + ) def test_recarray(simple_dtype, packed_dtype): elements = [(False, 0, 0.0, -0.0), (True, 1, 1.5, -2.5), (False, 2, 3.0, -5.0)] - for func, dtype in [(m.create_rec_simple, simple_dtype), (m.create_rec_packed, packed_dtype)]: + for func, dtype in [ + (m.create_rec_simple, simple_dtype), + (m.create_rec_packed, packed_dtype), + ]: arr = func(0) assert arr.dtype == dtype assert_equal(arr, [], simple_dtype) @@ -146,16 +195,16 @@ def test_recarray(simple_dtype, packed_dtype): assert m.print_rec_simple(arr) == [ "s:0,0,0,-0", "s:1,1,1.5,-2.5", - "s:0,2,3,-5" + "s:0,2,3,-5", ] else: assert m.print_rec_packed(arr) == [ "p:0,0,0,-0", "p:1,1,1.5,-2.5", - "p:0,2,3,-5" + "p:0,2,3,-5", ] - nested_dtype = np.dtype([('a', simple_dtype), ('b', packed_dtype)]) + nested_dtype = np.dtype([("a", simple_dtype), ("b", packed_dtype)]) arr = m.create_rec_nested(0) assert arr.dtype == nested_dtype @@ -163,33 +212,39 @@ def test_recarray(simple_dtype, packed_dtype): arr = m.create_rec_nested(3) assert arr.dtype == nested_dtype - assert_equal(arr, [((False, 0, 0.0, -0.0), (True, 1, 1.5, -2.5)), - ((True, 1, 1.5, -2.5), (False, 2, 3.0, -5.0)), - ((False, 2, 3.0, -5.0), (True, 3, 4.5, -7.5))], nested_dtype) + assert_equal( + arr, + [ + ((False, 0, 0.0, -0.0), (True, 1, 1.5, -2.5)), + ((True, 1, 1.5, -2.5), (False, 2, 3.0, -5.0)), + ((False, 2, 3.0, -5.0), (True, 3, 4.5, -7.5)), + ], + nested_dtype, + ) assert m.print_rec_nested(arr) == [ "n:a=s:0,0,0,-0;b=p:1,1,1.5,-2.5", "n:a=s:1,1,1.5,-2.5;b=p:0,2,3,-5", - "n:a=s:0,2,3,-5;b=p:1,3,4.5,-7.5" + "n:a=s:0,2,3,-5;b=p:1,3,4.5,-7.5", ] arr = m.create_rec_partial(3) assert str(arr.dtype) == partial_dtype_fmt() partial_dtype = arr.dtype - assert '' not in arr.dtype.fields + assert "" not in arr.dtype.fields assert partial_dtype.itemsize > simple_dtype.itemsize assert_equal(arr, elements, simple_dtype) assert_equal(arr, elements, packed_dtype) arr = m.create_rec_partial_nested(3) assert str(arr.dtype) == partial_nested_fmt() - assert '' not in arr.dtype.fields - assert '' not in arr.dtype.fields['a'][0].fields + assert "" not in arr.dtype.fields + assert "" not in arr.dtype.fields["a"][0].fields assert arr.dtype.itemsize > partial_dtype.itemsize - np.testing.assert_equal(arr['a'], m.create_rec_partial(3)) + np.testing.assert_equal(arr["a"], m.create_rec_partial(3)) def test_array_constructors(): - data = np.arange(1, 7, dtype='int32') + data = np.arange(1, 7, dtype="int32") for i in range(8): np.testing.assert_array_equal(m.test_array_ctors(10 + i), data.reshape((3, 2))) np.testing.assert_array_equal(m.test_array_ctors(20 + i), data.reshape((3, 2))) @@ -205,82 +260,92 @@ def test_string_array(): "a='',b=''", "a='a',b='a'", "a='ab',b='ab'", - "a='abc',b='abc'" + "a='abc',b='abc'", ] dtype = arr.dtype - assert arr['a'].tolist() == [b'', b'a', b'ab', b'abc'] - assert arr['b'].tolist() == [b'', b'a', b'ab', b'abc'] + assert arr["a"].tolist() == [b"", b"a", b"ab", b"abc"] + assert arr["b"].tolist() == [b"", b"a", b"ab", b"abc"] arr = m.create_string_array(False) assert dtype == arr.dtype def test_array_array(): from sys import byteorder - e = '<' if byteorder == 'little' else '>' + + e = "<" if byteorder == "little" else ">" arr = m.create_array_array(3) assert str(arr.dtype) == ( - "{{'names':['a','b','c','d'], " + - "'formats':[('S4', (3,)),('" + e + "i4', (2,)),('u1', (3,)),('{e}f4', (4, 2))], " + - "'offsets':[0,12,20,24], 'itemsize':56}}").format(e=e) + "{{'names':['a','b','c','d'], " + + "'formats':[('S4', (3,)),('" + + e + + "i4', (2,)),('u1', (3,)),('{e}f4', (4, 2))], " + + "'offsets':[0,12,20,24], 'itemsize':56}}" + ).format(e=e) assert m.print_array_array(arr) == [ - "a={{A,B,C,D},{K,L,M,N},{U,V,W,X}},b={0,1}," + - "c={0,1,2},d={{0,1},{10,11},{20,21},{30,31}}", - "a={{W,X,Y,Z},{G,H,I,J},{Q,R,S,T}},b={1000,1001}," + - "c={10,11,12},d={{100,101},{110,111},{120,121},{130,131}}", - "a={{S,T,U,V},{C,D,E,F},{M,N,O,P}},b={2000,2001}," + - "c={20,21,22},d={{200,201},{210,211},{220,221},{230,231}}", + "a={{A,B,C,D},{K,L,M,N},{U,V,W,X}},b={0,1}," + + "c={0,1,2},d={{0,1},{10,11},{20,21},{30,31}}", + "a={{W,X,Y,Z},{G,H,I,J},{Q,R,S,T}},b={1000,1001}," + + "c={10,11,12},d={{100,101},{110,111},{120,121},{130,131}}", + "a={{S,T,U,V},{C,D,E,F},{M,N,O,P}},b={2000,2001}," + + "c={20,21,22},d={{200,201},{210,211},{220,221},{230,231}}", ] - assert arr['a'].tolist() == [[b'ABCD', b'KLMN', b'UVWX'], - [b'WXYZ', b'GHIJ', b'QRST'], - [b'STUV', b'CDEF', b'MNOP']] - assert arr['b'].tolist() == [[0, 1], [1000, 1001], [2000, 2001]] + assert arr["a"].tolist() == [ + [b"ABCD", b"KLMN", b"UVWX"], + [b"WXYZ", b"GHIJ", b"QRST"], + [b"STUV", b"CDEF", b"MNOP"], + ] + assert arr["b"].tolist() == [[0, 1], [1000, 1001], [2000, 2001]] assert m.create_array_array(0).dtype == arr.dtype def test_enum_array(): from sys import byteorder - e = '<' if byteorder == 'little' else '>' + + e = "<" if byteorder == "little" else ">" arr = m.create_enum_array(3) dtype = arr.dtype - assert dtype == np.dtype([('e1', e + 'i8'), ('e2', 'u1')]) - assert m.print_enum_array(arr) == [ - "e1=A,e2=X", - "e1=B,e2=Y", - "e1=A,e2=X" - ] - assert arr['e1'].tolist() == [-1, 1, -1] - assert arr['e2'].tolist() == [1, 2, 1] + assert dtype == np.dtype([("e1", e + "i8"), ("e2", "u1")]) + assert m.print_enum_array(arr) == ["e1=A,e2=X", "e1=B,e2=Y", "e1=A,e2=X"] + assert arr["e1"].tolist() == [-1, 1, -1] + assert arr["e2"].tolist() == [1, 2, 1] assert m.create_enum_array(0).dtype == dtype def test_complex_array(): from sys import byteorder - e = '<' if byteorder == 'little' else '>' + + e = "<" if byteorder == "little" else ">" arr = m.create_complex_array(3) dtype = arr.dtype - assert dtype == np.dtype([('cflt', e + 'c8'), ('cdbl', e + 'c16')]) + assert dtype == np.dtype([("cflt", e + "c8"), ("cdbl", e + "c16")]) assert m.print_complex_array(arr) == [ "c:(0,0.25),(0.5,0.75)", "c:(1,1.25),(1.5,1.75)", - "c:(2,2.25),(2.5,2.75)" + "c:(2,2.25),(2.5,2.75)", ] - assert arr['cflt'].tolist() == [0.0 + 0.25j, 1.0 + 1.25j, 2.0 + 2.25j] - assert arr['cdbl'].tolist() == [0.5 + 0.75j, 1.5 + 1.75j, 2.5 + 2.75j] + assert arr["cflt"].tolist() == [0.0 + 0.25j, 1.0 + 1.25j, 2.0 + 2.25j] + assert arr["cdbl"].tolist() == [0.5 + 0.75j, 1.5 + 1.75j, 2.5 + 2.75j] assert m.create_complex_array(0).dtype == dtype def test_signature(doc): - assert doc(m.create_rec_nested) == \ - "create_rec_nested(arg0: int) -> numpy.ndarray[NestedStruct]" + assert ( + doc(m.create_rec_nested) + == "create_rec_nested(arg0: int) -> numpy.ndarray[NestedStruct]" + ) def test_scalar_conversion(): n = 3 - arrays = [m.create_rec_simple(n), m.create_rec_packed(n), - m.create_rec_nested(n), m.create_enum_array(n)] + arrays = [ + m.create_rec_simple(n), + m.create_rec_packed(n), + m.create_rec_nested(n), + m.create_enum_array(n), + ] funcs = [m.f_simple, m.f_packed, m.f_nested] for i, func in enumerate(funcs): @@ -290,7 +355,7 @@ def test_scalar_conversion(): else: with pytest.raises(TypeError) as excinfo: func(arr[0]) - assert 'incompatible function arguments' in str(excinfo.value) + assert "incompatible function arguments" in str(excinfo.value) def test_vectorize(): @@ -304,14 +369,14 @@ def test_vectorize(): def test_cls_and_dtype_conversion(simple_dtype): s = m.SimpleStruct() - assert s.astuple() == (False, 0, 0., 0.) + assert s.astuple() == (False, 0, 0.0, 0.0) assert m.SimpleStruct.fromtuple(s.astuple()).astuple() == s.astuple() s.uint_ = 2 assert m.f_simple(s) == 20 # Try as recarray of shape==(1,). - s_recarray = np.array([(False, 2, 0., 0.)], dtype=simple_dtype) + s_recarray = np.array([(False, 2, 0.0, 0.0)], dtype=simple_dtype) # Show that this will work for vectorized case. np.testing.assert_array_equal(m.f_simple_vectorized(s_recarray), [20]) @@ -327,17 +392,16 @@ def test_cls_and_dtype_conversion(simple_dtype): assert s_recarray_scalar.dtype == simple_dtype with pytest.raises(TypeError) as excinfo: m.f_simple(s_recarray_scalar) - assert 'incompatible function arguments' in str(excinfo.value) + assert "incompatible function arguments" in str(excinfo.value) # Explicitly convert to m.SimpleStruct. - assert m.f_simple( - m.SimpleStruct.fromtuple(s_recarray_scalar.item())) == 20 + assert m.f_simple(m.SimpleStruct.fromtuple(s_recarray_scalar.item())) == 20 # Show that an array of dtype=object does *not* convert. s_array_object = np.array([s]) assert s_array_object.dtype == object with pytest.raises(TypeError) as excinfo: m.f_simple_vectorized(s_array_object) - assert 'incompatible function arguments' in str(excinfo.value) + assert "incompatible function arguments" in str(excinfo.value) # Explicitly convert to `np.array(..., dtype=simple_dtype)` s_array = np.array([s.astuple()], dtype=simple_dtype) np.testing.assert_array_equal(m.f_simple_vectorized(s_array), [20]) @@ -346,12 +410,13 @@ def test_cls_and_dtype_conversion(simple_dtype): def test_register_dtype(): with pytest.raises(RuntimeError) as excinfo: m.register_dtype() - assert 'dtype is already registered' in str(excinfo.value) + assert "dtype is already registered" in str(excinfo.value) @pytest.mark.xfail("env.PYPY") def test_str_leak(): from sys import getrefcount + fmt = "f4" pytest.gc_collect() start = getrefcount(fmt) diff --git a/tests/test_numpy_vectorize.py b/tests/test_numpy_vectorize.py index 992ff8ecc..4e6b2d198 100644 --- a/tests/test_numpy_vectorize.py +++ b/tests/test_numpy_vectorize.py @@ -17,28 +17,40 @@ def test_vectorize(capture): assert capture == "my_func(x:int=1, y:float=2, z:float=3)" with capture: assert np.allclose(f(np.array([1, 3]), np.array([2, 4]), 3), [6, 36]) - assert capture == """ + assert ( + capture + == """ my_func(x:int=1, y:float=2, z:float=3) my_func(x:int=3, y:float=4, z:float=3) """ + ) with capture: - a = np.array([[1, 2], [3, 4]], order='F') - b = np.array([[10, 20], [30, 40]], order='F') + a = np.array([[1, 2], [3, 4]], order="F") + b = np.array([[10, 20], [30, 40]], order="F") c = 3 result = f(a, b, c) assert np.allclose(result, a * b * c) assert result.flags.f_contiguous # All inputs are F order and full or singletons, so we the result is in col-major order: - assert capture == """ + assert ( + capture + == """ my_func(x:int=1, y:float=10, z:float=3) my_func(x:int=3, y:float=30, z:float=3) my_func(x:int=2, y:float=20, z:float=3) my_func(x:int=4, y:float=40, z:float=3) """ + ) with capture: - a, b, c = np.array([[1, 3, 5], [7, 9, 11]]), np.array([[2, 4, 6], [8, 10, 12]]), 3 + a, b, c = ( + np.array([[1, 3, 5], [7, 9, 11]]), + np.array([[2, 4, 6], [8, 10, 12]]), + 3, + ) assert np.allclose(f(a, b, c), a * b * c) - assert capture == """ + assert ( + capture + == """ my_func(x:int=1, y:float=2, z:float=3) my_func(x:int=3, y:float=4, z:float=3) my_func(x:int=5, y:float=6, z:float=3) @@ -46,10 +58,13 @@ def test_vectorize(capture): my_func(x:int=9, y:float=10, z:float=3) my_func(x:int=11, y:float=12, z:float=3) """ + ) with capture: a, b, c = np.array([[1, 2, 3], [4, 5, 6]]), np.array([2, 3, 4]), 2 assert np.allclose(f(a, b, c), a * b * c) - assert capture == """ + assert ( + capture + == """ my_func(x:int=1, y:float=2, z:float=2) my_func(x:int=2, y:float=3, z:float=2) my_func(x:int=3, y:float=4, z:float=2) @@ -57,10 +72,13 @@ def test_vectorize(capture): my_func(x:int=5, y:float=3, z:float=2) my_func(x:int=6, y:float=4, z:float=2) """ + ) with capture: a, b, c = np.array([[1, 2, 3], [4, 5, 6]]), np.array([[2], [3]]), 2 assert np.allclose(f(a, b, c), a * b * c) - assert capture == """ + assert ( + capture + == """ my_func(x:int=1, y:float=2, z:float=2) my_func(x:int=2, y:float=2, z:float=2) my_func(x:int=3, y:float=2, z:float=2) @@ -68,10 +86,17 @@ def test_vectorize(capture): my_func(x:int=5, y:float=3, z:float=2) my_func(x:int=6, y:float=3, z:float=2) """ + ) with capture: - a, b, c = np.array([[1, 2, 3], [4, 5, 6]], order='F'), np.array([[2], [3]]), 2 + a, b, c = ( + np.array([[1, 2, 3], [4, 5, 6]], order="F"), + np.array([[2], [3]]), + 2, + ) assert np.allclose(f(a, b, c), a * b * c) - assert capture == """ + assert ( + capture + == """ my_func(x:int=1, y:float=2, z:float=2) my_func(x:int=2, y:float=2, z:float=2) my_func(x:int=3, y:float=2, z:float=2) @@ -79,36 +104,53 @@ def test_vectorize(capture): my_func(x:int=5, y:float=3, z:float=2) my_func(x:int=6, y:float=3, z:float=2) """ + ) with capture: a, b, c = np.array([[1, 2, 3], [4, 5, 6]])[::, ::2], np.array([[2], [3]]), 2 assert np.allclose(f(a, b, c), a * b * c) - assert capture == """ + assert ( + capture + == """ my_func(x:int=1, y:float=2, z:float=2) my_func(x:int=3, y:float=2, z:float=2) my_func(x:int=4, y:float=3, z:float=2) my_func(x:int=6, y:float=3, z:float=2) """ + ) with capture: - a, b, c = np.array([[1, 2, 3], [4, 5, 6]], order='F')[::, ::2], np.array([[2], [3]]), 2 + a, b, c = ( + np.array([[1, 2, 3], [4, 5, 6]], order="F")[::, ::2], + np.array([[2], [3]]), + 2, + ) assert np.allclose(f(a, b, c), a * b * c) - assert capture == """ + assert ( + capture + == """ my_func(x:int=1, y:float=2, z:float=2) my_func(x:int=3, y:float=2, z:float=2) my_func(x:int=4, y:float=3, z:float=2) my_func(x:int=6, y:float=3, z:float=2) """ + ) def test_type_selection(): assert m.selective_func(np.array([1], dtype=np.int32)) == "Int branch taken." assert m.selective_func(np.array([1.0], dtype=np.float32)) == "Float branch taken." - assert m.selective_func(np.array([1.0j], dtype=np.complex64)) == "Complex float branch taken." + assert ( + m.selective_func(np.array([1.0j], dtype=np.complex64)) + == "Complex float branch taken." + ) def test_docs(doc): - assert doc(m.vectorized_func) == """ + assert ( + doc(m.vectorized_func) + == """ vectorized_func(arg0: numpy.ndarray[numpy.int32], arg1: numpy.ndarray[numpy.float32], arg2: numpy.ndarray[numpy.float64]) -> object """ # noqa: E501 line too long + ) def test_trivial_broadcasting(): @@ -116,16 +158,24 @@ def test_trivial_broadcasting(): assert vectorized_is_trivial(1, 2, 3) == trivial.c_trivial assert vectorized_is_trivial(np.array(1), np.array(2), 3) == trivial.c_trivial - assert vectorized_is_trivial(np.array([1, 3]), np.array([2, 4]), 3) == trivial.c_trivial + assert ( + vectorized_is_trivial(np.array([1, 3]), np.array([2, 4]), 3) + == trivial.c_trivial + ) assert trivial.c_trivial == vectorized_is_trivial( - np.array([[1, 3, 5], [7, 9, 11]]), np.array([[2, 4, 6], [8, 10, 12]]), 3) - assert vectorized_is_trivial( - np.array([[1, 2, 3], [4, 5, 6]]), np.array([2, 3, 4]), 2) == trivial.non_trivial - assert vectorized_is_trivial( - np.array([[1, 2, 3], [4, 5, 6]]), np.array([[2], [3]]), 2) == trivial.non_trivial - z1 = np.array([[1, 2, 3, 4], [5, 6, 7, 8]], dtype='int32') - z2 = np.array(z1, dtype='float32') - z3 = np.array(z1, dtype='float64') + np.array([[1, 3, 5], [7, 9, 11]]), np.array([[2, 4, 6], [8, 10, 12]]), 3 + ) + assert ( + vectorized_is_trivial(np.array([[1, 2, 3], [4, 5, 6]]), np.array([2, 3, 4]), 2) + == trivial.non_trivial + ) + assert ( + vectorized_is_trivial(np.array([[1, 2, 3], [4, 5, 6]]), np.array([[2], [3]]), 2) + == trivial.non_trivial + ) + z1 = np.array([[1, 2, 3, 4], [5, 6, 7, 8]], dtype="int32") + z2 = np.array(z1, dtype="float32") + z3 = np.array(z1, dtype="float64") assert vectorized_is_trivial(z1, z2, z3) == trivial.c_trivial assert vectorized_is_trivial(1, z2, z3) == trivial.c_trivial assert vectorized_is_trivial(z1, 1, z3) == trivial.c_trivial @@ -135,7 +185,7 @@ def test_trivial_broadcasting(): assert vectorized_is_trivial(1, 1, z3[::2, ::2]) == trivial.non_trivial assert vectorized_is_trivial(z1, 1, z3[1::4, 1::4]) == trivial.c_trivial - y1 = np.array(z1, order='F') + y1 = np.array(z1, order="F") y2 = np.array(y1) y3 = np.array(y1) assert vectorized_is_trivial(y1, y2, y3) == trivial.f_trivial @@ -156,30 +206,41 @@ def test_trivial_broadcasting(): def test_passthrough_arguments(doc): assert doc(m.vec_passthrough) == ( - "vec_passthrough(" + ", ".join([ - "arg0: float", - "arg1: numpy.ndarray[numpy.float64]", - "arg2: numpy.ndarray[numpy.float64]", - "arg3: numpy.ndarray[numpy.int32]", - "arg4: int", - "arg5: m.numpy_vectorize.NonPODClass", - "arg6: numpy.ndarray[numpy.float64]"]) + ") -> object") + "vec_passthrough(" + + ", ".join( + [ + "arg0: float", + "arg1: numpy.ndarray[numpy.float64]", + "arg2: numpy.ndarray[numpy.float64]", + "arg3: numpy.ndarray[numpy.int32]", + "arg4: int", + "arg5: m.numpy_vectorize.NonPODClass", + "arg6: numpy.ndarray[numpy.float64]", + ] + ) + + ") -> object" + ) - b = np.array([[10, 20, 30]], dtype='float64') + b = np.array([[10, 20, 30]], dtype="float64") c = np.array([100, 200]) # NOT a vectorized argument - d = np.array([[1000], [2000], [3000]], dtype='int') - g = np.array([[1000000, 2000000, 3000000]], dtype='int') # requires casting + d = np.array([[1000], [2000], [3000]], dtype="int") + g = np.array([[1000000, 2000000, 3000000]], dtype="int") # requires casting assert np.all( - m.vec_passthrough(1, b, c, d, 10000, m.NonPODClass(100000), g) == - np.array([[1111111, 2111121, 3111131], - [1112111, 2112121, 3112131], - [1113111, 2113121, 3113131]])) + m.vec_passthrough(1, b, c, d, 10000, m.NonPODClass(100000), g) + == np.array( + [ + [1111111, 2111121, 3111131], + [1112111, 2112121, 3112131], + [1113111, 2113121, 3113131], + ] + ) + ) def test_method_vectorization(): o = m.VectorizeTestClass(3) - x = np.array([1, 2], dtype='int') - y = np.array([[10], [20]], dtype='float32') + x = np.array([1, 2], dtype="int") + y = np.array([[10], [20]], dtype="float32") assert np.all(o.method(x, y) == [[14, 15], [24, 25]]) @@ -188,7 +249,7 @@ def test_array_collapse(): assert not isinstance(m.vectorized_func(np.array(1), 2, 3), np.ndarray) z = m.vectorized_func([1], 2, 3) assert isinstance(z, np.ndarray) - assert z.shape == (1, ) + assert z.shape == (1,) z = m.vectorized_func(1, [[[2]]], 3) assert isinstance(z, np.ndarray) assert z.shape == (1, 1, 1) diff --git a/tests/test_opaque_types.py b/tests/test_opaque_types.py index ac6a8560e..773794634 100644 --- a/tests/test_opaque_types.py +++ b/tests/test_opaque_types.py @@ -32,12 +32,15 @@ def test_pointers(msg): with pytest.raises(TypeError) as excinfo: m.get_void_ptr_value([1, 2, 3]) # This should not work - assert msg(excinfo.value) == """ + assert ( + msg(excinfo.value) + == """ get_void_ptr_value(): incompatible function arguments. The following argument types are supported: 1. (arg0: capsule) -> int Invoked with: [1, 2, 3] """ # noqa: E501 line too long + ) assert m.return_null_str() is None assert m.get_null_str_value(m.return_null_str()) is not None diff --git a/tests/test_operator_overloading.py b/tests/test_operator_overloading.py index 39e3aee27..5dbfb32c8 100644 --- a/tests/test_operator_overloading.py +++ b/tests/test_operator_overloading.py @@ -56,23 +56,23 @@ def test_operator_overloading(): del v3 assert cstats.alive() == 0 assert cstats.values() == [ - '[1.000000, 2.000000]', - '[3.000000, -1.000000]', - '[1.000000, 2.000000]', - '[-3.000000, 1.000000]', - '[4.000000, 1.000000]', - '[-2.000000, 3.000000]', - '[-7.000000, -6.000000]', - '[9.000000, 10.000000]', - '[8.000000, 16.000000]', - '[0.125000, 0.250000]', - '[7.000000, 6.000000]', - '[9.000000, 10.000000]', - '[8.000000, 16.000000]', - '[8.000000, 4.000000]', - '[3.000000, -2.000000]', - '[3.000000, -0.500000]', - '[6.000000, -2.000000]', + "[1.000000, 2.000000]", + "[3.000000, -1.000000]", + "[1.000000, 2.000000]", + "[-3.000000, 1.000000]", + "[4.000000, 1.000000]", + "[-2.000000, 3.000000]", + "[-7.000000, -6.000000]", + "[9.000000, 10.000000]", + "[8.000000, 16.000000]", + "[0.125000, 0.250000]", + "[7.000000, 6.000000]", + "[9.000000, 10.000000]", + "[8.000000, 16.000000]", + "[8.000000, 4.000000]", + "[3.000000, -2.000000]", + "[3.000000, -0.500000]", + "[6.000000, -2.000000]", ] assert cstats.default_constructions == 0 assert cstats.copy_constructions == 0 diff --git a/tests/test_pickling.py b/tests/test_pickling.py index 9aee70505..6b27a73a5 100644 --- a/tests/test_pickling.py +++ b/tests/test_pickling.py @@ -42,5 +42,6 @@ def test_roundtrip_with_dict(cls_name): def test_enum_pickle(): from pybind11_tests import enums as e + data = pickle.dumps(e.EOne, 2) assert e.EOne == pickle.loads(data) diff --git a/tests/test_pytypes.py b/tests/test_pytypes.py index 403c4da4b..9e5c302e5 100644 --- a/tests/test_pytypes.py +++ b/tests/test_pytypes.py @@ -28,13 +28,16 @@ def test_list(capture, doc): lst.append("value2") m.print_list(lst) - assert capture.unordered == """ + assert ( + capture.unordered + == """ Entry at position 0: value list item 0: inserted-0 list item 1: overwritten list item 2: inserted-2 list item 3: value2 """ + ) assert doc(m.get_list) == "get_list() -> list" assert doc(m.print_list) == "print_list(arg0: list) -> None" @@ -52,12 +55,15 @@ def test_set(capture, doc): with capture: s.add("key4") m.print_set(s) - assert capture.unordered == """ + assert ( + capture.unordered + == """ key: key1 key: key2 key: key3 key: key4 """ + ) assert not m.set_contains(set([]), 42) assert m.set_contains({42}, 42) @@ -74,10 +80,13 @@ def test_dict(capture, doc): with capture: d["key2"] = "value2" m.print_dict(d) - assert capture.unordered == """ + assert ( + capture.unordered + == """ key: key, value=value key: key2, value=value2 """ + ) assert not m.dict_contains({}, 42) assert m.dict_contains({42: None}, 42) @@ -137,28 +146,37 @@ def test_capsule(capture): a = m.return_capsule_with_destructor() del a pytest.gc_collect() - assert capture.unordered == """ + assert ( + capture.unordered + == """ creating capsule destructing capsule """ + ) with capture: a = m.return_capsule_with_destructor_2() del a pytest.gc_collect() - assert capture.unordered == """ + assert ( + capture.unordered + == """ creating capsule destructing capsule: 1234 """ + ) with capture: a = m.return_capsule_with_name_and_destructor() del a pytest.gc_collect() - assert capture.unordered == """ + assert ( + capture.unordered + == """ created capsule (1234, 'pointer type description') destructing capsule (1234, 'pointer type description') """ + ) def test_accessors(): @@ -212,7 +230,7 @@ def test_constructors(): assert m.default_constructors() == expected data = { - bytes: b'41', # Currently no supported or working conversions. + bytes: b"41", # Currently no supported or working conversions. str: 42, bool: "Not empty", int: "42", @@ -221,14 +239,14 @@ def test_constructors(): list: range(3), dict: [("two", 2), ("one", 1), ("three", 3)], set: [4, 4, 5, 6, 6, 6], - memoryview: b'abc' + memoryview: b"abc", } inputs = {k.__name__: v for k, v in data.items()} expected = {k.__name__: k(v) for k, v in data.items()} if env.PY2: # Similar to the above. See comments above. - inputs["bytes"] = b'41' + inputs["bytes"] = b"41" inputs["str"] = 42 - expected["bytes"] = b'41' + expected["bytes"] = b"41" expected["str"] = u"42" assert m.converting_constructors(inputs) == expected @@ -255,7 +273,8 @@ def test_non_converting_constructors(): with pytest.raises(TypeError) as excinfo: m.nonconverting_constructor(t, v) expected_error = "Object of type '{}' is not an instance of '{}'".format( - type(v).__name__, t) + type(v).__name__, t + ) assert str(excinfo.value) == expected_error @@ -263,12 +282,12 @@ def test_pybind11_str_raw_str(): # specifically to exercise pybind11::str::raw_str cvt = m.convert_to_pybind11_str assert cvt(u"Str") == u"Str" - assert cvt(b'Bytes') == u"Bytes" if env.PY2 else "b'Bytes'" + assert cvt(b"Bytes") == u"Bytes" if env.PY2 else "b'Bytes'" assert cvt(None) == u"None" assert cvt(False) == u"False" assert cvt(True) == u"True" assert cvt(42) == u"42" - assert cvt(2**65) == u"36893488147419103232" + assert cvt(2 ** 65) == u"36893488147419103232" assert cvt(-1.50) == u"-1.5" assert cvt(()) == u"()" assert cvt((18,)) == u"(18,)" @@ -283,29 +302,40 @@ def test_pybind11_str_raw_str(): valid_utf8 = valid_orig.encode("utf-8") valid_cvt = cvt(valid_utf8) assert type(valid_cvt) == bytes # Probably surprising. - assert valid_cvt == b'\xc7\xb1' + assert valid_cvt == b"\xc7\xb1" - malformed_utf8 = b'\x80' + malformed_utf8 = b"\x80" malformed_cvt = cvt(malformed_utf8) assert type(malformed_cvt) == bytes # Probably surprising. - assert malformed_cvt == b'\x80' + assert malformed_cvt == b"\x80" def test_implicit_casting(): """Tests implicit casting when assigning or appending to dicts and lists.""" z = m.get_implicit_casting() - assert z['d'] == { - 'char*_i1': 'abc', 'char*_i2': 'abc', 'char*_e': 'abc', 'char*_p': 'abc', - 'str_i1': 'str', 'str_i2': 'str1', 'str_e': 'str2', 'str_p': 'str3', - 'int_i1': 42, 'int_i2': 42, 'int_e': 43, 'int_p': 44 + assert z["d"] == { + "char*_i1": "abc", + "char*_i2": "abc", + "char*_e": "abc", + "char*_p": "abc", + "str_i1": "str", + "str_i2": "str1", + "str_e": "str2", + "str_p": "str3", + "int_i1": 42, + "int_i2": 42, + "int_e": 43, + "int_p": 44, } - assert z['l'] == [3, 6, 9, 12, 15] + assert z["l"] == [3, 6, 9, 12, 15] def test_print(capture): with capture: m.print_function() - assert capture == """ + assert ( + capture + == """ Hello, World! 1 2.0 three True -- multiple args *args-and-a-custom-separator @@ -313,14 +343,15 @@ def test_print(capture): flush py::print + str.format = this """ + ) assert capture.stderr == "this goes to stderr" with pytest.raises(RuntimeError) as excinfo: m.print_failure() assert str(excinfo.value) == "make_tuple(): unable to convert " + ( "argument of type 'UnregisteredType' to Python object" - if debug_enabled else - "arguments to Python object (compile in debug mode for details)" + if debug_enabled + else "arguments to Python object (compile in debug mode for details)" ) @@ -342,8 +373,23 @@ def test_hash(): def test_number_protocol(): for a, b in [(1, 1), (3, 5)]: - li = [a == b, a != b, a < b, a <= b, a > b, a >= b, a + b, - a - b, a * b, a / b, a | b, a & b, a ^ b, a >> b, a << b] + li = [ + a == b, + a != b, + a < b, + a <= b, + a > b, + a >= b, + a + b, + a - b, + a * b, + a / b, + a | b, + a & b, + a ^ b, + a >> b, + a << b, + ] assert m.test_number_protocol(a, b) == li @@ -360,13 +406,16 @@ def test_issue2361(): assert "'NoneType' object is not iterable" in str(excinfo.value) -@pytest.mark.parametrize('method, args, fmt, expected_view', [ - (m.test_memoryview_object, (b'red',), 'B', b'red'), - (m.test_memoryview_buffer_info, (b'green',), 'B', b'green'), - (m.test_memoryview_from_buffer, (False,), 'h', [3, 1, 4, 1, 5]), - (m.test_memoryview_from_buffer, (True,), 'H', [2, 7, 1, 8]), - (m.test_memoryview_from_buffer_nativeformat, (), '@i', [4, 7, 5]), -]) +@pytest.mark.parametrize( + "method, args, fmt, expected_view", + [ + (m.test_memoryview_object, (b"red",), "B", b"red"), + (m.test_memoryview_buffer_info, (b"green",), "B", b"green"), + (m.test_memoryview_from_buffer, (False,), "h", [3, 1, 4, 1, 5]), + (m.test_memoryview_from_buffer, (True,), "H", [2, 7, 1, 8]), + (m.test_memoryview_from_buffer_nativeformat, (), "@i", [4, 7, 5]), + ], +) def test_memoryview(method, args, fmt, expected_view): view = method(*args) assert isinstance(view, memoryview) @@ -380,12 +429,15 @@ def test_memoryview(method, args, fmt, expected_view): @pytest.mark.xfail("env.PYPY", reason="getrefcount is not available") -@pytest.mark.parametrize('method', [ - m.test_memoryview_object, - m.test_memoryview_buffer_info, -]) +@pytest.mark.parametrize( + "method", + [ + m.test_memoryview_object, + m.test_memoryview_buffer_info, + ], +) def test_memoryview_refcount(method): - buf = b'\x0a\x0b\x0c\x0d' + buf = b"\x0a\x0b\x0c\x0d" ref_before = sys.getrefcount(buf) view = method(buf) ref_after = sys.getrefcount(buf) @@ -396,13 +448,13 @@ def test_memoryview_refcount(method): def test_memoryview_from_buffer_empty_shape(): view = m.test_memoryview_from_buffer_empty_shape() assert isinstance(view, memoryview) - assert view.format == 'B' + assert view.format == "B" if env.PY2: # Python 2 behavior is weird, but Python 3 (the future) is fine. # PyPy3 has = 0 # Doesn't invoke any @@ -63,7 +72,9 @@ def test_smart_ptr(capture): assert cstats.move_assignments == 0 # Object3 - for i, o in zip([9, 8, 9], [m.MyObject3(9), m.make_myobject3_1(), m.make_myobject3_2()]): + for i, o in zip( + [9, 8, 9], [m.MyObject3(9), m.make_myobject3_1(), m.make_myobject3_2()] + ): print(o) with capture: m.print_myobject3_1(o) @@ -76,7 +87,7 @@ def test_smart_ptr(capture): assert cstats.alive() == 1 o = None assert cstats.alive() == 0 - assert cstats.values() == ['MyObject3[9]', 'MyObject3[8]', 'MyObject3[9]'] + assert cstats.values() == ["MyObject3[9]", "MyObject3[8]", "MyObject3[9]"] assert cstats.default_constructions == 0 assert cstats.copy_constructions == 0 # assert cstats.move_constructions >= 0 # Doesn't invoke any @@ -96,7 +107,7 @@ def test_smart_ptr(capture): # ref<> cstats = m.cstats_ref() assert cstats.alive() == 0 - assert cstats.values() == ['from pointer'] * 10 + assert cstats.values() == ["from pointer"] * 10 assert cstats.default_constructions == 30 assert cstats.copy_constructions == 12 # assert cstats.move_constructions >= 0 # Doesn't invoke any @@ -186,7 +197,9 @@ def test_shared_ptr_from_this_and_references(): ref = s.ref # init_holder_helper(holder_ptr=false, owned=false, bad_wp=false) assert stats.alive() == 2 assert s.set_ref(ref) - assert s.set_holder(ref) # std::enable_shared_from_this can create a holder from a reference + assert s.set_holder( + ref + ) # std::enable_shared_from_this can create a holder from a reference bad_wp = s.bad_wp # init_holder_helper(holder_ptr=false, owned=false, bad_wp=true) assert stats.alive() == 2 @@ -200,12 +213,16 @@ def test_shared_ptr_from_this_and_references(): assert s.set_ref(copy) assert s.set_holder(copy) - holder_ref = s.holder_ref # init_holder_helper(holder_ptr=true, owned=false, bad_wp=false) + holder_ref = ( + s.holder_ref + ) # init_holder_helper(holder_ptr=true, owned=false, bad_wp=false) assert stats.alive() == 3 assert s.set_ref(holder_ref) assert s.set_holder(holder_ref) - holder_copy = s.holder_copy # init_holder_helper(holder_ptr=true, owned=true, bad_wp=false) + holder_copy = ( + s.holder_copy + ) # init_holder_helper(holder_ptr=true, owned=true, bad_wp=false) assert stats.alive() == 3 assert s.set_ref(holder_copy) assert s.set_holder(holder_copy) @@ -277,8 +294,10 @@ def test_smart_ptr_from_default(): instance = m.HeldByDefaultHolder() with pytest.raises(RuntimeError) as excinfo: m.HeldByDefaultHolder.load_shared_ptr(instance) - assert "Unable to load a custom holder type from a " \ - "default-holder instance" in str(excinfo.value) + assert ( + "Unable to load a custom holder type from a " + "default-holder instance" in str(excinfo.value) + ) def test_shared_ptr_gc(): diff --git a/tests/test_stl.py b/tests/test_stl.py index 141b3e849..330017544 100644 --- a/tests/test_stl.py +++ b/tests/test_stl.py @@ -88,7 +88,7 @@ def test_recursive_casting(): assert m.cast_rv_nested() == [[[{"b": "rvalue", "c": "rvalue"}], [{"a": "rvalue"}]]] assert m.cast_lv_nested() == { "a": [[["lvalue", "lvalue"]], [["lvalue", "lvalue"]]], - "b": [[["lvalue", "lvalue"], ["lvalue", "lvalue"]]] + "b": [[["lvalue", "lvalue"], ["lvalue", "lvalue"]]], } # Issue #853 test case: @@ -106,15 +106,15 @@ def test_move_out_container(): assert [x.value for x in moved_out_list] == [0, 1, 2] -@pytest.mark.skipif(not hasattr(m, "has_optional"), reason='no ') +@pytest.mark.skipif(not hasattr(m, "has_optional"), reason="no ") def test_optional(): assert m.double_or_zero(None) == 0 assert m.double_or_zero(42) == 84 - pytest.raises(TypeError, m.double_or_zero, 'foo') + pytest.raises(TypeError, m.double_or_zero, "foo") assert m.half_or_none(0) is None assert m.half_or_none(42) == 21 - pytest.raises(TypeError, m.half_or_none, 'foo') + pytest.raises(TypeError, m.half_or_none, "foo") assert m.test_nullopt() == 42 assert m.test_nullopt(None) == 42 @@ -134,15 +134,17 @@ def test_optional(): assert holder.member_initialized() -@pytest.mark.skipif(not hasattr(m, "has_exp_optional"), reason='no ') +@pytest.mark.skipif( + not hasattr(m, "has_exp_optional"), reason="no " +) def test_exp_optional(): assert m.double_or_zero_exp(None) == 0 assert m.double_or_zero_exp(42) == 84 - pytest.raises(TypeError, m.double_or_zero_exp, 'foo') + pytest.raises(TypeError, m.double_or_zero_exp, "foo") assert m.half_or_none_exp(0) is None assert m.half_or_none_exp(42) == 21 - pytest.raises(TypeError, m.half_or_none_exp, 'foo') + pytest.raises(TypeError, m.half_or_none_exp, "foo") assert m.test_nullopt_exp() == 42 assert m.test_nullopt_exp(None) == 42 @@ -160,7 +162,7 @@ def test_exp_optional(): assert holder.member_initialized() -@pytest.mark.skipif(not hasattr(m, "load_variant"), reason='no ') +@pytest.mark.skipif(not hasattr(m, "load_variant"), reason="no ") def test_variant(doc): assert m.load_variant(1) == "int" assert m.load_variant("1") == "std::string" @@ -172,34 +174,44 @@ def test_variant(doc): assert m.cast_variant() == (5, "Hello") - assert doc(m.load_variant) == "load_variant(arg0: Union[int, str, float, None]) -> str" + assert ( + doc(m.load_variant) == "load_variant(arg0: Union[int, str, float, None]) -> str" + ) def test_vec_of_reference_wrapper(): """#171: Can't return reference wrappers (or STL structures containing them)""" - assert str(m.return_vec_of_reference_wrapper(UserType(4))) == \ - "[UserType(1), UserType(2), UserType(3), UserType(4)]" + assert ( + str(m.return_vec_of_reference_wrapper(UserType(4))) + == "[UserType(1), UserType(2), UserType(3), UserType(4)]" + ) def test_stl_pass_by_pointer(msg): """Passing nullptr or None to an STL container pointer is not expected to work""" with pytest.raises(TypeError) as excinfo: m.stl_pass_by_pointer() # default value is `nullptr` - assert msg(excinfo.value) == """ + assert ( + msg(excinfo.value) + == """ stl_pass_by_pointer(): incompatible function arguments. The following argument types are supported: 1. (v: List[int] = None) -> List[int] Invoked with: """ # noqa: E501 line too long + ) with pytest.raises(TypeError) as excinfo: m.stl_pass_by_pointer(None) - assert msg(excinfo.value) == """ + assert ( + msg(excinfo.value) + == """ stl_pass_by_pointer(): incompatible function arguments. The following argument types are supported: 1. (v: List[int] = None) -> List[int] Invoked with: None """ # noqa: E501 line too long + ) assert m.stl_pass_by_pointer([1, 2, 3]) == [1, 2, 3] @@ -209,10 +221,12 @@ def test_missing_header_message(): should result in a helpful suggestion in the error message""" import pybind11_cross_module_tests as cm - expected_message = ("Did you forget to `#include `? Or ,\n" - ", , etc. Some automatic\n" - "conversions are optional and require extra headers to be included\n" - "when compiling your pybind11 module.") + expected_message = ( + "Did you forget to `#include `? Or ,\n" + ", , etc. Some automatic\n" + "conversions are optional and require extra headers to be included\n" + "when compiling your pybind11 module." + ) with pytest.raises(TypeError) as excinfo: cm.missing_header_arg([1.0, 2.0, 3.0]) @@ -226,9 +240,9 @@ def test_missing_header_message(): def test_function_with_string_and_vector_string_arg(): """Check if a string is NOT implicitly converted to a list, which was the behavior before fix of issue #1258""" - assert m.func_with_string_or_vector_string_arg_overload(('A', 'B', )) == 2 - assert m.func_with_string_or_vector_string_arg_overload(['A', 'B']) == 2 - assert m.func_with_string_or_vector_string_arg_overload('A') == 3 + assert m.func_with_string_or_vector_string_arg_overload(("A", "B")) == 2 + assert m.func_with_string_or_vector_string_arg_overload(["A", "B"]) == 2 + assert m.func_with_string_or_vector_string_arg_overload("A") == 3 def test_stl_ownership(): @@ -247,6 +261,6 @@ def test_array_cast_sequence(): def test_issue_1561(): """ check fix for issue #1561 """ bar = m.Issue1561Outer() - bar.list = [m.Issue1561Inner('bar')] + bar.list = [m.Issue1561Inner("bar")] bar.list - assert bar.list[0].data == 'bar' + assert bar.list[0].data == "bar" diff --git a/tests/test_stl_binders.py b/tests/test_stl_binders.py index f9b8ea4af..84132a2b4 100644 --- a/tests/test_stl_binders.py +++ b/tests/test_stl_binders.py @@ -45,7 +45,7 @@ def test_vector_int(): # test error handling, and that the vector is unchanged with pytest.raises(RuntimeError): - v_int2.extend([8, 'a']) + v_int2.extend([8, "a"]) assert v_int2 == m.VectorInt([0, 99, 2, 3, 4, 5, 6, 7]) @@ -79,8 +79,8 @@ def test_vector_buffer(): assert mv[2] == 5 mv[2] = 6 else: - assert mv[2] == '\x05' - mv[2] = '\x06' + assert mv[2] == "\x05" + mv[2] = "\x06" assert v[2] == 6 if not env.PY2: @@ -114,11 +114,17 @@ def test_vector_buffer_numpy(): v = m.get_vectorstruct() assert v[0].x == 5 ma = np.asarray(v) - ma[1]['x'] = 99 + ma[1]["x"] = 99 assert v[1].x == 99 - v = m.VectorStruct(np.zeros(3, dtype=np.dtype([('w', 'bool'), ('x', 'I'), - ('y', 'float64'), ('z', 'bool')], align=True))) + v = m.VectorStruct( + np.zeros( + 3, + dtype=np.dtype( + [("w", "bool"), ("x", "I"), ("y", "float64"), ("z", "bool")], align=True + ), + ) + ) assert len(v) == 3 b = np.array([1, 2, 3, 4], dtype=np.uint8) @@ -151,31 +157,31 @@ def test_vector_custom(): def test_map_string_double(): mm = m.MapStringDouble() - mm['a'] = 1 - mm['b'] = 2.5 + mm["a"] = 1 + mm["b"] = 2.5 - assert list(mm) == ['a', 'b'] - assert list(mm.items()) == [('a', 1), ('b', 2.5)] + assert list(mm) == ["a", "b"] + assert list(mm.items()) == [("a", 1), ("b", 2.5)] assert str(mm) == "MapStringDouble{a: 1, b: 2.5}" um = m.UnorderedMapStringDouble() - um['ua'] = 1.1 - um['ub'] = 2.6 + um["ua"] = 1.1 + um["ub"] = 2.6 - assert sorted(list(um)) == ['ua', 'ub'] - assert sorted(list(um.items())) == [('ua', 1.1), ('ub', 2.6)] + assert sorted(list(um)) == ["ua", "ub"] + assert sorted(list(um.items())) == [("ua", 1.1), ("ub", 2.6)] assert "UnorderedMapStringDouble" in str(um) def test_map_string_double_const(): mc = m.MapStringDoubleConst() - mc['a'] = 10 - mc['b'] = 20.5 + mc["a"] = 10 + mc["b"] = 20.5 assert str(mc) == "MapStringDoubleConst{a: 10, b: 20.5}" umc = m.UnorderedMapStringDoubleConst() - umc['a'] = 11 - umc['b'] = 21.5 + umc["a"] = 11 + umc["b"] = 21.5 str(umc) @@ -196,7 +202,7 @@ def test_noncopyable_containers(): i = 1 for j in dnc: - assert(j.value == i) + assert j.value == i i += 1 # std::map @@ -265,21 +271,21 @@ def test_noncopyable_containers(): def test_map_delitem(): mm = m.MapStringDouble() - mm['a'] = 1 - mm['b'] = 2.5 + mm["a"] = 1 + mm["b"] = 2.5 - assert list(mm) == ['a', 'b'] - assert list(mm.items()) == [('a', 1), ('b', 2.5)] - del mm['a'] - assert list(mm) == ['b'] - assert list(mm.items()) == [('b', 2.5)] + assert list(mm) == ["a", "b"] + assert list(mm.items()) == [("a", 1), ("b", 2.5)] + del mm["a"] + assert list(mm) == ["b"] + assert list(mm.items()) == [("b", 2.5)] um = m.UnorderedMapStringDouble() - um['ua'] = 1.1 - um['ub'] = 2.6 + um["ua"] = 1.1 + um["ub"] = 2.6 - assert sorted(list(um)) == ['ua', 'ub'] - assert sorted(list(um.items())) == [('ua', 1.1), ('ub', 2.6)] - del um['ua'] - assert sorted(list(um)) == ['ub'] - assert sorted(list(um.items())) == [('ub', 2.6)] + assert sorted(list(um)) == ["ua", "ub"] + assert sorted(list(um.items())) == [("ua", 1.1), ("ub", 2.6)] + del um["ua"] + assert sorted(list(um)) == ["ub"] + assert sorted(list(um.items())) == [("ub", 2.6)] diff --git a/tests/test_tagbased_polymorphic.py b/tests/test_tagbased_polymorphic.py index 94f374da9..64eb8a3c1 100644 --- a/tests/test_tagbased_polymorphic.py +++ b/tests/test_tagbased_polymorphic.py @@ -5,16 +5,24 @@ from pybind11_tests import tagbased_polymorphic as m def test_downcast(): zoo = m.create_zoo() assert [type(animal) for animal in zoo] == [ - m.Labrador, m.Dog, m.Chihuahua, m.Cat, m.Panther + m.Labrador, + m.Dog, + m.Chihuahua, + m.Cat, + m.Panther, ] assert [animal.name for animal in zoo] == [ - "Fido", "Ginger", "Hertzl", "Tiger", "Leo" + "Fido", + "Ginger", + "Hertzl", + "Tiger", + "Leo", ] zoo[1].sound = "woooooo" assert [dog.bark() for dog in zoo[:3]] == [ "Labrador Fido goes WOOF!", "Dog Ginger goes woooooo", - "Chihuahua Hertzl goes iyiyiyiyiyi and runs in circles" + "Chihuahua Hertzl goes iyiyiyiyiyi and runs in circles", ] assert [cat.purr() for cat in zoo[3:]] == ["mrowr", "mrrrRRRRRR"] zoo[0].excitement -= 1000 diff --git a/tests/test_virtual_functions.py b/tests/test_virtual_functions.py index 53bcfd120..ae1993016 100644 --- a/tests/test_virtual_functions.py +++ b/tests/test_virtual_functions.py @@ -14,18 +14,18 @@ def test_override(capture, msg): self.data = "Hello world" def run(self, value): - print('ExtendedExampleVirt::run(%i), calling parent..' % value) + print("ExtendedExampleVirt::run(%i), calling parent.." % value) return super(ExtendedExampleVirt, self).run(value + 1) def run_bool(self): - print('ExtendedExampleVirt::run_bool()') + print("ExtendedExampleVirt::run_bool()") return False def get_string1(self): return "override1" def pure_virtual(self): - print('ExtendedExampleVirt::pure_virtual(): %s' % self.data) + print("ExtendedExampleVirt::pure_virtual(): %s" % self.data) class ExtendedExampleVirt2(ExtendedExampleVirt): def __init__(self, state): @@ -37,21 +37,30 @@ def test_override(capture, msg): ex12 = m.ExampleVirt(10) with capture: assert m.runExampleVirt(ex12, 20) == 30 - assert capture == """ + assert ( + capture + == """ Original implementation of ExampleVirt::run(state=10, value=20, str1=default1, str2=default2) """ # noqa: E501 line too long + ) with pytest.raises(RuntimeError) as excinfo: m.runExampleVirtVirtual(ex12) - assert msg(excinfo.value) == 'Tried to call pure virtual function "ExampleVirt::pure_virtual"' + assert ( + msg(excinfo.value) + == 'Tried to call pure virtual function "ExampleVirt::pure_virtual"' + ) ex12p = ExtendedExampleVirt(10) with capture: assert m.runExampleVirt(ex12p, 20) == 32 - assert capture == """ + assert ( + capture + == """ ExtendedExampleVirt::run(20), calling parent.. Original implementation of ExampleVirt::run(state=11, value=21, str1=override1, str2=default2) """ # noqa: E501 line too long + ) with capture: assert m.runExampleVirtBool(ex12p) is False assert capture == "ExtendedExampleVirt::run_bool()" @@ -62,16 +71,19 @@ def test_override(capture, msg): ex12p2 = ExtendedExampleVirt2(15) with capture: assert m.runExampleVirt(ex12p2, 50) == 68 - assert capture == """ + assert ( + capture + == """ ExtendedExampleVirt::run(50), calling parent.. Original implementation of ExampleVirt::run(state=17, value=51, str1=override1, str2=override2) """ # noqa: E501 line too long + ) cstats = ConstructorStats.get(m.ExampleVirt) assert cstats.alive() == 3 del ex12, ex12p, ex12p2 assert cstats.alive() == 0 - assert cstats.values() == ['10', '11', '17'] + assert cstats.values() == ["10", "11", "17"] assert cstats.copy_constructions == 0 assert cstats.move_constructions >= 0 @@ -82,6 +94,7 @@ def test_alias_delay_initialization1(capture): If we just create and use an A instance directly, the trampoline initialization is bypassed and we only initialize an A() instead (for performance reasons). """ + class B(m.A): def __init__(self): super(B, self).__init__() @@ -103,12 +116,15 @@ def test_alias_delay_initialization1(capture): m.call_f(b) del b pytest.gc_collect() - assert capture == """ + assert ( + capture + == """ PyA.PyA() PyA.f() In python f() PyA.~PyA() """ + ) def test_alias_delay_initialization2(capture): @@ -118,6 +134,7 @@ def test_alias_delay_initialization2(capture): performance penalty, it also allows us to do more things with the trampoline class such as defining local variables and performing construction/destruction. """ + class B2(m.A2): def __init__(self): super(B2, self).__init__() @@ -135,7 +152,9 @@ def test_alias_delay_initialization2(capture): m.call_f(a3) del a3 pytest.gc_collect() - assert capture == """ + assert ( + capture + == """ PyA2.PyA2() PyA2.f() A2.f() @@ -145,6 +164,7 @@ def test_alias_delay_initialization2(capture): A2.f() PyA2.~PyA2() """ + ) # Python subclass version with capture: @@ -152,20 +172,22 @@ def test_alias_delay_initialization2(capture): m.call_f(b2) del b2 pytest.gc_collect() - assert capture == """ + assert ( + capture + == """ PyA2.PyA2() PyA2.f() In python B2.f() PyA2.~PyA2() """ + ) # PyPy: Reference count > 1 causes call with noncopyable instance # to fail in ncv1.print_nc() @pytest.mark.xfail("env.PYPY") @pytest.mark.skipif( - not hasattr(m, "NCVirt"), - reason="NCVirt does not work on Intel/PGI/NVCC compilers" + not hasattr(m, "NCVirt"), reason="NCVirt does not work on Intel/PGI/NVCC compilers" ) def test_move_support(): class NCVirtExt(m.NCVirt): @@ -205,8 +227,8 @@ def test_move_support(): del ncv1, ncv2 assert nc_stats.alive() == 0 assert mv_stats.alive() == 0 - assert nc_stats.values() == ['4', '9', '9', '9'] - assert mv_stats.values() == ['4', '5', '7', '7'] + assert nc_stats.values() == ["4", "9", "9", "9"] + assert mv_stats.values() == ["4", "5", "7", "7"] assert nc_stats.copy_constructions == 0 assert mv_stats.copy_constructions == 1 assert nc_stats.move_constructions >= 0 @@ -215,6 +237,7 @@ def test_move_support(): def test_dispatch_issue(msg): """#159: virtual function dispatch has problems with similar-named functions""" + class PyClass1(m.DispatchIssue): def dispatch(self): return "Yay.." @@ -223,7 +246,10 @@ def test_dispatch_issue(msg): def dispatch(self): with pytest.raises(RuntimeError) as excinfo: super(PyClass2, self).dispatch() - assert msg(excinfo.value) == 'Tried to call pure virtual function "Base::dispatch"' + assert ( + msg(excinfo.value) + == 'Tried to call pure virtual function "Base::dispatch"' + ) p = PyClass1() return m.dispatch_issue_go(p) @@ -339,7 +365,7 @@ def test_inherited_virtuals(): class DT(m.D_Tpl): def say_something(self, times): - return "DT says:" + (' quack' * times) + return "DT says:" + (" quack" * times) def unlucky_number(self): return 1234 @@ -355,7 +381,7 @@ def test_inherited_virtuals(): class DT2(DT): def say_something(self, times): - return "DT2: " + ('QUACK' * times) + return "DT2: " + ("QUACK" * times) def unlucky_number(self): return -3