<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def flatten(weights):
 """ Flatten weights into a long DataFrame. Parameters weights: pandas.DataFrame or dict A DataFrame of instrument weights with a MultiIndex where the top level contains pandas. Timestamps and the second level is instrument names. The columns consist of generic names. If dict is given this should be a dict of pandas.DataFrame in the above format, with keys for different root generics, e.g. 'CL' Returns ------- A long DataFrame of weights, where columns are "date", "contract", "generic" and "weight". If a dictionary is passed, DataFrame will contain additional colum "key" containing the key value and be sorted according to this key value. Example ------- """
  # NOQA
    if isinstance(weights, pd.DataFrame):
        wts = weights.stack().reset_index()
        wts.columns = ["date", "contract", "generic", "weight"]
    elif isinstance(weights, dict):
        wts = []
        for key in sorted(weights.keys()):
            wt = weights[key].stack().reset_index()
            wt.columns = ["date", "contract", "generic", "weight"]
            wt.loc[:, "key"] = key
            wts.append(wt)
        wts = pd.concat(wts, axis=0).reset_index(drop=True)
    else:
        raise ValueError("weights must be pd.DataFrame or dict")

    return wts