IO#

The prodock.io namespace collects shared utilities for molecular text parsing, RDKit-based format conversion, defensive environment cleanup, and structured logging. These helpers are intended to support the rest of the ProDock workflow stack while remaining reusable in standalone scripts and notebooks.

Overview#

Parsing

Read molecular text blocks such as SDF, PDB, MOL2, and XYZ into RDKit molecules with defensive fallbacks.

Conversion

Convert between SMILES, SDF, and PDB while optionally generating and optimizing 3D coordinates.

Utilities

Provide best-effort runtime helpers such as graceful PyMOL shutdown and module cleanup.

Logging

Expose structured logging, colored console formatters, JSON logs, step decorators, and timing helpers.

Submodules#

prodock.io.parser#

Small defensive parsers for text blocks used by grid-box and related modules. These functions attempt to recover an RDKit molecule from common chemical file formats and return None instead of raising when parsing fails, making them well suited for fallback-heavy preprocessing code.

prodock.io.parser#

Small text-to-RDKit parsers used by gridbox and other modules.

These helpers attempt to parse molecular text blocks (SDF, PDB, MOL2, XYZ) and return the first successfully parsed rdkit.Chem.rdchem.Mol or None when parsing failed. They are defensive by design: parser exceptions are swallowed and None is returned so callers can decide fallback behavior.

The main helpers are:

These functions are intentionally small and easy to unit-test.

_parse_block(block)#

Try to parse a single MDL mol block using RDKit.

Parameters:

block (str) – Text containing a single MDL Mol block.

Returns:

Parsed RDKit Mol on success, otherwise None.

Return type:

Optional[rdkit.Chem.rdchem.Mol]

_try_blocks(blocks)#

Iterate candidate mol-block strings and return the first successfully parsed molecule.

Parameters:

blocks (List[str]) – List of candidate mol-block strings.

Returns:

First parsed RDKit Mol or None if none parsed.

Return type:

Optional[rdkit.Chem.rdchem.Mol]

_sanitize_text(text)#

Apply light sanitization to SDF text to handle some common malformed cases.

Current rules: conservative replacements of “-0.” coordinate artifacts that sometimes break strict parsers.

Parameters:

text (str) – Raw SDF text.

Returns:

Sanitized text.

Return type:

str

_supplier_first_mol(text)#

Use RDKit’s SDMolSupplier as a robust fallback for SDF parsing.

Writes the provided text to a temporary .sdf file and iterates the SDMolSupplier collecting valid molecules. The temporary file is removed after supplier iteration completes to avoid races where RDKit may still read the file.

Parameters:

text (str) – Full SDF content (may contain multiple records).

Returns:

First parsed RDKit Mol or None.

Return type:

Optional[rdkit.Chem.rdchem.Mol]

_parse_sdf_text(text)#

Parse SDF-like text and return the first valid RDKit Mol.

Strategy:
  1. Quick-fail on empty input.

  2. Split by $$$$ and attempt per-block MolFromMolBlock.

  3. If that fails, apply light sanitization and retry per-block parsing.

  4. If still failing, write the text to a temporary .sdf file and use SDMolSupplier as a robust fallback.

Parameters:

text (str) – SDF-style content (possibly multiple records).

Returns:

First parsed RDKit Mol or None if parsing fails.

Return type:

Optional[rdkit.Chem.rdchem.Mol]

_parse_pdb_text(text)#

Parse a PDB block into an RDKit Mol.

Parameters:

text (str) – PDB-format text (single model/block).

Returns:

Parsed RDKit Mol or None on failure.

Return type:

Optional[rdkit.Chem.rdchem.Mol]

_parse_mol2_text(text)#

Parse a MOL2 block into an RDKit Mol.

Note:

Some RDKit binaries may lack MOL2 parsing support. In that case this function typically returns None.

Parameters:

text (str) – MOL2-format text.

Returns:

Parsed RDKit Mol or None on failure.

Return type:

Optional[rdkit.Chem.rdchem.Mol]

_parse_xyz_text(text)#

Parse an XYZ-format block into an RDKit Mol.

Uses Chem.MolFromXYZBlock when available; older RDKit releases may not provide this helper and the function will return None in that case.

Parameters:

text (str) – XYZ-format text.

Returns:

Parsed RDKit Mol or None on failure.

Return type:

Optional[rdkit.Chem.rdchem.Mol]

prodock.io.rdkit#

RDKit-focused molecular I/O functions for common format conversions. This module covers SMILES-to-molecule conversion, SDF and PDB writing, file-to-RDKit loading, and optional 3D embedding and optimization. When available, it can use an internal ProDock conformer engine before falling back to plain RDKit methods.

RDKit-only molecular I/O helpers that prefer prodock.chem.Conformer for embedding/optimization.

This module provides convenience functions to convert between SMILES, SDF and PDB formats, to embed 3D coordinates, and to optionally use the internal prodock.chem.conformer.Conformer class for higher-quality, parallelized embedding/optimization when available.

Provided functions#

  • smiles2mol, mol2smiles

  • smiles2sdf, sdf2mol, sdf2mols, sdftosmiles, mol2sdf

  • smiles2pdb, pdb2mol, pdb2smiles, mol2pdb

  • convenience: mol_from_smiles_write_all_formats, is_valid_smiles

Behavior notes#

  • If prodock.chem.conformer.Conformer is importable it will be used as the preferred engine for embedding/optimizing 3D conformers. If it is not available the module falls back to RDKit embedding/force-field optimization.

  • Functions that write 3D formats (SDF/PDB) will attempt to create coordinates when the provided RDKit Mol lacks conformers, honoring the embed3d and optimize flags.

smiles2mol(smiles, sanitize=True)#

Convert a SMILES string to an RDKit Mol (raises ValueError on failure).

Parameters:
  • smiles (str) – Input SMILES string (non-empty).

  • sanitize (bool) – Whether to run RDKit sanitization on the parsed Mol.

Returns:

Parsed RDKit Mol.

Return type:

rdkit.Chem.rdchem.Mol

Raises:

ValueError – If parsing fails or smiles is empty.

mol2smiles(mol, canonical=True, isomeric=True)#

Convert an RDKit Mol to a SMILES string.

Parameters:
  • mol (rdkit.Chem.rdchem.Mol) – RDKit Mol to convert.

  • canonical (bool) – If True produce canonical SMILES.

  • isomeric (bool) – If True include stereochemistry in SMILES.

Returns:

SMILES string representation.

Return type:

str

Raises:

ValueError – If mol is None.

smiles2sdf(
smiles,
out_path,
embed3d=True,
add_hs=True,
optimize=True,
embed_algorithm='ETKDGv3',
opt_method='MMFF94',
conformer_seed=42,
conformer_n_jobs=1,
opt_max_iters=200,
)#

Convert a SMILES string to an SDF file (single-record). Prefer the internal Conformer engine for embedding/optimization when available.

Parameters:
  • smiles (str) – Input SMILES string.

  • out_path (str | pathlib.Path) – Destination SDF path.

  • embed3d (bool) – Whether to embed 3D coordinates if missing.

  • add_hs (bool) – Whether to add explicit hydrogens for embedding.

  • optimize (bool) – Whether to optimize geometry after embedding.

  • embed_algorithm (Optional[str]) – Embedding algorithm name (e.g., “ETKDGv3”).

  • opt_method (Optional[str]) – Optimization method preference.

  • conformer_seed (int) – RNG seed to pass to Conformer if used.

  • conformer_n_jobs (int) – Parallel jobs for Conformer if available.

  • opt_max_iters (int) – Maximum optimizer iterations.

Returns:

Path to the written SDF file.

Return type:

pathlib.Path

Raises:

ValueError – If smiles is empty.

sdf2mol(sdf_path, sanitize=True, removeHs=False)#

Load the first molecule from an SDF file.

Parameters:
  • sdf_path (str | pathlib.Path) – Path to the SDF file.

  • sanitize (bool) – Whether to sanitize molecules while reading.

  • removeHs (bool) – If True drop explicit hydrogens from the returned Mol.

Returns:

The first RDKit Mol found or None if none are readable.

Return type:

Optional[rdkit.Chem.rdchem.Mol]

sdf2mols(sdf_path, sanitize=True)#

Load all molecules from an SDF file.

Parameters:
  • sdf_path (str | pathlib.Path) – Path to the SDF file.

  • sanitize (bool) – Whether to sanitize molecules while reading.

Returns:

List of RDKit Mol objects (may be empty).

Return type:

list[rdkit.Chem.rdchem.Mol]

sdftosmiles(sdf_path, sanitize=True)#

Read an SDF file and return a list of SMILES (one per molecule).

Parameters:
  • sdf_path (str | pathlib.Path) – Path to the SDF file.

  • sanitize (bool) – Whether to sanitize molecules while reading.

Returns:

List of SMILES strings corresponding to each molecule.

Return type:

list[str]

mol2sdf(
mol,
out_path,
sanitize=True,
embed3d=True,
add_hs=True,
optimize=True,
embed_algorithm='ETKDGv3',
opt_method='MMFF94',
conformer_seed=42,
conformer_n_jobs=1,
opt_max_iters=200,
)#

Write a single RDKit Mol to an SDF file. If embed3d is True and the molecule lacks coordinates, attempt to generate coordinates (preferring Conformer if available).

Parameters:
  • mol (rdkit.Chem.rdchem.Mol) – RDKit Mol to write.

  • out_path (str | pathlib.Path) – Destination SDF path.

  • sanitize (bool) – Whether to sanitize the molecule before writing.

  • embed3d (bool) – If True and no conformer present, attempt to embed 3D coords.

  • add_hs (bool) – Whether to add explicit hydrogens prior to embedding/optimization.

  • optimize (bool) – Whether to run force-field optimization after embedding.

  • embed_algorithm (Optional[str]) – Embedding algorithm name (e.g., “ETKDGv3”) or None.

  • opt_method (Optional[str]) – Preferred optimizer method (e.g., “MMFF94” or “UFF”).

  • conformer_seed (int) – RNG seed for Conformer or embedding fallbacks.

  • conformer_n_jobs (int) – Number of parallel jobs for Conformer fallback.

  • opt_max_iters (int) – Maximum optimizer iterations.

Returns:

Path to the written SDF file.

Return type:

pathlib.Path

Raises:

ValueError – If mol is None.

mol2pdb(
mol,
out_path,
add_hs=False,
embed3d=False,
optimize=True,
embed_algorithm=None,
opt_method=None,
conformer_seed=42,
conformer_n_jobs=1,
opt_max_iters=200,
)#

Write an RDKit Mol to a PDB file. If the molecule lacks coordinates and embed3d is True, attempt to generate coordinates (prefer Conformer).

Parameters:
  • mol (rdkit.Chem.rdchem.Mol) – RDKit Mol to write.

  • out_path (str | pathlib.Path) – Destination PDB file path.

  • add_hs (bool) – Whether to add explicit hydrogens for embedding.

  • embed3d (bool) – If True attempt to embed 3D coordinates when missing.

  • optimize (bool) – Whether to run geometry optimization after embedding.

  • embed_algorithm (Optional[str]) – Embedding algorithm name (e.g., “ETKDGv3”) or None.

  • opt_method (Optional[str]) – Optimization method (e.g., “MMFF94” or “UFF”).

  • conformer_seed (int) – RNG seed for Conformer fallback.

  • conformer_n_jobs (int) – Parallel jobs for Conformer fallback.

  • opt_max_iters (int) – Maximum optimizer iterations.

Returns:

Path to the written PDB file.

Return type:

pathlib.Path

Raises:

ValueError – If mol is None.

pdb2mol(pdb_path, sanitize=True, removeHs=False)#

Load a molecule from a PDB file.

Parameters:
  • pdb_path (str | pathlib.Path) – Path to a PDB file.

  • sanitize (bool) – Whether to sanitize the molecule during parsing.

  • removeHs (bool) – If True, remove explicit hydrogens from the returned Mol.

Returns:

RDKit Mol or None if reading fails.

Return type:

Optional[rdkit.Chem.rdchem.Mol]

pdb2smiles(pdb_path, sanitize=True, removeHs=True)#

Load a PDB file and return a SMILES string.

Parameters:
  • pdb_path (str | pathlib.Path) – Path to the PDB file.

  • sanitize (bool) – Whether to sanitize the molecule during parsing.

  • removeHs (bool) – If True remove explicit hydrogens prior to SMILES generation.

Returns:

SMILES string for the first molecule in the PDB.

Return type:

str

Raises:

ValueError – If the PDB cannot be parsed into a molecule.

smiles2pdb(
smiles,
out_path,
add_hs=False,
embed3d=True,
optimize=True,
embed_algorithm='ETKDGv3',
opt_method='MMFF94',
conformer_seed=42,
conformer_n_jobs=1,
opt_max_iters=200,
)#

Convert a SMILES string to a PDB file, using Conformer when embedding/optimization is requested and available.

Parameters:
  • smiles (str) – Input SMILES string.

  • out_path (str | pathlib.Path) – Destination PDB file path.

  • add_hs (bool) – Whether to add explicit hydrogens prior to embedding.

  • embed3d (bool) – Whether to embed 3D coordinates when missing.

  • optimize (bool) – Whether to optimize geometry after embedding.

  • embed_algorithm (Optional[str]) – Embedding algorithm name (e.g., “ETKDGv3”) or None.

  • opt_method (Optional[str]) – Optimization method preference (e.g., “MMFF94”).

  • conformer_seed (int) – RNG seed for Conformer fallback.

  • conformer_n_jobs (int) – Number of parallel jobs for Conformer fallback.

  • opt_max_iters (int) – Maximum optimizer iterations.

Returns:

Path to the written PDB file.

Return type:

pathlib.Path

Raises:

ValueError – If smiles is empty.

mol_from_smiles_write_all_formats(
smiles,
out_prefix,
write_sdf=True,
write_pdb=True,
embed3d=True,
add_hs=True,
embed_algorithm='ETKDGv3',
opt_method='MMFF94',
)#

Convenience helper: from SMILES write SDF and/or PDB files sharing the same prefix.

This function uses Conformer for embedding/optimization when available, otherwise falls back to RDKit.

Parameters:
  • smiles (str) – Input SMILES string.

  • out_prefix (str | pathlib.Path) – Output path prefix (the function appends .sdf and/or .pdb).

  • write_sdf (bool) – If True produce an SDF file.

  • write_pdb (bool) – If True produce a PDB file.

  • embed3d (bool) – Whether to embed 3D coordinates for outputs that require them.

  • add_hs (bool) – Whether to add hydrogens for embedding/optimization.

  • embed_algorithm (Optional[str]) – Embedding algorithm name (e.g., “ETKDGv3”) or None.

  • opt_method (Optional[str]) – Preferred optimization method (e.g., “MMFF94”).

Returns:

Dictionary mapping format keys (“sdf”,”pdb”) to written pathlib.Path objects.

Return type:

dict[str, pathlib.Path]

is_valid_smiles(smiles)#

Quick check whether a SMILES string can be parsed by RDKit.

Parameters:

smiles (str) – SMILES string to validate.

Returns:

True if RDKit can parse the SMILES; False otherwise.

Return type:

bool

prodock.io.utils#

General utility helpers that do not belong to a chemistry-specific conversion module. The current utility surface focuses on runtime environment cleanup for PyMOL-based workflows.

shutdown_pymol(remove_modules=True, quiet=True)#

Try to shut down any already-imported / running PyMOL instance and optionally remove pymol-related modules from sys.modules so a fresh import (or fake module injection) is possible.

This is best-effort: it will swallow errors and report them in the returned dict.

Args:
remove_modules: if True, delete any sys.modules entries that equal

“pymol” or start with “pymol.” after shutdown attempts.

quiet: if False, print a short summary; default True.

Returns:
A dict with keys:
  • imported: bool, whether an import of “pymol” succeeded initially

  • actions: dict mapping attempted action -> (success: bool, message:str)

  • clean: bool, whether no “pymol” entries remain in sys.modules

Parameters:
Return type:

Dict[str, Any]

prodock.io.logging#

The logging package provides a compact but flexible structured logging layer for scripts, notebooks, and automation runs. It includes a logger manager, structured adapters, console and JSON formatters, step decorators, and elapsed time measurement helpers.

Public API for prodock.io.logging package.

Export a compact and convenient surface for consumers.

class LoggerManager(
log_dir='logs',
log_file='prodock.log',
max_bytes=10 * 1024 * 1024,
backup_count=5,
level=logging.INFO,
colored=True,
json=False,
)#

Bases: object

Manager for configuring project-wide logging.

Parameters:
  • log_dir (Optional[Union[str, Path]]) – directory to put rotating log files. If None, no file handler.

  • log_file (str) – filename for log file.

  • max_bytes (int) – rotate file after this size (bytes).

  • backup_count (int) – number of rotated files to keep.

  • level (Union[str, int]) – root logging level (int or name).

  • colored (bool) – enable colored console output (ANSI; no external deps).

  • json (bool) – if True, use JSONFormatter for file (and optional console).

setup()#

Configure the root logger and handlers. Safe to call multiple times. :return: self

Return type:

LoggerManager

property configured: bool#
Returns:

True if logging has been configured by this manager.

property level_name: str#
Returns:

canonical level name (e.g., ‘DEBUG’, ‘INFO’).

get_logger(name)#

Retrieve a logger instance. Ensures manager is setup.

Parameters:

name (str) – logger name

Returns:

logger

Return type:

Logger

setup_logging(**kwargs)#

Convenience entry to configure logging.

Accepts the same kwargs as LoggerManager.__init__. Returns the configured LoggerManager.

Return type:

LoggerManager

get_logger(name)#

Get a logger via the default manager.

Parameters:

name (str) – logger name

Returns:

logging.Logger

Return type:

Logger

class StructuredAdapter(logger, extra=None)#

Bases: LoggerAdapter

LoggerAdapter that merges adapter-level context with per-call ‘extra’ dicts.

Parameters:
  • logger – base logger

  • extra – persistent context dict (e.g., {‘run_id’: ‘r1’, ‘pdb_id’: ‘5N2F’})

process(msg, kwargs)#

Process the logging message and keyword arguments passed in to a logging call to insert contextual information. You can either manipulate the message itself, the keyword args or both. Return the message and kwargs modified (or not) to suit your needs.

Normally, you’ll only need to override this one method in a LoggerAdapter subclass for your specific needs.

Parameters:
class Timer(label=None, logger=None)#

Bases: ContextDecorator

Measure elapsed time and optionally log a debug entry on exit.

Usage: >>> with Timer(“conformers”, logger=get_logger(“ProDock”)): >>> do_work()

Or as decorator: >>> @Timer(“step”) >>> def f(…): …

Parameters:
log_step(step_name=None)#

Decorator for pipeline methods representing a processing step.

Logs:
  • step.start (INFO)

  • step.finish (INFO) with elapsed and optional summary

  • step.error (exception logged) if exception occurs

Works for both sync and async methods.

Parameters:

step_name (str | None) – optional explicit step name (default: function name)

class SimpleColorFormatter(
fmt='%(asctime)s | %(levelname)-8s | %(name)s | %(message)s',
datefmt='%Y-%m-%d %H:%M:%S',
force_color=None,
)#

Bases: Formatter

Formatter that injects ANSI color codes into levelname when supported.

Parameters:
  • fmt (str) – format string

  • datefmt (Optional[str]) – date format string

  • force_color (Optional[bool]) – if True, force color on even when not TTY (uses FORCE_COLOR env too)

format(record)#

Format the specified record as text.

The record’s attribute dictionary is used as the operand to a string formatting operation which yields the returned string. Before formatting the dictionary, a couple of preparatory steps are carried out. The message attribute of the record is computed using LogRecord.getMessage(). If the formatting string uses the time (as determined by a call to usesTime(), formatTime() is called to format the event time. If there is exception information, it is formatted using formatException() and appended to the message.

Parameters:

record (LogRecord)

Return type:

str

class JSONFormatter(fmt=None, datefmt=None, style='%', validate=True, *, defaults=None)#

Bases: Formatter

Minimal one-line JSON formatter for logs suitable for ingestion.

The JSON contains: ts, level, logger, message and any extra fields.

format(record)#

Format the specified record as text.

The record’s attribute dictionary is used as the operand to a string formatting operation which yields the returned string. Before formatting the dictionary, a couple of preparatory steps are carried out. The message attribute of the record is computed using LogRecord.getMessage(). If the formatting string uses the time (as determined by a call to usesTime(), formatTime() is called to format the event time. If there is exception information, it is formatted using formatException() and appended to the message.

Parameters:

record (LogRecord)

Return type:

str

prodock.io.logging.manager#

LoggerManager and convenience helpers (setup_logging, get_logger).

class LoggerManager(
log_dir='logs',
log_file='prodock.log',
max_bytes=10 * 1024 * 1024,
backup_count=5,
level=logging.INFO,
colored=True,
json=False,
)#

Bases: object

Manager for configuring project-wide logging.

Parameters:
  • log_dir (Optional[Union[str, Path]]) – directory to put rotating log files. If None, no file handler.

  • log_file (str) – filename for log file.

  • max_bytes (int) – rotate file after this size (bytes).

  • backup_count (int) – number of rotated files to keep.

  • level (Union[str, int]) – root logging level (int or name).

  • colored (bool) – enable colored console output (ANSI; no external deps).

  • json (bool) – if True, use JSONFormatter for file (and optional console).

setup()#

Configure the root logger and handlers. Safe to call multiple times. :return: self

Return type:

LoggerManager

property configured: bool#
Returns:

True if logging has been configured by this manager.

property level_name: str#
Returns:

canonical level name (e.g., ‘DEBUG’, ‘INFO’).

get_logger(name)#

Retrieve a logger instance. Ensures manager is setup.

Parameters:

name (str) – logger name

Returns:

logger

Return type:

Logger

setup_logging(**kwargs)#

Convenience entry to configure logging.

Accepts the same kwargs as LoggerManager.__init__. Returns the configured LoggerManager.

Return type:

LoggerManager

get_logger(name)#

Get a logger via the default manager.

Parameters:

name (str) – logger name

Returns:

logging.Logger

Return type:

Logger

prodock.io.logging.decorators#

log_step decorator (sync + async) and helper summary discovery.

log_step(step_name=None)#

Decorator for pipeline methods representing a processing step.

Logs:
  • step.start (INFO)

  • step.finish (INFO) with elapsed and optional summary

  • step.error (exception logged) if exception occurs

Works for both sync and async methods.

Parameters:

step_name (str | None) – optional explicit step name (default: function name)

prodock.io.logging.formatters#

Log formatters: colored simple formatter and JSON formatter.

class SimpleColorFormatter(
fmt='%(asctime)s | %(levelname)-8s | %(name)s | %(message)s',
datefmt='%Y-%m-%d %H:%M:%S',
force_color=None,
)#

Bases: Formatter

Formatter that injects ANSI color codes into levelname when supported.

Parameters:
  • fmt (str) – format string

  • datefmt (Optional[str]) – date format string

  • force_color (Optional[bool]) – if True, force color on even when not TTY (uses FORCE_COLOR env too)

format(record)#

Format the specified record as text.

The record’s attribute dictionary is used as the operand to a string formatting operation which yields the returned string. Before formatting the dictionary, a couple of preparatory steps are carried out. The message attribute of the record is computed using LogRecord.getMessage(). If the formatting string uses the time (as determined by a call to usesTime(), formatTime() is called to format the event time. If there is exception information, it is formatted using formatException() and appended to the message.

Parameters:

record (LogRecord)

Return type:

str

class JSONFormatter(fmt=None, datefmt=None, style='%', validate=True, *, defaults=None)#

Bases: Formatter

Minimal one-line JSON formatter for logs suitable for ingestion.

The JSON contains: ts, level, logger, message and any extra fields.

format(record)#

Format the specified record as text.

The record’s attribute dictionary is used as the operand to a string formatting operation which yields the returned string. Before formatting the dictionary, a couple of preparatory steps are carried out. The message attribute of the record is computed using LogRecord.getMessage(). If the formatting string uses the time (as determined by a call to usesTime(), formatTime() is called to format the event time. If there is exception information, it is formatted using formatException() and appended to the message.

Parameters:

record (LogRecord)

Return type:

str

prodock.io.logging.timing#

Timer context/decorator for logging elapsed times.

class Timer(label=None, logger=None)#

Bases: ContextDecorator

Measure elapsed time and optionally log a debug entry on exit.

Usage: >>> with Timer(“conformers”, logger=get_logger(“ProDock”)): >>> do_work()

Or as decorator: >>> @Timer(“step”) >>> def f(…): …

Parameters:

prodock.io.logging.compat_logging#

Compatibility shim for older imports that used a single-file logging module.

This module re-exports the public API from the refactored package while emitting a DeprecationWarning so callers know to update their imports to prodock.io.logging.

class LoggerManager(
log_dir='logs',
log_file='prodock.log',
max_bytes=10 * 1024 * 1024,
backup_count=5,
level=logging.INFO,
colored=True,
json=False,
)#

Bases: object

Manager for configuring project-wide logging.

Parameters:
  • log_dir (Optional[Union[str, Path]]) – directory to put rotating log files. If None, no file handler.

  • log_file (str) – filename for log file.

  • max_bytes (int) – rotate file after this size (bytes).

  • backup_count (int) – number of rotated files to keep.

  • level (Union[str, int]) – root logging level (int or name).

  • colored (bool) – enable colored console output (ANSI; no external deps).

  • json (bool) – if True, use JSONFormatter for file (and optional console).

setup()#

Configure the root logger and handlers. Safe to call multiple times. :return: self

Return type:

LoggerManager

property configured: bool#
Returns:

True if logging has been configured by this manager.

property level_name: str#
Returns:

canonical level name (e.g., ‘DEBUG’, ‘INFO’).

get_logger(name)#

Retrieve a logger instance. Ensures manager is setup.

Parameters:

name (str) – logger name

Returns:

logger

Return type:

Logger

setup_logging(**kwargs)#

Convenience entry to configure logging.

Accepts the same kwargs as LoggerManager.__init__. Returns the configured LoggerManager.

Return type:

LoggerManager

get_logger(name)#

Get a logger via the default manager.

Parameters:

name (str) – logger name

Returns:

logging.Logger

Return type:

Logger

class StructuredAdapter(logger, extra=None)#

Bases: LoggerAdapter

LoggerAdapter that merges adapter-level context with per-call ‘extra’ dicts.

Parameters:
  • logger – base logger

  • extra – persistent context dict (e.g., {‘run_id’: ‘r1’, ‘pdb_id’: ‘5N2F’})

process(msg, kwargs)#

Process the logging message and keyword arguments passed in to a logging call to insert contextual information. You can either manipulate the message itself, the keyword args or both. Return the message and kwargs modified (or not) to suit your needs.

Normally, you’ll only need to override this one method in a LoggerAdapter subclass for your specific needs.

Parameters:
class Timer(label=None, logger=None)#

Bases: ContextDecorator

Measure elapsed time and optionally log a debug entry on exit.

Usage: >>> with Timer(“conformers”, logger=get_logger(“ProDock”)): >>> do_work()

Or as decorator: >>> @Timer(“step”) >>> def f(…): …

Parameters:
log_step(step_name=None)#

Decorator for pipeline methods representing a processing step.

Logs:
  • step.start (INFO)

  • step.finish (INFO) with elapsed and optional summary

  • step.error (exception logged) if exception occurs

Works for both sync and async methods.

Parameters:

step_name (str | None) – optional explicit step name (default: function name)

class SimpleColorFormatter(
fmt='%(asctime)s | %(levelname)-8s | %(name)s | %(message)s',
datefmt='%Y-%m-%d %H:%M:%S',
force_color=None,
)#

Bases: Formatter

Formatter that injects ANSI color codes into levelname when supported.

Parameters:
  • fmt (str) – format string

  • datefmt (Optional[str]) – date format string

  • force_color (Optional[bool]) – if True, force color on even when not TTY (uses FORCE_COLOR env too)

format(record)#

Format the specified record as text.

The record’s attribute dictionary is used as the operand to a string formatting operation which yields the returned string. Before formatting the dictionary, a couple of preparatory steps are carried out. The message attribute of the record is computed using LogRecord.getMessage(). If the formatting string uses the time (as determined by a call to usesTime(), formatTime() is called to format the event time. If there is exception information, it is formatted using formatException() and appended to the message.

Parameters:

record (LogRecord)

Return type:

str

class JSONFormatter(fmt=None, datefmt=None, style='%', validate=True, *, defaults=None)#

Bases: Formatter

Minimal one-line JSON formatter for logs suitable for ingestion.

The JSON contains: ts, level, logger, message and any extra fields.

format(record)#

Format the specified record as text.

The record’s attribute dictionary is used as the operand to a string formatting operation which yields the returned string. Before formatting the dictionary, a couple of preparatory steps are carried out. The message attribute of the record is computed using LogRecord.getMessage(). If the formatting string uses the time (as determined by a call to usesTime(), formatTime() is called to format the event time. If there is exception information, it is formatted using formatException() and appended to the message.

Parameters:

record (LogRecord)

Return type:

str