mirror of
https://github.com/weewx/weewx.git
synced 2026-04-18 00:26:57 -04:00
675 lines
27 KiB
Python
Executable File
675 lines
27 KiB
Python
Executable File
#!/usr/bin/env python
|
|
#
|
|
# weewx --- A simple, high-performance weather station server
|
|
#
|
|
# Copyright (c) 2009-2019 Tom Keffer <tkeffer@gmail.com>
|
|
#
|
|
# See the file LICENSE.txt for your full rights.
|
|
#
|
|
"""Customized distutils setup file for weewx."""
|
|
|
|
from __future__ import with_statement
|
|
from __future__ import absolute_import
|
|
from __future__ import print_function
|
|
|
|
import os.path
|
|
import sys
|
|
import re
|
|
import tempfile
|
|
import shutil
|
|
|
|
import configobj
|
|
|
|
from distutils.core import setup
|
|
from distutils.command.install import install
|
|
from distutils.command.install_data import install_data
|
|
from distutils.command.install_lib import install_lib
|
|
from distutils.command.install_scripts import install_scripts
|
|
from distutils.command.sdist import sdist
|
|
import distutils.dir_util
|
|
|
|
# Useful for debugging setup.py. Set the environment variable
|
|
# DISTUTILS_DEBUG to get more debug info.
|
|
from distutils.debug import DEBUG
|
|
|
|
# Find the install bin subdirectory:
|
|
this_file = os.path.join(os.getcwd(), __file__)
|
|
this_dir = os.path.abspath(os.path.dirname(this_file))
|
|
bin_dir = os.path.abspath(os.path.join(this_dir, 'bin'))
|
|
|
|
# Now that we've found the bin subdirectory, inject it into the path:
|
|
sys.path.insert(0, bin_dir)
|
|
|
|
# Now we can import some weewx modules
|
|
import weewx
|
|
|
|
VERSION = weewx.__version__
|
|
import weecfg.extension
|
|
import weeutil.weeutil
|
|
from weecfg import Logger
|
|
|
|
logger = Logger(verbosity=1)
|
|
|
|
start_scripts = ['util/init.d/weewx.bsd',
|
|
'util/init.d/weewx.debian',
|
|
'util/init.d/weewx.lsb',
|
|
'util/init.d/weewx.redhat',
|
|
'util/init.d/weewx.suse']
|
|
|
|
# The default station information:
|
|
stn_info = {'station_type': 'Simulator',
|
|
'driver': 'weewx.drivers.simulator'}
|
|
|
|
|
|
# ==============================================================================
|
|
# install
|
|
# ==============================================================================
|
|
|
|
class weewx_install(install):
|
|
"""Specialized version of install, which adds a --no-prompt option to
|
|
the 'install' command."""
|
|
|
|
# Add an option for --no-prompt:
|
|
user_options = install.user_options + [('no-prompt', None, 'Do not prompt for station info')]
|
|
|
|
def initialize_options(self, *args, **kwargs):
|
|
install.initialize_options(self, *args, **kwargs)
|
|
self.no_prompt = None
|
|
|
|
def finalize_options(self):
|
|
install.finalize_options(self)
|
|
if self.no_prompt is None:
|
|
self.no_prompt = False
|
|
|
|
|
|
# ==============================================================================
|
|
# install_lib
|
|
# ==============================================================================
|
|
|
|
class weewx_install_lib(install_lib):
|
|
"""Specialized version of install_lib, which backs up old bin subdirectories."""
|
|
|
|
def run(self):
|
|
# Save any existing 'bin' subdirectory:
|
|
if os.path.exists(self.install_dir):
|
|
bin_savedir = weeutil.weeutil.move_with_timestamp(self.install_dir)
|
|
print("Saved bin subdirectory as %s" % bin_savedir)
|
|
else:
|
|
bin_savedir = None
|
|
|
|
# Run the superclass's version. This will install all incoming files.
|
|
install_lib.run(self)
|
|
|
|
# If the bin subdirectory previously existed, and if it included
|
|
# a 'user' subsubdirectory, then restore it
|
|
if bin_savedir:
|
|
user_backupdir = os.path.join(bin_savedir, 'user')
|
|
if os.path.exists(user_backupdir):
|
|
user_dir = os.path.join(self.install_dir, 'user')
|
|
distutils.dir_util.copy_tree(user_backupdir, 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
|
|
|
|
# ==============================================================================
|
|
# install_data
|
|
# ==============================================================================
|
|
|
|
class weewx_install_data(install_data):
|
|
"""Specialized version of install_data. Mostly, it deals with upgrading
|
|
and merging any old weewx.conf configuration files."""
|
|
|
|
def initialize_options(self):
|
|
# Initialize my superclass's options:
|
|
install_data.initialize_options(self)
|
|
# Set to None so we inherit whatever setting comes from weewx_install:
|
|
self.no_prompt = None
|
|
|
|
def finalize_options(self):
|
|
# Finalize my superclass's options:
|
|
install_data.finalize_options(self)
|
|
# This will set no_prompt to whatever is in weewx_install:
|
|
self.set_undefined_options('install', ('no_prompt', 'no_prompt'))
|
|
|
|
def copy_file(self, f, install_dir, **kwargs):
|
|
# If this is the configuration file, then merge it instead
|
|
# of copying it
|
|
if f == 'weewx.conf':
|
|
rv = self.process_config_file(f, install_dir, **kwargs)
|
|
elif f in start_scripts:
|
|
rv = self.massage_start_file(f, install_dir, **kwargs)
|
|
else:
|
|
rv = install_data.copy_file(self, f, install_dir, **kwargs)
|
|
return rv
|
|
|
|
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
|
|
|
|
remove_obsolete_files(self.install_dir)
|
|
|
|
# Run the superclass's run():
|
|
install_data.run(self)
|
|
|
|
def process_config_file(self, f, install_dir, **kwargs):
|
|
global stn_info
|
|
|
|
# Open up and parse the distribution config file:
|
|
try:
|
|
dist_config_dict = configobj.ConfigObj(f, interpolation=False, file_error=True, encoding='utf-8')
|
|
except IOError as e:
|
|
sys.exit(str(e))
|
|
except SyntaxError as e:
|
|
sys.exit("Syntax error in distribution configuration file '%s': %s"
|
|
% (f, e))
|
|
|
|
# The path where the weewx.conf configuration file will be installed
|
|
install_path = os.path.join(install_dir, os.path.basename(f))
|
|
|
|
# Do we have an old config file?
|
|
if os.path.isfile(install_path):
|
|
# Yes. Read it
|
|
config_path, config_dict = weecfg.read_config(install_path, None, interpolation=False)
|
|
if DEBUG:
|
|
print("Old configuration file found at", config_path)
|
|
|
|
# Update the old configuration file to the current version,
|
|
# then merge it into the distribution file
|
|
weecfg.update_and_merge(config_dict, dist_config_dict)
|
|
else:
|
|
# No old config file. Use the distribution file, then, if we can,
|
|
# prompt the user for station specific info
|
|
config_dict = dist_config_dict
|
|
if not self.no_prompt:
|
|
# Prompt the user for the station information:
|
|
stn_info = weecfg.prompt_for_info()
|
|
driver = weecfg.prompt_for_driver(stn_info.get('driver'))
|
|
stn_info['driver'] = driver
|
|
stn_info.update(weecfg.prompt_for_driver_settings(driver, config_dict))
|
|
if DEBUG:
|
|
print("Station info =", stn_info)
|
|
weecfg.modify_config(config_dict, stn_info, DEBUG)
|
|
|
|
# Set the WEEWX_ROOT
|
|
config_dict['WEEWX_ROOT'] = os.path.normpath(install_dir)
|
|
|
|
# NB: use mkstemp instead of NamedTemporaryFile because we need to
|
|
# do the delete (windows gets mad otherwise) and there is no delete
|
|
# parameter in NamedTemporaryFile in python 2.5.
|
|
|
|
# Time to write it out. Get a temporary file:
|
|
tmpfd, tmpfn = tempfile.mkstemp()
|
|
try:
|
|
# We don't need the file descriptor
|
|
os.close(tmpfd)
|
|
# Set the filename we will write to
|
|
config_dict.filename = tmpfn
|
|
# Write the config file
|
|
config_dict.write()
|
|
|
|
# Save the old config file if it exists:
|
|
if not self.dry_run and os.path.exists(install_path):
|
|
backup_path = weeutil.weeutil.move_with_timestamp(install_path)
|
|
print("Saved old configuration file as %s" % backup_path)
|
|
if not self.dry_run:
|
|
# Now install the temporary file (holding the merged config data)
|
|
# into the proper place:
|
|
rv = install_data.copy_file(self, tmpfn, install_path, **kwargs)
|
|
finally:
|
|
# Get rid of the temporary file
|
|
os.unlink(tmpfn)
|
|
|
|
# Set the permission bits unless this is a dry run:
|
|
if not self.dry_run:
|
|
shutil.copymode(f, install_path)
|
|
|
|
return rv
|
|
|
|
def massage_start_file(self, f, install_dir, **kwargs):
|
|
|
|
outname = os.path.join(install_dir, os.path.basename(f))
|
|
sre = re.compile(r"WEEWX_ROOT\s*=")
|
|
|
|
with open(f, 'r') as infile:
|
|
with tempfile.NamedTemporaryFile("w") as tmpfile:
|
|
for line in infile:
|
|
if sre.match(line):
|
|
tmpfile.writelines("WEEWX_ROOT=%s\n" % self.install_dir)
|
|
else:
|
|
tmpfile.writelines(line)
|
|
tmpfile.flush()
|
|
|
|
rv = install_data.copy_file(self, tmpfile.name, outname, **kwargs)
|
|
|
|
# Set the permission bits unless this is a dry run:
|
|
if not self.dry_run:
|
|
shutil.copymode(f, outname)
|
|
|
|
return rv
|
|
|
|
|
|
# ==============================================================================
|
|
# install_scripts
|
|
# ==============================================================================
|
|
|
|
class weewx_install_scripts(install_scripts):
|
|
|
|
def run(self):
|
|
# Run the superclass's version:
|
|
install_scripts.run(self)
|
|
|
|
|
|
# ==============================================================================
|
|
# sdist
|
|
# ==============================================================================
|
|
|
|
class weewx_sdist(sdist):
|
|
"""Specialized version of sdist which checks for password information in
|
|
the configuration file before creating the distribution.
|
|
|
|
For other sdist methods, see:
|
|
http://epydoc.sourceforge.net/stdlib/distutils.command.sdist.sdist-class.html
|
|
"""
|
|
|
|
def copy_file(self, f, install_dir, **kwargs):
|
|
"""Specialized version of copy_file that checks for stray passwords."""
|
|
|
|
# If this is the configuration file, check for passwords
|
|
if f == 'weewx.conf':
|
|
import configobj
|
|
config = configobj.ConfigObj(f, interpolation=False, encoding='utf-8')
|
|
|
|
for section in ['StdRESTful', 'StdReport']:
|
|
for subsection in config[section].sections:
|
|
try:
|
|
password = config[section][subsection]['password']
|
|
if password != 'replace_me':
|
|
sys.exit("\n*** [%s][[%s]] password found in configuration file. Aborting ***\n\n" \
|
|
% (section, subsection))
|
|
except KeyError:
|
|
pass
|
|
|
|
# Pass on to my superclass:
|
|
return sdist.copy_file(self, f, install_dir, **kwargs)
|
|
|
|
|
|
# ==============================================================================
|
|
# utility functions
|
|
# ==============================================================================
|
|
|
|
def remove_obsolete_files(install_dir):
|
|
"""Remove no longer needed files from the installation
|
|
directory, nominally /home/weewx."""
|
|
|
|
# If the file #upstream.last exists, delete it, as it is no longer used.
|
|
try:
|
|
os.remove(os.path.join(install_dir, 'public_html/#upstream.last'))
|
|
except OSError:
|
|
pass
|
|
|
|
# If the file $WEEWX_INSTALL/readme.htm exists, delete it. It's
|
|
# the old readme (since replaced with README.md)
|
|
try:
|
|
os.remove(os.path.join(install_dir, 'readme.htm'))
|
|
except OSError:
|
|
pass
|
|
|
|
# If the file $WEEWX_INSTALL/CHANGES.txt exists, delete it. It's
|
|
# been moved to the docs subdirectory and renamed
|
|
try:
|
|
os.remove(os.path.join(install_dir, 'CHANGES.txt'))
|
|
except OSError:
|
|
pass
|
|
|
|
# The directory start_scripts is no longer used
|
|
shutil.rmtree(os.path.join(install_dir, 'start_scripts'), True)
|
|
|
|
# The file docs/README.txt is now gone
|
|
try:
|
|
os.remove(os.path.join(install_dir, 'docs/README.txt'))
|
|
except OSError:
|
|
pass
|
|
|
|
# If the file docs/CHANGES.txt exists, delete it. It's been renamed
|
|
# to docs/changes.txt
|
|
try:
|
|
os.remove(os.path.join(install_dir, 'docs/CHANGES.txt'))
|
|
except OSError:
|
|
pass
|
|
|
|
# setup.py is no longer left in WEEWX_ROOT.
|
|
try:
|
|
os.remove(os.path.join(install_dir, 'setup.py'))
|
|
except OSError:
|
|
pass
|
|
|
|
|
|
# ==============================================================================
|
|
# 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,
|
|
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 :: GPLv3',
|
|
'Operating System :: POSIX :: LINUX',
|
|
'Operating System :: Unix',
|
|
'Operating System :: MacOS',
|
|
'Programming Language :: Python',
|
|
'Programming Language :: Python :: 2.6',
|
|
'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'
|
|
],
|
|
requires=[
|
|
'cheetah3(>=3.0)',
|
|
'configobj(>=4.5)',
|
|
'pillow(>=5.4)',
|
|
'pyephem(>=3.7)',
|
|
'pyserial(>=2.3)',
|
|
'pyusb(>=1.0)'
|
|
],
|
|
packages=[
|
|
'schemas',
|
|
'user',
|
|
'weecfg',
|
|
'weedb',
|
|
'weeimport',
|
|
'weeplot',
|
|
'weeutil',
|
|
'weewx',
|
|
'weewx.drivers'
|
|
],
|
|
cmdclass={
|
|
"sdist": weewx_sdist,
|
|
"install": weewx_install,
|
|
"install_scripts": weewx_install_scripts,
|
|
"install_data": weewx_install_data,
|
|
"install_lib": weewx_install_lib
|
|
},
|
|
platforms=['any'],
|
|
package_dir={'': 'bin'},
|
|
py_modules=['daemon', 'six'],
|
|
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']),
|
|
('docs',
|
|
['docs/changes.txt',
|
|
'docs/copyright.htm',
|
|
'docs/customizing.htm',
|
|
'docs/debian.htm',
|
|
'docs/devnotes.htm',
|
|
'docs/hardware.htm',
|
|
'docs/macos.htm',
|
|
'docs/readme.htm',
|
|
'docs/redhat.htm',
|
|
'docs/setup.htm',
|
|
'docs/suse.htm',
|
|
'docs/upgrading.htm',
|
|
'docs/usersguide.htm',
|
|
'docs/utilities.htm']),
|
|
('docs/css',
|
|
['docs/css/tocbot-4.3.1.css',
|
|
'docs/css/weewx_ui.css']),
|
|
('docs/images',
|
|
['docs/images/antialias.gif',
|
|
'docs/images/day-gap-not-shown.png',
|
|
'docs/images/day-gap-showing.png',
|
|
'docs/images/daycompare.png',
|
|
'docs/images/daytemp_with_avg.png',
|
|
'docs/images/daywindvec.png',
|
|
'docs/images/favicon.png',
|
|
'docs/images/ferrites.jpg',
|
|
'docs/images/funky_degree.png',
|
|
'docs/images/image_parts.png',
|
|
'docs/images/image_parts.xcf',
|
|
'docs/images/logo-apple.png',
|
|
'docs/images/logo-centos.png',
|
|
'docs/images/logo-debian.png',
|
|
'docs/images/logo-fedora.png',
|
|
'docs/images/logo-linux.png',
|
|
'docs/images/logo-mint.png',
|
|
'docs/images/logo-opensuse.png',
|
|
'docs/images/logo-pypi.svg',
|
|
'docs/images/logo-redhat.png',
|
|
'docs/images/logo-rpi.png',
|
|
'docs/images/logo-suse.png',
|
|
'docs/images/logo-ubuntu.png',
|
|
'docs/images/logo-weewx.png',
|
|
'docs/images/sample_monthrain.png',
|
|
'docs/images/sample_monthtempdew.png',
|
|
'docs/images/weekgustoverlay.png',
|
|
'docs/images/weektempdew.png',
|
|
'docs/images/yearhilow.png']),
|
|
('docs/js',
|
|
['docs/js/cash.js',
|
|
'docs/js/tocbot-4.3.1.js',
|
|
'docs/js/weewx.js']),
|
|
('docs/examples',
|
|
['docs/examples/tag.htm']),
|
|
('examples',
|
|
['examples/alarm.py',
|
|
'examples/lowBattery.py',
|
|
'examples/mem.py',
|
|
'examples/stats.py',
|
|
'examples/transfer_db.py']),
|
|
('examples/basic',
|
|
['examples/basic/changelog',
|
|
'examples/basic/install.py',
|
|
'examples/basic/readme.txt']),
|
|
('examples/basic/skins/basic',
|
|
['examples/basic/skins/basic/basic.css',
|
|
'examples/basic/skins/basic/current.inc',
|
|
'examples/basic/skins/basic/favicon.ico',
|
|
'examples/basic/skins/basic/hilo.inc',
|
|
'examples/basic/skins/basic/index.html.tmpl',
|
|
'examples/basic/skins/basic/skin.conf']),
|
|
('examples/fileparse',
|
|
['examples/fileparse/changelog',
|
|
'examples/fileparse/install.py',
|
|
'examples/fileparse/readme.txt']),
|
|
('examples/fileparse/bin/user',
|
|
['examples/fileparse/bin/user/fileparse.py']),
|
|
('examples/pmon',
|
|
['examples/pmon/changelog',
|
|
'examples/pmon/install.py',
|
|
'examples/pmon/readme.txt']),
|
|
('examples/pmon/bin/user',
|
|
['examples/pmon/bin/user/pmon.py']),
|
|
('examples/pmon/skins/pmon',
|
|
['examples/pmon/skins/pmon/index.html.tmpl',
|
|
'examples/pmon/skins/pmon/skin.conf']),
|
|
('examples/xstats',
|
|
['examples/xstats/changelog',
|
|
'examples/xstats/install.py',
|
|
'examples/xstats/readme.txt']),
|
|
('examples/xstats/bin/user',
|
|
['examples/xstats/bin/user/xstats.py']),
|
|
('examples/xstats/skins/xstats',
|
|
['examples/xstats/skins/xstats/index.html.tmpl',
|
|
'examples/xstats/skins/xstats/skin.conf']),
|
|
('skins/Ftp',
|
|
['skins/Ftp/skin.conf']),
|
|
('skins/Rsync',
|
|
['skins/Rsync/skin.conf']),
|
|
('skins/Smartphone',
|
|
['skins/Smartphone/barometer.html.tmpl',
|
|
'skins/Smartphone/custom.js',
|
|
'skins/Smartphone/favicon.ico',
|
|
'skins/Smartphone/humidity.html.tmpl',
|
|
'skins/Smartphone/index.html.tmpl',
|
|
'skins/Smartphone/rain.html.tmpl',
|
|
'skins/Smartphone/skin.conf',
|
|
'skins/Smartphone/temp.html.tmpl',
|
|
'skins/Smartphone/wind.html.tmpl']),
|
|
('skins/Smartphone/icons',
|
|
['skins/Smartphone/icons/icon_ipad_x1.png',
|
|
'skins/Smartphone/icons/icon_ipad_x2.png',
|
|
'skins/Smartphone/icons/icon_iphone_x1.png',
|
|
'skins/Smartphone/icons/icon_iphone_x2.png']),
|
|
('skins/Seasons',
|
|
['skins/Seasons/about.inc',
|
|
'skins/Seasons/analytics.inc',
|
|
'skins/Seasons/celestial.html.tmpl',
|
|
'skins/Seasons/celestial.inc',
|
|
'skins/Seasons/current.inc',
|
|
'skins/Seasons/favicon.ico',
|
|
'skins/Seasons/hilo.inc',
|
|
'skins/Seasons/identifier.inc',
|
|
'skins/Seasons/index.html.tmpl',
|
|
'skins/Seasons/map.inc',
|
|
'skins/Seasons/radar.inc',
|
|
'skins/Seasons/rss.xml.tmpl',
|
|
'skins/Seasons/satellite.inc',
|
|
'skins/Seasons/sensors.inc',
|
|
'skins/Seasons/skin.conf',
|
|
'skins/Seasons/seasons.css',
|
|
'skins/Seasons/seasons.js',
|
|
'skins/Seasons/statistics.html.tmpl',
|
|
'skins/Seasons/statistics.inc',
|
|
'skins/Seasons/sunmoon.inc',
|
|
'skins/Seasons/tabular.html.tmpl',
|
|
'skins/Seasons/telemetry.html.tmpl',
|
|
'skins/Seasons/titlebar.inc']),
|
|
('skins/Seasons/NOAA',
|
|
['skins/Seasons/NOAA/NOAA-%Y-%m.txt.tmpl',
|
|
'skins/Seasons/NOAA/NOAA-%Y.txt.tmpl']),
|
|
('skins/Seasons/font',
|
|
['skins/Seasons/font/OpenSans-Bold.ttf',
|
|
'skins/Seasons/font/OpenSans-Regular.ttf',
|
|
'skins/Seasons/font/OpenSans.woff',
|
|
'skins/Seasons/font/OpenSans.woff2']),
|
|
('skins/Mobile',
|
|
['skins/Mobile/favicon.ico',
|
|
'skins/Mobile/index.html.tmpl',
|
|
'skins/Mobile/skin.conf',
|
|
'skins/Mobile/mobile.css']),
|
|
('skins/Standard',
|
|
['skins/Standard/favicon.ico',
|
|
'skins/Standard/index.html.tmpl',
|
|
'skins/Standard/mobile.css',
|
|
'skins/Standard/mobile.html.tmpl',
|
|
'skins/Standard/month.html.tmpl',
|
|
'skins/Standard/skin.conf',
|
|
'skins/Standard/week.html.tmpl',
|
|
'skins/Standard/weewx.css',
|
|
'skins/Standard/year.html.tmpl']),
|
|
('skins/Standard/NOAA',
|
|
['skins/Standard/NOAA/NOAA-%Y-%m.txt.tmpl',
|
|
'skins/Standard/NOAA/NOAA-%Y.txt.tmpl']),
|
|
('skins/Standard/RSS',
|
|
['skins/Standard/RSS/weewx_rss.xml.tmpl']),
|
|
('skins/Standard/backgrounds',
|
|
['skins/Standard/backgrounds/band.gif',
|
|
'skins/Standard/backgrounds/butterfly.jpg',
|
|
'skins/Standard/backgrounds/drops.gif',
|
|
'skins/Standard/backgrounds/flower.jpg',
|
|
'skins/Standard/backgrounds/leaf.jpg',
|
|
'skins/Standard/backgrounds/night.gif']),
|
|
('skins/Standard/smartphone',
|
|
['skins/Standard/smartphone/barometer.html.tmpl',
|
|
'skins/Standard/smartphone/custom.js',
|
|
'skins/Standard/smartphone/humidity.html.tmpl',
|
|
'skins/Standard/smartphone/index.html.tmpl',
|
|
'skins/Standard/smartphone/radar.html.tmpl',
|
|
'skins/Standard/smartphone/rain.html.tmpl',
|
|
'skins/Standard/smartphone/temp_outside.html.tmpl',
|
|
'skins/Standard/smartphone/wind.html.tmpl']),
|
|
('skins/Standard/smartphone/icons',
|
|
['skins/Standard/smartphone/icons/icon_ipad_x1.png',
|
|
'skins/Standard/smartphone/icons/icon_ipad_x2.png',
|
|
'skins/Standard/smartphone/icons/icon_iphone_x1.png',
|
|
'skins/Standard/smartphone/icons/icon_iphone_x2.png']),
|
|
('util/apache/conf.d',
|
|
['util/apache/conf.d/weewx.conf']),
|
|
('util/import',
|
|
['util/import/csv-example.conf',
|
|
'util/import/cumulus-example.conf',
|
|
'util/import/wd-example.conf',
|
|
'util/import/wu-example.conf']),
|
|
('util/init.d',
|
|
['util/init.d/weewx.bsd',
|
|
'util/init.d/weewx.debian',
|
|
'util/init.d/weewx.lsb',
|
|
'util/init.d/weewx.redhat',
|
|
'util/init.d/weewx.suse']),
|
|
('util/launchd',
|
|
['util/launchd/com.weewx.weewxd.plist']),
|
|
('util/logrotate.d',
|
|
['util/logrotate.d/weewx']),
|
|
('util/logwatch/conf/logfiles',
|
|
['util/logwatch/conf/logfiles/weewx.conf']),
|
|
('util/logwatch/conf/services',
|
|
['util/logwatch/conf/services/weewx.conf']),
|
|
('util/logwatch/scripts/services',
|
|
['util/logwatch/scripts/services/weewx']),
|
|
('util/newsyslog.d',
|
|
['util/newsyslog.d/weewx.conf']),
|
|
('util/rsyslog.d',
|
|
['util/rsyslog.d/weewx.conf']),
|
|
('util/solaris',
|
|
['util/solaris/weewx-smf.xml']),
|
|
('util/systemd',
|
|
['util/systemd/weewx.service']),
|
|
('util/udev/rules.d',
|
|
['util/udev/rules.d/acurite.rules',
|
|
'util/udev/rules.d/cc3000.rules',
|
|
'util/udev/rules.d/fousb.rules',
|
|
'util/udev/rules.d/te923.rules',
|
|
'util/udev/rules.d/vantage.rules',
|
|
'util/udev/rules.d/wmr100.rules',
|
|
'util/udev/rules.d/wmr200.rules',
|
|
'util/udev/rules.d/wmr300.rules',
|
|
'util/udev/rules.d/ws28xx.rules'])
|
|
]
|
|
)
|