Skip to content

Instantly share code, notes, and snippets.

@momijiame
Last active January 26, 2016 06:24
Show Gist options
  • Save momijiame/849375f7df9d7ea20705 to your computer and use it in GitHub Desktop.
Save momijiame/849375f7df9d7ea20705 to your computer and use it in GitHub Desktop.
Click で Python のインポート可能なパスを受け取るための型
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import importlib
import click
class ImportableType(click.ParamType):
''' Python のインポート可能なパスを受け取るための型 '''
name = 'importable'
def convert(self, value, param, ctx):
# パスをモジュールとアトリビュートの要素に分割する
module_elements = value.split('.')
attr_elements = []
while len(module_elements) > 0:
try:
module_path = '.'.join(module_elements)
importlib.import_module(module_path)
except (ImportError, ValueError):
last_element = module_elements.pop()
attr_elements.insert(0, last_element)
else:
break
if len(module_elements) < 1:
# モジュールを構成する要素がないときはパスが間違っている
message = 'can\'t import module from \'{value}\''.format(value=value) # noqa
self.fail(message, param, ctx)
# 見つかった最も長いパスのモジュールを読み込む
module_path = '.'.join(module_elements)
module = importlib.import_module(module_path)
# アトリビュートを再帰的に取得する
target = module
for attr_name in attr_elements:
try:
target = getattr(target, attr_name)
except AttributeError as e:
self.fail(str(e), param, ctx)
return target
IMPORTABLE = ImportableType()
@click.command()
@click.argument('location', type=IMPORTABLE)
def cmd(location):
click.echo(location)
def main():
cmd()
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment