setup.py (95 lines of code) (raw):

import json import os import platform import shutil import sys from pathlib import Path from setuptools import find_packages, setup from setuptools.command.build_py import build_py MODEL_SOURCE_DIR = "orbit/stan" MODELS = ["dlt", "ets", "lgt", "ktrlite"] DESCRIPTION = "Orbit is a package for Bayesian time series modeling and inference." BINARIES = ["diagnose", "print", "stanc", "stansummary"] with open("orbit/config.json") as f: config = json.load(f) CMDSTAN_VERSION = config["CMDSTAN_VERSION"] IS_WINDOWS = platform.platform().startswith("Win") def read_long_description(filename="README.md"): # with open(filename) as f: with open("README.md", "r", encoding="utf-8") as f: return f.read().strip() def requirements(filename="requirements.txt"): with open(filename) as f: return f.readlines() def remove_older_cmdstan(cmdstan_version): """ Checks the default CmdStan path (~/.cmdstan) for folders with older versions and removes them. Args: cmdstan_version (str): The current CmdStan version. """ default_path = os.path.expanduser("~/.cmdstan") if not os.path.exists(default_path): # Path doesn't exist, nothing to remove return for folder in os.listdir(default_path): if folder.startswith("cmdstan-"): # Extract version number from folder name folder_version = folder.split("-")[1] if folder_version < cmdstan_version: # Remove folder if version is older full_path = os.path.join(default_path, folder) try: print(f"Removing older CmdStan version: {folder} : {full_path}") shutil.rmtree(full_path) print(f"Done.") except OSError as e: print(f"Error removing {folder}: {e}") def install_stan(): """ Compile and install stan backend Reference from prophet """ from multiprocessing import cpu_count import cmdstanpy remove_older_cmdstan(CMDSTAN_VERSION) if not cmdstanpy.install_cmdstan( version=CMDSTAN_VERSION, overwrite=True, verbose=True, cores=cpu_count(), progress=True, compiler=IS_WINDOWS, ): raise RuntimeError("CmdStan failed to install in repackaged directory") print("Installed cmdstanpy package.") def build_model(model: str, model_dir: str): import cmdstanpy # compile stan file in place model_name = f"{model}.stan" model_path = os.path.join(model_dir, model_name) print(f"Compiling stan file in place: {model_path}") _ = cmdstanpy.CmdStanModel(stan_file=model_path, force_compile=True) def build_stan_models(): if "conda" not in sys.prefix.lower(): for model in MODELS: build_model( model=model, model_dir=MODEL_SOURCE_DIR, ) else: print("Conda env is detected in the package path. Skip compilation.") class BuildPyCommand(build_py): """Custom build command to make sure install cmdstanpy properly.""" def run(self): print("Running build py command.") if not self.dry_run: print("Not a dry run, run with build") # install cmdstan and compilers, in the default directory for simplicity install_stan() # build all stan models build_stan_models() build_py.run(self) about = {} here = Path(__file__).parent.resolve() with open(here / "orbit" / "__version__.py", "r") as f: exec(f.read(), about) setup( version=about["__version__"], packages=find_packages(), name="orbit-ml", description=DESCRIPTION, include_package_data=True, install_requires=requirements("requirements.txt"), tests_require=requirements("requirements-test.txt"), cmdclass={ "build_py": BuildPyCommand, }, test_suite="orbit.tests", long_description=read_long_description(), long_description_content_type="text/markdown", url="https://orbit-ml.readthedocs.io/en/stable/", zip_safe=False, )