Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Creating the logger. Setting `create_dir=True` means on creation of the logfile,

```python
from scitrack import CachingLogger

LOGGER = CachingLogger(create_dir=True)
LOGGER.log_file_path = "somedir/some_path.log"
```
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Documentation = "https://github.com/HuttleyLab/scitrack"
"Source Code" = "https://github.com/HuttleyLab/scitrack"

[dependency-groups]
dev = ["numpy", "pytest", "pytest-cov", "ruff==0.15.22", "nox", "mypy>=2.1.0"]
dev = ["numpy", "pytest", "pytest-cov", "ruff==0.16.1", "nox", "mypy>=2.3.0"]

[tool.hatch.version]
path = "src/scitrack/__init__.py"
Expand Down
90 changes: 47 additions & 43 deletions tests/test_logging.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import importlib

Check notice on line 1 in tests/test_logging.py

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

tests/test_logging.py#L1

Missing copyright notice at top of file (CPY001)
import logging
import sys
from collections import Counter
Expand Down Expand Up @@ -31,6 +32,27 @@
return tmp_path / LOGFILE_NAME


@pytest.fixture
def make_module(tmp_path, monkeypatch):
# creates an importable module from source in an isolated tmp dir
monkeypatch.syspath_prepend(str(tmp_path))
created: list[str] = []

def make(name, source):
(tmp_path / f"{name}.py").write_text(source)
# invalidate_caches() is required because the directory is added to
# sys.path after interpreter start, so the import system's directory
# cache would otherwise not see the newly written file
importlib.invalidate_caches()
created.append(name)
return importlib.import_module(name)

yield make

for name in created:
sys.modules.pop(name, None)


def test_creates_path(logfile):
"""creates a log path"""
LOGGER = CachingLogger(create_dir=True)
Expand Down Expand Up @@ -312,46 +334,32 @@
assert not any("version :" in line for line in logfile.read_text().splitlines())


def test_log_versions_uninstalled_module_does_not_raise(logfile):
# an imported module with no installed dist -> no raise; version recorded
pyfile = TEST_ROOTDIR / "delme_log.py"
pyfile.write_text("__version__ = 'local-only'\n")
sys.path.append(str(TEST_ROOTDIR))
import delme_log
def test_log_versions_uninstalled_module_does_not_raise(logfile, make_module):
# an imported module with no installed dist -> version is recorded
module = make_module("delme_log", "__version__ = 'local-only'\n")

LOGGER = CachingLogger(create_dir=True)
LOGGER.log_file_path = logfile
LOGGER.log_versions(delme_log)
LOGGER.log_versions(module)
LOGGER.shutdown()
pyfile.unlink()
assert any(
"delme_log==local-only" in line for line in logfile.read_text().splitlines()
)


def test_get_version_for_package():
def test_get_version_for_package(make_module):
"""should track version if package is a module"""
import numpy as np

got = get_version_for_package(np)
assert got == np.__version__
# one with a callable
pyfile = TEST_ROOTDIR / "delme.py"
pyfile.write_text("def version():\n return 'my-version'")
sys.path.append(TEST_ROOTDIR)
import delme

got = get_version_for_package("delme")
assert got == "my-version"
pyfile.unlink()
# version is a callable
make_module("delme_callable", "def version():\n return 'my-version'")
assert get_version_for_package("delme_callable") == "my-version"

# func returns a list
pyfile.write_text("version = ['my-version']\n")
from importlib import reload

got = get_version_for_package(reload(delme))
assert got == "my-version"
pyfile.unlink()
# version is a list
module = make_module("delme_list", "version = ['my-version']\n")
assert get_version_for_package(module) == "my-version"


def test_tracks_versions_module(logfile):
Expand All @@ -369,18 +377,14 @@
assert expect in line, line


def test_log_versions_unresolvable_version_logs_unknown(logfile):
def test_log_versions_unresolvable_version_logs_unknown(logfile, make_module):
# a module with no version attribute -> version None normalised to UNKNOWN
pyfile = TEST_ROOTDIR / "delme_nover.py"
pyfile.write_text("answer = 42\n")
sys.path.append(str(TEST_ROOTDIR))
import delme_nover
module = make_module("delme_nover", "answer = 42\n")

LOGGER = CachingLogger(create_dir=True)
LOGGER.log_file_path = logfile
LOGGER.log_versions(delme_nover)
LOGGER.log_versions(module)
LOGGER.shutdown()
pyfile.unlink()
lines = logfile.read_text().splitlines()
assert any("delme_nover==UNKNOWN" in line for line in lines)
assert not any("delme_nover==None" in line for line in lines)
Expand Down Expand Up @@ -611,29 +615,29 @@
assert probed == []


def _records_without_timestamp(logfile):
# count log lines with the leading "%Y-%m-%d %H:%M:%S" field dropped so
# two runs are comparable even when they straddle a one-second boundary
records = Counter()
for line in logfile.read_text().splitlines():
records[line.split("\t", 1)[-1]] += 1
return set(records.values())


def test_appending(logfile):
"""appending to an existing logfile should work"""
LOGGER = CachingLogger(create_dir=True)
LOGGER.log_file_path = logfile
LOGGER.input_file(TEST_ROOTDIR / "sample-lf.fasta")
LOGGER.shutdown()
records = Counter()
for line in logfile.read_text().splitlines():
records[line] += 1
vals = set(records.values())
assert vals == {1}
assert _records_without_timestamp(logfile) == {1}
LOGGER = CachingLogger(create_dir=True)
LOGGER.mode = "a"
LOGGER.log_file_path = logfile
LOGGER.input_file(TEST_ROOTDIR / "sample-lf.fasta")
LOGGER.shutdown()

records = Counter()
for line in logfile.read_text().splitlines():
records[line] += 1
vals = set(records.values())

assert vals == {2}
assert _records_without_timestamp(logfile) == {2}


def test_mdsum_input(logfile):
Expand Down
Loading
Loading