From bc180a8ff2a3e20dc686f002d7478bfbca5087b9 Mon Sep 17 00:00:00 2001 From: "Stefan K. Seritan" Date: Tue, 1 Apr 2025 15:34:30 -0700 Subject: [PATCH 1/3] Guard a minimal install matplotlib import --- pygsti/layouts/prefixtable.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pygsti/layouts/prefixtable.py b/pygsti/layouts/prefixtable.py index 2e0aecd0f..81d2387e4 100644 --- a/pygsti/layouts/prefixtable.py +++ b/pygsti/layouts/prefixtable.py @@ -12,7 +12,6 @@ import collections as _collections import networkx as _nx -import matplotlib.pyplot as plt from math import ceil from pygsti.baseobjs import Label as _Label from pygsti.circuits.circuit import SeparatePOVMCircuit as _SeparatePOVMCircuit @@ -1208,6 +1207,8 @@ def _draw_graph(G, node_label_key='label', edge_label_key='promotion_cost', figu An optional size specifier passed into the matplotlib figure constructor to set the plot size. """ + import matplotlib.pyplot as plt + plt.figure(figsize=figure_size) pos = _nx.nx_agraph.graphviz_layout(G, prog="dot", args="-Granksep=5 -Gnodesep=10") labels = _nx.get_node_attributes(G, node_label_key) From 7c8b1afb571e1d0f178af6d807f66ea26dc82322 Mon Sep 17 00:00:00 2001 From: "Stefan K. Seritan" Date: Tue, 1 Apr 2025 15:36:59 -0700 Subject: [PATCH 2/3] Add environment variables to control Cython extension compilation. PYGSTI_CYTHON_SKIP being defined will fully skip extension compilation. PYGSTI_CYTHON_EXCLUDE_FAILURES will run cythonize with exclude_failures=True. Also removes the unneeded setup.cfg, and applies PYGSTI_CYTHON_SKIP to the "No Cython" GitHub Actions. --- .github/workflows/reuseable-main.yml | 2 +- MANIFEST.in | 1 - pyproject.toml | 2 +- setup.cfg | 12 - setup.py | 430 ++++++++++++++------------- 5 files changed, 218 insertions(+), 229 deletions(-) delete mode 100644 setup.cfg diff --git a/.github/workflows/reuseable-main.yml b/.github/workflows/reuseable-main.yml index e3606f9ce..4d6329897 100644 --- a/.github/workflows/reuseable-main.yml +++ b/.github/workflows/reuseable-main.yml @@ -69,7 +69,7 @@ jobs: - name: Install package (No Cython) if: ${{ inputs.use-cython != 'true' }} run: | - python -m pip install -e .[testing_no_cython] + PYGSTI_CYTHON_SKIP=1 python -m pip install -e .[testing_no_cython] - name: Lint with flake8 (Linux only) if: ${{ inputs.os == 'ubuntu-latest'}} run: | diff --git a/MANIFEST.in b/MANIFEST.in index a68760abf..145a916c1 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,6 +1,5 @@ include README.md CONTRIBUTING.md LICENSE include pyproject.toml -include install_locally.py include requirements.txt include optional-requirements.txt include jupyter_notebooks/START_HERE.ipynb diff --git a/pyproject.toml b/pyproject.toml index 8eb61fce6..6b1cbc0db 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,13 +41,13 @@ keywords=[ classifiers=[ "Development Status :: 4 - Beta", "Intended Audience :: Science/Research", - "License :: OSI Approved :: Apache Software License", "Programming Language :: Python", "Topic :: Scientific/Engineering :: Physics", "Operating System :: Microsoft :: Windows", "Operating System :: MacOS :: MacOS X", "Operating System :: Unix" ] +license = "Apache-2.0" [project.optional-dependencies] diamond_norm = [ diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index dc121fd46..000000000 --- a/setup.cfg +++ /dev/null @@ -1,12 +0,0 @@ -[metadata] -description_file = README.md -license_file = LICENSE - -[bdist_wheel] -universal = 1 - -[nosetests] -verbosity=2 -with-timer=1 -with-id=1 -rednose=1 diff --git a/setup.py b/setup.py index 32ebbb2a4..537818eba 100644 --- a/setup.py +++ b/setup.py @@ -2,6 +2,7 @@ from warnings import warn from collections import defaultdict +import os try: from setuptools import setup, find_packages @@ -34,7 +35,6 @@ def custom_version(version): return local_scheme - #Create a custom command class that allows us to specify different compiler flags # based on the compiler (~platform) being used (see # https://stackoverflow.com/questions/30985862/how-to-identify-compiler-before-defining-cython-extensions) @@ -44,7 +44,6 @@ def custom_version(version): ('gcc', ["-std=c++11", "-Wno-deprecated"])]: BUILD_ARGS[compiler] = args - class build_ext_compiler_check(build_ext): def build_extensions(self): compiler = self.compiler.compiler_type @@ -55,12 +54,219 @@ def build_extensions(self): ext.extra_compile_args = args build_ext.build_extensions(self) +# Check if environment can try to build extensions +try: + import numpy as np + from Cython.Build import cythonize + + if "PYGSTI_SKIP_CYTHON" in os.environ: + warn("PYGSTI_SKIP_CYTHON env variable defined. Installing without Cython extensions...") + extensions = None + else: + ext_modules = [ + Extension( + "pygsti.tools.fastcalc", + sources=["pygsti/tools/fastcalc.pyx"], # , "fastcalc.c + # # Cython docs on NumPy usage should mention this! + # define_macros = [('NPY_NO_DEPRECATED_API','NPY_1_7_API_VERSION')], + # # leave above commented + # # see http://docs.cython.org/en/latest/src/reference/compilation.html#configuring-the-c-build + # define_macros = [('CYTHON_TRACE','1')], #for profiling + include_dirs=['.', np.get_include()] + # libraries=['m'] #math lib? + ), + Extension( + "pygsti.baseobjs.opcalc.fastopcalc", + sources=["pygsti/baseobjs/opcalc/fastopcalc.pyx"], + include_dirs=['.', np.get_include()], + language="c++", + extra_link_args=["-std=c++11"] + ), + Extension( + "pygsti.evotypes.basereps_cython", + sources=[ + "pygsti/evotypes/basereps_cython.pyx", + "pygsti/evotypes/basecreps.cpp" + ], + include_dirs=['.', np.get_include()], + language="c++", + extra_link_args=["-std=c++11"] + ), + Extension( + "pygsti.evotypes.densitymx.statereps", + sources=[ + "pygsti/evotypes/densitymx/statereps.pyx", + "pygsti/evotypes/densitymx/statecreps.cpp" + ], + include_dirs=['.', 'pygsti/evotypes', np.get_include()], + language="c++", + extra_link_args=["-std=c++11"] + ), + Extension( + "pygsti.evotypes.densitymx.opreps", + sources=[ + "pygsti/evotypes/densitymx/opreps.pyx", + "pygsti/evotypes/densitymx/opcreps.cpp", + "pygsti/evotypes/densitymx/statecreps.cpp" + ], + include_dirs=['.', 'pygsti/evotypes', np.get_include()], + language="c++", + extra_link_args=["-std=c++11"] + ), + Extension( + "pygsti.evotypes.densitymx.effectreps", + sources=[ + "pygsti/evotypes/densitymx/effectreps.pyx", + "pygsti/evotypes/densitymx/effectcreps.cpp", + "pygsti/evotypes/densitymx/statecreps.cpp", + "pygsti/evotypes/densitymx/opcreps.cpp" + ], + include_dirs=['.', 'pygsti/evotypes', np.get_include()], + language="c++", + extra_link_args=["-std=c++11"] + ), + Extension( + "pygsti.evotypes.statevec.statereps", + sources=[ + "pygsti/evotypes/statevec/statereps.pyx", + "pygsti/evotypes/statevec/statecreps.cpp" + ], + include_dirs=['.', 'pygsti/evotypes', np.get_include()], + language="c++", + extra_link_args=["-std=c++11"] + ), + Extension( + "pygsti.evotypes.statevec.opreps", + sources=[ + "pygsti/evotypes/statevec/opreps.pyx", + "pygsti/evotypes/statevec/opcreps.cpp", + "pygsti/evotypes/statevec/statecreps.cpp" + ], + include_dirs=['.', 'pygsti/evotypes', np.get_include()], + language="c++", + extra_link_args=["-std=c++11"] + ), + Extension( + "pygsti.evotypes.statevec.effectreps", + sources=[ + "pygsti/evotypes/statevec/effectreps.pyx", + "pygsti/evotypes/statevec/effectcreps.cpp", + "pygsti/evotypes/statevec/statecreps.cpp", + "pygsti/evotypes/statevec/opcreps.cpp" + ], + include_dirs=['.', 'pygsti/evotypes', np.get_include()], + language="c++", + extra_link_args=["-std=c++11"] + ), + Extension( + "pygsti.evotypes.statevec.termreps", + sources=[ + "pygsti/evotypes/statevec/termreps.pyx", + "pygsti/evotypes/statevec/termcreps.cpp", + "pygsti/evotypes/statevec/statecreps.cpp", + "pygsti/evotypes/statevec/opcreps.cpp", + "pygsti/evotypes/statevec/effectcreps.cpp" + ], + include_dirs=['.', 'pygsti/evotypes', np.get_include()], + language="c++", + extra_link_args=["-std=c++11"] + ), + Extension( + "pygsti.evotypes.stabilizer.statereps", + sources=[ + "pygsti/evotypes/stabilizer/statereps.pyx", + "pygsti/evotypes/stabilizer/statecreps.cpp" + ], + include_dirs=['.', 'pygsti/evotypes', np.get_include()], + language="c++", + extra_link_args=["-std=c++11"] + ), + Extension( + "pygsti.evotypes.stabilizer.opreps", + sources=[ + "pygsti/evotypes/stabilizer/opreps.pyx", + "pygsti/evotypes/stabilizer/opcreps.cpp", + "pygsti/evotypes/stabilizer/statecreps.cpp" + ], + include_dirs=['.', 'pygsti/evotypes', np.get_include()], + language="c++", + extra_link_args=["-std=c++11"] + ), + Extension( + "pygsti.evotypes.stabilizer.effectreps", + sources=[ + "pygsti/evotypes/stabilizer/effectreps.pyx", + "pygsti/evotypes/stabilizer/effectcreps.cpp", + "pygsti/evotypes/stabilizer/statecreps.cpp", + "pygsti/evotypes/stabilizer/opcreps.cpp" + ], + include_dirs=['.', 'pygsti/evotypes', np.get_include()], + language="c++", + extra_link_args=["-std=c++11"] + ), + Extension( + "pygsti.evotypes.stabilizer.termreps", + sources=[ + "pygsti/evotypes/stabilizer/termreps.pyx", + "pygsti/evotypes/stabilizer/termcreps.cpp", + "pygsti/evotypes/stabilizer/statecreps.cpp", + "pygsti/evotypes/stabilizer/opcreps.cpp", + "pygsti/evotypes/stabilizer/effectcreps.cpp" + ], + include_dirs=['.', 'pygsti/evotypes', np.get_include()], + language="c++", + extra_link_args=["-std=c++11"] + ), + Extension( + "pygsti.forwardsims.mapforwardsim_calc_densitymx", + sources=[ + "pygsti/forwardsims/mapforwardsim_calc_densitymx.pyx", + "pygsti/evotypes/densitymx/statecreps.cpp", + ], + include_dirs=['.', 'pygsti/evotypes', 'pygsti/evotypes/densitymx', np.get_include()], + language="c++", + extra_link_args=["-std=c++11"] + ), + Extension( + "pygsti.forwardsims.termforwardsim_calc_statevec", + sources=[ + "pygsti/forwardsims/termforwardsim_calc_statevec.pyx", + "pygsti/evotypes/statevec/statecreps.cpp", + "pygsti/evotypes/basecreps.cpp" + ], + include_dirs=['.', 'pygsti/evotypes', 'pygsti/evotypes/statevec', np.get_include()], + language="c++", + extra_link_args=["-std=c++11"] + ), + Extension( + "pygsti.forwardsims.termforwardsim_calc_stabilizer", + sources=[ + "pygsti/forwardsims/termforwardsim_calc_stabilizer.pyx", + "pygsti/evotypes/stabilizer/statecreps.cpp", + "pygsti/evotypes/basecreps.cpp" + ], + include_dirs=['.', 'pygsti/evotypes', 'pygsti/evotypes/stabilizer', np.get_include()], + language="c++", + extra_link_args=["-std=c++11"] + ), + Extension( + "pygsti.circuits.circuitparser.fastcircuitparser", + sources=["pygsti/circuits/circuitparser/fastcircuitparser.pyx"], + include_dirs=['.', np.get_include()], + language="c++", + extra_link_args=["-std=c++11"] + ) + ] + extensions = cythonize(ext_modules, compiler_directives={'language_level': "3"}, exclude_failures="PYGSTI_CYTHON_EXCLUDE_FAILURES" in os.environ) +except ImportError: + warn("Extensions build tools are not available. Installing without Cython extensions...") + extensions = None -def setup_with_extensions(extensions=None): +try: setup( use_scm_version={'version_scheme': 'no-guess-dev', 'version_file': "pygsti/_version.py", 'local_scheme': custom_version}, cmdclass={'build_ext': build_ext_compiler_check}, - ext_modules=extensions or [], + ext_modules=extensions, packages=find_packages(where='.', include=['pygsti']), package_data={ 'pygsti.tools': ['fastcalc.pyx'], @@ -146,213 +352,9 @@ def setup_with_extensions(extensions=None): ] } ) - - -try: - # Try to compile extensions first - - import numpy as np - from Cython.Build import cythonize - ext_modules = [ - Extension( - "pygsti.tools.fastcalc", - sources=["pygsti/tools/fastcalc.pyx"], # , "fastcalc.c - # # Cython docs on NumPy usage should mention this! - # define_macros = [('NPY_NO_DEPRECATED_API','NPY_1_7_API_VERSION')], - # # leave above commented - # # see http://docs.cython.org/en/latest/src/reference/compilation.html#configuring-the-c-build - # define_macros = [('CYTHON_TRACE','1')], #for profiling - include_dirs=['.', np.get_include()] - # libraries=['m'] #math lib? - ), - Extension( - "pygsti.baseobjs.opcalc.fastopcalc", - sources=["pygsti/baseobjs/opcalc/fastopcalc.pyx"], - include_dirs=['.', np.get_include()], - language="c++", - extra_link_args=["-std=c++11"] - ), - Extension( - "pygsti.evotypes.basereps_cython", - sources=[ - "pygsti/evotypes/basereps_cython.pyx", - "pygsti/evotypes/basecreps.cpp" - ], - include_dirs=['.', np.get_include()], - language="c++", - extra_link_args=["-std=c++11"] - ), - Extension( - "pygsti.evotypes.densitymx.statereps", - sources=[ - "pygsti/evotypes/densitymx/statereps.pyx", - "pygsti/evotypes/densitymx/statecreps.cpp" - ], - include_dirs=['.', 'pygsti/evotypes', np.get_include()], - language="c++", - extra_link_args=["-std=c++11"] - ), - Extension( - "pygsti.evotypes.densitymx.opreps", - sources=[ - "pygsti/evotypes/densitymx/opreps.pyx", - "pygsti/evotypes/densitymx/opcreps.cpp", - "pygsti/evotypes/densitymx/statecreps.cpp" - ], - include_dirs=['.', 'pygsti/evotypes', np.get_include()], - language="c++", - extra_link_args=["-std=c++11"] - ), - Extension( - "pygsti.evotypes.densitymx.effectreps", - sources=[ - "pygsti/evotypes/densitymx/effectreps.pyx", - "pygsti/evotypes/densitymx/effectcreps.cpp", - "pygsti/evotypes/densitymx/statecreps.cpp", - "pygsti/evotypes/densitymx/opcreps.cpp" - ], - include_dirs=['.', 'pygsti/evotypes', np.get_include()], - language="c++", - extra_link_args=["-std=c++11"] - ), - Extension( - "pygsti.evotypes.statevec.statereps", - sources=[ - "pygsti/evotypes/statevec/statereps.pyx", - "pygsti/evotypes/statevec/statecreps.cpp" - ], - include_dirs=['.', 'pygsti/evotypes', np.get_include()], - language="c++", - extra_link_args=["-std=c++11"] - ), - Extension( - "pygsti.evotypes.statevec.opreps", - sources=[ - "pygsti/evotypes/statevec/opreps.pyx", - "pygsti/evotypes/statevec/opcreps.cpp", - "pygsti/evotypes/statevec/statecreps.cpp" - ], - include_dirs=['.', 'pygsti/evotypes', np.get_include()], - language="c++", - extra_link_args=["-std=c++11"] - ), - Extension( - "pygsti.evotypes.statevec.effectreps", - sources=[ - "pygsti/evotypes/statevec/effectreps.pyx", - "pygsti/evotypes/statevec/effectcreps.cpp", - "pygsti/evotypes/statevec/statecreps.cpp", - "pygsti/evotypes/statevec/opcreps.cpp" - ], - include_dirs=['.', 'pygsti/evotypes', np.get_include()], - language="c++", - extra_link_args=["-std=c++11"] - ), - Extension( - "pygsti.evotypes.statevec.termreps", - sources=[ - "pygsti/evotypes/statevec/termreps.pyx", - "pygsti/evotypes/statevec/termcreps.cpp", - "pygsti/evotypes/statevec/statecreps.cpp", - "pygsti/evotypes/statevec/opcreps.cpp", - "pygsti/evotypes/statevec/effectcreps.cpp" - ], - include_dirs=['.', 'pygsti/evotypes', np.get_include()], - language="c++", - extra_link_args=["-std=c++11"] - ), - Extension( - "pygsti.evotypes.stabilizer.statereps", - sources=[ - "pygsti/evotypes/stabilizer/statereps.pyx", - "pygsti/evotypes/stabilizer/statecreps.cpp" - ], - include_dirs=['.', 'pygsti/evotypes', np.get_include()], - language="c++", - extra_link_args=["-std=c++11"] - ), - Extension( - "pygsti.evotypes.stabilizer.opreps", - sources=[ - "pygsti/evotypes/stabilizer/opreps.pyx", - "pygsti/evotypes/stabilizer/opcreps.cpp", - "pygsti/evotypes/stabilizer/statecreps.cpp" - ], - include_dirs=['.', 'pygsti/evotypes', np.get_include()], - language="c++", - extra_link_args=["-std=c++11"] - ), - Extension( - "pygsti.evotypes.stabilizer.effectreps", - sources=[ - "pygsti/evotypes/stabilizer/effectreps.pyx", - "pygsti/evotypes/stabilizer/effectcreps.cpp", - "pygsti/evotypes/stabilizer/statecreps.cpp", - "pygsti/evotypes/stabilizer/opcreps.cpp" - ], - include_dirs=['.', 'pygsti/evotypes', np.get_include()], - language="c++", - extra_link_args=["-std=c++11"] - ), - Extension( - "pygsti.evotypes.stabilizer.termreps", - sources=[ - "pygsti/evotypes/stabilizer/termreps.pyx", - "pygsti/evotypes/stabilizer/termcreps.cpp", - "pygsti/evotypes/stabilizer/statecreps.cpp", - "pygsti/evotypes/stabilizer/opcreps.cpp", - "pygsti/evotypes/stabilizer/effectcreps.cpp" - ], - include_dirs=['.', 'pygsti/evotypes', np.get_include()], - language="c++", - extra_link_args=["-std=c++11"] - ), - Extension( - "pygsti.forwardsims.mapforwardsim_calc_densitymx", - sources=[ - "pygsti/forwardsims/mapforwardsim_calc_densitymx.pyx", - "pygsti/evotypes/densitymx/statecreps.cpp", - ], - include_dirs=['.', 'pygsti/evotypes', 'pygsti/evotypes/densitymx', np.get_include()], - language="c++", - extra_link_args=["-std=c++11"] - ), - Extension( - "pygsti.forwardsims.termforwardsim_calc_statevec", - sources=[ - "pygsti/forwardsims/termforwardsim_calc_statevec.pyx", - "pygsti/evotypes/statevec/statecreps.cpp", - "pygsti/evotypes/basecreps.cpp" - ], - include_dirs=['.', 'pygsti/evotypes', 'pygsti/evotypes/statevec', np.get_include()], - language="c++", - extra_link_args=["-std=c++11"] - ), - Extension( - "pygsti.forwardsims.termforwardsim_calc_stabilizer", - sources=[ - "pygsti/forwardsims/termforwardsim_calc_stabilizer.pyx", - "pygsti/evotypes/stabilizer/statecreps.cpp", - "pygsti/evotypes/basecreps.cpp" - ], - include_dirs=['.', 'pygsti/evotypes', 'pygsti/evotypes/stabilizer', np.get_include()], - language="c++", - extra_link_args=["-std=c++11"] - ), - Extension( - "pygsti.circuits.circuitparser.fastcircuitparser", - sources=["pygsti/circuits/circuitparser/fastcircuitparser.pyx"], - include_dirs=['.', np.get_include()], - language="c++", - extra_link_args=["-std=c++11"] - ) - ] - setup_with_extensions(cythonize(ext_modules, compiler_directives={'language_level': "3"}, exclude_failures=True)) -except ImportError: - # Cython or numpy is not available - warn("Extensions build tools are not available. Installing without Cython extensions...") - setup_with_extensions() -except SystemExit: - # Extension compilation failed - warn("Error in extension compilation. Installing without Cython extensions...") - setup_with_extensions() +except SystemExit as e: + print("\nAn error occurred while compiling Cython extensions.") + print("Either fix the compilation issue or use the PYGSTI_CYTHON_SKIP to skip compilation,",) + print('e.g. PYGSTI_CYTHON_SKIP=1 pip install pygsti\n') + print("To enable partial Cython failures (i.e. the exclude_failures=True flag of cythonize), use PYGSTI_CYTHON_EXCLUDE_FAILURES instead.") + raise e \ No newline at end of file From f20b6d275ebbc3e3b30b52cc53ac7194a195192b Mon Sep 17 00:00:00 2001 From: "Stefan K. Seritan" Date: Tue, 1 Apr 2025 15:41:41 -0700 Subject: [PATCH 3/3] Minor typo. --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 537818eba..6c7c7aebb 100644 --- a/setup.py +++ b/setup.py @@ -355,6 +355,6 @@ def build_extensions(self): except SystemExit as e: print("\nAn error occurred while compiling Cython extensions.") print("Either fix the compilation issue or use the PYGSTI_CYTHON_SKIP to skip compilation,",) - print('e.g. PYGSTI_CYTHON_SKIP=1 pip install pygsti\n') - print("To enable partial Cython failures (i.e. the exclude_failures=True flag of cythonize), use PYGSTI_CYTHON_EXCLUDE_FAILURES instead.") + print('e.g. PYGSTI_CYTHON_SKIP=1 pip install pygsti') + print("To enable partial Cython failures (i.e. the exclude_failures=True flag of cythonize), use PYGSTI_CYTHON_EXCLUDE_FAILURES instead.\n") raise e \ No newline at end of file