mirror of
https://github.com/biopython/biopython.git
synced 2025-10-21 23:38:51 +08:00
93 lines
2.8 KiB
Python
93 lines
2.8 KiB
Python
# Copyright 2010 by Eric Talevich. All rights reserved.
|
|
# Copyright 2012 by Wibowo Arindrarto. All rights reserved.
|
|
#
|
|
# This file is part of the Biopython distribution and governed by your
|
|
# choice of the "Biopython License Agreement" or the "BSD 3-Clause License".
|
|
# Please see the LICENSE file that should have been included as part of this
|
|
# package.
|
|
"""Common utility functions for various Bio submodules."""
|
|
|
|
import os
|
|
from typing import Any
|
|
from collections.abc import Callable
|
|
from typing import cast
|
|
from typing import Optional
|
|
from typing import Protocol
|
|
from typing import TypeVar
|
|
|
|
# workaround type checking method attributes from https://github.com/python/mypy/issues/2087#issuecomment-587741762
|
|
|
|
F = TypeVar("F", bound=Callable[..., object])
|
|
|
|
|
|
class _FunctionWithPrevious(Protocol[F]):
|
|
previous: int | None
|
|
__call__: F
|
|
|
|
|
|
def function_with_previous(func: F) -> _FunctionWithPrevious[F]:
|
|
"""Decorate a function as having an attribute named 'previous'."""
|
|
function_with_previous = cast(_FunctionWithPrevious[F], func)
|
|
# Make sure the cast isn't a lie.
|
|
function_with_previous.previous = None
|
|
return function_with_previous
|
|
|
|
|
|
def find_test_dir(start_dir: str | None = None) -> str:
|
|
"""Find the absolute path of Biopython's Tests directory.
|
|
|
|
Arguments:
|
|
start_dir -- Initial directory to begin lookup (default to current dir)
|
|
|
|
If the directory is not found up the filesystem's root directory, an
|
|
exception will be raised.
|
|
|
|
"""
|
|
if not start_dir:
|
|
# no callbacks in function signatures!
|
|
# defaults to the current directory
|
|
# (using __file__ would give the installed Biopython)
|
|
start_dir = "."
|
|
|
|
target = os.path.abspath(start_dir)
|
|
while True:
|
|
if os.path.isdir(os.path.join(target, "Bio")) and os.path.isdir(
|
|
os.path.join(target, "Tests")
|
|
):
|
|
# Good, we're in the Biopython root now
|
|
return os.path.abspath(os.path.join(target, "Tests"))
|
|
# Recurse up the tree
|
|
# TODO - Test this on Windows
|
|
new, tmp = os.path.split(target)
|
|
if target == new:
|
|
# Reached root
|
|
break
|
|
target = new
|
|
raise ValueError(
|
|
f"Not within Biopython source tree: {os.path.abspath(start_dir)!r}"
|
|
)
|
|
|
|
|
|
def run_doctest(target_dir: str | None = None, *args: Any, **kwargs: Any) -> None:
|
|
"""Run doctest for the importing module."""
|
|
import doctest
|
|
|
|
# default doctest options
|
|
doctest_attributes: dict[str, Any] = {"optionflags": doctest.ELLIPSIS}
|
|
doctest_attributes.update(kwargs)
|
|
|
|
cur_dir = os.path.abspath(os.curdir)
|
|
|
|
print("Running doctests...")
|
|
try:
|
|
os.chdir(find_test_dir(target_dir))
|
|
doctest.testmod(*args, **doctest_attributes)
|
|
finally:
|
|
# and revert back to initial directory
|
|
os.chdir(cur_dir)
|
|
print("Done")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
run_doctest()
|