tsio/register-formula: do not lose the previous user metadata in case of an update
2 files changed, 23 insertions(+), 4 deletions(-)

M test/test_formula.py
M tshistory_formula/tsio.py
M test/test_formula.py +18 -2
@@ 197,15 197,31 @@ def test_user_meta(engine, tsh):
 
     meta = tsh.metadata(engine, 'test_user_meta')
     assert meta['foo'] == 42
+    assert meta == {
+        'foo': 42,
+        'index_dtype': '|M8[ns]',
+        'index_type': 'datetime64[ns, UTC]',
+        'tzaware': True,
+        'value_dtype': '<f8',
+        'value_type': 'float64'
+    }
 
     tsh.register_formula(
         engine,
         'test_user_meta',
-        '(+ 3 (series "user_metadata"))',
+        '(+ 3 (naive (series "user_metadata")))',
         update=True
     )
     meta = tsh.metadata(engine, 'test_user_meta')
-    assert 'foo' not in meta
+    # user meta preserved, core meta correctly updated
+    assert meta == {
+        'foo': 42,
+        'index_dtype': '<M8[ns]',
+        'index_type': 'datetime64[ns]',
+        'tzaware': False,
+        'value_dtype': '<f8',
+        'value_type': 'float64'
+    }
 
 
 def test_series_options(engine, tsh):

          
M tshistory_formula/tsio.py +5 -2
@@ 113,7 113,8 @@ class timeseries(basets):
                          reject_unknown=True, update=False):
         if not update:
             assert not self.formula(cn, name), f'`{name}` already exists'
-        if self.exists(cn, name) and self.type(cn, name) == 'primary':
+        update = self.exists(cn, name)
+        if update and self.type(cn, name) == 'primary':
             raise TypeError(
                 f'primary series `{name}` cannot be overriden by a formula'
             )

          
@@ 168,7 169,9 @@ class timeseries(basets):
             # bad situation ...
             return
 
-        meta = self.default_meta(tzaware)
+        coremeta = self.default_meta(tzaware)
+        meta = self.metadata(cn, name) if update else {}
+        meta = dict(meta, **coremeta)
         self.update_metadata(cn, name, meta, internal=True)
 
     def default_meta(self, tzaware):