def test_task_names(): for desc, input_, output in ( ('top level (single)', {'a': 5}, ['a']), ('top level (multiple, sorting)', {'a': 5, 'b': 6}, ['a', 'b']), ('just nested', {'a': {'b': 5}}, ['a.b']), ('mixed', {'a': 5, 'b': {'c': 6}}, ['a', 'b.c']), ('top level comes before nested', {'z': 5, 'b': {'c': 6}}, ['z', 'b.c']), ('peers sorted equally', {'z': 5, 'b': {'c': 6}, 'd': {'e': 7}}, ['z', 'b.c', 'd.e']), ( 'complex tree', { 'z': 5, 'b': { 'c': 6, 'd': { 'e': { 'f': '7' } }, 'g': 8 }, 'h': 9, 'w': { 'y': 10 } }, ['h', 'z', 'b.c', 'b.g', 'b.d.e.f', 'w.y'] ), ): eq_.description = "task name flattening: %s" % desc yield eq_, _task_names(strings_to_tasks(input_)), output del eq_.description
def get_task_list(parts): fabfile = '%s.py' % os.path.join(satellite.commands.__path__[0], *parts) if not os.path.exists(fabfile): return [] docstring, callables, default = load_fabfile(fabfile) callables = dict((k, v) for k, v in callables.iteritems() if v.__module__ == parts[-1]) return _task_names(callables)
def load_blueprints(packages=None): """ Load blueprints/tasks from fabric env """ callables = {} executables = {} # Fallback on blueprints from env packages = packages or fabric.state.env.get('blueprints') or [] #with python_path(): for package in packages: # Import blueprint module package = str(package) blueprint = package.rsplit('.', 1)[-1] imported = __import__(package) # Load tasks _, new_style, classic, _ = load_tasks_from_module(imported) tasks = new_style if fabric.state.env.new_style_tasks else classic if tasks: # Prefix top level imports with module/blueprint name if not package: tasks = {blueprint: tasks} callables.update(tasks) executables[blueprint] = dict((name.split('.', 1)[-1], name) for name in _task_names(tasks)) # Update available tasks for fabric fabric.state.commands.update(callables) # Update available blueprints blueprints.update(executables)
def test_newstyle_task_presence_skips_classic_task_modules(self): """ Classic-task-only modules shouldn't add tasks if any new-style tasks exist """ module = fabfile('deep') with path_prefix(module): docs, funcs = load_fabfile(module) eq_(len(funcs), 1) ok_('submodule.classic_task' not in _task_names(funcs))
def test_recursion_steps_into_nontask_modules(self): """ Recursive loading will continue through modules with no tasks """ module = fabfile('deep') with path_prefix(module): docs, funcs = load_fabfile(module) eq_(len(funcs), 1) ok_('submodule.subsubmodule.deeptask' in _task_names(funcs))
def get_fabric_tasks(request): """ Generate a list of fabric tasks that are available """ try: docstring, callables, default = load_fabfile(find_fabfile(None)) all_tasks = _task_names(callables) dict_with_docs = {task: callables[task].__doc__ for task in all_tasks} except Exception as e: messages.error(request, 'Error loading fabfile: ' + e.message) dict_with_docs = {} return dict_with_docs
def validate_command(cmd): """ Tests whether a command-name is valid: name = fabric.api.prompt(msg, validate=validate_command) """ import fabric.state from fabric.main import _task_names cmd = cmd.strip() if cmd not in _task_names(fabric.state.commands): raise InvalidChoice("%r is not a valid command!" % cmd) return cmd
def get_fabric_tasks(request): """ Generate a list of fabric tasks that are available """ try: docstring, callables, default = load_fabfile(settings.FABFILE_PATH) all_tasks = _task_names(callables) dict_with_docs = {task: callables[task].__doc__ for task in all_tasks} except Exception as e: messages.error(request, "Error loading fabfile: " + str(e)) dict_with_docs = {} return dict_with_docs
def test_task_names(): for desc, input_, output in ( ("top level (single)", {"a": 5}, ["a"]), ("top level (multiple, sorting)", {"a": 5, "b": 6}, ["a", "b"]), ("just nested", {"a": {"b": 5}}, ["a.b"]), ("mixed", {"a": 5, "b": {"c": 6}}, ["a", "b.c"]), ("top level comes before nested", {"z": 5, "b": {"c": 6}}, ["z", "b.c"]), ("peers sorted equally", {"z": 5, "b": {"c": 6}, "d": {"e": 7}}, ["z", "b.c", "d.e"]), ( "complex tree", {"z": 5, "b": {"c": 6, "d": {"e": {"f": "7"}}, "g": 8}, "h": 9, "w": {"y": 10}}, ["h", "z", "b.c", "b.g", "b.d.e.f", "w.y"], ), ): eq_.description = "task name flattening: %s" % desc yield eq_, _task_names(strings_to_tasks(input_)), output del eq_.description
def schema(request): """ Parses the project fabfile and returns API listing the available commands. Commands are made available by adding the @tailored decorator to a fabric function. """ if request.REQUEST.get('key'): if request.REQUEST.get('key') in djangosettings.TAILOR_API_KEYS.values(): fabfile = djangosettings.TAILOR_FABFILE_PATH fabric_dir = os.path.dirname(fabfile) # Custom importer importer = lambda _: imp.load_source('fabfile', fabfile) sys.path.insert(0, fabric_dir) os.chdir(fabric_dir) try: _, task_map, _ = load_fabfile('/fabfile.py', importer) task_list = _task_names(task_map) fab_dict = { 'tasks' : { 'map' : task_map, 'folded' : task_list } } del sys.path[0] response = json.dumps(fab_dict) return HttpResponse(response, mimetype='application/json', status=200) except: return HttpResponse("Failed to build schema", status=500) finally: else: return HttpResponse("API Key Not Recognized", status=403) else: return HttpResponse("API Key Required", status=403)
def prompt_for_command(): import fabric.state from fabric.main import list_commands, _task_names command_list = [ cmd for cmd in list_commands('No command supplied!', 'normal') if not cmd.startswith(' prompt_for_command') and re.subn(r'^ ([^\s]+).*', r'\1', cmd)[0] not in stages.STAGE_NAMES ] print '\n'.join(command_list) + '\n' cmd = None while cmd is None: cmd = prompt(white('Please select a command:', bold=True)).strip() if cmd == 'prompt_for_command': print "Stop being an ass." cmd = None elif cmd not in _task_names(fabric.state.commands): print "%r is not a valid command!" % cmd cmd = None execute(cmd)