docs: def register_commands(package=None, version=None, release=None, srcdir='.'):
      """
      This function generates a dictionary containing customized commands that
      can then be passed to the ``cmdclass`` argument in ``setup()``.
      """
  
      if package is not None:
          warnings.warn('The package argument to generate_version_py has '
                        'been deprecated and will be removed in future. Specify '
                        'the package name in setup.cfg instead', AstropyDeprecationWarning)
  
      if version is not None:
          warnings.warn('The version argument to generate_version_py has '
                        'been deprecated and will be removed in future. Specify '
                        'the version number in setup.cfg instead', AstropyDeprecationWarning)
  
      if release is not None:
          warnings.warn('The release argument to generate_version_py has '
                        'been deprecated and will be removed in future. We now '
                        'use the presence of the "dev" string in the version to '
                        'determine whether this is a release', AstropyDeprecationWarning)
  
      # We use ConfigParser instead of read_configuration here because the latter
      # only reads in keys recognized by setuptools, but we need to access
      # package_name below.
      conf = ConfigParser()
      conf.read('setup.cfg')
  
      if conf.has_option('metadata', 'name'):
          package = conf.get('metadata', 'name')
      elif conf.has_option('metadata', 'package_name'):
          # The package-template used package_name instead of name for a while
          warnings.warn('Specifying the package name using the "package_name" '
                        'option in setup.cfg is deprecated - use the "name" '
                        'option instead.', AstropyDeprecationWarning)
          package = conf.get('metadata', 'package_name')
      elif package is not None:  # deprecated
          pass
      else:
          sys.stderr.write('ERROR: Could not read package name from setup.cfg\n')
          sys.exit(1)
  
      if _module_state['registered_commands'] is not None:
          return _module_state['registered_commands']
  
      if _module_state['have_sphinx']:
          try:
              from .commands.build_sphinx import (AstropyBuildSphinx,
                                                  AstropyBuildDocs)
          except ImportError:
              AstropyBuildSphinx = AstropyBuildDocs = FakeBuildSphinx
      else:
          AstropyBuildSphinx = AstropyBuildDocs = FakeBuildSphinx
  
      _module_state['registered_commands'] = registered_commands = {
          'test': generate_test_command(package),
  
          # Use distutils' sdist because it respects package_data.
          # setuptools/distributes sdist requires duplication of information in
          # MANIFEST.in
          'sdist': DistutilsSdist,
  
          'build_ext': AstropyHelpersBuildExt,
          'build_sphinx': AstropyBuildSphinx,
          'build_docs': AstropyBuildDocs
      }
  
      # Need to override the __name__ here so that the commandline options are
      # presented as being related to the "build" command, for example; normally
      # this wouldn't be necessary since commands also have a command_name
      # attribute, but there is a bug in distutils' help display code that it
      # uses __name__ instead of command_name. Yay distutils!
      for name, cls in registered_commands.items():
          cls.__name__ = name
  
      # Add a few custom options; more of these can be added by specific packages
      # later
      for option in [
              ('use-system-libraries',
               "Use system libraries whenever possible", True)]:
          add_command_option('build', *option)
          add_command_option('install', *option)
  
      add_command_hooks(registered_commands, srcdir=srcdir)
  
      return registered_commands