text: #!/usr/bin/env python3.8
  # Copyright 2020 The Fuchsia Authors. All rights reserved.
  # Use of this source code is governed by a BSD-style license that can be
  # found in the LICENSE file.
  '''Reads the contents of a package config file generated by the build and
    converts it to a real package_config.json file
  '''
  
  import argparse
  import collections
  import json
  import os
  import re
  import sys
  
  DEFAULT_LANGUAGE_VERSION = "2.8"
  
  Package = collections.namedtuple(
      'Package', ['name', 'rootUri', 'languageVersion', 'packageUri'])
  
  
  class PackageConfig:
      # The version of the package config.
      VERSION = 2
  
      # The name of the generator which gets written to the json output
      GENERATOR_NAME = os.path.basename(__file__)
  
      def __init__(self, packages):
          self.packages = packages
  
      def asdict(self):
          '''Converts the package config to a dictionary'''
          return {
              'configVersion': self.VERSION,
              'packages': [p._asdict() for p in sorted(self.packages)],
              'generator': self.GENERATOR_NAME,
          }
  
  
  def language_version_from_pubspec(pubspec):
      """ parse the content of a pubspec.yaml """
      import yaml
      with open(pubspec) as pubspec:
          parsed = yaml.safe_load(pubspec)
          if not parsed:
              return DEFAULT_LANGUAGE_VERSION
  
          # If a format like sdk: '>=a.b' or sdk: 'a.b' is found, we'll use a.b.
          # In all other cases we default to "2.8"
          env_sdk = parsed.get('environment', {}).get('sdk', 'any')
          match = re.search(r"^(>=)?((0|[1-9]\d*)\.(0|[1-9]\d*))", env_sdk)
          if match:
              min_sdk_version = match.group(2)
          else:
              min_sdk_version = DEFAULT_LANGUAGE_VERSION
  
          return min_sdk_version
  
  
  def collect_packages(items, relative_to):
      '''Reads metadata produced by GN to create lists of packages and pubspecs.
    - items: a list of objects collected from gn
    - relative_to: The directory which the packages are relative to. This is
                    the location that contains the package_config.json file
  
    Returns None if there was a problem parsing packages
    '''
      packages = []
      pubspec_paths = []
      for item in items:
          if 'language_version' in item:
              language_version = item['language_version']
          elif 'pubspec_path' in item:
              pubspec_paths.append(item['pubspec_path'])
              language_version = language_version_from_pubspec(
                  item['pubspec_path'])
          else:
              language_version = DEFAULT_LANGUAGE_VERSION
  
          package = Package(
              name=item['name'],
              rootUri=os.path.relpath(item['root_uri'], relative_to),
              languageVersion=language_version,
              packageUri=item['package_uri'])
  
          #TODO(fxbug.dev/56428): enable once we sort out our duplicate packages
          # for p in packages:
          #   if p.rootUri == package.rootUri:
          #     print('Failed to create package_config.json file')
          #     print('The following packages contain the same package root ' + p.rootUri)
          #     print('  - ' + p.rootUri)
          #     print('  - ' + package.rootUri)
          #     return None
  
          packages.append(package)
  
      return packages, pubspec_paths
  
  
  def main():
      parser = argparse.ArgumentParser(description=__doc__)
      parser.add_argument(
          '--input', help='Path to original package_config', required=True)
      parser.add_argument(
          '--output', help='Path to the updated package_config', required=True)
      parser.add_argument('--root', help='Path to fuchsia root', required=True)
      parser.add_argument('--depfile', help='Path to the depfile', required=True)
      args = parser.parse_args()
  
      sys.path += [os.path.join(args.root, 'third_party', 'pyyaml', 'lib3')]
  
      with open(args.input, 'r') as input_file:
          contents = json.load(input_file)
  
      output_dir = os.path.dirname(os.path.abspath(args.output))
      packages, pubspec_paths = collect_packages(contents, output_dir)
      if packages is None:
          return 1
  
      with open(args.depfile, 'w') as depfile:
          depfile.write('%s: %s' % (args.output, ' '.join(pubspec_paths)))
  
      with open(args.output, 'w') as output_file:
          package_config = PackageConfig(packages)
          json.dump(
              package_config.asdict(),
              output_file,
              indent=2,
              sort_keys=True,
              separators=(',', ': '))
  
      return 0
  
  
  if __name__ == '__main__':
      sys.exit(main())
  