docs: def generate_meta_features(path, base_learner_id):
      """Generates meta-features for specified base learner
  
      After generation of meta-features, the file is saved into the meta-features folder
  
      Args:
          path (str): Path to Xcessiv notebook
  
          base_learner_id (str): Base learner ID
      """
      with functions.DBContextManager(path) as session:
          base_learner = session.query(models.BaseLearner).filter_by(id=base_learner_id).first()
          if not base_learner:
              raise exceptions.UserError('Base learner {} '
                                         'does not exist'.format(base_learner_id))
  
          base_learner.job_id = get_current_job().id
          base_learner.job_status = 'started'
  
          session.add(base_learner)
          session.commit()
  
          try:
              est = base_learner.return_estimator()
              extraction = session.query(models.Extraction).first()
              X, y = extraction.return_train_dataset()
              return_splits_iterable = functions.import_object_from_string_code(
                  extraction.meta_feature_generation['source'],
                  'return_splits_iterable'
              )
  
              meta_features_list = []
              trues_list = []
              for train_index, test_index in return_splits_iterable(X, y):
                  X_train, X_test = X[train_index], X[test_index]
                  y_train, y_test = y[train_index], y[test_index]
                  est = est.fit(X_train, y_train)
                  meta_features_list.append(
                      getattr(est, base_learner.base_learner_origin.
                              meta_feature_generator)(X_test)
                  )
                  trues_list.append(y_test)
              meta_features = np.concatenate(meta_features_list, axis=0)
              y_true = np.concatenate(trues_list)
  
              for key in base_learner.base_learner_origin.metric_generators:
                  metric_generator = functions.import_object_from_string_code(
                      base_learner.base_learner_origin.metric_generators[key],
                      'metric_generator'
                  )
                  base_learner.individual_score[key] = metric_generator(y_true, meta_features)
  
              meta_features_path = base_learner.meta_features_path(path)
  
              if not os.path.exists(os.path.dirname(meta_features_path)):
                  os.makedirs(os.path.dirname(meta_features_path))
  
              np.save(meta_features_path, meta_features, allow_pickle=False)
              base_learner.job_status = 'finished'
              base_learner.meta_features_exists = True
              session.add(base_learner)
              session.commit()
  
          except:
              session.rollback()
              base_learner.job_status = 'errored'
              base_learner.description['error_type'] = repr(sys.exc_info()[0])
              base_learner.description['error_value'] = repr(sys.exc_info()[1])
              base_learner.description['error_traceback'] = \
                  traceback.format_exception(*sys.exc_info())
              session.add(base_learner)
              session.commit()
              raise