setup.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. import os.path
  2. import pickle
  3. import platform
  4. import sys
  5. from pkg_resources import (
  6. normalize_path,
  7. working_set,
  8. add_activation_listener,
  9. require,
  10. )
  11. from setuptools import setup
  12. from setuptools.command.build_py import build_py
  13. from setuptools.command.develop import develop
  14. from setuptools.command.test import test as test_command
  15. PLATFORM = 'unix'
  16. if platform.platform().startswith('Win'):
  17. PLATFORM = 'win'
  18. SETUP_DIR = os.path.dirname(os.path.abspath(__file__))
  19. MODEL_DIR = os.path.join(SETUP_DIR, 'stan', PLATFORM)
  20. MODEL_TARGET_DIR = os.path.join('fbprophet', 'stan_model')
  21. def build_stan_model(target_dir, model_dir=MODEL_DIR):
  22. from pystan import StanModel
  23. model_name = 'prophet.stan'
  24. target_name = 'prophet_model.pkl'
  25. with open(os.path.join(model_dir, model_name)) as f:
  26. model_code = f.read()
  27. sm = StanModel(model_code=model_code)
  28. with open(os.path.join(target_dir, target_name), 'wb') as f:
  29. pickle.dump(sm, f, protocol=pickle.HIGHEST_PROTOCOL)
  30. class BuildPyCommand(build_py):
  31. """Custom build command to pre-compile Stan models."""
  32. def run(self):
  33. if not self.dry_run:
  34. target_dir = os.path.join(self.build_lib, MODEL_TARGET_DIR)
  35. self.mkpath(target_dir)
  36. build_stan_model(target_dir)
  37. build_py.run(self)
  38. class DevelopCommand(develop):
  39. """Custom develop command to pre-compile Stan models in-place."""
  40. def run(self):
  41. if not self.dry_run:
  42. target_dir = os.path.join(self.setup_path, MODEL_TARGET_DIR)
  43. self.mkpath(target_dir)
  44. build_stan_model(target_dir)
  45. develop.run(self)
  46. class TestCommand(test_command):
  47. """We must run tests on the build directory, not source."""
  48. def with_project_on_sys_path(self, func):
  49. # Ensure metadata is up-to-date
  50. self.reinitialize_command('build_py', inplace=0)
  51. self.run_command('build_py')
  52. bpy_cmd = self.get_finalized_command("build_py")
  53. build_path = normalize_path(bpy_cmd.build_lib)
  54. # Build extensions
  55. self.reinitialize_command('egg_info', egg_base=build_path)
  56. self.run_command('egg_info')
  57. self.reinitialize_command('build_ext', inplace=0)
  58. self.run_command('build_ext')
  59. ei_cmd = self.get_finalized_command("egg_info")
  60. old_path = sys.path[:]
  61. old_modules = sys.modules.copy()
  62. try:
  63. sys.path.insert(0, normalize_path(ei_cmd.egg_base))
  64. working_set.__init__()
  65. add_activation_listener(lambda dist: dist.activate())
  66. require('%s==%s' % (ei_cmd.egg_name, ei_cmd.egg_version))
  67. func()
  68. finally:
  69. sys.path[:] = old_path
  70. sys.modules.clear()
  71. sys.modules.update(old_modules)
  72. working_set.__init__()
  73. with open('requirements.txt', 'r') as f:
  74. install_requires = f.read().splitlines()
  75. setup(
  76. name='fbprophet',
  77. version='0.3',
  78. description='Automatic Forecasting Procedure',
  79. url='https://facebook.github.io/prophet/',
  80. author='Sean J. Taylor <sjt@fb.com>, Ben Letham <bletham@fb.com>',
  81. author_email='sjt@fb.com',
  82. license='BSD',
  83. packages=['fbprophet', 'fbprophet.tests'],
  84. setup_requires=[
  85. ],
  86. install_requires=install_requires,
  87. zip_safe=False,
  88. include_package_data=True,
  89. # For Python 3, Will enforce that tests are run after a build.
  90. use_2to3=True,
  91. cmdclass={
  92. 'build_py': BuildPyCommand,
  93. 'develop': DevelopCommand,
  94. 'test': TestCommand,
  95. },
  96. test_suite='fbprophet.tests',
  97. long_description="""
  98. Implements a procedure for forecasting time series data based on an additive model where non-linear trends are fit with yearly, weekly, and daily seasonality, plus holiday effects. It works best with time series that have strong seasonal effects and several seasons of historical data. Prophet is robust to missing data and shifts in the trend, and typically handles outliers well.
  99. """
  100. )