BETSE 0.9.2 (Luckiest Levin) released. Significant changes include: * Downstream data dirname issues resolved. Previously, downstream consumers (e.g., the BETSEE GUI) were erroneously required to recreate rather than share the default simulation configuration provided by the BETSE codebase. This has now been resolved, reducing unseemly Don't Repeat Yourself (DRY). * Gene regulatory network (GRN) pathname issues resolved. Specifically, the "gene regulatory network settings/gene regulatory network config" setting in YAML-formatted simulation configuration files has now been generalized to be relative to the directory containing those files. * Resource consumption reduced. Matplotlib-based figures, graphs, plots, and animations are now properly destroyed on completion, substantially reducing memory usage during long-running simulation exports. * Deprecation warnings eliminated. The codebase now complies with all upstream deprecations, including breaking NumPy, py.test, and Python changes. Notably, NumPy >= 1.16 has deprecated the passing of arbitrary iterables to the np.column_stack() function, which now requires strict sequences: FutureWarning: arrays to stack must be passed as a "sequence" type such as list or tuple. Support for non-sequence iterables such as generators is deprecated as of NumPy 1.16 and will raise an error in the future. Since converting non-sequence iterables to sequences is trivial (ignoring the obvious edge case of infinite generators, which much like the legendary Pokemon of yore appear not to exist in the wild), NumPy developers chose poorly when they chose to explicitly break rather than implicitly resolve this non-issue. Thanks for generating more meaningless boilerplate, NumPy. * Significant continuous integration (CI) improvements, including: * Conda-forge-centric testing. All CI host environments (i.e., GitLab-CI, AppVeyor) now install all mandatory and optional application dependencies from the open-source volunteer "conda-forge" channel rather than the closed-source proprietary "anaconda" channel. Doing so better mimics real-world installation environments and enables us to begin exercising optional dependencies (e.g., FFmpeg, NetworkX, PyDot). * Early-time logging verbosity increased. To simplify testing maintenance, Early-time logging verbosity increased has now been increased during tests. * CI-specific decorators added. The new betse.util.test.pytest.mark.pytskip.skip_if_ci_gitlab() decorator skips the decorated test or fixture if GitLab-CI is currently hosting these tests. * The following previously failing tests have been corrected: * The test_packages_init() unit test, which is now conditionally skipped under GitLab-CI by the aforementioned decorator. GitLab-CI no longer clones this repository correctly, erroneously preserving empty subdirectories no longer tracked by git. While usually innocuous, empty subdirectories trigger false negatives from this unit test. Since this test succeeds both locally and under AppVeyor, GitLab-CI's misconfigured git checkout policy inexplicably remains the culprit. * The test_c_* pair of unit tests, which erupted into incoherent flames due to inappropriate assumptions about the internal structure of NumPy. NumPy 1.16.0 unified the prior public "numpy.core.multiarray" and "numpy.core.umath" C extensions into a new private "numpy.core._multiarray_umath" C extension. * The pivotal test_cli_sim_compat() functional test, which has now been reenabled in a manner seemingly incompatible with recent py.test changes. Since this test safeguards backward compatibility with respect to our YAML-based simulation configuration format, enabling this test is critical to long-term joy. * Installation-time improvements, including: * Substantial "setup.py" streamlining. The contents of our topmost setuptools-based installation script now reflect those of their counterpart in the BETSEE GUI -- which is to say, this script has been compacted into a fairly minimal line length. * "betse.metadata.PYTHON_VERSION_MINOR_MAX" addition. This integer global specifies the maximum minor stable version of the Python 3.x mainline, as required by this "setup.py" streamlining. * "betse_setup.buputil" streamlining. This submodule collects miscellaneous utility functions required only at BETSE installation. This submodule has now been reduced in length, reducing our maintenance burden. * Significant internal API improvements, including: * Application API creation. The new "betse.util.app" subpackage now provides: * The prior "betse.util.meta" subpackage, which has been subsumed under "betse.util.app.meta" for maintainability. * Application pathname API creation. The new "betse.util.app.apppath" submodule enables callers to query the absolute pathnames of application-relative paths regardless of application installation specifics (e.g., setuptools-based egg, frozen application). * Application initialization API centralized. The existing "betse.util.app.meta.metaappabc.MetaAppABC" superclass now centralizes all application initialization logic into a single coherent object-oriented API previously distributed throughout the codebase as a cacophony of incoherent procedural APIs not reusable by downstream consumers. This includes: * The "MetaAppABC" constructor, which now guarantees the current application to be completely initialized excluding third-party dependencies (e.g., NumPy, SciPy), whose initialization must necessarily be deferred until later in the application startup process. This constructor now entirely obsoletes the prior "betse.ignition" API. * The MetaAppABC.init_libs() method, which now initializes third-party dependencies (e.g., NumPy, SciPy) in a user-configurable manner late in the application startup process. This method now obsoletes a significant portion of the existing "betse.lib.libs" API. * The MetaAppABC.init_libs_if_needed() method, which efficiently simplifies the aforementioned process on behalf of low-level automation (e.g., dark voodoo in the "betse.science.__init__" module). * Application metadata singleton API creation. The new "betse.util.app.meta.metaappton" submodule centralizes all logic concerning the application metadata singleton previously residing in the "betse.metaapp" submodule. * Bitwise API creation. The new "betse.util.type.numeric.bits" submodule now provides general-purpose bit and bit field functionality, including an is_bit_on() function implementing a standard bit field testing routine. * Matplotlib Figure API creation. The new "betse.lib.matplotlib.mplfigure" submodule defines critical functionality for reliably closing matplotlib figures, a prevalent "pain point" in most matplotlib-based applications. * Testing API creation. The new "betse.util.test" subpackage now defines testing-specific APIs, including: * The new "betse.util.test.tests" submodule, defining general-purpose test suite functionality. This includes the is_testing() tester, enabling the codebase itself to query whether or not it is currently being tested. * The new "betse.util.test.tstci" submodule, defining CI-specific functionality. This includes one tester for each well-known CI host (e.g., is_ci_gitlab() for GitLab-CI), returning true only when the active Python interpreter is exercising tests on that host. * The new py.test API. The BETSE-specific and hence non-reusable "betse_test.util" subpackage has been moved to the BETSE-agnostic and hence reusable "betse.util.test.pytest" subpackage, enabling reuse by downstream consumers (e.g., BETSEE). * Class API generalizations. The "betse.util.type.cls.classes" submodule now defines a host of new general-purpose getter functions, including: * get_name_qualified(), obtaining the fully-qualified name of the passed class. The implementation proved highly non-trivial, due to common edge cases (e.g., classes with no or poorly defined modules). * get_module_name_qualified_or_none(), obtaining the fully-qualified name of the module defining the passed class if any or "None" otherwise. * Module API generalizations. A new "betse.util.py.module" subpackage has been created, replacing the prior "betse.util.py.pymodule" submodule. This subpackage provides the following new submodules: * "betse.util.py.module.pymodname", providing lookup facilities both to and from fully-qualified module names and their corresponding module objects. * "betse.util.py.module.pymodule", providing generic module handling. * "betse.util.py.module.pypackage", providing generic package handling -- notably, the get_object_type_package_root() function returning the root package transitively defining any arbitrary object's class. * String API generalizations. The existing "betse.util.type.text.strs" submodule now defines a holy trifecta of "get_prefix_preceding_char"-prefixed functions, enabling callers to obtain the prefix preceding any character in arbitrary strings. * Obsolete subdirectories removed, including: * The long-broken "doc/examples" subdirectory, whose code snippets have all non-working for at least several major application revisions. While documentation in and of itself is commendable, bad documentation is readily worse than no documentation. * The long-unused "betse/data/yamale" subdirectory.