From 209fd340267f5b3af8fb50ddfe8d844fa362cfdc Mon Sep 17 00:00:00 2001 From: Tom Keffer Date: Sun, 6 Nov 2022 13:51:00 -0800 Subject: [PATCH] Fix bug that prevents group_deltatime from being used by timespans Fixes issue #808. --- bin/weewx/almanac.py | 6 +-- bin/weewx/defaults.py | 15 ++++-- bin/weewx/station.py | 6 +-- .../tests/expected/StandardTest/index.html | 5 ++ .../expected/StandardTest/metric/index.html | 5 ++ bin/weewx/tests/gen_fake_data.py | 3 +- bin/weewx/tests/test_daily.py | 6 +-- .../test_skins/StandardTest/index.html.tmpl | 5 ++ bin/weewx/tests/testgen.conf | 6 +-- bin/weewx/tests/tst_schema.py | 38 +++++++++++++ bin/weewx/units.py | 30 +++++++---- docs/changes.txt | 4 ++ docs/upgrading.htm | 54 +++++++++++++++++++ 13 files changed, 154 insertions(+), 29 deletions(-) create mode 100644 bin/weewx/tests/tst_schema.py diff --git a/bin/weewx/almanac.py b/bin/weewx/almanac.py index 02ae852f..95b20078 100644 --- a/bin/weewx/almanac.py +++ b/bin/weewx/almanac.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2009-2021 Tom Keffer +# Copyright (c) 2009-2022 Tom Keffer # # See the file LICENSE.txt for your full rights. # @@ -392,7 +392,7 @@ class AlmanacBinder(object): visible = (time_setting_djd - time_rising_djd) * weewx.units.SECS_PER_DAY return weewx.units.ValueHelper(ValueTuple(visible, "second", "group_deltatime"), - context="short_delta", + context="day", formatter=self.almanac.formatter, converter=self.almanac.converter) @@ -409,7 +409,7 @@ class AlmanacBinder(object): # Take the difference diff = today_visible.raw - then_visible.raw return weewx.units.ValueHelper(ValueTuple(diff, "second", "group_deltatime"), - context="brief_delta", + context="hour", formatter=self.almanac.formatter, converter=self.almanac.converter) diff --git a/bin/weewx/defaults.py b/bin/weewx/defaults.py index 7eea2cd0..3349db40 100644 --- a/bin/weewx/defaults.py +++ b/bin/weewx/defaults.py @@ -1,6 +1,6 @@ # coding: utf-8 # -# Copyright (c) 2019-2021 Tom Keffer +# Copyright (c) 2019-2022 Tom Keffer # # See the file LICENSE.txt for your rights. # @@ -221,10 +221,15 @@ log_failure = False current = %x %X ephem_day = %X ephem_year = %x %X - brief_delta = "%(minute)d%(minute_label)s, %(second)d%(second_label)s" - short_delta = "%(hour)d%(hour_label)s, %(minute)d%(minute_label)s, %(second)d%(second_label)s" - long_delta = "%(day)d%(day_label)s, %(hour)d%(hour_label)s, %(minute)d%(minute_label)s" - delta_time = "%(day)d%(day_label)s, %(hour)d%(hour_label)s, %(minute)d%(minute_label)s" + + [[DeltaTimeFormats]] + current = "%(minute)d%(minute_label)s, %(second)d%(second_label)s" + hour = "%(minute)d%(minute_label)s, %(second)d%(second_label)s" + day = "%(hour)d%(hour_label)s, %(minute)d%(minute_label)s, %(second)d%(second_label)s" + week = "%(day)d%(day_label)s, %(hour)d%(hour_label)s, %(minute)d%(minute_label)s" + month = "%(day)d%(day_label)s, %(hour)d%(hour_label)s, %(minute)d%(minute_label)s" + year = "%(day)d%(day_label)s, %(hour)d%(hour_label)s, %(minute)d%(minute_label)s" + [[Ordinates]] diff --git a/bin/weewx/station.py b/bin/weewx/station.py index 604e4f36..d2f3915c 100644 --- a/bin/weewx/station.py +++ b/bin/weewx/station.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2009-2021 Tom Keffer +# Copyright (c) 2009-2022 Tom Keffer # # See the file LICENSE.txt for your full rights. # @@ -92,7 +92,7 @@ class Station(object): delta_time = time.time() - weewx.launchtime_ts if weewx.launchtime_ts else None return weewx.units.ValueHelper(value_t=(delta_time, "second", "group_deltatime"), - context="long_delta", + context="month", formatter=self.formatter, converter=self.converter) @@ -101,7 +101,7 @@ class Station(object): """Lazy evaluation of the server uptime.""" os_uptime_secs = _os_uptime() return weewx.units.ValueHelper(value_t=(os_uptime_secs, "second", "group_deltatime"), - context="long_delta", + context="month", formatter=self.formatter, converter=self.converter) diff --git a/bin/weewx/tests/expected/StandardTest/index.html b/bin/weewx/tests/expected/StandardTest/index.html index 5e8366f5..08fddecb 100644 --- a/bin/weewx/tests/expected/StandardTest/index.html +++ b/bin/weewx/tests/expected/StandardTest/index.html @@ -575,6 +575,11 @@ Test for a bad aggregation type on a $day tag: $day.outTemp.foo $day.outTemp.foo + + + Test for sunshineDur: $day.sunshineDur.sum + 7 hours, 0 minutes, 0 seconds +
diff --git a/bin/weewx/tests/expected/StandardTest/metric/index.html b/bin/weewx/tests/expected/StandardTest/metric/index.html index 735d95b9..02189c85 100644 --- a/bin/weewx/tests/expected/StandardTest/metric/index.html +++ b/bin/weewx/tests/expected/StandardTest/metric/index.html @@ -575,6 +575,11 @@ Test for a bad aggregation type on a $day tag: $day.outTemp.foo $day.outTemp.foo + + + Test for sunshineDur: $day.sunshineDur.sum + 7 Stunden, 0 Minuten, 0 Sekunden +
diff --git a/bin/weewx/tests/gen_fake_data.py b/bin/weewx/tests/gen_fake_data.py index 73b6ac32..4d503027 100644 --- a/bin/weewx/tests/gen_fake_data.py +++ b/bin/weewx/tests/gen_fake_data.py @@ -1,6 +1,6 @@ # # -# Copyright (c) 2009-2019 Tom Keffer +# Copyright (c) 2009-2022 Tom Keffer # # See the file LICENSE.txt for your full rights. # @@ -193,6 +193,7 @@ def genFakeRecords(start_ts=start_ts, stop_ts=stop_ts, interval=interval, record['rain'] = 0.0 record['radiation'] = max(amplitude * 800 * math.sin(daily_phase - math.pi / 2.0), 0) record['radiation'] *= 0.5 * (math.cos(annual_phase + math.pi) + 1.5) + record['sunshineDur'] = interval if record['radiation'] else 0.0 # Make every 71st observation (a prime number) a null. This is a deterministic algorithm, so it # will produce the same results every time. diff --git a/bin/weewx/tests/test_daily.py b/bin/weewx/tests/test_daily.py index 3a83d127..8d449e06 100644 --- a/bin/weewx/tests/test_daily.py +++ b/bin/weewx/tests/test_daily.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (c) 2009-2021 Tom Keffer +# Copyright (c) 2009-2022 Tom Keffer # # See the file LICENSE.txt for your full rights. # @@ -23,7 +23,7 @@ from six.moves import map import configobj import gen_fake_data -import schemas.wview_small +import tst_schema import weeutil.logger import weeutil.weeutil import weewx.manager @@ -39,7 +39,7 @@ weeutil.logger.setup('test_daily', {}) os.environ['TZ'] = 'America/Los_Angeles' time.tzset() -day_keys = [x[0] for x in schemas.wview_small.schema['day_summaries']] +day_keys = [x[0] for x in tst_schema.schema['day_summaries']] # Find the configuration file. It's assumed to be in the same directory as me: config_path = os.path.join(os.path.dirname(__file__), "testgen.conf") diff --git a/bin/weewx/tests/test_skins/StandardTest/index.html.tmpl b/bin/weewx/tests/test_skins/StandardTest/index.html.tmpl index 6aff4931..0ee7c86a 100644 --- a/bin/weewx/tests/test_skins/StandardTest/index.html.tmpl +++ b/bin/weewx/tests/test_skins/StandardTest/index.html.tmpl @@ -575,6 +575,11 @@ FALSE#slurp Test for a bad aggregation type on a \$day tag: \$day.outTemp.foo $day.outTemp.foo + + + Test for sunshineDur: \$day.sunshineDur.sum + $day.sunshineDur.sum +
diff --git a/bin/weewx/tests/testgen.conf b/bin/weewx/tests/testgen.conf index 98863ddd..1731de59 100644 --- a/bin/weewx/tests/testgen.conf +++ b/bin/weewx/tests/testgen.conf @@ -6,7 +6,7 @@ # # ############################################################################### # # -# Copyright (c) 2009, 2010, 2011, 2021 Tom Keffer # +# Copyright (c) 2009 - 2022 Tom Keffer # # # # See the file LICENSE.txt for your full rights. # # # @@ -117,7 +117,7 @@ version = test # The class to manage the database manager = weewx.manager.DaySummaryManager # For the schema, use the "small" schema. It is much faster. - schema = schemas.wview_small.schema + schema = tst_schema.schema [[alt_binding]] # The database to be used - it should match one of the sections in [Databases] @@ -127,7 +127,7 @@ version = test # The class to manage the database manager = weewx.wxmanager.WXDaySummaryManager # For the "alternate" database, use the "small" schema. - schema = schemas.wview_small.schema + schema = tst_schema.schema [Databases] diff --git a/bin/weewx/tests/tst_schema.py b/bin/weewx/tests/tst_schema.py new file mode 100644 index 00000000..584978e0 --- /dev/null +++ b/bin/weewx/tests/tst_schema.py @@ -0,0 +1,38 @@ +# +# Copyright (c) 2019-2022 Tom Keffer +# +# See the file LICENSE.txt for your full rights. +# +table = [('dateTime', 'INTEGER NOT NULL UNIQUE PRIMARY KEY'), + ('usUnits', 'INTEGER NOT NULL'), + ('interval', 'INTEGER NOT NULL'), + ('altimeter', 'REAL'), + ('barometer', 'REAL'), + ('dewpoint', 'REAL'), + ('ET', 'REAL'), + ('heatindex', 'REAL'), + ('inHumidity', 'REAL'), + ('inTemp', 'REAL'), + ('outHumidity', 'REAL'), + ('outTemp', 'REAL'), + ('pressure', 'REAL'), + ('radiation', 'REAL'), + ('rain', 'REAL'), + ('rainRate', 'REAL'), + ('rxCheckPercent', 'REAL'), + ('sunshineDur', 'REAL'), + ('UV', 'REAL'), + ('windchill', 'REAL'), + ('windDir', 'REAL'), + ('windGust', 'REAL'), + ('windGustDir', 'REAL'), + ('windSpeed', 'REAL'), + ] + +day_summaries = [(e[0], 'scalar') for e in table + if e[0] not in ('dateTime', 'usUnits', 'interval')] + [('wind', 'VECTOR')] + +schema = { + 'table': table, + 'day_summaries' : day_summaries +} diff --git a/bin/weewx/units.py b/bin/weewx/units.py index 49051958..9c8ba8b3 100644 --- a/bin/weewx/units.py +++ b/bin/weewx/units.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (c) 2009-2021 Tom Keffer +# Copyright (c) 2009-2022 Tom Keffer # # See the file LICENSE.txt for your full rights. # @@ -572,7 +572,8 @@ class Formatter(object): def __init__(self, unit_format_dict = None, unit_label_dict = None, time_format_dict = None, - ordinate_names = None): + ordinate_names = None, + deltatime_format_dict = None): """ Args: @@ -583,12 +584,15 @@ class Formatter(object): time_format_dict (dict): Key is a context (e.g., 'week'), value is a strftime format (e.g., "%d-%b-%Y %H:%M"). ordinate_names(list): A list containing ordinal compass names (e.g., ['N', 'NNE', etc.] + deltatime_format_dict (dict): Key is a context (e.g., 'week'), value is a deltatime + format string (e.g., "%(minute)d%(minute_label)s, %(second)d%(second_label)s") """ self.unit_format_dict = unit_format_dict or {} self.unit_label_dict = unit_label_dict or {} self.time_format_dict = time_format_dict or {} self.ordinate_names = ordinate_names or DEFAULT_ORDINATE_NAMES + self.deltatime_format_dict = deltatime_format_dict or {} @staticmethod def fromSkinDict(skin_dict): @@ -614,10 +618,16 @@ class Formatter(object): except KeyError: ordinate_names = {} + try: + deltatime_format_dict = skin_dict['Units']['DeltaTimeFormats'] + except KeyError: + deltatime_format_dict = {} + return Formatter(unit_format_dict, unit_label_dict, time_format_dict, - ordinate_names) + ordinate_names, + deltatime_format_dict) def get_format_string(self, unit): """Return a suitable format string.""" @@ -747,14 +757,10 @@ class Formatter(object): addLabel = False elif val_t[2] == "group_deltatime": # Get a delta-time format string. Use a default if the user did not supply one: - if useThisFormat is None: - # For group_deltatime formatting, the default context cannot be 'current'. - # Change it to something sensible. - if context == 'current': - context = 'delta_time' - format_string = self.time_format_dict.get(context, DEFAULT_DELTATIME_FORMAT) - else: + if useThisFormat: format_string = useThisFormat + else: + format_string = self.deltatime_format_dict.get(context, DEFAULT_DELTATIME_FORMAT) # Now format the delta time, using the function delta_secs_to_string: val_str = self.delta_secs_to_string(val_t[0], format_string) addLabel = False @@ -1629,7 +1635,9 @@ def get_default_formatter(): unit_format_dict=weewx.defaults.defaults['Units']['StringFormats'], unit_label_dict=weewx.defaults.defaults['Units']['Labels'], time_format_dict=weewx.defaults.defaults['Units']['TimeFormats'], - ordinate_names=weewx.defaults.defaults['Units']['Ordinates']['directions']) + ordinate_names=weewx.defaults.defaults['Units']['Ordinates']['directions'], + deltatime_format_dict=weewx.defaults.defaults['Units']['DeltaTimeFormats'] + ) return formatter diff --git a/docs/changes.txt b/docs/changes.txt index f49050d2..54dbef13 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -11,6 +11,10 @@ Different wake-up strategy for the Vantage console. Do not write config_path and entry_path to updated configuration dictionary. Fixes issue #806. +Fix bug that prevents group_deltatime from being used by timespans. Users +who used custom formatting for delta times will be affected. See the Upgrade +Guide. Fixes issue #808. + 4.9.1 10/25/2022 Fix problem with `wind` for older versions of sqlite. diff --git a/docs/upgrading.htm b/docs/upgrading.htm index b53f828f..49e401cf 100644 --- a/docs/upgrading.htm +++ b/docs/upgrading.htm @@ -250,6 +250,60 @@ sudo apt-get install weewx

Instructions for specific versions

+

Upgrading to V4.10

+

Changes for custom delta time formats

+

+ The bad news is that fixing issue #808 required + introducing a separate dictionary for members of group group_deltatime. This + means that if you specified custom formats under [Units]/[[TimeFormats]], then + you will have to move them to the new section [Units]/[[DeltaTimeFormats]]. + Very few users should be affected as being able to set custom delta time formats is an undocumented feature. +

+

+ The good news is that the contexts they now use have more standard names. The table below summarizes: +

+ + + + + + + + + + +
V4.9 and earlier4.10
+
+    def __init__(self, altitude_vt, latitude_f, longitude_f,
+    [[TimeFormats]]
+        ...
+        current     = %x %X
+        ephem_day   = %X
+        ephem_year  = %x %X
+        brief_delta = "%(minute)d%(minute_label)s, %(second)d%(second_label)s"
+        short_delta = "%(hour)d%(hour_label)s, %(minute)d%(minute_label)s, %(second)d%(second_label)s"
+        long_delta  = "%(day)d%(day_label)s, %(hour)d%(hour_label)s, %(minute)d%(minute_label)s"
+        delta_time  = "%(day)d%(day_label)s, %(hour)d%(hour_label)s, %(minute)d%(minute_label)s"
+
+
+
+    [[TimeFormats]]
+        ...
+        current     = %x %X
+        ephem_day   = %X
+        ephem_year  = %x %X
+
+    [[DeltaTimeFormats]]
+        current = "%(minute)d%(minute_label)s, %(second)d%(second_label)s"
+        hour    = "%(minute)d%(minute_label)s, %(second)d%(second_label)s"
+        day     = "%(hour)d%(hour_label)s, %(minute)d%(minute_label)s, %(second)d%(second_label)s"
+        week    = "%(day)d%(day_label)s, %(hour)d%(hour_label)s, %(minute)d%(minute_label)s"
+        month   = "%(day)d%(day_label)s, %(hour)d%(hour_label)s, %(minute)d%(minute_label)s"
+        year    = "%(day)d%(day_label)s, %(hour)d%(hour_label)s, %(minute)d%(minute_label)s"
+
+
+
+

Upgrading to V4.9

wee_reports may require --epoch option.