old_contents: # pyinfra
  # File: pyinfra_cli/config.py
  # Desc: config handling for the CLI
  
  import ast
  
  from os import path
  
  import six
  
  from pyinfra.api import Config
  from pyinfra.api.util import exec_file
  
  
  def _extract_config_assignments(filename, config):
      with open(filename, 'r') as f:
          data = ast.parse(f.read())
  
      for node in data.body:
          if not isinstance(node, ast.Assign):
              continue
  
          # Named Python objects (eg True/False/None)
          if isinstance(node.value, ast.Name):
              if node.value.id == 'True':
                  value = True
              elif node.value.id == 'False':
                  value = False
              else:
                  value = None
  
          # NameConstant is Python 3+ only
          elif six.PY3 and isinstance(node.value, ast.NameConstant):
              value = node.value.value
  
          # Strings
          elif isinstance(node.value, ast.Str):
              value = node.value.s
  
          # Integers
          elif isinstance(node.value, ast.Num):
              value = node.value.n
  
          # Config cannot be anything else
          else:
              continue
  
          # If one of the assignments matches a config variable (eg SUDO = True)
          # then assign it to the config object!
          for target in node.targets:
              if hasattr(config, target.id):
                  setattr(config, target.id, value)
  
  
  def load_config(deploy_dir):
      '''
      Loads any local config.py file.
      '''
  
      config = Config()
      config_filename = path.join(deploy_dir, 'config.py')
  
      if path.exists(config_filename):
          _extract_config_assignments(config_filename, config)
  
          # Now execute the file to trigger loading of any hooks
          exec_file(config_filename)
  
      return config
  
  
  def load_deploy_config(deploy_filename, config):
      '''
      Loads any local config overrides in the deploy file.
      '''
  
      if not deploy_filename:
          return
  
      if path.exists(deploy_filename):
          _extract_config_assignments(deploy_filename, config)
  
      return config
  
new_contents: # pyinfra
  # File: pyinfra_cli/config.py
  # Desc: config handling for the CLI
  
  import ast
  
  from os import path
  
  import six
  
  from pyinfra.api import Config
  from pyinfra.api.util import exec_file
  
  
  def _extract_config_assignments(filename, config):
      with open(filename, 'r') as f:
          data = f.read()
  
      ast_data = ast.parse(data, filename=filename)
  
      for node in ast_data.body:
          if not isinstance(node, ast.Assign):
              continue
  
          # Named Python objects (eg True/False/None)
          if isinstance(node.value, ast.Name):
              if node.value.id == 'True':
                  value = True
              elif node.value.id == 'False':
                  value = False
              else:
                  value = None
  
          # NameConstant is Python 3+ only
          elif six.PY3 and isinstance(node.value, ast.NameConstant):
              value = node.value.value
  
          # Strings
          elif isinstance(node.value, ast.Str):
              value = node.value.s
  
          # Integers
          elif isinstance(node.value, ast.Num):
              value = node.value.n
  
          # Config cannot be anything else
          else:
              continue
  
          # If one of the assignments matches a config variable (eg SUDO = True)
          # then assign it to the config object!
          for target in node.targets:
              if hasattr(config, target.id):
                  setattr(config, target.id, value)
  
  
  def load_config(deploy_dir):
      '''
      Loads any local config.py file.
      '''
  
      config = Config()
      config_filename = path.join(deploy_dir, 'config.py')
  
      if path.exists(config_filename):
          _extract_config_assignments(config_filename, config)
  
          # Now execute the file to trigger loading of any hooks
          exec_file(config_filename)
  
      return config
  
  
  def load_deploy_config(deploy_filename, config):
      '''
      Loads any local config overrides in the deploy file.
      '''
  
      if not deploy_filename:
          return
  
      if path.exists(deploy_filename):
          _extract_config_assignments(deploy_filename, config)
  
      return config
  
subject: Improve AST parsing exceptions by specifying the filename.