diff --git a/pytools/__init__.py b/pytools/__init__.py index 5f1203e16ca54bab39519c6c85cd26e1b4b257a0..8ebcb633456d8aac95613aed809681f3e1ed822f 100644 --- a/pytools/__init__.py +++ b/pytools/__init__.py @@ -27,23 +27,22 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ -import re -from functools import reduce, wraps -import operator -import sys -import logging -from typing import ( - Any, Callable, Dict, Generic, Hashable, Iterable, - List, Optional, Set, Tuple, TypeVar, Union, ClassVar) import builtins - +import logging import math +import operator +import re +import sys +from functools import reduce, wraps from sys import intern +from typing import (Any, Callable, ClassVar, Dict, Generic, Hashable, Iterable, + List, Optional, Set, Tuple, TypeVar, Union) + try: - from typing import SupportsIndex, Concatenate + from typing import Concatenate, SupportsIndex except ImportError: - from typing_extensions import SupportsIndex, Concatenate + from typing_extensions import Concatenate, SupportsIndex try: from typing import ParamSpec @@ -1584,6 +1583,8 @@ def get_write_to_map_from_permutation(original, permuted): # {{{ graph algorithms from pytools.graph import a_star as a_star_moved + + a_star = MovedFunctionDeprecationWrapper(a_star_moved) # }}} @@ -1871,7 +1872,7 @@ def string_histogram( # pylint: disable=too-many-arguments,too-many-locals print(value, bin_nr, bin_starts) raise - from math import floor, ceil + from math import ceil, floor if use_unicode: def format_bar(cnt): scaled = cnt*width/max_count @@ -2169,7 +2170,7 @@ def assert_not_a_file(name): def add_python_path_relative_to_script(rel_path): - from os.path import dirname, join, abspath + from os.path import abspath, dirname, join script_name = sys.argv[0] rel_script_dir = dirname(script_name) @@ -2391,8 +2392,9 @@ def download_from_web_if_not_present(url, local_name=None): local_name = basename(url) if not exists(local_name): - from pytools.version import VERSION_TEXT from urllib.request import Request, urlopen + + from pytools.version import VERSION_TEXT req = Request(url, headers={ "User-Agent": f"pytools/{VERSION_TEXT}" }) @@ -2412,7 +2414,7 @@ def find_git_revision(tree_root): # pylint: disable=too-many-locals # Keep this routine self-contained so that it can be copy-pasted into # setup.py. - from os.path import join, exists, abspath + from os.path import abspath, exists, join tree_root = abspath(tree_root) if not exists(join(tree_root, ".git")): @@ -2432,7 +2434,7 @@ def find_git_revision(tree_root): # pylint: disable=too-many-locals env["LANG"] = "C" env["LC_ALL"] = "C" - from subprocess import Popen, PIPE, STDOUT + from subprocess import PIPE, STDOUT, Popen p = Popen(["git", "rev-parse", "HEAD"], shell=False, stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True, cwd=tree_root, env=env) @@ -2808,8 +2810,8 @@ def unordered_hash(hash_instance, iterable, hash_constructor=None): """ if hash_constructor is None: - from functools import partial import hashlib + from functools import partial hash_constructor = partial(hashlib.new, hash_instance.name) h_int = 0 diff --git a/pytools/batchjob.py b/pytools/batchjob.py index e1a01a5773d658ebb41eef3e6862fd38a404f4a3..780efed490f73435916ef90c691a24f9b8a76373 100644 --- a/pytools/batchjob.py +++ b/pytools/batchjob.py @@ -120,7 +120,7 @@ class PBSJob(BatchJob): def guess_job_class(): - from subprocess import Popen, PIPE, STDOUT + from subprocess import PIPE, STDOUT, Popen qstat_helplines = Popen(["qstat", "--help"], stdout=PIPE, stderr=STDOUT).communicate()[0].split("\n") if qstat_helplines[0].startswith("GE"): diff --git a/pytools/convergence.py b/pytools/convergence.py index e302ac72e3c9f62611373257a2805af721ba5d53..ead7f97ff6425c2f5f054a26ca85f29cd3e403b0 100644 --- a/pytools/convergence.py +++ b/pytools/convergence.py @@ -1,7 +1,7 @@ +import numbers from typing import List, Optional, Tuple import numpy as np -import numbers # {{{ eoc estimation -------------------------------------------------------------- diff --git a/pytools/debug.py b/pytools/debug.py index c002bcede62761e836975c8272ce5a75baff3f6f..03ae1546fee5cdf26688e75c203b53b5a5a9d109 100644 --- a/pytools/debug.py +++ b/pytools/debug.py @@ -11,8 +11,8 @@ def make_unique_filesystem_object(stem, extension="", directory="", :param extension: needs a leading dot. :param directory: must not have a trailing slash. """ - from os.path import join import os + from os.path import join if creator is None: def default_creator(name): diff --git a/pytools/graph.py b/pytools/graph.py index 00bac77fb69e1bd37af6a42c82ee06379e107fd4..7b0f3423e032e1bb3075d7788205018b8040f17e 100644 --- a/pytools/graph.py +++ b/pytools/graph.py @@ -1,5 +1,6 @@ from __future__ import annotations + __copyright__ = """ Copyright (C) 2009-2013 Andreas Kloeckner Copyright (C) 2020 Matt Wala @@ -63,9 +64,9 @@ Type Variables Used is included as a key in the graph. """ -from typing import (Collection, Mapping, List, Optional, Any, - Callable, Set, MutableSet, Dict, Iterator, Tuple, - Hashable, TypeVar) +from typing import (Any, Callable, Collection, Dict, Hashable, Iterator, List, + Mapping, MutableSet, Optional, Set, Tuple, TypeVar) + try: from typing import TypeAlias diff --git a/pytools/graphviz.py b/pytools/graphviz.py index 3340b7bc0d582507971a0547efb735c4d34a0498..6e7c7485c83fb0d7e2e28117bb86c38021daf548 100644 --- a/pytools/graphviz.py +++ b/pytools/graphviz.py @@ -31,10 +31,11 @@ Dot helper functions .. autofunction:: show_dot """ -from typing import Optional - import html import logging +from typing import Optional + + logger = logging.getLogger(__name__) @@ -76,8 +77,8 @@ def show_dot(dot_code: str, output_to: Optional[str] = None) -> Optional[str]: generated SVG file, otherwise returns ``None``. """ - from tempfile import mkdtemp import subprocess + from tempfile import mkdtemp temp_dir = mkdtemp(prefix="tmp_pytools_dot") dot_file_name = "code.dot" diff --git a/pytools/log.py b/pytools/log.py index 33863dc4d0c72d42f4a281aec4cf0cf6bf63fb8c..ad45bab016b424ce4e9393a74f522844cc351594 100644 --- a/pytools/log.py +++ b/pytools/log.py @@ -1,5 +1,6 @@ from warnings import warn + warn("pytools.log was moved to https://github.com/illinois-ceesd/logpyle/. " "I will try to import that for you. If the import fails, say " "'pip install logpyle', and change your imports from 'pytools.log' " diff --git a/pytools/mpi.py b/pytools/mpi.py index 9961d76614e1b623b7e96618b03221bc5abc7bce..f74c130751c3dbb83720303249b8c97858154756 100644 --- a/pytools/mpi.py +++ b/pytools/mpi.py @@ -32,8 +32,8 @@ MPI helper functionality .. autofunction:: pytest_raises_on_rank """ -from contextlib import contextmanager, AbstractContextManager -from typing import Generator, Tuple, Union, Type +from contextlib import AbstractContextManager, contextmanager +from typing import Generator, Tuple, Type, Union def check_for_mpi_relaunch(argv): @@ -52,8 +52,8 @@ def run_with_mpi_ranks(py_script, ranks, callable_, args=(), kwargs=None): if kwargs is None: kwargs = {} - import sys import os + import sys newenv = os.environ.copy() newenv["PYTOOLS_RUN_WITHIN_MPI"] = "1" @@ -74,9 +74,10 @@ def pytest_raises_on_rank(my_rank: int, fail_rank: int, """ Like :func:`pytest.raises`, but only expect an exception on rank *fail_rank*. """ - import pytest from contextlib import nullcontext + import pytest + if my_rank == fail_rank: cm: AbstractContextManager = pytest.raises(expected_exception) else: diff --git a/pytools/mpiwrap.py b/pytools/mpiwrap.py index b14c88c3a21671daaf4ca901cbbd386b9d8bf26a..e0492e00bfb1abd06c66a32c0f6052d67475b97f 100644 --- a/pytools/mpiwrap.py +++ b/pytools/mpiwrap.py @@ -1,11 +1,15 @@ """See pytools.prefork for this module's reason for being.""" import mpi4py.rc # pylint:disable=import-error + + mpi4py.rc.initialize = False from mpi4py.MPI import * # noqa pylint:disable=wildcard-import,wrong-import-position import pytools.prefork # pylint:disable=wrong-import-position + + pytools.prefork.enable_prefork() diff --git a/pytools/obj_array.py b/pytools/obj_array.py index 38039459e3d703cafd612d1c9b4b0bcd98a92911..3ed4fb9058e3f5c74c2773f80537db2f4ef7a1e1 100644 --- a/pytools/obj_array.py +++ b/pytools/obj_array.py @@ -20,10 +20,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ -import numpy as np from functools import partial, update_wrapper from warnings import warn +import numpy as np + __doc__ = """ Handling :mod:`numpy` Object Arrays diff --git a/pytools/persistent_dict.py b/pytools/persistent_dict.py index 03fc2de4e49f24a5162d93da5fe41aa2c3ece41a..8fd6f849a87c410757022f740ccf2be1f261bc72 100644 --- a/pytools/persistent_dict.py +++ b/pytools/persistent_dict.py @@ -26,11 +26,12 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ -from enum import Enum -import logging -import hashlib import collections.abc as abc -from dataclasses import is_dataclass, fields +import hashlib +import logging +from dataclasses import fields, is_dataclass +from enum import Enum + # Removing this in 2020-12 broke a shocking amount of stuff, such as # https://github.com/OP2/PyOP2/pull/605 @@ -38,10 +39,11 @@ from dataclasses import is_dataclass, fields # away in 2021 at the latest. new_hash = hashlib.sha256 +import errno import os import shutil import sys -import errno + logger = logging.getLogger(__name__) @@ -533,12 +535,13 @@ class _PersistentDictBase: @staticmethod def _write(path, value): - from pickle import dump, HIGHEST_PROTOCOL + from pickle import HIGHEST_PROTOCOL, dump with open(path, "wb") as outf: dump(value, outf, protocol=HIGHEST_PROTOCOL) def _item_dir(self, hexdigest_key): from os.path import join + # Some file systems limit the number of directories in a directory. # For ext4, that limit appears to be 64K for example. # This doesn't solve that problem, but it makes it much less likely diff --git a/pytools/prefork.py b/pytools/prefork.py index 67b0cd64095db732fe0971be422b7524782777d5..c2ed6d3c3b9c634c1a193712317a37cad18b7609 100644 --- a/pytools/prefork.py +++ b/pytools/prefork.py @@ -40,7 +40,7 @@ class DirectForker: @staticmethod def call_capture_output(cmdline, cwd=None, error_on_nonzero=True): - from subprocess import Popen, PIPE + from subprocess import PIPE, Popen try: popen = Popen(cmdline, cwd=cwd, stdin=PIPE, stdout=PIPE, @@ -73,8 +73,8 @@ class DirectForker: def _send_packet(sock, data): - from struct import pack from pickle import dumps + from struct import pack packet = dumps(data) diff --git a/pytools/py_codegen.py b/pytools/py_codegen.py index a388433af4a49b21e867892d8b899bf94b1cdcbf..6d2b25976dcf798c98f58d0b79ba03e0bd2a3c11 100644 --- a/pytools/py_codegen.py +++ b/pytools/py_codegen.py @@ -21,15 +21,13 @@ THE SOFTWARE. """ import marshal +from importlib.util import MAGIC_NUMBER as BYTECODE_VERSION from types import FunctionType, ModuleType from pytools.codegen import CodeGenerator as CodeGeneratorBase from pytools.codegen import Indentation, remove_common_indentation # noqa -from importlib.util import MAGIC_NUMBER as BYTECODE_VERSION - - class PythonCodeGenerator(CodeGeneratorBase): def get_module(self, name=None): if name is None: diff --git a/pytools/spatial_btree.py b/pytools/spatial_btree.py index 91e0f0d7ff1db55e7fe26089adede9b67b5a8c19..5b3634f4246d5ec5ef3532de9b6f630ab05b258b 100644 --- a/pytools/spatial_btree.py +++ b/pytools/spatial_btree.py @@ -152,8 +152,8 @@ class SpatialBinaryTreeBucket: i.visualize(file) def plot(self, **kwargs): - import matplotlib.pyplot as pt import matplotlib.patches as mpatches + import matplotlib.pyplot as pt from matplotlib.path import Path el = self.bottom_left diff --git a/pytools/stopwatch.py b/pytools/stopwatch.py index 864c25387395bd1dfb23dd066c583f297a9cc660..5103d83ccd2cf7d4807925df5bd17545c5634bb5 100644 --- a/pytools/stopwatch.py +++ b/pytools/stopwatch.py @@ -1,4 +1,5 @@ import time + import pytools diff --git a/pytools/tag.py b/pytools/tag.py index d58cda5a7b23c97fe01faaa3f1b4ec0a2187dee9..7359082f2a75ceb90db4e0f730b15bf5bcd91eda 100644 --- a/pytools/tag.py +++ b/pytools/tag.py @@ -30,8 +30,9 @@ Internal stuff that is only here because the documentation tool wants it import sys from dataclasses import dataclass -from typing import (Tuple, Set, Any, FrozenSet, Union, Iterable, # noqa: F401 - TypeVar, Type) +from typing import (Any, FrozenSet, Iterable, Set, Tuple, Type, # noqa: F401 + TypeVar, Union) + from pytools import memoize, memoize_method @@ -138,6 +139,7 @@ class Tag: (self.__class__.__module__, self.__class__.__qualname__)) from dataclasses import fields + # Fields are ordered consistently, so ordered hashing is OK. # # No need to dispatch to superclass: fields() automatically gives us diff --git a/setup.cfg b/setup.cfg index 35884ee71538e133d1f0f7fa6177e4bdca9ca301..299be3d5a88ff2c12d75799eb952eeacdec09130 100644 --- a/setup.cfg +++ b/setup.cfg @@ -7,6 +7,10 @@ docstring-quotes = " multiline-quotes = """ # enable-flake8-bugbear +# enable-isort + +[isort] +lines_after_imports = 2 [wheel] universal = 1 diff --git a/test/test_graph_tools.py b/test/test_graph_tools.py index f9814ea0c0f98c347e7ffed4a15bcf7327a3025b..688c6e4cfebb7d2c6464f4a2a17dd979d4eeb8dd 100644 --- a/test/test_graph_tools.py +++ b/test/test_graph_tools.py @@ -1,11 +1,13 @@ import sys + import pytest def test_compute_sccs(): - from pytools.graph import compute_sccs import random + from pytools.graph import compute_sccs + rng = random.Random(0) def generate_random_graph(nnodes): @@ -47,7 +49,7 @@ def test_compute_sccs(): def test_compute_topological_order(): - from pytools.graph import compute_topological_order, CycleError + from pytools.graph import CycleError, compute_topological_order empty = {} assert compute_topological_order(empty) == [] @@ -251,6 +253,7 @@ def test_prioritized_topological_sort_examples(): def test_prioritized_topological_sort(): import random + from pytools.graph import compute_topological_order rng = random.Random(0) @@ -299,7 +302,7 @@ def test_as_graphviz_dot(): "B": [], "C": ["A"]} - from pytools.graph import as_graphviz_dot, NodeT + from pytools.graph import NodeT, as_graphviz_dot def edge_labels(n1: NodeT, n2: NodeT) -> str: if n1 == "A" and n2 == "B": diff --git a/test/test_persistent_dict.py b/test/test_persistent_dict.py index 4c072d3d677000c7cd05fec7299a6ba6a253f8f9..66b1d567ec988c590855e1a427ca8787c9642ca5 100644 --- a/test/test_persistent_dict.py +++ b/test/test_persistent_dict.py @@ -1,14 +1,15 @@ -from dataclasses import dataclass -from enum import Enum, IntEnum import shutil import sys # noqa import tempfile +from dataclasses import dataclass +from enum import Enum, IntEnum import pytest -from pytools.tag import Tag, tag_dataclass from pytools.persistent_dict import (CollisionWarning, NoSuchEntryError, - PersistentDict, ReadOnlyEntryError, WriteOncePersistentDict) + PersistentDict, ReadOnlyEntryError, + WriteOncePersistentDict) +from pytools.tag import Tag, tag_dataclass # {{{ type for testing diff --git a/test/test_pytools.py b/test/test_pytools.py index d89e9c9ed77d781d56428ebecc812b9bdb3faf35..9ec0dff98908c9692b4bb374a00921e2cc72814c 100644 --- a/test/test_pytools.py +++ b/test/test_pytools.py @@ -21,10 +21,12 @@ THE SOFTWARE. """ +import logging import sys + import pytest -import logging + logger = logging.getLogger(__name__) from typing import FrozenSet @@ -171,6 +173,7 @@ def test_memoize_keyfunc(): def test_memoize_frozen(): from dataclasses import dataclass + from pytools import memoize_method # {{{ check frozen dataclass @@ -297,6 +300,7 @@ def test_processlogger(): def test_table(): import math + from pytools import Table tbl = Table() @@ -373,7 +377,7 @@ def test_eoc(): def test_natsorted(): - from pytools import natsorted, natorder + from pytools import natorder, natsorted assert natorder("1.001") < natorder("1.01") @@ -490,9 +494,8 @@ def test_obj_array_vectorize(c=1): def test_tag(): - from pytools.tag import ( - Taggable, Tag, UniqueTag, NonUniqueTagError, check_tag_uniqueness - ) + from pytools.tag import (NonUniqueTagError, Tag, Taggable, UniqueTag, + check_tag_uniqueness) # Need a subclass that defines the copy function in order to test. class TaggableWithCopy(Taggable): @@ -581,8 +584,8 @@ def test_tag(): def test_unordered_hash(): - import random import hashlib + import random # FIXME: Use randbytes once >=3.9 is OK lst = [bytes([random.randrange(256) for _ in range(20)]) @@ -609,6 +612,7 @@ def test_unordered_hash(): ]) def test_sphere_sampling(sampling, visualize=False): from functools import partial + from pytools import sphere_sample_equidistant, sphere_sample_fibonacci npoints = 128