code: def _data_checks_pivot_longer(
      df,
      index,
      column_names,
      names_to,
      values_to,
      column_level,
      names_sep,
      names_pattern,
      names_transform,
      dropna,
      sort_by_appearance,
      ignore_index,
  ) -> tuple:
      """
      This function raises errors if the arguments have the wrong python type,
      or if an unneeded argument is provided. It also raises errors for some
      other scenarios(e.g if there are no matches returned for the regular
      expression in `names_pattern`, or if the dataframe has MultiIndex
      columns and `names_sep` or `names_pattern` is provided).
  
      This function is executed before proceeding to the computation phase.
  
      Type annotations are not provided because this function is where type
      checking happens.
      """
  
      # checks here are only on the columns
      # a slice is safe
      df = df[:]
  
      if column_level is not None:
          check("column_level", column_level, [int, str])
          df.columns = df.columns.get_level_values(column_level)
  
      if any((names_sep, names_pattern)) and (
          isinstance(df.columns, pd.MultiIndex)
      ):
          raise ValueError(
              "Unpivoting a MultiIndex column dataframe "
              "when names_sep or names_pattern is supplied "
              "is not supported."
          )
  
      if all((names_sep is None, names_pattern is None)):
          # adapted from pandas' melt source code
          if (
              (index is not None)
              and isinstance(df.columns, pd.MultiIndex)
              and (not isinstance(index, list))
          ):
              raise ValueError(
                  "index must be a list of tuples "
                  "when the columns are a MultiIndex."
              )
  
          if (
              (column_names is not None)
              and isinstance(df.columns, pd.MultiIndex)
              and (not isinstance(column_names, list))
          ):
              raise ValueError(
                  "column_names must be a list of tuples "
                  "when the columns are a MultiIndex."
              )
  
      is_multi_index = isinstance(df.columns, pd.MultiIndex)
      if column_names is not None:
          if is_multi_index:
              column_names = _check_tuples_multiindex(
                  df.columns, column_names, "column_names"
              )
          else:
              if is_list_like(column_names):
                  column_names = list(column_names)
              column_names = get_index_labels(
                  column_names, df, axis="columns"
              )
              if not is_list_like(column_names):
                  column_names = [column_names]
              else:
                  column_names = list(column_names)
  
      if index is not None:
          if is_multi_index:
              index = _check_tuples_multiindex(
                  df.columns, index, "index"
              )
          else:
              if is_list_like(index):
                  index = list(index)
              index = get_index_labels(index, df, axis="columns")
              if not is_list_like(index):
                  index = [index]
              else:
                  index = list(index)
  
      if index is None:
          if column_names is None:
              column_names = df.columns.tolist()
          else:
              index = df.columns.difference(
                  column_names, sort=False
              ).tolist()
      else:
          if column_names is None:
              column_names = df.columns.difference(
                  index, sort=False
              ).tolist()
  
      if names_to is not None:
          if isinstance(names_to, str):
              names_to = [names_to]
          elif isinstance(names_to, tuple):
              names_to = [*names_to]
  
          check("names_to", names_to, [list, str, tuple])
  
          uniques = set()
          for word in names_to:
              check(f"'{word}' in names_to", word, [str])
              if (word in uniques) and (word != ".value"):
                  raise ValueError(
                      f"'{word}' is duplicated in names_to."
                  )
              uniques.add(word)
  
      else:
          if not any((names_sep, names_pattern)):
              names_to = ["variable"]
  
      check("values_to", values_to, [str, list, tuple])
      if isinstance(values_to, (list, tuple)):
          if not isinstance(names_pattern, (list, tuple)):
              raise TypeError(
                  "values_to can be a list/tuple only "
                  "if names_pattern is a list/tuple."
              )
          if index:
              exclude = set(values_to).intersection(index)
              if exclude:
                  raise ValueError(
                      f"Labels {*exclude, } in values_to already exist as "
                      "column labels assigned to the dataframe's "
                      "index parameter. Kindly use unique labels."
                  )
      if (
          (names_sep is None)
          and (names_pattern is None)
          and index
          and (values_to in index)
      ):
          raise ValueError(
              "The argument provided to values_to "
              "already exist as a column label "
              "assigned to the dataframe's index parameter. "
              "Kindly use a unique label."
          )
  
      if names_sep and names_pattern:
          raise ValueError(
              "Only one of names_pattern or names_sep should be provided."
          )
  
      if names_pattern is not None:
          check(
              "names_pattern",
              names_pattern,
              [str, Pattern, list, tuple, dict],
          )
          if isinstance(names_pattern, (str, Pattern)):
              regex = re.compile(names_pattern)
              if names_to is None:
                  if regex.groupindex:
                      names_to = regex.groupindex.keys()
                      names_to = [
                          ".value"
                          if ("_" in name) and (len(set(name)) == 1)
                          else name
                          for name in names_to
                      ]
                      len_names_to = len(names_to)
                  else:
                      raise ValueError(
                          "Kindly provide values for names_to."
                      )
              else:
                  len_names_to = len(names_to)
              if len_names_to != regex.groups:
                  raise ValueError(
                      f"The length of names_to does not match "
                      "the number of groups in names_pattern. "
                      f"The length of names_to is {len_names_to} "
                      "while the number of groups in the regex "
                      f"is {regex.groups}."
                  )
  
          elif isinstance(names_pattern, (list, tuple)):
              if names_to is None:
                  raise ValueError(
                      "Kindly provide values for names_to."
                  )
              for word in names_pattern:
                  check(
                      f"'{word}' in names_pattern", word, [str, Pattern]
                  )
              len_names_to = len(names_to)
              if len(names_pattern) != len_names_to:
                  raise ValueError(
                      f"The length of names_to does not match "
                      "the number of regexes in names_pattern. "
                      f"The length of names_to is {len_names_to} "
                      f"while the number of regexes is {len(names_pattern)}."
                  )
  
              if names_to and (".value" in names_to):
                  raise ValueError(
                      ".value is not accepted in names_to "
                      "if names_pattern is a list/tuple."
                  )
  
              if isinstance(values_to, (list, tuple)):
                  if len(values_to) != len(names_pattern):
                      raise ValueError(
                          f"The length of values_to does not match "
                          "the number of regexes in names_pattern. "
                          f"The length of values_to is {len(values_to)} "
                          f"while the number of regexes is {len(names_pattern)}."
                      )
                  uniques = set()
                  for word in values_to:
                      check(f"{word} in values_to", word, [str])
                      if word in names_to:
                          raise ValueError(
                              f"'{word}' in values_to "
                              "already exists in names_to."
                          )
  
                      if word in uniques:
                          raise ValueError(
                              f"'{word}' is duplicated in values_to."
                          )
                      uniques.add(word)
          # outer keys belong to names_to
          # if the values are dicts,
          # then the inner key belongs to values_to
          # inner keys should not exist in the outer keys
          # non keys belong to names_pattern
          elif isinstance(names_pattern, dict):
              if names_to is not None:
                  raise ValueError(
                      "names_to should be None "
                      "when names_pattern is a dictionary"
                  )
              for key, value in names_pattern.items():
                  check(f"'{key}' in names_pattern", key, [str])
                  if index and (key in index):
                      raise ValueError(
                          f"'{key}' in the names_pattern dictionary "
                          "already exists as a column label "
                          "assigned to the index parameter. "
                          "Kindly use a unique name"
                      )
              names_to = list(names_pattern)
              is_dict = (
                  isinstance(arg, dict)
                  for _, arg in names_pattern.items()
              )
              if all(is_dict):
                  values_to = []
                  patterns = []
                  for key, value in names_pattern.items():
                      if len(value) != 1:
                          raise ValueError(
                              "The length of the dictionary paired "
                              f"with '{key}' in names_pattern "
                              "should be length 1, instead got "
                              f"{len(value)}"
                          )
                      for k, v in value.items():
                          if not isinstance(k, str):
                              raise TypeError(
                                  "The key in the nested dictionary "
                                  f"for '{key}' in names_pattern "
                                  "should be a string, instead got {type(k)}"
                              )
                          if k in names_pattern:
                              raise ValueError(
                                  f"'{k}' in the nested dictionary "
                                  "already exists as one of the main "
                                  "keys in names_pattern"
                              )
                          if index and (k in index):
                              raise ValueError(
                                  f"'{k}' in the nested dictionary "
                                  "already exists as a column label "
                                  "assigned to the index parameter. "
                                  "Kindly use a unique name"
                              )
                          check(
                              f"The value paired with '{k}' "
                              "in the nested dictionary in names_pattern",
                              v,
                              [str, Pattern],
                          )
                          patterns.append(v)
                          values_to.append(k)
              else:
                  patterns = []
                  for key, value in names_pattern.items():
                      check(
                          f"The value paired with '{key}' "
                          "in the names_pattern dictionary",
                          value,
                          [str, Pattern],
                      )
  
                      patterns.append(value)
              names_pattern = patterns
              patterns = None
  
      if names_sep is not None:
          check("names_sep", names_sep, [str, Pattern])
          if names_to is None:
              raise ValueError("Kindly provide values for names_to.")
  
      dot_value = (names_to is not None) and (
          (".value" in names_to)
          or (isinstance(names_pattern, (list, tuple)))
      )
  
      # avoid duplicate columns in the final output
      if (names_to is not None) and (not dot_value):
          if values_to in names_to:
              raise ValueError(
                  "The argument provided for values_to "
                  "already exists in names_to; "
                  "Kindly use a unique name."
              )
          # idea is that if there is no `.value`
          # then the label should not exist in the index
          # there is no need to check the columns
          # since that is what we are replacing with names_to
          if index:
              exclude = set(names_to).intersection(index)
              if exclude:
                  raise ValueError(
                      f"Labels {*exclude, } in names_to already exist "
                      "as column labels assigned to the dataframe's "
                      "index parameter. Kindly provide unique label(s)."
                  )
  
      check("dropna", dropna, [bool])
  
      check("sort_by_appearance", sort_by_appearance, [bool])
  
      check("ignore_index", ignore_index, [bool])
  
      if isinstance(df.columns, pd.MultiIndex):
          if not any(df.columns.names):
              if len(names_to) == 1:
                  names = [
                      f"{names_to[0]}_{i}"
                      for i in range(df.columns.nlevels)
                  ]
                  df.columns = df.columns.set_names(names)
              elif len(names_to) == df.columns.nlevels:
                  df.columns = df.columns.set_names(names_to)
              else:
                  raise ValueError(
                      "The length of names_to does not match "
                      "the number of levels in the columns. "
                      f"names_to has a length of {len(names_to)}, "
                      "while the number of column levels is "
                      f"{df.columns.nlevels}."
                  )
          elif None in df.columns.names:
              raise ValueError(
                  "Kindly ensure there is no None "
                  "in the names for the column levels."
              )
      elif (
          not isinstance(df.columns, pd.MultiIndex)
          and not any((names_sep, names_pattern))
          and (not df.columns.names[0])
      ):
          df.columns = pd.Index(df.columns, name=names_to[0])
  
      return (
          df,
          index,
          column_names,
          names_to,
          values_to,
          names_sep,
          names_pattern,
          names_transform,
          dropna,
          sort_by_appearance,
          ignore_index,
      )
  
imports: import re
  import warnings
  from collections import defaultdict
  from itertools import chain, zip_longest
  from typing import Callable, Optional, Pattern, Union
  import numpy
  import pandas
  import pandas_flavor
  from pandas.api.types import is_categorical_dtype, is_extension_array_dtype, is_list_like
  from pandas.core.dtypes.concat import concat_compat
  from janitor.functions.utils import _computations_expand_grid, get_index_labels
  from janitor.utils import check, refactored_function
label_desc: Use image node_id 2 for calling a global function with example usage: _data_checks_pivot_longer(df, index, column_names, names_to, values_to, column_level, names_sep, names_pattern, names_transform, dropna, sort_by_appearance, ignore_index) and returns: df,  index,  column_names,  names_to,  values_to,  names_sep,  names_pattern,  names_transform,  dropna,  sort_by_appearance,  ignore_index