Skip to content
BETSE 1.1.1 (Nicer Nestor) released.

Significant changes include:

* Dependencies bumped:
  * setuptools >= 38.2.0. The same version of setuptools required by
    BETSEE is now required by BETSE, ensuring parity between the two
    codebases and avoiding painful dependency conflicts. For uniformity,
    this dependency is repeated in both the top-level "pyproject.toml"
    and "tox.ini" configuration files.
* Issues resolved:
  * pypa/pip#6163 and pypa/pip#6434. This commit circumvents a countably
    infinite number of issues introduced by both pip 19.0.0 and 19.1.0 -
    all pertaining to PEP 517 and 518, which is to say "pyproject.toml".
    The mere existence of a "pyproject.toml" file fundamentally breaks
    pip in inexplicable and horrifying ways: a significantly worse state
    of affairs than the pre-PEP 517 and 518 days of setuptools yore. Say
    what you will of setuptools ("...so much hate"), but at least it
    sorta worked. The same cannot be said of recent pip versions, which
    absolutely do not work whatsoever. "Die, pip! Die!" Specifically:
    * pypa/pip#6163 resolved. All files and subdirectories of the
      project directory containing the top-level "setup.py" script are
      now safely registered to be importable modules and packages.
      Technically, this should not be needed. The current build
      framework (e.g., pip, setuptools) should implicitly guarantee this
      to be the case. Indeed, the obsolete setuptools-based
      "easy_install" script does so. Sadly, pip >= 19.0.0 fails to do so
      for projects defining a top-level "pyproject.toml" file. Although
      upstream purports to have resolved this, the most recent stable
      release of pip continues to suffer this. This is suffering.
    * pypa/pip#6434 resolved. The top-level "pyproject.toml" file now
      explicitly declares a default value for the "build-backend" key.
      Doing so safeguards backward compatibility with pip 19.1.0, which
      erroneously violated PEP 51{7,8} by failing to fallback to a sane
      default value in the absence of this key. If this key is left
      undeclared, pip 19.1.0 fails on attempting to perform an editable
      (i.e., developer-specific) installation of this project.
  * tox-dev/tox#765 resolved. "tox" bundles an obsolete version of
    "virtualenv" itself bundling obsolete versions of both "pip" and
    "setuptools", which obstructs sanity. Our "tox.ini" configuration
    resolves this issue by instructing "tox" to manually update both
    "setuptools" and "virtualenv" to their most recent stable releases.
  * Entry points (i.e., wrapper scripts) resolved. Specifically:
    * Windows-specific entry points installable. Entry points yet again
      install as expected under non-WSL Windows variants (i.e., vanilla,
      Cygwin Windows).
    * Dependency entry points preserved. Long-standing issues with a
      custom monkey patch applied by our top-level "setup.py" script at
      setuptools-based application installation time have now been
      resolved. Previously, this patch globally applied to all
      dependencies installed by "easy_install" (but neither "pip" nor
      "conda", which fortuitously remain unaffected). Now, this monkey
      patch only locally applies to this project and downstream
      consumers of this project (e.g., BETSEE).
  * Setuptools validation relaxed. Validation of the currently installed
    version of setuptools has been relaxed to accept recent non-standard
    version strings (e.g., "41.6.0.post20191029").
* Testing improved:
  * GitLab CI + "tox". Specifically:
    * Rewrote the top-level ".gitlab-ci.yml" file from the ground up to
      test both installation and runtime on all supported Python 3.x
      versions (rather than runtime on the most recent stable Python 3.x
      version) and leverage industry standards, including:
      * A test matrix exercising all official Python version-tagged
        Docker images rather than a single unofficial Python
        version-agnostic Docker image (i.e., "continuumio/anaconda3").
        Non-slim images are currently preferred to slim variants with
        names suffixed by "-slim" (e.g., "python:3.8-slim"), as the
        latter fail to include C and C++ compilers required to build and
        install wheels for Python packages both lacking official wheels
        and containing mandatory C extensions (e.g., "psutil").
      * The Python-specific "pip" and Debian-based "apt" package
        managers rather than the Anaconda-based "conda" package manager.
        An initial "apt" package cache is now explicitly created before
        attempting to install system-wide packages requiring this cache.
      * The high-level "tox" wrapper rather than the lower-level
        "pytest" test harness.
      * The standard "virtualenv" package rather than GitLab-CI
        internals for isolating test results between different Python
        3.x versions.
      * YAML anchor-based key mapping interpolation rather than external
        scripts for resolving DRY between different Python 3.x versions.
    * Defined a top-level "tox.ini" configuration file, installing all
      optional runtime dependencies to maximize test coverage.
    * Removed the top-level "requirements-pip.txt" file, which was
      frankly superfluous.
* Documentation revised:
  * Installation instructions rewritten. These instructions have been
    revised from the ground up for simplicity, consistency, and with an
    increased emphasis on the standard pip ecosystem rather than the
    increasingly non-standard Anaconda ecosystem. Specifically:
    * "README.rst" truncated. The top-level "README.rst" file now
      provides only minimal instructions for installing BETSE under the
      two most popular platform-agnostic package managers: pip
      (recommeded) and Anaconda.
    * "INSTALL.rst" added. A new "doc/rst/INSTALL.rst" file providing
      verbose platform-specific instructions for installing BETSE under
      each supported platform (i.e., Linux, macOS, Windows) as
      well as Git-based development and Docker-based containerization
      has now been added.
    * "INSTALL.md" obsoleted. The "doc/md/INSTALL.md" file has been
      removed in favor of the new "doc/rst/INSTALL.rst" file, whose
      underlying reStructuredText is significantly easier to maintain.
    * The sub-level "doc/rst/INSTALL.rst" file
  * pip-based editable installation. The top-level "README.rst" file now
    advises developers to leverage pip rather than setuptools when
    performing an editable installation of this project.
  * "setup.cfg"-based PyPI documentation. The top-level "setup.cfg" file
    now transcludes the contents of the top-level "README.rst" file, a
    substantial improvement over the prior code-based approach strewn
    throughout the codebase (e.g., "setup.py", "betse_setup.buputil").
  * Extraneous files removed. All irrelevant image masks have now been
    pruned from the "doc/yaml/paper" subdirectory. Doing so reduces the
    filesize of release tarballs, minimizes the maintenance burden, and
    presumably eliminates bitrot.
* Git maintenance:
  * pip directories untracked. All top-level pip-specific temporary
    directories (e.g., "pip-wheel-metadata") are now ignored with
    respect to Git tracking.
* API generalized:
  * Renamed:
    * The "betse.util.path.command" subpackage to
      "betse.util.os.command".
    * The "betse.util.test.tests" submodule to
      "betse.util.test.tsttest".
  * Generalized the top-level py.test-specific "conftest.py" plugin:
    * Defined a new private _clean_imports() function to perform the
      following when the active Python interpreter is isolated to a venv
      (e.g., due to being exercised by "tox"):
      1. If the top-level directory for this project is listed in the
         global list of all import directories (i.e., "sys.path"),
         remove this directory from this list. Doing so prevents this
         test session from accidentally importing from modules not
         isolated to this venv, including this project being tested.
      2. If the first directory on this list is not isolated to this
         venv, raise an exception. This condition implies that modules
         will be imported from outside this venv, which entirely defeats
         the purpose of isolating tests with "tox" to a venv.
      3. If the top-level "betse" package is not isolated to this venv,
         raise an exception. This condition implies that this project
         has been imported from outside this venv.
    * Refactored the pytest_sessionstart() hook run at test session
      startup to sanitize import directories by calling the newly
      defined _clean_imports() function. Specifically, if this session
      is isolated to a venv, this hook now removes all import
      directories not isolated to this venv from "sys.path" -- as
      required for sane "tox"-based testing. (See above.)
  * Generalized the top-level "setup.py" script:
    * Called the newly defined
      betse_setup.buputil.die_unless_setuptools_version_at_least()
      validator to ensure the currently installed version of setuptools
      satisfies all installation-time requirements.
    * Added a new "test" key-value pair to the setuptools-specific
      "extras_require" dictionary, enabling "tox" to install all
      mandatory testing requirements of this application without
      duplicating those requirements in the top-level "tox.ini" file.
  * Generalized the "betse.exceptions" submodule:
    * Defined new "BetseFunctionUnimplementedException",
      "BetseProcessException", and "BetseProcessNotFoundException"
      classes.
    * Renamed the "BetseOSShellEnvException" class to
      "BetseShellEnvException".
  * Generalized the "betse.metadeps" submodule:
    * Defined a new "SETUPTOOLS_VERSION_MIN" global, providing the
      minimum version of "setuptools" required at both install- and
      runtime. Previously, this global was inaccessibly hardcoded into
      the coarse-grained "RUNTIME_MANDATORY" global.
  * Generalized the "betse.lib.setuptools.command.supcommand" submodule:
    * Defined a new "SetuptoolsCommandDistributionTypes" global tuple of
      all distribution types commonly passed to methods called by the
      "setuptools.command.easy_install.easy_install" class, suitable for
      use in type checking.
  * Defined a new "betse.lib.setuptools.command.supcmdbuild" submodule,
    preserving the most critical of the contents of the prior
    implementation of the "betse_setup.bupbuild" submodule:
    * For safety, this submodule now safely monkey patches
      "easy_install" in an application-local manner.
    * For reusability, this submodule is now generically applicable to
      arbitrary applications -- including both BETSE and downstream
      consumers thereof (e.g., BETSEE).
    * Refactored the _scriptwriter_get_args_patched() class method to:
      * Accept any "ScriptWriter" or "VersionlessRequirement" instance
        as the passed "distribution" parameter.
      * Silently defer to the default ScriptWriter.get_args() method
        under non-WSL Windows variants (i.e., vanilla, Cygwin Windows).
  * Generalized the "betse.util.cli.cliabc" submodule:
    * Improved the CLIABC._options_top() method to print human-readable
      version specifiers when the "-V" and "--version" options are
      passed, complete with optional human-readable codename (e.g.,
      "BETSE 1.1.0 (Nice Nestor)").
  * Defined a new "betse.util.os.process" subpackage:
    * Defined a new "betse.util.os.process.prctest" submodule:
      * Defined a new is_process_command() tester, returning true only
        if the parent process of the active Python interpreter is
        running an external command with the passed basename. This
        function currently requires the optional "psutil" dependency --
        but could theoretically be expanded with platform-specific
        implementations circumventing this requirement.
  * Generalized the "betse.util.os.shell.shellenv" submodule:
    * Refactored the to_str() converter in terms of the
      mappings.to_str_flat() converter.
  * Defined a new "betse.util.py.module.pyimport" submodule:
    * Renamed the prior betse.util.py.pys.add_import_dirname() function
      to register_dir() for brevity and clarity.
    * Defined a new to_str_modules_imported_name() converter, returning
      a human-readable string of the fully-qualified names of all
      previously imported modules.
  * Defined a new "betse.util.py.pyvenv" submodule:
    * Defined a new is_venv() tester, returning true only if the active
      Python interpreter is isolated to a venv.
    * Defined a new get_system_prefix() getter, returning the absolute
      dirname of the top-level directory containing the system-wide
      Python interpreter.
  * Generalized the "betse.util.type.cls.classes" submodule:
    * Revised the die_unless_subclass() docstring to note that all
      classes are considered to be subclasses of themselves within the
      context of this function, complete with a minimal length example
      (MLE) demonstrating this.
  * Generalized the "betse.util.type.iterable.mapping.mappings"
    submodule:
    * Defined a new to_str_flat() converter, flattening the passed
      string-keyed and -valued dictionary into a human-readable string.
  * Refactored the "betse_setup.bupbuild" submodule to defer to the
    new "betse.lib.setuptools.command.supcmdbuild" submodule.
  * Generalized the "betse.lib.setuptools.command.supcmdtest" submodule:
    * Refactored the "test" subclass to inherit the test suite-specific
      "setuptools.command.test.test" superclass rather than the generic
      "setuptools.Command" superclass.
  * Generalized the "betse.util.path.dirs" submodule:
    * Renamed for disambiguity:
      * copy() to copy_dir().
      * copy_into_dir() to copy_dir_into_dir().
    * Defined a new die_if_subdir() function, raising an exception if
      the second passed directory is a subdirectory of the first passed
      directory.
    * Defined a new is_subdir() function, returning true if the second
      passed directory is a subdirectory of the first passed directory.
    * Defined a new remove_dir() function, recursively removing the
      passed directory after logging a warning and waiting several
      seconds for user intervention.
    * Revised docstrings for various existing functions.
  * Generalized the "betse.util.path.files" submodule:
    * Renamed for disambiguity:
      * remove() to remove_file().
      * remove_if_found() to remove_file_if_found().
  * Generalized the "betse.util.path.paths" submodule:
    * Renamed for disambiguity:
      * move() to move_path().
    * Defined a new remove_path() function, either recursively removing
      the passed path if a directory or non-recursively removing this
      path if a file.
  * Generalized the "betse.util.type.obj.objtest" submodule:
    * Defined a new die_unless_is() validator, raising an exception if
      any passed object is not identical to every passed object.
  * Refactored the "betse_setup.bupbuild" submodule to defer to the
    new "betse.lib.setuptools.command.supcmdbuild" submodule.
  * Generalized the "betse_setup.buputil" submodule:
    * Minimized this submodule to the smallest set of requisite
      functions required by the top-level "setup.py" script.
    * Defined a new die_unless_setuptools_version_at_least() validator,
      copied verbatim from the "betsee.beuputil" submodule.
    * Generalized the die_unless_setuptools_version_at_least() function
      to use the general-purpose "distutils.version.LooseVersion" class
      rather than the strict "distutils.version.StrictVersion" class.
  * Debugged the "betse_test.func.sim.test_sim" submodule:
    * Improved the test_cli_sim_compat() functional test to squelch
      (i.e., silence) warnings emitted by matplotlib during this test.
      Specifically, interactive visualizations are now disabled during
      this test by enabling the "betse_cli_sim_compat" fixture to
      overwrite the old simulation configuration required by this test.

(Bituminous arbiter delicately dangles the provocative invocation!)