# coding=utf-8

import json
import logging
import os
import os.path

class PackageParser:
    DESCRIPTION_FILE = 'index.json'
    KEY_TITLE = 'title'
    KEY_LICENSE = 'license'
    KEY_LICENSE_FILE = 'license-file'
    KEY_FILES = 'files'
    KEY_DESCRIPTION = 'description'
    REQUIRED_KEYS = [KEY_TITLE, KEY_LICENSE, KEY_LICENSE_FILE, KEY_FILES]

    def __init__(self, path, logger=logging.getLogger(__name__)):
        self.path = path
        self.logger = logger

    def get_packages(self):
        packages = []
        for item in os.listdir(self.path):
            self.logger.debug(' * Checking {0}'.format(item))
            if os.path.isdir(os.path.join(self.path, item)):
                self.logger.debug('   - added to the package list')
                packages.append(item)
            else:
                self.logger.debug('   - not a directory')
        return packages

    def get_versions(self, package):
        versions = []
        path = os.path.join(self.path, package)
        for item in os.listdir(path):
            self.logger.debug(' * Checking {0}/{1}'.format(package, item))
            if os.path.isdir(os.path.join(path, item)):
                self.logger.debug('   - added to the version list')
                versions.append(item)
            else:
                self.logger.debug('   - not a directory')
        return versions

    def get_description_path(self, package, version):
        path = os.path.join(self.path, package)
        if version is not None:
            path = os.path.join(path, version)
        return os.path.join(path, PackageParser.DESCRIPTION_FILE)

    def parse_description(self, package, version=None):
        path = self.get_description_path(package, version)
        self.logger.debug(' * Parsing description file {0}'.format(path))
        if not os.path.isfile(path):
            return dict()
        try:
            with open(path) as f:
                self.logger.debug('   - parsing')
                return json.load(f)
        except:
            self.logger.debug('   - failed')
            return dict()

    def validate_description(self, description):
        valid = True
        for key in PackageParser.REQUIRED_KEYS:
            valid = valid and key in description and description[key]
        return valid

    def parse(self):
        result = dict()
        packages = self.get_packages()
        for package in packages:
            package_description = self.parse_description(package)
            versions = self.get_versions(package)
            for version in versions:
                version_description = self.parse_description(package, version)
                for key, value in package_description.iteritems():
                    version_description.setdefault(key, value)
                if self.validate_description(version_description):
                    self.logger.debug(' * Registering package {0}/{1}'.format(package, version))
                    if not package in result:
                        result[package] = dict()
                    result[package][version] = version_description
                else:
                    self.logger.debug(' * Invalid description for {0}/{1}'.format(package, version))
        return result

@@ -3252,8 +3252,1328 @@
  result%0A
+%0A    def validate(self):%0A        success = True%0A        packages = self.get_packages()%0A        for package in packages:%0A            package_description = self.parse_description(package)%0A            versions = self.get_versions(package)%0A            for version in versions:%0A                version_description = self.parse_description(package, version)%0A                path = os.path.join(os.path.join(self.path, package), version)%0A                for key, value in package_description.iteritems():%0A                    version_description.setdefault(key, value)%0A                if not self.validate_description(version_description):%0A                    print %22%7B0%7D/%7B1%7D: description invalid%22.format(package, version)%0A                    success = False%0A                else:%0A                    if not os.path.isfile(os.path.join(path, version_description%5B'license-file'%5D)):%0A                        print %22%7B0%7D/%7B1%7D: license file does not exist%22.format(package, version)%0A                        success = False%0A                    for file in version_description%5B'files'%5D:%0A                        if not os.path.isfile(os.path.join(path, file)):%0A                            print %22%7B0%7D/%7B1%7D: referenced file does not exist: %7B2%7D%22.format(package, version, file)%0A                            success = False%0A        return success%0A

Add validation to parser