Repository: sunpy/sunpy

Issue:
TimeSeriesMetaData isn't a valid metadata type to TimeSeries factory
Dict like objects are fine, but our own metadata object isn't!!


Discussion:
I'll have a go at fixing this for Hacktoberfest, if that is okay?
@sadielbartholomew that is perfectly fine. 
hey @sadielbartholomew how did you get on with this?:)
Hi there @hayesla, I didn't get onto this sadly. I'm still happy to give it a go but it will be a week or two before I can put in a PR, so if someone else wants or needs to take over I completely understand. Sorry for being a bit optimistic about how much I could do for Hacktoberfest!
Hey @sadielbartholomew  - no worries just wanted to check in to see if you needed any assistance with it :)
@sadielbartholomew  hi, are you still working on this? 
Hi, due to unanticipated events I never got to start this, sorry! Please consider me unassigned as I don't think I will have time to address this. I'll let someone else step in.
Um. I have a doubt. When you say ``Dict like objects are fine, but our own metadata object isn't!!``, do you mean that the there shouldn't be a separate metadata object and we should use a simple dictionary or do you mean that there is a bug in the custom object?
The latter. It seems that we can't pass in our own metaclass to create a timesseries (how was there not a test for this?)

Resolving patch:
diff --git a/sunpy/timeseries/timeseries_factory.py b/sunpy/timeseries/timeseries_factory.py
--- a/sunpy/timeseries/timeseries_factory.py
+++ b/sunpy/timeseries/timeseries_factory.py
@@ -150,6 +150,8 @@ def _validate_meta(meta):
             return True
         elif isinstance(meta, dict):
             return True
+        elif isinstance(meta, sunpy.timeseries.TimeSeriesMetaData):
+            return True
         else:
             return False
 
@@ -287,7 +289,11 @@ def _parse_args(self, *args, **kwargs):
                                 # to preserve multi-line comments
                                 if isinstance(args[i+1], astropy.io.fits.header.Header):
                                     args[i+1] = MetaDict(sunpy.io.header.FileHeader(args[i+1]))
-                                meta.update(args[i+1])
+                                if isinstance(args[i+1], sunpy.timeseries.TimeSeriesMetaData):
+                                    for j in args[i+1].metas:
+                                        meta.update(j)
+                                else:
+                                    meta.update(args[i+1])
                                 i += 1  # an extra increment to account for the meta
 
                 # Add a 3-tuple for this TimeSeries.


Test patch:
diff --git a/sunpy/timeseries/tests/test_timeseries_factory.py b/sunpy/timeseries/tests/test_timeseries_factory.py
--- a/sunpy/timeseries/tests/test_timeseries_factory.py
+++ b/sunpy/timeseries/tests/test_timeseries_factory.py
@@ -273,6 +273,7 @@ def test_generic_construction_basic_different_meta_types(self):
         base = parse_time(datetime.datetime.today())
         times = base - TimeDelta(np.arange(24 * 60)*u.minute)
         intensity = np.sin(np.arange(0, 12 * np.pi, ((12 * np.pi) / (24*60))))
+        tr = sunpy.time.TimeRange(times[0], times[-1])
 
         # Create the data DataFrame, header MetaDict and units OrderedDict
         data = DataFrame(intensity, index=times, columns=['intensity'])
@@ -280,13 +281,16 @@ def test_generic_construction_basic_different_meta_types(self):
         meta_md = MetaDict({'key': 'value'})
         meta_di = {'key': 'value'}
         meta_od = OrderedDict({'key': 'value'})
+        meta_obj = sunpy.timeseries.TimeSeriesMetaData(timerange=tr, colnames=['GOES'],
+                                                       meta=MetaDict({'key': 'value'}))
 
         # Create TS using different dictionary meta types
         ts_md = sunpy.timeseries.TimeSeries(data, meta_md, units)
         ts_di = sunpy.timeseries.TimeSeries(data, meta_di, units)
         ts_od = sunpy.timeseries.TimeSeries(data, meta_od, units)
-        assert ts_md == ts_di == ts_od
-        assert ts_md.meta.metadata[0][2] == ts_di.meta.metadata[0][2] == ts_od.meta.metadata[0][2]
+        ts_obj = sunpy.timeseries.TimeSeries(data, meta_obj, units)
+        assert ts_md == ts_di == ts_od == ts_obj
+        assert ts_md.meta.metadata[0][2] == ts_di.meta.metadata[0][2] == ts_od.meta.metadata[0][2] == ts_obj.meta.metadata[0][2]
 
     def test_generic_construction_ts_list(self):
         # Generate the data and the corrisponding dates
@@ -431,6 +435,9 @@ def test_validate_meta_basic(self):
         assert sunpy.timeseries.TimeSeries._validate_meta(valid_meta_1)
         valid_meta_2 = OrderedDict({'key': 'value'})
         assert sunpy.timeseries.TimeSeries._validate_meta(valid_meta_2)
+        time_range = sunpy.time.TimeRange('2020-01-01 12:00', '2020-01-02 12:00')
+        valid_meta_3 = sunpy.timeseries.TimeSeriesMetaData(time_range)
+        assert sunpy.timeseries.TimeSeries._validate_meta(valid_meta_3)
         invalid_meta = []
         assert not sunpy.timeseries.TimeSeries._validate_meta(invalid_meta)