diff --git a/.flake8 b/.flake8 new file mode 100644 index 00000000..f0df1f05 --- /dev/null +++ b/.flake8 @@ -0,0 +1,10 @@ +[flake8] +max-line-length = 120 +exclude = docs/src, build, dist +ignore = F811,E121,E123,E126,E226,E24,E704,W503,W504,E203 +per-file-ignores = + test/examples/test_sensor_fusion.py:E128 + funsor/ops/__init__.py:F401,F403 + funsor/jax/distributions.py:F821 + funsor/torch/distributions.py:F821 + test/conftest.py:E402 diff --git a/funsor/__init__.py b/funsor/__init__.py index 127f9492..fea56e1e 100644 --- a/funsor/__init__.py +++ b/funsor/__init__.py @@ -53,7 +53,7 @@ testing, ) -__version__ = "0.4.7" # mirrored in setup.py +__version__ = "0.4.7" # used by pyproject.toml __all__ = [ "__version__", diff --git a/funsor/adjoint.py b/funsor/adjoint.py index 77a07d56..37494f33 100644 --- a/funsor/adjoint.py +++ b/funsor/adjoint.py @@ -224,7 +224,7 @@ def adjoint_contract_generic( sum_op, prod_op, reduced_vars, - *terms + *terms, ) diff --git a/funsor/cnf.py b/funsor/cnf.py index 936f1e12..95b1ba84 100644 --- a/funsor/cnf.py +++ b/funsor/cnf.py @@ -184,7 +184,7 @@ def _sample(self, sampled_vars, sample_inputs, rng_key): self.red_op, self.bin_op, self.reduced_vars, - *(terms + sampled_terms) + *(terms + sampled_terms), ) else: raise NotImplementedError( @@ -431,7 +431,7 @@ def normalize_contraction_commute_joint(red_op, bin_op, reduced_vars, mixture, o mixture.red_op if red_op is ops.null else red_op, bin_op, reduced_vars | mixture.reduced_vars, - *(mixture.terms + (other,)) + *(mixture.terms + (other,)), ) @@ -443,7 +443,7 @@ def normalize_contraction_commute_joint(red_op, bin_op, reduced_vars, other, mix mixture.red_op if red_op is ops.null else red_op, bin_op, reduced_vars | mixture.reduced_vars, - *(mixture.terms + (other,)) + *(mixture.terms + (other,)), ) diff --git a/funsor/optimizer.py b/funsor/optimizer.py index 105df5ed..b9ed5db0 100644 --- a/funsor/optimizer.py +++ b/funsor/optimizer.py @@ -38,7 +38,7 @@ def unfold_contraction_generic_tuple(red_op, bin_op, reduced_vars, terms): v.red_op, bin_op, v.reduced_vars, - *(terms[:i] + (vt,) + terms[i + 1 :]) + *(terms[:i] + (vt,) + terms[i + 1 :]), ) for vt in v.terms ) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..256d0a25 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,107 @@ +[build-system] +requires = ["setuptools>=77"] +build-backend = "setuptools.build_meta" + +[project] +name = "funsor" +description = "A tensor-like library for functions and distributions" +readme = { file = "README.md", content-type = "text/markdown" } +requires-python = ">=3.10" +license = "Apache-2.0" +license-files = ["LICENSE.md"] +dynamic = ["version"] +authors = [ + { name = "Uber AI Labs" }, +] +keywords = ["probabilistic", "machine learning", "bayesian statistics", "pytorch", "jax"] +classifiers = [ + "Intended Audience :: Developers", + "Intended Audience :: Education", + "Intended Audience :: Science/Research", + "Operating System :: POSIX :: Linux", + "Operating System :: MacOS :: MacOS X", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", +] +dependencies = [ + "makefun", + "multipledispatch", + "numpy>=1.7", + "opt_einsum>=2.3.2", + "typing_extensions", +] + +[project.optional-dependencies] +torch = [ + "pyro-ppl>=1.8.0", + "torch>=1.11.0", + "torchvision>=0.12.0", +] +jax = [ + "numpyro>=0.7.0", + "jax>=0.2.21", + "jaxlib>=0.1.71", +] +test = [ + "black", + "flake8", + "isort>=5.0", + "pandas", + "pyro-api>=0.1.2", + "pytest>=7", + "pytest-xdist>=3", + "requests", + "scipy", +] +dev = [ + "black", + "flake8", + "isort>=5.0", + "nbsphinx", + "pandas", + "pytest>=7", + "pytest-xdist>=3", + "scipy", + "sphinx>=2.0", + "sphinx-gallery", + "sphinx_rtd_theme", + "torchvision>=0.12.0", +] + +[project.urls] +Homepage = "https://github.com/pyro-ppl/funsor" +Documentation = "https://funsor.pyro.ai" +Repository = "https://github.com/pyro-ppl/funsor" +Issues = "https://github.com/pyro-ppl/funsor/issues" + +[tool.setuptools.dynamic] +version = { attr = "funsor.__version__" } + +[tool.setuptools.packages.find] +include = ["funsor", "funsor.*"] + +[tool.isort] +profile = "black" +known_first_party = ["funsor", "test"] +known_third_party = ["opt_einsum", "pyro", "pyroapi", "torch", "torchvision"] + +[tool.pytest.ini_options] +filterwarnings = [ + "error", + "ignore:numpy.ufunc size changed:RuntimeWarning", + "ignore:numpy.dtype size changed:RuntimeWarning", + "ignore:Mixed memory format:UserWarning", + "ignore:Cannot memoize Op:UserWarning", + "ignore::DeprecationWarning", + "ignore:CUDA initialization:UserWarning", + "ignore:floor_divide is deprecated:UserWarning", + "ignore:__floordiv__ is deprecated:UserWarning", + "ignore:__rfloordiv__ is deprecated:UserWarning", + "ignore:torch.cholesky is deprecated:UserWarning", + "ignore:torch.symeig is deprecated:UserWarning", + "once::DeprecationWarning", +] +doctest_optionflags = "ELLIPSIS NORMALIZE_WHITESPACE IGNORE_EXCEPTION_DETAIL" diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 402892fc..00000000 --- a/setup.cfg +++ /dev/null @@ -1,36 +0,0 @@ -[metadata] -# This includes the license file(s) in the wheel. -license_files = LICENSE.md - -[flake8] -max-line-length = 120 -exclude = docs/src, build, dist -ignore = F811,E121,E123,E126,E226,E24,E704,W503,W504,E203 -per-file-ignores = - test/examples/test_sensor_fusion.py:E128 - funsor/ops/__init__.py:F401,F403 - funsor/jax/distributions.py:F821 - funsor/torch/distributions.py:F821 - test/conftest.py:E402 - -[isort] -profile = black -known_first_party = funsor, test -known_third_party = opt_einsum, pyro, pyroapi, torch, torchvision - -[tool:pytest] -filterwarnings = error - ignore:numpy.ufunc size changed:RuntimeWarning - ignore:numpy.dtype size changed:RuntimeWarning - ignore:Mixed memory format:UserWarning - ignore:Cannot memoize Op:UserWarning - ignore::DeprecationWarning - ignore:CUDA initialization:UserWarning - ignore:floor_divide is deprecated:UserWarning - ignore:__floordiv__ is deprecated:UserWarning - ignore:__rfloordiv__ is deprecated:UserWarning - ignore:torch.cholesky is deprecated:UserWarning - ignore:torch.symeig is deprecated:UserWarning - once::DeprecationWarning - -doctest_optionflags = ELLIPSIS NORMALIZE_WHITESPACE IGNORE_EXCEPTION_DETAIL diff --git a/setup.py b/setup.py deleted file mode 100644 index cd711bff..00000000 --- a/setup.py +++ /dev/null @@ -1,93 +0,0 @@ -# Copyright Contributors to the Pyro project. -# SPDX-License-Identifier: Apache-2.0 - -import sys - -from setuptools import find_packages, setup - -# READ README.md for long description on PyPi. -# This requires uploading via twine, e.g.: -# $ python setup.py sdist bdist_wheel -# $ twine upload --repository-url https://test.pypi.org/legacy/ dist/* # test version -# $ twine upload dist/* -try: - long_description = open("README.md", encoding="utf-8").read() -except Exception as e: - sys.stderr.write("Failed to convert README.md to rst:\n {}\n".format(e)) - sys.stderr.flush() - long_description = "" - -# Remove badges since they will always be obsolete. -# This assumes the first 4 lines contain badge info. -long_description = "\n".join(line for line in long_description.split("\n")[4:]) - -setup( - name="funsor", - version="0.4.7", # mirrored in funsor/__init__.py - description="A tensor-like library for functions and distributions", - packages=find_packages(include=["funsor", "funsor.*"]), - url="https://github.com/pyro-ppl/funsor", - project_urls={"Documentation": "https://funsor.pyro.ai"}, - author="Uber AI Labs", - python_requires=">=3.10", - install_requires=[ - "makefun", - "multipledispatch", - "numpy>=1.7", - "opt_einsum>=2.3.2", - "typing_extensions", - ], - extras_require={ - "torch": [ - "pyro-ppl>=1.8.0", - "torch>=1.11.0", - "torchvision>=0.12.0", - ], - "jax": [ - "numpyro>=0.7.0", - "jax>=0.2.21", - "jaxlib>=0.1.71", - ], - "test": [ - "black", - "flake8", - "isort>=5.0", - "pandas", - "pyro-api>=0.1.2", - "pytest>=7", - "pytest-xdist>=3", - "requests", - "scipy", - ], - "dev": [ - "black", - "flake8", - "isort>=5.0", - "nbsphinx", - "pandas", - "pytest>=7", - "pytest-xdist>=3", - "scipy", - "sphinx>=2.0", - "sphinx-gallery", - "sphinx_rtd_theme", - "torchvision>=0.12.0", - ], - }, - long_description=long_description, - long_description_content_type="text/markdown", - keywords="probabilistic machine learning bayesian statistics pytorch jax", - classifiers=[ - "Intended Audience :: Developers", - "Intended Audience :: Education", - "Intended Audience :: Science/Research", - "License :: OSI Approved :: Apache Software License", - "Operating System :: POSIX :: Linux", - "Operating System :: MacOS :: MacOS X", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: 3.13", - "Programming Language :: Python :: 3.14", - ], -) diff --git a/test/test_distribution_generic.py b/test/test_distribution_generic.py index 1b662e0a..3ae97351 100644 --- a/test/test_distribution_generic.py +++ b/test/test_distribution_generic.py @@ -778,9 +778,10 @@ def test_generic_stats(case, statistic): raw_dist, output=funsor.Real, dim_to_name=dim_to_name ) - with xfail_if_not_implemented( - msg="entropy not implemented for some distributions" - ), xfail_if_not_found(msg="stats not implemented yet for TransformedDist"): + with ( + xfail_if_not_implemented(msg="entropy not implemented for some distributions"), + xfail_if_not_found(msg="stats not implemented yet for TransformedDist"), + ): actual_stat = getattr(funsor_dist, statistic)() with xfail_if_not_implemented(): diff --git a/test/test_memoize.py b/test/test_memoize.py index 359e261e..d2af147d 100644 --- a/test/test_memoize.py +++ b/test/test_memoize.py @@ -178,14 +178,14 @@ def test_nested_einsum_complete_sharing( output2_1 = einsum_impl2( outputs1[0] + "," + eqn2, *([output1_1] + funsor_operands2), - backend=backend2 + backend=backend2, ) output1_2 = einsum_impl1(eqn1, *funsor_operands1, backend=backend1) output2_2 = einsum_impl2( outputs1[0] + "," + eqn2, *([output1_2] + funsor_operands2), - backend=backend2 + backend=backend2, ) assert output1_1 is output1_2 diff --git a/test/test_optimizer.py b/test/test_optimizer.py index 7951cd27..9c3b6606 100644 --- a/test/test_optimizer.py +++ b/test/test_optimizer.py @@ -98,7 +98,7 @@ def test_nested_einsum( outputs1[0] + "," + eqn2, *([expected1] + operands2), backend=backend2, - modulo_total=True + modulo_total=True, )[0] with normalize: