diff --git a/CHANGELOG.md b/CHANGELOG.md index b2ccf6745..b0c6d9ead 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added * Added a compiler metadata flag for suppressing warnings when Var indirection is unavoidable (#1052) +### Fixed + * Basilisp now respects the value of Python's `sys.dont_write_bytecode` flag when generating bytecode (#1054) + ## [v0.2.2] ### Added * Added the `-p`/`--include-path` CLI command to prepend entries to the `sys.path` as an alternative to `PYTHONPATH` (#1027) diff --git a/docs/compiler.rst b/docs/compiler.rst index eef20b7ee..c4daad9d2 100644 --- a/docs/compiler.rst +++ b/docs/compiler.rst @@ -99,14 +99,12 @@ Namespace Caching The Basilisp compiler aggressively caches compiled namespace modules because compilation is relatively expensive and leads to significant slowdowns when starting Basilisp. Basilisp namespaces are cached using the `same mechanism as the Python compiler uses `_ -- namespaces are cached as bytecode and only recomputed when the ``mtime`` of the source file differs from the ``mtime`` stored in the header of the cached file. +Cache files are stored with an ``.lpyc`` prefix and respect the Python ``PYTHONCACHEPREFIX`` (:external:py:data:`sys.pycache_prefix`) setting. There may be times when the caching behavior is undesirable for whatever reason. Often in development, it is not desirable to allow namespace caching since such files may get out of sync of other uncached modules you are frequently updating, causing hard-to-diagnose bugs. -In such cases, you can tell the Basilisp import mechanism to always ignore the cached copy of a namespace using the ``BASILISP_DO_NOT_CACHE_NAMESPACES`` environment variable. - -.. code-block:: bash - - export BASILISP_DO_NOT_CACHE_NAMESPACES=true +In such cases, you can tell the Basilisp import mechanism to always ignore the cached copy of a namespace using the ``BASILISP_DO_NOT_CACHE_NAMESPACES`` environment variable or ``--disable-ns-cache`` CLI flag. +Additionally, it is possible to disable Basilisp's generation of bytecode files using the standard Python ``PYTHONDONTWRITEBYTECODE`` environment variable or :external:py:data:`sys.dont_write_bytecode` value. .. _direct_linking: diff --git a/src/basilisp/importer.py b/src/basilisp/importer.py index 47566a461..c3879a296 100644 --- a/src/basilisp/importer.py +++ b/src/basilisp/importer.py @@ -359,6 +359,10 @@ def _exec_module( collect_bytecode=all_bytecode.append, ) + if sys.dont_write_bytecode: + logger.debug(f"Skipping bytecode generation for '{fullname}'") + return + # Cache the bytecode that was collected through the compilation run. cache_file_bytes = _basilisp_bytecode( path_stats["mtime"], path_stats["size"], all_bytecode diff --git a/tests/basilisp/importer_test.py b/tests/basilisp/importer_test.py index 7ccc5eaf1..692bff05e 100644 --- a/tests/basilisp/importer_test.py +++ b/tests/basilisp/importer_test.py @@ -226,6 +226,21 @@ def test_import_module_with_cache( using_cache = load_namespace(cached_module_ns) assert cached_module_ns == using_cache.find(sym.symbol("val")).value + def test_import_module_without_writing_cache( + self, + monkeypatch, + module_dir, + make_new_module, + load_namespace, + ): + monkeypatch.setattr(sys, "dont_write_bytecode", True) + module_path = ["importer", "namespace", "no_bytecode.lpy"] + make_new_module(*module_path, ns_name="importer.namespace.no-bytecode") + load_namespace("importer.namespace.no-bytecode") + assert not os.path.exists( + importer._cache_from_source(os.path.join(module_dir, *module_path)) + ) + def test_import_module_with_invalid_cache_magic_number( self, module_dir, cached_module_ns, cached_module_file, load_namespace ):