mirror of
https://github.com/weewx/weewx.git
synced 2026-04-18 16:46:56 -04:00
302 lines
11 KiB
Python
Executable File
302 lines
11 KiB
Python
Executable File
#!/usr/bin/env python
|
|
#
|
|
# weewx --- A simple, high-performance weather station server
|
|
#
|
|
# Copyright (c) 2009-2020 Tom Keffer <tkeffer@gmail.com>
|
|
#
|
|
# See the file LICENSE.txt for your full rights.
|
|
#
|
|
"""Customized setup file for weewx.
|
|
|
|
For more debug information, set the environment variable DISTUTILS_DEBUG
|
|
before running.
|
|
|
|
"""
|
|
|
|
from __future__ import absolute_import
|
|
from __future__ import print_function
|
|
from __future__ import with_statement
|
|
|
|
import distutils.dir_util
|
|
import distutils.file_util
|
|
import fnmatch
|
|
import os.path
|
|
import shutil
|
|
import sys
|
|
from distutils.command.install_data import install_data
|
|
from distutils.command.install_lib import install_lib
|
|
from setuptools import setup, find_packages
|
|
from setuptools.command.install import install
|
|
|
|
if sys.version_info < (2, 7):
|
|
print('WeeWX requires Python V2.7 or greater.')
|
|
print('For earlier versions of Python, use WeeWX V3.9.')
|
|
sys.exit("Python version unsupported.")
|
|
|
|
# Find the install lib subdirectory:
|
|
this_file = os.path.join(os.getcwd(), __file__)
|
|
this_dir = os.path.abspath(os.path.dirname(this_file))
|
|
lib_dir = os.path.abspath(os.path.join(this_dir, 'bin'))
|
|
|
|
# Now that we've found where the libraries are, inject it into the path:
|
|
sys.path.insert(0, lib_dir)
|
|
|
|
# Now we can get the weewx version
|
|
import weewx
|
|
|
|
VERSION = weewx.__version__
|
|
|
|
|
|
# ==============================================================================
|
|
# install
|
|
# ==============================================================================
|
|
|
|
class weewx_install(install):
|
|
"""Specialized version of install, which runs a post-install script"""
|
|
|
|
def run(self):
|
|
"""Specialized version of run, which runs post-install commands"""
|
|
|
|
# First run the install.
|
|
rv = install.run(self)
|
|
|
|
# Now the post-install
|
|
update_and_install_config(self.install_data)
|
|
|
|
return rv
|
|
|
|
|
|
# ==============================================================================
|
|
# install_lib
|
|
# ==============================================================================
|
|
|
|
class weewx_install_lib(install_lib):
|
|
"""Specialized version of install_lib, which saves the user subdirectory."""
|
|
|
|
def run(self):
|
|
# Location of the user subdirectory, if it exists.
|
|
user_dir = os.path.join(self.install_dir, 'user')
|
|
if os.path.exists(user_dir):
|
|
# It exists. Save it under a timestamp
|
|
user_savedir = move_with_timestamp(user_dir)
|
|
else:
|
|
user_savedir = None
|
|
|
|
# Run the superclass's version. This will install all incoming files, including
|
|
# a new user subdirectory
|
|
rv = install_lib.run(self)
|
|
|
|
# If we set aside an old user subdirectory, restore it
|
|
if user_savedir:
|
|
# Remove the user directory we just installed...
|
|
distutils.dir_util.remove_tree(user_dir)
|
|
# ... then move the saved version back:
|
|
shutil.move(user_savedir, user_dir)
|
|
try:
|
|
# The file schemas.py is no longer used, and can interfere with schema
|
|
# imports. See issue #54.
|
|
os.rename(os.path.join(user_dir, 'schemas.py'),
|
|
os.path.join(user_dir, 'schemas.py.old'))
|
|
except OSError:
|
|
pass
|
|
try:
|
|
os.remove(os.path.join(user_dir, 'schemas.pyc'))
|
|
except OSError:
|
|
pass
|
|
|
|
return rv
|
|
|
|
|
|
# ==============================================================================
|
|
# install_data
|
|
# ==============================================================================
|
|
|
|
class weewx_install_data(install_data):
|
|
"""Specialized version of install_data."""
|
|
|
|
def run(self):
|
|
# If there is a skins directory already, just install what the user doesn't already have.
|
|
if os.path.exists(os.path.join(self.install_dir, 'skins')):
|
|
# A skins directory already exists. Build a list of skins that are missing and should
|
|
# be added to it.
|
|
install_files = []
|
|
for skin_name in ['Ftp', 'Mobile', 'Rsync', 'Seasons', 'Smartphone', 'Standard']:
|
|
rel_name = 'skins/' + skin_name
|
|
if not os.path.exists(os.path.join(self.install_dir, rel_name)):
|
|
# The skin has not already been installed. Include it.
|
|
install_files += [dat for dat in self.data_files if
|
|
dat[0].startswith(rel_name)]
|
|
# Exclude all the skins files...
|
|
other_files = [dat for dat in self.data_files if not dat[0].startswith('skins')]
|
|
# ... then add the needed skins back in
|
|
self.data_files = other_files + install_files
|
|
|
|
# Run the superclass's run():
|
|
return install_data.run(self)
|
|
|
|
def copy_file(self, f, install_dir, **kwargs):
|
|
# If this is the configuration file, then process it separately
|
|
if f == 'weewx.conf':
|
|
rv = self.process_config_file(f, install_dir, **kwargs)
|
|
else:
|
|
rv = install_data.copy_file(self, f, install_dir, **kwargs)
|
|
return rv
|
|
|
|
def process_config_file(self, f, install_dir, **kwargs):
|
|
"""Process weewx.conf separately"""
|
|
|
|
# Location of the incoming weewx.conf file
|
|
install_path = os.path.join(install_dir, os.path.basename(f))
|
|
|
|
if self.dry_run:
|
|
rv = None
|
|
else:
|
|
# Install the config file using the template name. Later, we will merge
|
|
# it with any old config file.
|
|
template_name = install_path + "." + VERSION
|
|
rv = install_data.copy_file(self, f, template_name, **kwargs)
|
|
shutil.copymode(f, template_name)
|
|
|
|
return rv
|
|
|
|
|
|
# ==============================================================================
|
|
# utilities
|
|
# ==============================================================================
|
|
def find_files(directory, file_excludes=['*.pyc'], dir_excludes=['*/__pycache__']):
|
|
"""Find all files under a directory, honoring some exclusions.
|
|
|
|
Returns:
|
|
A list of two-way tuples (directory_path, file_list), where file_list is a list
|
|
of relative file paths.
|
|
"""
|
|
# First recursively create a list of all the directories
|
|
dir_list = []
|
|
for dirpath, _, _ in os.walk(directory):
|
|
# Make sure the directory name doesn't match the excluded pattern
|
|
if not any(fnmatch.fnmatch(dirpath, d) for d in dir_excludes):
|
|
dir_list.append(dirpath)
|
|
|
|
data_files = []
|
|
# Now search each directory for all files
|
|
for d_path in dir_list:
|
|
file_list = []
|
|
# Find all the files in this directory
|
|
for fn in os.listdir(d_path):
|
|
filepath = os.path.join(d_path, fn)
|
|
# Make sure it's a file, and that it's name doesn't match the excluded pattern
|
|
if os.path.isfile(filepath) \
|
|
and not any(fnmatch.fnmatch(filepath, f) for f in file_excludes):
|
|
file_list.append(filepath)
|
|
# Add the directory and the list of files in it, to the list of all files.
|
|
data_files.append((d_path, file_list))
|
|
return data_files
|
|
|
|
|
|
def move_with_timestamp(filepath):
|
|
"""Save a file to a path with a timestamp."""
|
|
import shutil
|
|
import time
|
|
# Sometimes the target has a trailing '/'. This will take care of it:
|
|
filepath = os.path.normpath(filepath)
|
|
newpath = filepath + time.strftime(".%Y%m%d%H%M%S")
|
|
# Check to see if this name already exists
|
|
if os.path.exists(newpath):
|
|
# It already exists. Stick a version number on it:
|
|
version = 1
|
|
while os.path.exists(newpath + '-' + str(version)):
|
|
version += 1
|
|
newpath = newpath + '-' + str(version)
|
|
shutil.move(filepath, newpath)
|
|
return newpath
|
|
|
|
|
|
def update_and_install_config(install_dir, config_name='weewx.conf'):
|
|
import subprocess
|
|
|
|
dist_config = os.path.join(install_dir, config_name + '.' + VERSION)
|
|
wee_config_path = os.path.join(install_dir, 'bin/wee_config')
|
|
print("path to wee_config=%s" % wee_config_path)
|
|
|
|
# proc = subprocess.Popen([wee_config_path,
|
|
# '--install',
|
|
# '--dist-config=%s' % dist_config,
|
|
# '--output=%s' % dist_config,
|
|
# ], stdout=subprocess.PIPE,
|
|
# stderr=subprocess.PIPE)
|
|
# out, err = proc.communicate()
|
|
# print('out=', out.decode())
|
|
# print('err=', err.decode())
|
|
|
|
|
|
# ==============================================================================
|
|
# main entry point
|
|
# ==============================================================================
|
|
|
|
if __name__ == "__main__":
|
|
# Use the README.md for the long description:
|
|
with open(os.path.join(this_dir, "README.md"), "r") as fd:
|
|
long_description = fd.read()
|
|
|
|
setup(name='weewx',
|
|
version=VERSION,
|
|
description='The WeeWX weather software system',
|
|
long_description=long_description,
|
|
long_description_content_type="text/markdown",
|
|
author='Tom Keffer',
|
|
author_email='tkeffer@gmail.com',
|
|
url='http://www.weewx.com',
|
|
license='GPLv3',
|
|
classifiers=[
|
|
'Development Status :: 5 - Production/Stable',
|
|
'Intended Audience :: End Users/Desktop',
|
|
'Intended Audience :: Science/Research',
|
|
'License :: OSI Approved :: GNU General Public License v3 (GPLv3)',
|
|
'Operating System :: POSIX :: Linux',
|
|
'Operating System :: Unix',
|
|
'Programming Language :: Python',
|
|
'Programming Language :: Python :: 2.7',
|
|
'Programming Language :: Python :: 3.5',
|
|
'Programming Language :: Python :: 3.6',
|
|
'Programming Language :: Python :: 3.7',
|
|
'Programming Language :: Python :: 3.8',
|
|
'Topic :: Scientific/Engineering :: Physics'
|
|
],
|
|
platforms=['any'],
|
|
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4',
|
|
install_requires=[
|
|
'configobj>=4.7',
|
|
'pillow>=6.2',
|
|
'pyephem>=3.7',
|
|
'pyserial>=3.4',
|
|
'pyusb>=1.0.2',
|
|
'six>=1'
|
|
],
|
|
extras_require={':python_version == "2.7"': ['cheetah>=2.4'],
|
|
':python_version >= "3.5"': ['cheetah3>=3.2,<4.0']},
|
|
py_modules=['daemon', 'six'],
|
|
package_dir={'': 'bin'},
|
|
packages=find_packages('bin'),
|
|
scripts=[
|
|
'bin/wee_config',
|
|
'bin/wee_database',
|
|
'bin/wee_debug',
|
|
'bin/wee_device',
|
|
'bin/wee_extension',
|
|
'bin/wee_import',
|
|
'bin/wee_reports',
|
|
'bin/weewxd',
|
|
'bin/wunderfixer'
|
|
],
|
|
data_files=[('', ['LICENSE.txt', 'README.md', 'weewx.conf']), ]
|
|
+ find_files('docs')
|
|
+ find_files('examples')
|
|
+ find_files('skins')
|
|
+ find_files('util'),
|
|
cmdclass={
|
|
"install": weewx_install,
|
|
"install_data": weewx_install_data,
|
|
"install_lib": weewx_install_lib,
|
|
},
|
|
)
|