From c0f35fbebeb35ea64e07e85bcabfde65954e78f9 Mon Sep 17 00:00:00 2001 From: Eric Arellano <14852634+Eric-Arellano@users.noreply.github.com> Date: Thu, 13 Apr 2023 08:56:42 -0600 Subject: [PATCH] Replace pycodestyle with Black and Isort (#1689) * Replace pycodestyle with Black and Isort * Get rid of wheel in pyproject.toml * Also format `tools/` * Exclude benchmarks * Review feedback * Use isort 5.11 because 5.12 drops Py37 support * Review feedback --- docs/conf.py | 129 ++++++++++++++------------- docs/custom_directives.py | 176 +++++++++++++++++++------------------ docs/custom_extensions.py | 60 ++++++------- docs/url_redirects.py | 84 ++++++++++-------- docs/versionutils.py | 163 ++++++++++++++++------------------ pyproject.toml | 12 +++ requirements-dev.txt | 4 + setup.py | 37 ++++---- test/base.py | 45 ++++++---- test/test_simulation.py | 6 +- test/test_url_redirects.py | 24 ++--- tox.ini | 11 ++- 12 files changed, 384 insertions(+), 367 deletions(-) create mode 100644 pyproject.toml diff --git a/docs/conf.py b/docs/conf.py index 399ad8226bc1..db59a24b5336 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -22,55 +22,58 @@ import os import sys -sys.path.insert(0, os.path.abspath('.')) +sys.path.insert(0, os.path.abspath(".")) import custom_extensions -from custom_directives import (IncludeDirective, GalleryItemDirective, - CustomGalleryItemDirective, CustomCalloutItemDirective, - CustomCardItemDirective) import url_redirects - +from custom_directives import ( + CustomCalloutItemDirective, + CustomCardItemDirective, + CustomGalleryItemDirective, + GalleryItemDirective, + IncludeDirective, +) # -- General configuration --------------------------------------------------- -project = 'Qiskit' +project = "Qiskit" copyright = f"2017-{datetime.date.today().year}, Qiskit Development Team" -author = 'Qiskit Development Team' +author = "Qiskit Development Team" # The short X.Y version -version = '' +version = "" # The full version, including alpha/beta/rc tags -release = '0.42.1' +release = "0.42.1" rst_prolog = """ .. |version| replace:: {0} -""".format(release) +""".format( + release +) extensions = [ - 'sphinx.ext.napoleon', - 'sphinx.ext.autodoc', + "sphinx.ext.napoleon", + "sphinx.ext.autodoc", "sphinx.ext.autosummary", - 'sphinx.ext.mathjax', - 'sphinx.ext.viewcode', - 'sphinx.ext.extlinks', - 'jupyter_sphinx', - 'nbsphinx', - 'sphinx_design', - 'sphinx_reredirects', + "sphinx.ext.mathjax", + "sphinx.ext.viewcode", + "sphinx.ext.extlinks", + "jupyter_sphinx", + "nbsphinx", + "sphinx_design", + "sphinx_reredirects", "matplotlib.sphinxext.plot_directive", ] redirects = url_redirects.determine_redirects() nbsphinx_timeout = 300 -nbsphinx_execute = os.getenv('QISKIT_DOCS_BUILD_TUTORIALS', 'never') -nbsphinx_widgets_path = '' -html_sourcelink_suffix = '' -exclude_patterns = ['_build', '**.ipynb_checkpoints'] +nbsphinx_execute = os.getenv("QISKIT_DOCS_BUILD_TUTORIALS", "never") +nbsphinx_widgets_path = "" +html_sourcelink_suffix = "" +exclude_patterns = ["_build", "**.ipynb_checkpoints"] -nbsphinx_thumbnails = { - '**': '_static/no_image.png' -} +nbsphinx_thumbnails = {"**": "_static/no_image.png"} nbsphinx_prolog = """ {% set docname = env.doc2path(env.docname, base=None) %} @@ -91,15 +94,15 @@ "tabs-color-label-active": "rgb(138, 63, 252)", "tabs-color-label-inactive": "rgb(221, 225, 230)", } -templates_path = ['_templates'] +templates_path = ["_templates"] -source_suffix = '.rst' -master_doc = 'index' +source_suffix = ".rst" +master_doc = "index" # Number figures, tables and code-blocks if they have a caption. numfig = True # Available keys are 'figure', 'table', 'code-block' and 'section'. '%s' is the number. -numfig_format = {'table': 'Table %s'} +numfig_format = {"table": "Table %s"} # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # This is also used if you do content translation via gettext catalogs. @@ -107,10 +110,10 @@ language = "en" # For Adding Locale -locale_dirs = ['locale/'] # path is example but recommended. -gettext_compact = False # optional. +locale_dirs = ["locale/"] # path is example but recommended. +gettext_compact = False # optional. -pygments_style = 'colorful' +pygments_style = "colorful" # Whether module names are included in crossrefs of functions, classes, etc. add_module_names = False @@ -119,38 +122,39 @@ # (e.g., if this is set to ['foo.'], then foo.bar is shown under B, not F). # This can be handy if you document a project that consists of a single # package. Works only for the HTML builder currently. -modindex_common_prefix = ['qiskit.'] - +modindex_common_prefix = ["qiskit."] # -- Configuration for extlinks extension ------------------------------------ # Refer to https://www.sphinx-doc.org/en/master/usage/extensions/extlinks.html extlinks = { - 'pull_terra': ('https://github.com/Qiskit/qiskit-terra/pull/%s', '#'), - 'pull_aer': ('https://github.com/Qiskit/qiskit-aer/pull/%s', '#'), - 'pull_ibmq-provider': ('https://github.com/Qiskit/qiskit-ibmq-provider/pull/%s', '#') + "pull_terra": ("https://github.com/Qiskit/qiskit-terra/pull/%s", "#"), + "pull_aer": ("https://github.com/Qiskit/qiskit-aer/pull/%s", "#"), + "pull_ibmq-provider": ("https://github.com/Qiskit/qiskit-ibmq-provider/pull/%s", "#"), } # -- Options for HTML output ------------------------------------------------- html_theme = "qiskit_sphinx_theme" html_theme_options = { - 'logo_only': False, - 'display_version': True, - 'prev_next_buttons_location': 'bottom', - 'style_external_links': True, + "logo_only": False, + "display_version": True, + "prev_next_buttons_location": "bottom", + "style_external_links": True, # Toc options - 'collapse_navigation': True, - 'sticky_navigation': True, - 'navigation_depth': 4, - 'includehidden': True, - 'titles_only': False, + "collapse_navigation": True, + "sticky_navigation": True, + "navigation_depth": 4, + "includehidden": True, + "titles_only": False, } -html_static_path = ['_static'] -html_css_files = ['custom.css', 'gallery.css'] -html_favicon = 'images/favicon.ico' -html_last_updated_fmt = '%Y/%m/%d' -html_context = {'analytics_enabled': os.getenv('QISKIT_ENABLE_ANALYTICS', False)} # enable segment analytics for qiskit.org/documentation +html_static_path = ["_static"] +html_css_files = ["custom.css", "gallery.css"] +html_favicon = "images/favicon.ico" +html_last_updated_fmt = "%Y/%m/%d" +html_context = { + "analytics_enabled": os.getenv("QISKIT_ENABLE_ANALYTICS", False) +} # enable segment analytics for qiskit.org/documentation # -- Options for Autosummary and Autodoc ------------------------------------ # Note that setting autodoc defaults here may not have as much of an effect as you may expect; any @@ -158,7 +162,7 @@ # which likely overrides the autodoc defaults. autosummary_generate = True autosummary_generate_overwrite = False -autoclass_content = 'both' +autoclass_content = "both" # Move type hints from signatures to the parameter descriptions (except in overload cases, where # that's not possible). @@ -174,15 +178,16 @@ # -- Extension configuration ------------------------------------------------- + def setup(app): - app.add_directive('includenodoc', IncludeDirective) - app.add_directive('galleryitem', GalleryItemDirective) - app.add_directive('customgalleryitem', CustomGalleryItemDirective) - app.add_directive('customcarditem', CustomCardItemDirective) - app.add_directive('customcalloutitem', CustomCalloutItemDirective) + app.add_directive("includenodoc", IncludeDirective) + app.add_directive("galleryitem", GalleryItemDirective) + app.add_directive("customgalleryitem", CustomGalleryItemDirective) + app.add_directive("customcarditem", CustomCardItemDirective) + app.add_directive("customcalloutitem", CustomCalloutItemDirective) custom_extensions.load_api_sources(app) custom_extensions.load_tutorials(app) - app.setup_extension('versionutils') - app.connect('build-finished', custom_extensions.clean_api_source) - app.connect('build-finished', custom_extensions.clean_tutorials) - app.connect('source-read', custom_extensions.deprecate_ibmq_provider) + app.setup_extension("versionutils") + app.connect("build-finished", custom_extensions.clean_api_source) + app.connect("build-finished", custom_extensions.clean_tutorials) + app.connect("source-read", custom_extensions.deprecate_ibmq_provider) diff --git a/docs/custom_directives.py b/docs/custom_directives.py index fc2d15ff3816..fd48c123f607 100644 --- a/docs/custom_directives.py +++ b/docs/custom_directives.py @@ -10,12 +10,13 @@ # copyright notice, and modified files need to carry a notice indicating # that they have been altered from the originals. -from docutils.parsers.rst import Directive, directives -from docutils.statemachine import StringList -from docutils import nodes -import re import os +import re + import sphinx_gallery +from docutils import nodes +from docutils.parsers.rst import Directive, directives +from docutils.statemachine import StringList try: FileNotFoundError @@ -53,7 +54,7 @@ def run(self): try: text = open(filename).read() - text_no_docstring = self.docstring_regex.sub('', text, count=1) + text_no_docstring = self.docstring_regex.sub("", text, count=1) code_block = nodes.literal_block(text=text_no_docstring) return [code_block] @@ -82,8 +83,7 @@ class GalleryItemDirective(Directive): required_arguments = 1 optional_arguments = 0 final_argument_whitespace = True - option_spec = {'figure': directives.unchanged, - 'intro': directives.unchanged} + option_spec = {"figure": directives.unchanged, "intro": directives.unchanged} has_content = False add_index = False @@ -97,33 +97,30 @@ def run(self): dirname = os.path.dirname(fname) try: - if 'intro' in self.options: - intro = self.options['intro'][:195] + '...' + if "intro" in self.options: + intro = self.options["intro"][:195] + "..." else: _, blocks = sphinx_gallery.gen_rst.split_code_and_text_blocks(abs_fname) intro, _ = sphinx_gallery.gen_rst.extract_intro_and_title(abs_fname, blocks[0][1]) - thumbnail_rst = sphinx_gallery.backreferences._thumbnail_div( - dirname, basename, intro) + thumbnail_rst = sphinx_gallery.backreferences._thumbnail_div(dirname, basename, intro) - if 'figure' in self.options: - rel_figname, figname = env.relfn2path(self.options['figure']) - save_figname = os.path.join('_static/thumbs/', - os.path.basename(figname)) + if "figure" in self.options: + rel_figname, figname = env.relfn2path(self.options["figure"]) + save_figname = os.path.join("_static/thumbs/", os.path.basename(figname)) try: - os.makedirs('_static/thumbs') + os.makedirs("_static/thumbs") except OSError: pass - sphinx_gallery.gen_rst.scale_image(figname, save_figname, - 400, 280) + sphinx_gallery.gen_rst.scale_image(figname, save_figname, 400, 280) # replace figure in rst with simple regex - thumbnail_rst = re.sub(r'..\sfigure::\s.*\.png', - '.. figure:: /{}'.format(save_figname), - thumbnail_rst) + thumbnail_rst = re.sub( + r"..\sfigure::\s.*\.png", ".. figure:: /{}".format(save_figname), thumbnail_rst + ) - thumbnail = StringList(thumbnail_rst.split('\n')) + thumbnail = StringList(thumbnail_rst.split("\n")) thumb = nodes.paragraph() self.state.nested_parse(thumbnail, self.content_offset, thumb) @@ -170,38 +167,40 @@ class CustomGalleryItemDirective(Directive): required_arguments = 0 optional_arguments = 0 final_argument_whitespace = True - option_spec = {'tooltip': directives.unchanged, - 'figure': directives.unchanged, - 'description': directives.unchanged} + option_spec = { + "tooltip": directives.unchanged, + "figure": directives.unchanged, + "description": directives.unchanged, + } has_content = False add_index = False def run(self): try: - if 'tooltip' in self.options: - tooltip = self.options['tooltip'][:195] + '...' + if "tooltip" in self.options: + tooltip = self.options["tooltip"][:195] + "..." else: - raise ValueError('tooltip not found') + raise ValueError("tooltip not found") - if 'figure' in self.options: + if "figure" in self.options: env = self.state.document.settings.env - rel_figname, figname = env.relfn2path(self.options['figure']) - thumbnail = os.path.join('_static/thumbs/', os.path.basename(figname)) + rel_figname, figname = env.relfn2path(self.options["figure"]) + thumbnail = os.path.join("_static/thumbs/", os.path.basename(figname)) try: - os.makedirs('_static/thumbs') + os.makedirs("_static/thumbs") except FileExistsError: pass sphinx_gallery.gen_rst.scale_image(figname, thumbnail, 400, 280) else: - thumbnail = '_static/img/thumbnails/default.png' + thumbnail = "_static/img/thumbnails/default.png" - if 'description' in self.options: - description = self.options['description'] + if "description" in self.options: + description = self.options["description"] else: - raise ValueError('description not doc found') + raise ValueError("description not doc found") except FileNotFoundError as e: print(e) @@ -211,48 +210,50 @@ def run(self): raise return [] - thumbnail_rst = GALLERY_TEMPLATE.format(tooltip=tooltip, - thumbnail=thumbnail, - description=description) - thumbnail = StringList(thumbnail_rst.split('\n')) + thumbnail_rst = GALLERY_TEMPLATE.format( + tooltip=tooltip, thumbnail=thumbnail, description=description + ) + thumbnail = StringList(thumbnail_rst.split("\n")) thumb = nodes.paragraph() self.state.nested_parse(thumbnail, self.content_offset, thumb) return [thumb] class CustomCardItemDirective(Directive): - option_spec = {'header': directives.unchanged, - 'image': directives.unchanged, - 'link': directives.unchanged, - 'card_description': directives.unchanged, - 'tags': directives.unchanged} + option_spec = { + "header": directives.unchanged, + "image": directives.unchanged, + "link": directives.unchanged, + "card_description": directives.unchanged, + "tags": directives.unchanged, + } def run(self): try: - if 'header' in self.options: - header = self.options['header'] + if "header" in self.options: + header = self.options["header"] else: - raise ValueError('header not doc found') + raise ValueError("header not doc found") - if 'image' in self.options: - image = "" + if "image" in self.options: + image = "" else: - image = '_static/img/thumbnails/default.png' + image = "_static/img/thumbnails/default.png" - if 'link' in self.options: - link = self.options['link'] + if "link" in self.options: + link = self.options["link"] else: - link = '' + link = "" - if 'card_description' in self.options: - card_description = self.options['card_description'] + if "card_description" in self.options: + card_description = self.options["card_description"] else: - card_description = '' + card_description = "" - if 'tags' in self.options: - tags = self.options['tags'] + if "tags" in self.options: + tags = self.options["tags"] else: - tags = '' + tags = "" except FileNotFoundError as e: print(e) @@ -262,12 +263,10 @@ def run(self): raise return [] - card_rst = CARD_TEMPLATE.format(header=header, - image=image, - link=link, - card_description=card_description, - tags=tags) - card_list = StringList(card_rst.split('\n')) + card_rst = CARD_TEMPLATE.format( + header=header, image=image, link=link, card_description=card_description, tags=tags + ) + card_list = StringList(card_rst.split("\n")) card = nodes.paragraph() self.state.nested_parse(card_list, self.content_offset, card) return [card] @@ -299,33 +298,36 @@ def run(self): """ + class CustomCalloutItemDirective(Directive): - option_spec = {'header': directives.unchanged, - 'description': directives.unchanged, - 'button_link': directives.unchanged, - 'button_text': directives.unchanged} + option_spec = { + "header": directives.unchanged, + "description": directives.unchanged, + "button_link": directives.unchanged, + "button_text": directives.unchanged, + } def run(self): try: - if 'description' in self.options: - description = self.options['description'] + if "description" in self.options: + description = self.options["description"] else: - description = '' + description = "" - if 'header' in self.options: - header = self.options['header'] + if "header" in self.options: + header = self.options["header"] else: - raise ValueError('header not doc found') + raise ValueError("header not doc found") - if 'button_link' in self.options: - button_link = self.options['button_link'] + if "button_link" in self.options: + button_link = self.options["button_link"] else: - button_link = '' + button_link = "" - if 'button_text' in self.options: - button_text = self.options['button_text'] + if "button_text" in self.options: + button_text = self.options["button_text"] else: - button_text = '' + button_text = "" except FileNotFoundError as e: print(e) @@ -335,15 +337,15 @@ def run(self): raise return [] - callout_rst = CALLOUT_TEMPLATE.format(description=description, - header=header, - button_link=button_link, - button_text=button_text) - callout_list = StringList(callout_rst.split('\n')) + callout_rst = CALLOUT_TEMPLATE.format( + description=description, header=header, button_link=button_link, button_text=button_text + ) + callout_list = StringList(callout_rst.split("\n")) callout = nodes.paragraph() self.state.nested_parse(callout_list, self.content_offset, callout) return [callout] + CALLOUT_TEMPLATE = """ .. raw:: html diff --git a/docs/custom_extensions.py b/docs/custom_extensions.py index fc2b7f64f8b1..4d030d39065d 100644 --- a/docs/custom_extensions.py +++ b/docs/custom_extensions.py @@ -20,18 +20,18 @@ from distutils import dir_util # Elements with api doc sources -qiskit_elements = ['qiskit-terra', 'qiskit-ibmq-provider'] +qiskit_elements = ["qiskit-terra", "qiskit-ibmq-provider"] apidocs_exists = False apidocs_master = None def _get_current_versions(app): versions = {} - setup_py_path = os.path.join(os.path.dirname(app.srcdir), 'setup.py') - with open(setup_py_path, 'r') as fd: + setup_py_path = os.path.join(os.path.dirname(app.srcdir), "setup.py") + with open(setup_py_path, "r") as fd: setup_py = fd.read() for package in qiskit_elements: - version_regex = re.compile(package + '[=|>]=(.*)\"') + version_regex = re.compile(package + '[=|>]=(.*)"') match = version_regex.search(setup_py) if match: ver = match[1] @@ -40,44 +40,41 @@ def _get_current_versions(app): def _install_from_master(): - for package in qiskit_elements + ['qiskit-ignis']: - github_url = 'git+https://github.com/Qiskit/%s' % package - cmd = [sys.executable, '-m', 'pip', 'install', '-U', github_url] + for package in qiskit_elements + ["qiskit-ignis"]: + github_url = "git+https://github.com/Qiskit/%s" % package + cmd = [sys.executable, "-m", "pip", "install", "-U", github_url] subprocess.run(cmd) def _git_copy(package, sha1, api_docs_dir): try: with tempfile.TemporaryDirectory() as temp_dir: - github_source = 'https://github.com/Qiskit/%s' % package - subprocess.run(['git', 'clone', github_source, temp_dir], - capture_output=True) - subprocess.run(['git', 'checkout', sha1], cwd=temp_dir, - capture_output=True) - dir_util.copy_tree( - os.path.join(temp_dir, 'docs', 'apidocs'), - api_docs_dir) + github_source = "https://github.com/Qiskit/%s" % package + subprocess.run(["git", "clone", github_source, temp_dir], capture_output=True) + subprocess.run(["git", "checkout", sha1], cwd=temp_dir, capture_output=True) + dir_util.copy_tree(os.path.join(temp_dir, "docs", "apidocs"), api_docs_dir) except FileNotFoundError: - warnings.warn('Copy from git failed for %s at %s, skipping...' % - (package, sha1), RuntimeWarning) + warnings.warn( + "Copy from git failed for %s at %s, skipping..." % (package, sha1), RuntimeWarning + ) def load_api_sources(app): """Git clones and sets up Qiskit repos so that we can generate their API docs.""" - api_docs_dir = os.path.join(app.srcdir, 'apidoc') - if os.getenv('DOCS_FROM_MASTER'): + api_docs_dir = os.path.join(app.srcdir, "apidoc") + if os.getenv("DOCS_FROM_MASTER"): global apidocs_master apidocs_master = tempfile.mkdtemp() shutil.move(api_docs_dir, apidocs_master) _install_from_master() for package in qiskit_elements: - _git_copy(package, 'HEAD', api_docs_dir) + _git_copy(package, "HEAD", api_docs_dir) return elif os.path.isdir(api_docs_dir): global apidocs_exists apidocs_exists = True - warnings.warn('docs/apidocs already exists skipping source clone') + warnings.warn("docs/apidocs already exists skipping source clone") return meta_versions = _get_current_versions(app) for package in qiskit_elements: @@ -86,39 +83,36 @@ def load_api_sources(app): def load_tutorials(app): """Git clones the tutorials repo so that we can generate their docs.""" - tutorials_dir = os.path.join(app.srcdir, 'tutorials') + tutorials_dir = os.path.join(app.srcdir, "tutorials") try: with tempfile.TemporaryDirectory() as temp_dir: - github_source = 'https://github.com/Qiskit/qiskit-tutorials' - subprocess.run(['git', 'clone', github_source, temp_dir], - capture_output=True) - dir_util.copy_tree( - os.path.join(temp_dir, 'tutorials'), - tutorials_dir) + github_source = "https://github.com/Qiskit/qiskit-tutorials" + subprocess.run(["git", "clone", github_source, temp_dir], capture_output=True) + dir_util.copy_tree(os.path.join(temp_dir, "tutorials"), tutorials_dir) except FileNotFoundError: warnings.warn( - 'Copy from git failed for qiskit-tutorials, skipping...', + "Copy from git failed for qiskit-tutorials, skipping...", RuntimeWarning, ) def clean_api_source(app, exc): """Deletes the Git cloned repos used for API doc generation.""" - api_docs_dir = os.path.join(app.srcdir, 'apidoc') + api_docs_dir = os.path.join(app.srcdir, "apidoc") global apidocs_exists global apidocs_master if apidocs_exists: return elif apidocs_master: shutil.rmtree(api_docs_dir) - shutil.move(os.path.join(apidocs_master, 'apidoc'), api_docs_dir) + shutil.move(os.path.join(apidocs_master, "apidoc"), api_docs_dir) return shutil.rmtree(api_docs_dir) def clean_tutorials(app, exc): """Deletes the Git cloned tutorials repo used for doc generation.""" - tutorials_dir = os.path.join(app.srcdir, 'tutorials') + tutorials_dir = os.path.join(app.srcdir, "tutorials") shutil.rmtree(tutorials_dir) @@ -128,5 +122,5 @@ def deprecate_ibmq_provider(app, docname, source): The package ``qiskit-ibmq-provider`` is being deprecated and its repo is going to be archived soon. Please transition to the new packages. More information in https://ibm.biz/provider_migration_guide\n\n""" - if 'apidoc/ibmq' in docname or 'qiskit.providers.ibmq' in docname: + if "apidoc/ibmq" in docname or "qiskit.providers.ibmq" in docname: source[0] = message + source[0] diff --git a/docs/url_redirects.py b/docs/url_redirects.py index 934be4f96664..5e500aaa896c 100644 --- a/docs/url_redirects.py +++ b/docs/url_redirects.py @@ -29,48 +29,48 @@ def determine_redirects() -> Dict[str, str]: _optimization_tutorials = [ - '1_quadratic_program', - '2_converters_for_quadratic_programs', - '3_minimum_eigen_optimizer', - '4_grover_optimizer', - '5_admm_optimizer', - '6_examples_max_cut_and_tsp', - '7_examples_vehicle_routing', - '8_cvar_optimization', - 'index.html' + "1_quadratic_program", + "2_converters_for_quadratic_programs", + "3_minimum_eigen_optimizer", + "4_grover_optimizer", + "5_admm_optimizer", + "6_examples_max_cut_and_tsp", + "7_examples_vehicle_routing", + "8_cvar_optimization", + "index.html", ] _finance_tutorials = [ - '01_portfolio_optimization', - '02_portfolio_diversification', - '03_european_call_option_pricing', - '04_european_put_option_pricing', - '05_bull_spread_pricing', - '06_basket_option_pricing', - '07_asian_barrier_spread_pricing', - '08_fixed_income_pricing', - '09_credit_risk_analysis', - '10_qgan_option_pricing', - '11_time_series', - 'index' + "01_portfolio_optimization", + "02_portfolio_diversification", + "03_european_call_option_pricing", + "04_european_put_option_pricing", + "05_bull_spread_pricing", + "06_basket_option_pricing", + "07_asian_barrier_spread_pricing", + "08_fixed_income_pricing", + "09_credit_risk_analysis", + "10_qgan_option_pricing", + "11_time_series", + "index", ] _chemistry_tutorials = [ - '01_electronic_structure', - '02_vibronic_structure', - '03_ground_state_solvers', - '04_excited_states_solvers', - '05_Sampling_potential_energy_surfaces', - '06_calculating_thermodynamic_observables', - 'index' + "01_electronic_structure", + "02_vibronic_structure", + "03_ground_state_solvers", + "04_excited_states_solvers", + "05_Sampling_potential_energy_surfaces", + "06_calculating_thermodynamic_observables", + "index", ] _ml_tutorials = [ - '01_qsvm_classification', - '02_qsvm_multiclass', - '03_vqc', - '04_qgans_for_loading_random_distributions', - 'index' + "01_qsvm_classification", + "02_qsvm_multiclass", + "03_vqc", + "04_qgans_for_loading_random_distributions", + "index", ] _dynamics_tutorials = [ @@ -96,22 +96,28 @@ def _redirects_for_tutorials() -> Dict[str, str]: result = {} for tutorial in _optimization_tutorials: result[ - 'tutorials/optimization/%s' % tutorial] = "https://qiskit.org/documentation/optimization/tutorials/index.html" + "tutorials/optimization/%s" % tutorial + ] = "https://qiskit.org/documentation/optimization/tutorials/index.html" for tutorial in _finance_tutorials: result[ - 'tutorials/finance/%s' % tutorial] = "https://qiskit.org/documentation/finance/tutorials/index.html" + "tutorials/finance/%s" % tutorial + ] = "https://qiskit.org/documentation/finance/tutorials/index.html" for tutorial in _chemistry_tutorials: result[ - "tutorials/chemistry/%s" % tutorial] = "https://qiskit.org/documentation/nature/tutorials/index.html" + "tutorials/chemistry/%s" % tutorial + ] = "https://qiskit.org/documentation/nature/tutorials/index.html" for tutorial in _ml_tutorials: result[ - "tutorials/machine_learning/%s" % tutorial] = "https://qiskit.org/documentation/machine-learning/tutorials/index.html" + "tutorials/machine_learning/%s" % tutorial + ] = "https://qiskit.org/documentation/machine-learning/tutorials/index.html" for tutorial in _dynamics_tutorials: result[ - "tutorials/circuits_advanced/%s" % tutorial] = "https://qiskit.org/documentation/dynamics/tutorials/index.html" + "tutorials/circuits_advanced/%s" % tutorial + ] = "https://qiskit.org/documentation/dynamics/tutorials/index.html" for tutorial in _experiments_tutorials: result[ - "tutorials/noise/%s" % tutorial] = "https://qiskit.org/documentation/experiments/tutorials/index.html" + "tutorials/noise/%s" % tutorial + ] = "https://qiskit.org/documentation/experiments/tutorials/index.html" return result diff --git a/docs/versionutils.py b/docs/versionutils.py index af772976fe63..241d9a4391d8 100644 --- a/docs/versionutils.py +++ b/docs/versionutils.py @@ -19,44 +19,43 @@ from functools import partial from docutils import nodes -from docutils.parsers.rst.directives.tables import Table from docutils.parsers.rst import Directive, directives +from docutils.parsers.rst.directives.tables import Table from sphinx.util import logging - logger = logging.getLogger(__name__) translations_list = [ - ('en', 'English'), - ('bn_BN', 'Bengali'), - ('fr_FR', 'French'), - ('de_DE', 'German'), - ('ja_JP', 'Japanese'), - ('ko_KR', 'Korean'), - ('pt_UN', 'Portuguese'), - ('es_UN', 'Spanish'), - ('ta_IN', 'Tamil'), + ("en", "English"), + ("bn_BN", "Bengali"), + ("fr_FR", "French"), + ("de_DE", "German"), + ("ja_JP", "Japanese"), + ("ko_KR", "Korean"), + ("pt_UN", "Portuguese"), + ("es_UN", "Spanish"), + ("ta_IN", "Tamil"), ] -default_language = 'en' +default_language = "en" def setup(app): - app.connect('config-inited', _extend_html_context) - app.add_config_value('content_prefix', '', '') - app.add_config_value('translations', True, 'html') - app.add_directive('version-history', _VersionHistory) + app.connect("config-inited", _extend_html_context) + app.add_config_value("content_prefix", "", "") + app.add_config_value("translations", True, "html") + app.add_directive("version-history", _VersionHistory) def _extend_html_context(app, config): context = config.html_context - context['translations'] = config.translations - context['translations_list'] = translations_list - context['version_list'] = _get_version_list() - context['current_translation'] = _get_current_translation(config) or config.language - context['translation_url'] = partial(_get_translation_url, config) - context['version_label'] = _get_version_label(config) - context['language_label'] = _get_language_label(config) + context["translations"] = config.translations + context["translations_list"] = translations_list + context["version_list"] = _get_version_list() + context["current_translation"] = _get_current_translation(config) or config.language + context["translation_url"] = partial(_get_translation_url, config) + context["version_label"] = _get_version_label(config) + context["language_label"] = _get_language_label(config) def _get_current_translation(config): @@ -69,112 +68,110 @@ def _get_current_translation(config): def _get_translation_url(config, code, pagename): - base = '/locale/%s' % code if code and code != default_language else '' + base = "/locale/%s" % code if code and code != default_language else "" return _get_url(config, base, pagename) def _get_version_label(config): proc = subprocess.run( - ['git', 'describe', '--abbrev=0', '--tags', 'HEAD'], - encoding='utf8', capture_output=True) + ["git", "describe", "--abbrev=0", "--tags", "HEAD"], encoding="utf8", capture_output=True + ) return proc.stdout -def _get_language_label(config): - return '%s' % (_get_current_translation(config) or config.language,) +def _get_language_label(config): + return "%s" % (_get_current_translation(config) or config.language,) def _get_version_list(): start_version = (0, 24, 0) - proc = subprocess.run(['git', 'describe', '--abbrev=0'], - capture_output=True) + proc = subprocess.run(["git", "describe", "--abbrev=0"], capture_output=True) proc.check_returncode() - current_version = proc.stdout.decode('utf8') - current_version_info = current_version.split('.') - if current_version_info[0] == '0': + current_version = proc.stdout.decode("utf8") + current_version_info = current_version.split(".") + if current_version_info[0] == "0": version_list = [ - '0.%s' % x for x in range(start_version[1], - int(current_version_info[1]) + 1)] + "0.%s" % x for x in range(start_version[1], int(current_version_info[1]) + 1) + ] else: - #TODO: When 1.0.0 add code to handle 0.x version list + # TODO: When 1.0.0 add code to handle 0.x version list version_list = [] pass # Prepend version 0.19 which was built and uploaded manually: - version_list.insert(0, '0.19') + version_list.insert(0, "0.19") return version_list def _get_url(config, base, pagename): - return _add_content_prefix(config, '%s/%s.html' % (base, pagename)) + return _add_content_prefix(config, "%s/%s.html" % (base, pagename)) def _add_content_prefix(config, url): - prefix = '' + prefix = "" if config.content_prefix: - prefix = '/%s' % config.content_prefix - return '%s%s' % (prefix, url) + prefix = "/%s" % config.content_prefix + return "%s%s" % (prefix, url) class _VersionHistory(Table): - - headers = ["Qiskit Metapackage Version", "qiskit-terra", "qiskit-aer", - "qiskit-ignis", "qiskit-ibmq-provider", "qiskit-aqua", - "Release Date"] + headers = [ + "Qiskit Metapackage Version", + "qiskit-terra", + "qiskit-aer", + "qiskit-ignis", + "qiskit-ibmq-provider", + "qiskit-aqua", + "Release Date", + ] repo_root = os.path.abspath(os.path.dirname(__file__)) def _get_setup_py(self, version, git_dir): - cmd = ['git', 'show', '%s:setup.py' % version] - proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - cwd=git_dir) + cmd = ["git", "show", "%s:setup.py" % version] + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=git_dir) stdout, stderr = proc.communicate() if proc.returncode > 0: - logger.warn("%s failed with:\nstdout:\n%s\nstderr:\n%s\n" - % (cmd, stdout, stderr)) - return '' - return stdout.decode('utf8') + logger.warn("%s failed with:\nstdout:\n%s\nstderr:\n%s\n" % (cmd, stdout, stderr)) + return "" + return stdout.decode("utf8") def _get_date(self, version, git_dir): - cmd = ['git', 'log', '--format=%ai', str(version), '-1'] - proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - cwd=git_dir) + cmd = ["git", "log", "--format=%ai", str(version), "-1"] + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=git_dir) stdout, stderr = proc.communicate() if proc.returncode > 0: - logger.warn("%s failed with:\nstdout:\n%s\nstderr:\n%s\n" - % (cmd, stdout, stderr)) - return '' - return stdout.decode('utf8').split(' ')[0] + logger.warn("%s failed with:\nstdout:\n%s\nstderr:\n%s\n" % (cmd, stdout, stderr)) + return "" + return stdout.decode("utf8").split(" ")[0] def get_versions(self, tags, git_dir): versions = {} for tag in tags: version = {} setup_py = self._get_setup_py(tag, git_dir) - version['Release Date'] = self._get_date(tag, git_dir) - for package in self.headers[1:] + ['qiskit_terra']: - version_regex = re.compile(package + '[=|>]=(.*)\"') + version["Release Date"] = self._get_date(tag, git_dir) + for package in self.headers[1:] + ["qiskit_terra"]: + version_regex = re.compile(package + '[=|>]=(.*)"') match = version_regex.search(setup_py) if match: ver = match[1] - if '<' in match[1]: - ver = '>=' + ver - if package != 'qiskit_terra': + if "<" in match[1]: + ver = ">=" + ver + if package != "qiskit_terra": version[package] = ver else: - version['qiskit-terra'] = ver + version["qiskit-terra"] = ver if version: versions[tag] = version return versions def build_table(self, versions): table = nodes.table() - table['classes'] += ['colwidths-auto'] + table["classes"] += ["colwidths-auto"] tgroup = nodes.tgroup(cols=len(self.headers)) table += tgroup - self.options['widths'] = [30, 15, 15, 15, 20, 15] + self.options["widths"] = [30, 15, 15, 15, 20, 15] tgroup.extend( - nodes.colspec(colwidth=col_width, colname='c' + str(idx)) + nodes.colspec(colwidth=col_width, colname="c" + str(idx)) for idx, col_width in enumerate(self.col_widths) ) @@ -183,8 +180,7 @@ def build_table(self, versions): row_node = nodes.row() thead += row_node - row_node.extend(nodes.entry(h, nodes.paragraph(text=h)) - for h in self.headers) + row_node.extend(nodes.entry(h, nodes.paragraph(text=h)) for h in self.headers) tbody = nodes.tbody() tgroup += tbody @@ -221,27 +217,22 @@ def run(self): def _get_qiskit_metapackage_git_tags(tmp_dir): - cmd = ['git', 'clone', 'https://github.com/Qiskit/qiskit.git'] - proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, - stderr=subprocess.PIPE, cwd=tmp_dir) + cmd = ["git", "clone", "https://github.com/Qiskit/qiskit.git"] + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=tmp_dir) stdout, stderr = proc.communicate() if proc.returncode > 0: - logger.warn("%s failed with:\nstdout:\n%s\nstderr:\n%s\n" - % (cmd, stdout, stderr)) + logger.warn("%s failed with:\nstdout:\n%s\nstderr:\n%s\n" % (cmd, stdout, stderr)) return [] else: - - return _get_git_tags(os.path.join(tmp_dir, 'qiskit')) + return _get_git_tags(os.path.join(tmp_dir, "qiskit")) def _get_git_tags(git_dir): - cmd = ['git', 'tag', '--sort=-creatordate'] - proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, - stderr=subprocess.PIPE, cwd=git_dir) + cmd = ["git", "tag", "--sort=-creatordate"] + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=git_dir) stdout, stderr = proc.communicate() if proc.returncode > 0: - logger.warn("%s failed with:\nstdout:\n%s\nstderr:\n%s\n" - % (cmd, stdout, stderr)) + logger.warn("%s failed with:\nstdout:\n%s\nstderr:\n%s\n" % (cmd, stdout, stderr)) return [] - return stdout.decode('utf8').splitlines(), git_dir + return stdout.decode("utf8").splitlines(), git_dir diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 000000000000..f0a74e02df76 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,12 @@ +[build-system] +requires = ["setuptools"] +build-backend = "setuptools.build_meta" + +[tool.black] +line-length = 100 +target-version = ["py37", "py38", "py39", "py310", "py311"] +extend-exclude = "test/benchmarks/" + +[tool.isort] +profile = "black" +extend_skip_glob = "test/benchmarks/**" diff --git a/requirements-dev.txt b/requirements-dev.txt index 370601e9bc4d..30d96bc76042 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -17,3 +17,7 @@ nbsphinx cvxpy networkx>=2.3 sphinx-reredirects + +# Dev tooling +black~=23.3 +isort~=5.11 diff --git a/setup.py b/setup.py index e10e897dead5..491965475b7c 100755 --- a/setup.py +++ b/setup.py @@ -16,9 +16,7 @@ from setuptools import setup - -README_PATH = os.path.join(os.path.abspath(os.path.dirname(__file__)), - 'README.md') +README_PATH = os.path.join(os.path.abspath(os.path.dirname(__file__)), "README.md") with open(README_PATH) as readme_file: README = readme_file.read() @@ -56,13 +54,13 @@ ] visualization_extra = [ - 'matplotlib>=2.1', - 'ipywidgets>=7.3.0', - 'pydot', + "matplotlib>=2.1", + "ipywidgets>=7.3.0", + "pydot", "pillow>=4.2.1", "pylatexenc>=1.4", "seaborn>=0.9.0", - "pygments>=2.4" + "pygments>=2.4", ] @@ -71,7 +69,7 @@ version="0.42.1", description="Software for developing quantum computing programs", long_description=README, - long_description_content_type='text/markdown', + long_description_content_type="text/markdown", url="https://qiskit.org/", author="Qiskit Development Team", author_email="hello@qiskit.org", @@ -102,14 +100,17 @@ include_package_data=True, python_requires=">=3.7", extras_require={ - 'visualization': visualization_extra, - 'all': optimization_extra - + finance_extra + machine_learning_extra - + nature_extra + experiments_extra + visualization_extra, - 'experiments': experiments_extra, - 'optimization': optimization_extra, - 'finance': finance_extra, - 'machine-learning': machine_learning_extra, - 'nature': nature_extra, - } + "visualization": visualization_extra, + "all": optimization_extra + + finance_extra + + machine_learning_extra + + nature_extra + + experiments_extra + + visualization_extra, + "experiments": experiments_extra, + "optimization": optimization_extra, + "finance": finance_extra, + "machine-learning": machine_learning_extra, + "nature": nature_extra, + }, ) diff --git a/test/base.py b/test/base.py index c6919a6cdeec..86de79e2293e 100644 --- a/test/base.py +++ b/test/base.py @@ -23,8 +23,9 @@ class QiskitTestCase(TestCase): """TestCase subclass with a custom assertion.""" - def assertDictAlmostEqual(self, dict1, dict2, delta=None, msg=None, - places=None, default_value=0): + def assertDictAlmostEqual( + self, dict1, dict2, delta=None, msg=None, places=None, default_value=0 + ): """Assert two dictionaries with numeric values are almost equal Fail if the two dictionaries are unequal as determined by @@ -54,7 +55,7 @@ def assertDictAlmostEqual(self, dict1, dict2, delta=None, msg=None, if places is not None: success = True - standard_msg = '' + standard_msg = "" # check value for keys in target keys1 = set(dict1.keys()) for key in keys1: @@ -62,9 +63,11 @@ def assertDictAlmostEqual(self, dict1, dict2, delta=None, msg=None, val2 = dict2.get(key, default_value) if round(abs(val1 - val2), places) != 0: success = False - standard_msg += '(%s: %s != %s), ' % (safe_repr(key), - safe_repr(val1), - safe_repr(val2)) + standard_msg += "(%s: %s != %s), " % ( + safe_repr(key), + safe_repr(val1), + safe_repr(val2), + ) # check values for keys in counts, not in target keys2 = set(dict2.keys()) - keys1 for key in keys2: @@ -72,18 +75,20 @@ def assertDictAlmostEqual(self, dict1, dict2, delta=None, msg=None, val2 = dict2.get(key, default_value) if round(abs(val1 - val2), places) != 0: success = False - standard_msg += '(%s: %s != %s), ' % (safe_repr(key), - safe_repr(val1), - safe_repr(val2)) + standard_msg += "(%s: %s != %s), " % ( + safe_repr(key), + safe_repr(val1), + safe_repr(val2), + ) if success is True: return - standard_msg = standard_msg[:-2] + ' within %s places' % places + standard_msg = standard_msg[:-2] + " within %s places" % places else: if delta is None: delta = 1e-8 # default delta value success = True - standard_msg = '' + standard_msg = "" # check value for keys in target keys1 = set(dict1.keys()) for key in keys1: @@ -91,9 +96,11 @@ def assertDictAlmostEqual(self, dict1, dict2, delta=None, msg=None, val2 = dict2.get(key, default_value) if abs(val1 - val2) > delta: success = False - standard_msg += '(%s: %s != %s), ' % (safe_repr(key), - safe_repr(val1), - safe_repr(val2)) + standard_msg += "(%s: %s != %s), " % ( + safe_repr(key), + safe_repr(val1), + safe_repr(val2), + ) # check values for keys in counts, not in target keys2 = set(dict2.keys()) - keys1 for key in keys2: @@ -101,12 +108,14 @@ def assertDictAlmostEqual(self, dict1, dict2, delta=None, msg=None, val2 = dict2.get(key, default_value) if abs(val1 - val2) > delta: success = False - standard_msg += '(%s: %s != %s), ' % (safe_repr(key), - safe_repr(val1), - safe_repr(val2)) + standard_msg += "(%s: %s != %s), " % ( + safe_repr(key), + safe_repr(val1), + safe_repr(val2), + ) if success is True: return - standard_msg = standard_msg[:-2] + ' within %s delta' % delta + standard_msg = standard_msg[:-2] + " within %s delta" % delta msg = self._formatMessage(msg, standard_msg) raise self.failureException(msg) diff --git a/test/test_simulation.py b/test/test_simulation.py index bf249fd11071..7cbc316d84b3 100644 --- a/test/test_simulation.py +++ b/test/test_simulation.py @@ -30,9 +30,7 @@ def test_execute_in_aer(self): circuit.h(qr[0]) circuit.measure(qr, cr) - backend = qiskit.Aer.get_backend('qasm_simulator') + backend = qiskit.Aer.get_backend("qasm_simulator") shots = 2000 results = qiskit.execute(circuit, backend, shots=shots).result() - self.assertDictAlmostEqual({'0': 1000, '1': 1000}, - results.get_counts(), - delta=100) + self.assertDictAlmostEqual({"0": 1000, "1": 1000}, results.get_counts(), delta=100) diff --git a/test/test_url_redirects.py b/test/test_url_redirects.py index 3756cd6de265..a63754ba9cbe 100644 --- a/test/test_url_redirects.py +++ b/test/test_url_redirects.py @@ -8,46 +8,34 @@ class CustomExtensionsTest(TestCase): """Test url_redirects.py.""" + def test_redirects_for_aer(self) -> None: """Test _redirects_for_aer().""" result = _redirects_for_aer() num_lines_aer_sources = len( - Path("docs/aer_sources.txt") - .read_text(encoding="utf-8") - .splitlines() + Path("docs/aer_sources.txt").read_text(encoding="utf-8").splitlines() ) self.assertEqual(len(result), num_lines_aer_sources * 2) # Spot check some redirects. self.assertEqual( result["stubs/qiskit.providers.aer.AerError.html"], - ( - "https://qiskit.org/documentation/aer/" - "stubs/qiskit_aer.AerError.html" - ), + "https://qiskit.org/documentation/aer/stubs/qiskit_aer.AerError.html", ) self.assertEqual( result["stubs/qiskit_aer.AerError.html"], - ( - "https://qiskit.org/documentation/aer/" - "stubs/qiskit_aer.AerError.html" - ), + "https://qiskit.org/documentation/aer/stubs/qiskit_aer.AerError.html", ) self.assertEqual( - result[ - "stubs/qiskit.providers.aer.library." - "SaveAmplitudes.is_parameterized.html" - ], + result["stubs/qiskit.providers.aer.library.SaveAmplitudes.is_parameterized.html"], ( "https://qiskit.org/documentation/aer/" "stubs/qiskit_aer.library.SaveAmplitudes.is_parameterized.html" ), ) self.assertEqual( - result[ - "stubs/qiskit_aer.library.SaveAmplitudes.is_parameterized.html" - ], + result["stubs/qiskit_aer.library.SaveAmplitudes.is_parameterized.html"], ( "https://qiskit.org/documentation/aer/stubs/" "qiskit_aer.library.SaveAmplitudes.is_parameterized.html" diff --git a/tox.ini b/tox.ini index 32afe4faf9b8..d43b4d6c1fd0 100644 --- a/tox.ini +++ b/tox.ini @@ -14,14 +14,21 @@ commands = pip check python -m unittest -v +[testenv:fmt] +deps = + -r requirements-dev.txt +commands = + black docs/ test/ tools/ setup.py + isort docs/ test/ tools/ setup.py [testenv:lint] deps = - pycodestyle + -r requirements-dev.txt pylint doc8 ipython commands = - pycodestyle test + black --check docs/ test/ tools/ setup.py + isort --check docs/ test/ tools/ setup.py pylint -rn --rcfile={toxinidir}/.pylintrc test doc8 docs --ignore-path docs/_templates --ignore-path docs/stubs