71 lines
2.1 KiB
Python
71 lines
2.1 KiB
Python
import json
|
|
import os
|
|
from os import path
|
|
|
|
def find_in_parent(filename, starting_dir=None):
|
|
'''Look up the directory tree until you find a file.'''
|
|
if starting_dir is None:
|
|
starting_dir = os.getcwd()
|
|
|
|
candidate_file = path.join(starting_dir, filename)
|
|
|
|
if (path.isfile(candidate_file)):
|
|
return candidate_file
|
|
elif starting_dir == '/':
|
|
raise IOError('File not found in any directory')
|
|
else:
|
|
return find_in_parent(filename, path.dirname(starting_dir))
|
|
|
|
def _parse_composer_manifest(path):
|
|
'''Parse composer.json into dict'''
|
|
with open(path, 'r') as composer_file:
|
|
manifest = json.load(composer_file)
|
|
return manifest
|
|
|
|
def _get_all_autoloaders(manifest):
|
|
'''Combine all PSR-0 and PSR-4 autoloaders'''
|
|
autoloaders = dict()
|
|
|
|
for type in ['psr-0', 'psr-4']:
|
|
autoloaders.update(_get_autoloaders_by_type(manifest, type))
|
|
|
|
return dict((p, ns) for (ns, p) in autoloaders.items())
|
|
|
|
def _get_autoloaders_by_type(manifest, type):
|
|
'''Get one kind of autoloader'''
|
|
try:
|
|
return manifest['autoload'][type]
|
|
except KeyError:
|
|
return dict()
|
|
|
|
def match_path(autoloaders, dirname):
|
|
'''Find namespace for a given path'''
|
|
prefixes = sorted(autoloaders.keys(), key=len)
|
|
|
|
try:
|
|
prefix = next(p for p in prefixes if dirname.startswith(p))
|
|
namespace = autoloaders[prefix]
|
|
remainder = dirname.replace(prefix, '', 1)
|
|
except StopIteration:
|
|
namespace = ''
|
|
remainder = dirname
|
|
|
|
return (namespace, remainder)
|
|
|
|
def convert_path(dirname):
|
|
'''Naively convert path to namespace'''
|
|
return dirname.replace('/', '\\')
|
|
|
|
def get_namespace(dirname):
|
|
'''Convert dirname into namespace intelligently.'''
|
|
composer_json = find_in_parent('composer.json', dirname)
|
|
composer_manifest = _parse_composer_manifest(composer_json)
|
|
repo_root = path.dirname(composer_json)
|
|
relative_path = path.relpath(dirname, repo_root)
|
|
|
|
autoloaders = _get_all_autoloaders(composer_manifest)
|
|
|
|
(namespace, remainder) = match_path(autoloaders, relative_path)
|
|
|
|
return namespace + convert_path(remainder)
|
|
|