code: def hash_callable(
      obj,
      ignore_line_comments=True,
      ignore_first_line=False,
      ignore_module=False,
      ignore_name=False,
      ignore_keywords=False,
      ignore_source_lines=False,
  ):
      """Prepare callable object for hashing by selecting important characterization properties
  
      Parameters
      ----------
      obj: Callable
          Callable to convert to a hashable format. Supports: function, class, `functools.partial`
      ignore_line_comments: Boolean, default=True
          If True, any line comments will be stripped from the source code of `obj`, specifically any
          lines that start with zero or more whitespaces, followed by an octothorpe (#). This does not
          apply to comments on the same line as code
      ignore_first_line: Boolean, default=False
          If True, strip the first line from the callable's source code, specifically its name and
          signature. If `ignore_name=True`, this will be treated as True
      ignore_module: Boolean, default=False
          If True, ignore the name of the module containing the source code (:attr:`obj.__module__`)
      ignore_name: Boolean, default=False
          If True, ignore :attr:`obj.__name__`. Note the difference from `ignore_first_line`, which
          strips the entire callable signature from the source code. `ignore_name` does not alter the
          source code. To ensure thorough ignorance, `ignore_first_line=True` is recommended
      ignore_keywords: Boolean, default=False
          If True and `obj` is a :class:`functools.partial`, ignore :attr:`obj.keywords`
      ignore_source_lines: Boolean, default=False
          If True, all source code will be ignored by the hashing function. Ignoring all other kwargs,
          this means that only :attr:`obj.__module__`, and :attr:`obj.__name__`,
          (and :attr:`obj.keywords` if `obj` is partial) will be used for hashing
  
      Returns
      -------
      Tuple
          Hashable properties of the callable object input"""
      keywords, source_lines = None, None
  
      #################### Clean Up Partial ####################
      if isinstance(obj, partial):
          keywords = None if ignore_keywords else obj.keywords
          obj = (
              obj.func
          )  # Set partial to "func" attr - Expose same functionality as normal callable
  
      #################### Get Identifying Data ####################
      module = None if ignore_module else obj.__module__
      try:
          name = None if ignore_name else obj.__name__
      except AttributeError:
          obj = obj.__class__
          name = obj.__name__
  
      #################### Format Source Code Lines ####################
      if not ignore_source_lines:
          # TODO: Only works on modified Keras `build_fn` in optimization if temp file still exists
          source_lines = getsourcelines(obj)[0]
  
          if ignore_line_comments:
              source_lines = [
                  _ for _ in source_lines if not is_line_comment(_)
              ]
          if (ignore_first_line is True) or (ignore_name is True):
              source_lines = source_lines[1:]
  
      #################### Select Relevant Data ####################
      relevant_data = [
          _
          for _ in [module, name, keywords, source_lines]
          if _ is not None
      ]
      # noinspection PyTypeChecker
      return tuple(to_hashable(relevant_data))
  
file_path: hyperparameter_hunter/hyperparameter_hunter/keys/hashing.py
imports: import base64
  from functools import partial
  import hashlib
  from inspect import getsourcelines
  import pandas
  import re
label_desc: Use image node_id 3 for calling a global function with example usage: hash_callable(obj, ignore_line_comments, ignore_first_line, ignore_module, ignore_name, ignore_keywords, ignore_source_lines) and returns: tuple