Source code for pharmpy.source

"""
=============================
Generic Sources/Resources I/O
=============================

Source code/resource manager for a :class:`~pharmpy.generic.Model` class implementation.

Noteworthy
----------

Module is target for *all* generalizable and non-agnostic code that concerns:

    1. Reading *in* streams/file-like resources.
    2. Formatting/generating source code from current state of :class:`~pharmpy.generic.Model`.
    3. Writing *out* source code to streams/file-like resources.
"""

import io
from pathlib import Path


[docs]def Source(obj): """Factory to create source object""" if isinstance(obj, str) or isinstance(obj, Path) or isinstance(obj, io.IOBase): src = FileSource(obj) return src
[docs]class SourceBase: """API to manage the original source object of a model. Is a model API attached to attribute :attr:`Model.source <pharmpy.generic.Model.source>`. The source format can be a text file, but it could also be any kind of object, i.e. an R object. """ def __init__(self, obj): self.obj = obj self.code = self.read(obj)
[docs] def write(self, path, force=False): """Write source to file.""" if not force and path.exists(): raise FileExistsError(f'Cannot overwrite model at {path} with "force" not set') with open(path, 'w', encoding='latin-1') as fp: fp.write(self.code) self.path = path
[docs]class FileSource(SourceBase): """Source formats for files property: filename_extension (includes the dot) """ def __init__(self, obj): if isinstance(obj, str) or isinstance(obj, Path): path = Path(obj) self.filename_extension = path.suffix else: self.filename_extension = '' super().__init__(obj)
[docs] def read(self, path_or_io): """Read source from io object or from str path or path object""" if isinstance(path_or_io, str) or isinstance(path_or_io, Path): self.path = Path(path_or_io) with open(path_or_io, 'r', encoding='latin-1') as fp: return fp.read() else: self.path = Path('.') return path_or_io.read()