mirror of
https://github.com/weewx/weewx.git
synced 2026-06-10 10:05:20 -04:00
Merge branch 'master' of https://github.com/weewx/weewx.git
Conflicts: docs/changes.txt
This commit is contained in:
@@ -17,6 +17,7 @@ import tempfile
|
||||
import configobj
|
||||
|
||||
import weeutil.weeutil
|
||||
from weewx.engine import all_service_groups
|
||||
|
||||
minor_comment_block = [""]
|
||||
major_comment_block = ["", "##############################################################################", ""]
|
||||
@@ -48,6 +49,15 @@ metricwx_group = {'group_altitude': 'meter',
|
||||
'group_speed2': 'meter_per_second2',
|
||||
'group_temperature': 'degree_C'}
|
||||
|
||||
class Logger(object):
|
||||
def __init__(self, verbosity=0):
|
||||
self.verbosity = verbosity
|
||||
def log(self, msg, level=0):
|
||||
if self.verbosity >= level:
|
||||
print "%s%s" % (' ' * (level - 1), msg)
|
||||
def set_verbosity(self, verbosity):
|
||||
self.verbosity = verbosity
|
||||
|
||||
#==============================================================================
|
||||
# Utilities that find and save ConfigObj objects
|
||||
#==============================================================================
|
||||
@@ -852,6 +862,13 @@ def prompt_with_limits(prompt, default=None, low_limit=None, high_limit=None):
|
||||
|
||||
return value
|
||||
|
||||
#==============================================================================
|
||||
# Classes and utilities for installing extensions
|
||||
#==============================================================================
|
||||
|
||||
class ExtensionInstaller(dict):
|
||||
"""Base class for extension installers."""
|
||||
|
||||
def extract_roots(config_path, config_dict):
|
||||
"""Get the location of the various root directories used by weewx."""
|
||||
|
||||
@@ -873,3 +890,4 @@ def extract_roots(config_path, config_dict):
|
||||
|
||||
return root_dict
|
||||
|
||||
|
||||
|
||||
@@ -8,15 +8,13 @@
|
||||
"""Install and remove extensions."""
|
||||
from __future__ import with_statement
|
||||
|
||||
import os.path
|
||||
import optparse
|
||||
import sys
|
||||
import shutil
|
||||
import os
|
||||
import optparse
|
||||
from subprocess import Popen, PIPE
|
||||
|
||||
import configobj
|
||||
|
||||
import config_util
|
||||
from config_util import Logger
|
||||
|
||||
usage = """wee_extension --help
|
||||
wee_extension --list
|
||||
@@ -59,28 +57,19 @@ def main():
|
||||
# Now we are ready to parse the command line:
|
||||
(options, _args) = parser.parse_args()
|
||||
|
||||
ext = Extension(_args,
|
||||
config=options.config,
|
||||
tmpdir=options.tmpdir,
|
||||
bin_root=options.bin_root,
|
||||
dry_run=options.dry_run,
|
||||
logger=Logger(verbosity=options.verbosity))
|
||||
ext = ExtensionEngine(_args,
|
||||
config=options.config,
|
||||
tmpdir=options.tmpdir,
|
||||
bin_root=options.bin_root,
|
||||
dry_run=options.dry_run,
|
||||
logger=Logger(verbosity=options.verbosity))
|
||||
|
||||
if options.list_extensions:
|
||||
ext.enumerate_extensions()
|
||||
|
||||
return 0
|
||||
|
||||
class Logger(object):
|
||||
def __init__(self, verbosity=0):
|
||||
self.verbosity = verbosity
|
||||
def log(self, msg, level=0):
|
||||
if self.verbosity >= level:
|
||||
print "%s%s" % (' ' * (level - 1), msg)
|
||||
def set_verbosity(self, verbosity):
|
||||
self.verbosity = verbosity
|
||||
|
||||
class Extension(object):
|
||||
class ExtensionEngine(object):
|
||||
"""Engine that manages extensions."""
|
||||
def __init__(self, args=None, config=None, tmpdir=None, bin_root=None,
|
||||
dry_run=None, logger=Logger()):
|
||||
@@ -107,6 +96,56 @@ class Extension(object):
|
||||
except OSError:
|
||||
self.logger.log("No extension cache '%s'" % ext_root, level=2)
|
||||
self.logger.log("No extensions installed", level=0)
|
||||
|
||||
def install_extension(self, extension_path):
|
||||
self.logger.log("Request to install %s" % extension_path)
|
||||
ifile = 'install'
|
||||
__import__(ifile)
|
||||
module = sys.modules[ifile]
|
||||
loader = getattr(module, 'loader')
|
||||
installer = loader()
|
||||
|
||||
self.logger.log("Request to install extension %s" % extension_path)
|
||||
|
||||
|
||||
self.log("install_files", level=1)
|
||||
for t in installer['files']:
|
||||
dstdir = self.prepend_layout_path(t[0])
|
||||
try:
|
||||
self.log("mkdir %s" % dstdir, level=2)
|
||||
if self.doit:
|
||||
mkdir(dstdir)
|
||||
except os.error:
|
||||
pass
|
||||
for f in t[1]:
|
||||
src = os.path.join(self.layout['EXTRACT_ROOT'], f)
|
||||
dst = self.prepend_layout_path(f)
|
||||
if os.path.exists(dst):
|
||||
self.log("save existing file %s" % dst, level=2)
|
||||
if self.doit:
|
||||
save_path(dst)
|
||||
self.log("copy %s to %s" % (src, dst), level=2)
|
||||
if self.doit:
|
||||
distutils.file_util.copy_file(src, dst)
|
||||
|
||||
|
||||
|
||||
# self.log("request to install %s" % self.filename)
|
||||
# self.layout_type = self.guess_type(self.layout_type)
|
||||
# self.layout = self.verify_layout(self.layout_type)
|
||||
# (self.basename, self.extdir, self.delete_extdir) = \
|
||||
# self.verify_installer(self.filename, self.tmpdir)
|
||||
# self.verify_src(self.extdir)
|
||||
# # everything is ok, so use the extdir
|
||||
# self.layout['EXTRACT_ROOT'] = self.extdir
|
||||
# self.load_installer(self.extdir, self.basename, self.layout)
|
||||
# self.installer.install()
|
||||
# self.cleanup()
|
||||
|
||||
# self.install_files()
|
||||
# self.merge_config_options()
|
||||
# self.install_history()
|
||||
|
||||
|
||||
if __name__=="__main__" :
|
||||
main()
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
# Thanks to Weather Guy and Andrew Daviel (2015)
|
||||
# decoding of the R3 messages
|
||||
#
|
||||
# Slow-clap thanks to Michael Walsh
|
||||
# golf clap to Michael Walsh
|
||||
# http://forum1.valleyinfosys.com/index.php
|
||||
#
|
||||
# No thanks to AcuRite or Chaney instruments. They refused to provide any
|
||||
@@ -288,6 +288,7 @@ X1 - 2 bytes
|
||||
|
||||
# FIXME: decode inside humidity
|
||||
# FIXME: decode historical records
|
||||
# FIXME: perhaps retry read when dodgey data or short read?
|
||||
|
||||
from __future__ import with_statement
|
||||
import syslog
|
||||
@@ -295,6 +296,7 @@ import time
|
||||
import usb
|
||||
|
||||
import weewx.drivers
|
||||
import weewx.wxformulas
|
||||
|
||||
DRIVER_NAME = 'AcuRite'
|
||||
DRIVER_VERSION = '0.15'
|
||||
@@ -402,7 +404,8 @@ class AcuRiteDriver(weewx.drivers.AbstractDevice):
|
||||
ntries = 0
|
||||
yield packet
|
||||
next_read = min(self.r1_next_read, self.r2_next_read)
|
||||
delay = max(next_read - time.time(), self.polling_interval)
|
||||
delay = max(int(next_read - time.time() + 1),
|
||||
self.polling_interval)
|
||||
logdbg("next read in %s seconds" % delay)
|
||||
time.sleep(delay)
|
||||
except (usb.USBError, weewx.WeeWxIOError), e:
|
||||
@@ -417,11 +420,13 @@ class AcuRiteDriver(weewx.drivers.AbstractDevice):
|
||||
def _augment_packet(self, packet):
|
||||
# calculate the rain delta from the total
|
||||
if 'rain_total' in packet:
|
||||
if self.last_rain is not None:
|
||||
packet['rain'] = packet['rain_total'] - self.last_rain
|
||||
else:
|
||||
packet['rain'] = None
|
||||
self.last_rain = packet['rain_total']
|
||||
total = packet['rain_total']
|
||||
if (total is not None and self.last_rain is not None and
|
||||
total < self.last_rain):
|
||||
loginf("rain counter decrement ignored:"
|
||||
" new: %s old: %s" % (total, self.last_rain))
|
||||
packet['rain'] = wxformulas.calculate_rain(total, self.last_rain)
|
||||
self.last_rain = total
|
||||
|
||||
# no wind direction when wind speed is zero
|
||||
if 'windSpeed' in packet and not packet['windSpeed']:
|
||||
|
||||
570
setup2.py
570
setup2.py
@@ -1,570 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# weewx --- A simple, high-performance weather station server
|
||||
#
|
||||
# Copyright (c) 2009-2015 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
|
||||
|
||||
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 config_util
|
||||
import weeutil.weeutil
|
||||
|
||||
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):
|
||||
# Determine whether the user is still using an old-style schema
|
||||
schema_type = get_schema_type(self.install_dir)
|
||||
|
||||
# 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)
|
||||
|
||||
# But, there is one exception: if the old user subdirectory included an
|
||||
# old-style schema, then it should be overwritten with the new version.
|
||||
if schema_type == 'old':
|
||||
incoming_schema_path = os.path.join(bin_dir, 'user/schemas.py')
|
||||
target_path = os.path.join(self.install_dir, 'user/schemas.py')
|
||||
distutils.file_util.copy_file(incoming_schema_path, target_path)
|
||||
|
||||
#==============================================================================
|
||||
# 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 an existing skins subdirectory, do not overwrite it.
|
||||
if os.path.exists(os.path.join(self.install_dir, 'skins')):
|
||||
# Do this by filtering it out of the list of subdirectories to
|
||||
# be installed:
|
||||
self.data_files = filter(lambda dat : not dat[0].startswith('skins/'), self.data_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, file_error=True)
|
||||
except IOError, e:
|
||||
sys.exit(str(e))
|
||||
except SyntaxError, 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 = config_util.read_config(install_path, None)
|
||||
if DEBUG:
|
||||
print "Old configuration file found at", config_path
|
||||
|
||||
# Update the old configuration file to the current version:
|
||||
config_util.update_config(config_dict)
|
||||
|
||||
# Then merge it into the distribution file
|
||||
config_util.merge_config(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 = config_util.prompt_for_info()
|
||||
driver = config_util.prompt_for_driver(stn_info.get('driver'))
|
||||
stn_info['driver'] = driver
|
||||
stn_info.update(config_util.prompt_for_driver_settings(driver))
|
||||
if DEBUG:
|
||||
print "Station info =", stn_info
|
||||
config_util.modify_config(config_dict, stn_info, DEBUG)
|
||||
|
||||
# Time to write it out. Get a temporary file:
|
||||
with tempfile.NamedTemporaryFile("w") as tmpfile:
|
||||
# Write the finished configuration file to it:
|
||||
config_dict.write(tmpfile)
|
||||
tmpfile.flush()
|
||||
|
||||
# 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
|
||||
|
||||
# Now install the temporary file (holding the merged config data)
|
||||
# into the proper place:
|
||||
rv = install_data.copy_file(self, tmpfile.name, install_path, **kwargs)
|
||||
|
||||
# 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)
|
||||
|
||||
try:
|
||||
# Put in a symbolic link for weewxd.py
|
||||
os.symlink('./weewxd', os.path.join(self.install_dir, 'weewxd.py'))
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
#==============================================================================
|
||||
# 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, then check it for passwords
|
||||
if f == 'weewx.conf':
|
||||
import configobj
|
||||
config = configobj.ConfigObj(f)
|
||||
|
||||
try:
|
||||
password = config['StdReport']['FTP']['password']
|
||||
sys.exit("\n*** FTP password found in configuration file. Aborting ***\n\n")
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
try:
|
||||
password = config['StdRESTful']['Wunderground']['password']
|
||||
sys.exit("\n*** Wunderground password found in configuration file. Aborting ***\n\n")
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
try:
|
||||
password = config['StdRESTful']['Wunderground']['password']
|
||||
sys.exit("\n*** PWSweather password found in configuration file. Aborting ***\n\n")
|
||||
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)
|
||||
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
|
||||
|
||||
def get_schema_type(bin_dir):
|
||||
"""Checks whether the schema in user.schemas is a new style or old style
|
||||
schema.
|
||||
|
||||
bin_dir: The directory to be checked. This is nominally /home/weewx/bin.
|
||||
|
||||
Returns:
|
||||
'none': There is no schema at all.
|
||||
'old' : It is an old-style schema.
|
||||
'new' : It is a new-style schema
|
||||
"""
|
||||
tmp_path = list(sys.path)
|
||||
sys.path.insert(0, bin_dir)
|
||||
|
||||
try:
|
||||
import user.schemas
|
||||
except ImportError:
|
||||
# There is no existing schema at all.
|
||||
result = 'none'
|
||||
else:
|
||||
# There is a schema. Determine if it is old-style or new-style
|
||||
try:
|
||||
# Try the old style 'drop_list'. If it fails, it must be
|
||||
# a new-style schema
|
||||
_ = user.schemas.drop_list # @UnusedVariable @UndefinedVariable
|
||||
except AttributeError:
|
||||
# New style schema
|
||||
result = 'new'
|
||||
else:
|
||||
# It did not fail. Must be an old-style schema
|
||||
result = 'old'
|
||||
finally:
|
||||
del user.schemas
|
||||
|
||||
# Restore the path
|
||||
sys.path = tmp_path
|
||||
|
||||
return result
|
||||
|
||||
#==============================================================================
|
||||
# main entry point
|
||||
#==============================================================================
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
setup(name='weewx',
|
||||
version=VERSION,
|
||||
description='weather software',
|
||||
long_description="weewx interacts with a weather station to produce graphs, "
|
||||
"reports, and HTML pages. weewx can upload data to services such as the "
|
||||
"WeatherUnderground, PWSweather.com, or CWOP.",
|
||||
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',
|
||||
'License :: GPLv3',
|
||||
'Operating System :: OS Independent',
|
||||
'Programming Language :: Python',
|
||||
'Programming Language :: Python :: 2',
|
||||
],
|
||||
requires=['configobj(>=4.5)',
|
||||
'serial(>=2.3)',
|
||||
'Cheetah(>=2.0)',
|
||||
'sqlite3(>=2.5)',
|
||||
'PIL(>=1.1.6)'],
|
||||
provides=['weedb',
|
||||
'weeplot',
|
||||
'weeutil',
|
||||
'weewx'],
|
||||
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'},
|
||||
packages=['examples',
|
||||
'schemas',
|
||||
'user',
|
||||
'weedb',
|
||||
'weeplot',
|
||||
'weeutil',
|
||||
'weewx',
|
||||
'weewx.drivers'],
|
||||
py_modules=['daemon',
|
||||
'config_util'],
|
||||
scripts=['bin/wee_config_database',
|
||||
'bin/wee_config_device',
|
||||
'bin/weewxd',
|
||||
'bin/wee_reports'],
|
||||
data_files=[
|
||||
('',
|
||||
['LICENSE.txt',
|
||||
'README',
|
||||
'weewx.conf']),
|
||||
('docs',
|
||||
['docs/changes.txt',
|
||||
'docs/copyright.htm',
|
||||
'docs/customizing.htm',
|
||||
'docs/debian.htm',
|
||||
'docs/readme.htm',
|
||||
'docs/redhat.htm',
|
||||
'docs/setup.htm',
|
||||
'docs/suse.htm',
|
||||
'docs/upgrading.htm',
|
||||
'docs/usersguide.htm']),
|
||||
('docs/css',
|
||||
['docs/css/jquery.tocify.css',
|
||||
'docs/css/weewx_docs.css']),
|
||||
('docs/css/ui-lightness',
|
||||
['docs/css/ui-lightness/jquery-ui-1.10.4.custom.css',
|
||||
'docs/css/ui-lightness/jquery-ui-1.10.4.custom.min.css']),
|
||||
('docs/css/ui-lightness/images',
|
||||
['docs/css/ui-lightness/images/animated-overlay.gif',
|
||||
'docs/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png',
|
||||
'docs/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png',
|
||||
'docs/css/ui-lightness/images/ui-bg_flat_10_000000_40x100.png',
|
||||
'docs/css/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png',
|
||||
'docs/css/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png',
|
||||
'docs/css/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png',
|
||||
'docs/css/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png',
|
||||
'docs/css/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png',
|
||||
'docs/css/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png',
|
||||
'docs/css/ui-lightness/images/ui-icons_222222_256x240.png',
|
||||
'docs/css/ui-lightness/images/ui-icons_228ef1_256x240.png',
|
||||
'docs/css/ui-lightness/images/ui-icons_ef8c08_256x240.png',
|
||||
'docs/css/ui-lightness/images/ui-icons_ffd27a_256x240.png',
|
||||
'docs/css/ui-lightness/images/ui-icons_ffffff_256x240.png']),
|
||||
('docs/images',
|
||||
['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/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-redhat.png',
|
||||
'docs/images/logo-suse.png',
|
||||
'docs/images/logo-ubuntu.png',
|
||||
'docs/images/logo-weewx.png',
|
||||
'docs/images/sample_monthrain.png',
|
||||
'docs/images/weekgustoverlay.png',
|
||||
'docs/images/weektempdew.png',
|
||||
'docs/images/yearhilow.png']),
|
||||
('docs/js',
|
||||
['docs/js/jquery-1.11.1.min.js',
|
||||
'docs/js/jquery-ui-1.10.4.custom.min.js',
|
||||
'docs/js/jquery.tocify-1.9.0.js',
|
||||
'docs/js/jquery.tocify-1.9.0.min.js',
|
||||
'docs/js/weewx.js']),
|
||||
('skins/Ftp',
|
||||
['skins/Ftp/skin.conf']),
|
||||
('skins/Rsync',
|
||||
['skins/Rsync/skin.conf']),
|
||||
('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-YYYY-MM.txt.tmpl',
|
||||
'skins/Standard/NOAA/NOAA-YYYY.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/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/rsyslog.d',
|
||||
['util/rsyslog.d/weewx.conf']),
|
||||
('util/systemd',
|
||||
['util/systemd/weewx.service'])
|
||||
]
|
||||
)
|
||||
Reference in New Issue
Block a user