def list_pattern(topics): project = topics[0] be = _extern.load_be(project) templates = _extern.load_templates(project) inventory = _extern.load_inventory(project) # Get item try: key = be.get("templates", {}).get("key") or "{1}" item = _format.item_from_topics(key, topics) binding = _format.binding_from_item(inventory, item) except KeyError: return [] except IndexError as exc: raise IndexError("At least %s topics are required" % str(exc)) fields = _format.replacement_fields_from_context(context(project)) binding = _format.binding_from_item(inventory, item) pattern = _format.pattern_from_template(templates, binding) # 2 arguments, {1}/{2}/{3} -> {1}/{2} # 2 arguments, {1}/{2}/assets/{3} -> {1}/{2}/assets index_end = pattern.index(str(len(topics)-1)) + 2 trimmed_pattern = pattern[:index_end] # If there aren't any more positional arguments, we're done if not re.findall("{[\d]+}", pattern[index_end:]): return [] # Append trail # e.g. {1}/{2}/assets # ^^^^^^^ try: index_trail = pattern[index_end:].index("{") trail = pattern[index_end:index_end + index_trail - 1] trimmed_pattern += trail except ValueError: pass try: path = trimmed_pattern.format(*topics, **fields) except IndexError: raise IndexError("Template for \"%s\" has unordered " "positional arguments: \"%s\"" % (item, pattern)) if not os.path.isdir(path): return [] items = list() for dirname in os.listdir(path): if not os.path.isdir(os.path.join(path, dirname)): continue items.append(dirname) return items
def in_(ctx, topics, yes, as_, enter): """Set the current topics to `topics` Environment: BE_PROJECT: First topic BE_CWD: Current `be` working directory BE_TOPICS: Arguments to `in` BE_DEVELOPMENTDIR: Absolute path to current development directory BE_PROJECTROOT: Absolute path to current project BE_PROJECTSROOT: Absolute path to where projects are located BE_ACTIVE: 0 or 1, indicates an active be environment BE_USER: Current user, overridden with `--as` BE_SCRIPT: User-supplied shell script BE_PYTHON: User-supplied python script BE_ENTER: 0 or 1 depending on whether the topic was entered BE_GITHUB_API_TOKEN: Optional GitHub API token BE_ENVIRONMENT: Space-separated list of user-added environment variables BE_TEMPDIR: Directory in which temporary files are stored BE_PRESETSDIR: Directory in which presets are searched BE_ALIASDIR: Directory in which aliases are written BE_BINDING: Binding between template and item in inventory \b Usage: $ be in project topics """ topics = map(str, topics) # They enter as unicode if self.isactive(): lib.echo("ERROR: Exit current project first") sys.exit(lib.USER_ERROR) # Determine topic syntax if len(topics[0].split("/")) == 3: topic_syntax = lib.FIXED project = topics[0].split("/")[0] else: topic_syntax = lib.POSITIONAL project = topics[0] project_dir = _format.project_dir(_extern.cwd(), project) if not os.path.exists(project_dir): lib.echo("Project \"%s\" not found. " % project) lib.echo("\nAvailable:") ctx.invoke(ls) sys.exit(lib.USER_ERROR) # Boot up context = lib.context(project) be = _extern.load_be(project) templates = _extern.load_templates(project) inventory = _extern.load_inventory(project) context.update({ "BE_PROJECT": project, "BE_USER": str(as_), "BE_ENTER": "1" if enter else "", "BE_TOPICS": " ".join(topics) }) # Remap topic syntax, for backwards compatibility # In cases where the topic is entered in a way that # differs from the template, remap topic to template. if any(re.findall("{\d+}", pattern) for pattern in templates.values()): template_syntax = lib.POSITIONAL else: template_syntax = lib.FIXED if topic_syntax & lib.POSITIONAL and not template_syntax & lib.POSITIONAL: topics = ["/".join(topics)] if topic_syntax & lib.FIXED and not template_syntax & lib.FIXED: topics[:] = topics[0].split("/") try: key = be.get("templates", {}).get("key") or "{1}" item = _format.item_from_topics(key, topics) binding = _format.binding_from_item(inventory, item) context["BE_BINDING"] = binding except IndexError as exc: lib.echo("At least %s topics are required" % str(exc)) sys.exit(lib.USER_ERROR) except KeyError as exc: lib.echo("\"%s\" not found" % item) if exc.bindings: lib.echo("\nAvailable:") for item_ in sorted(exc.bindings, key=lambda a: (exc.bindings[a], a)): lib.echo("- %s (%s)" % (item_, exc.bindings[item_])) sys.exit(lib.USER_ERROR) # Finally, determine a development directory # based on the template-, not topic-syntax. if template_syntax & lib.POSITIONAL: try: development_dir = _format.pos_development_directory( templates=templates, inventory=inventory, context=context, topics=topics, user=as_, item=item) except KeyError as exc: lib.echo("\"%s\" not found" % item) if exc.bindings: lib.echo("\nAvailable:") for item_ in sorted(exc.bindings, key=lambda a: (exc.bindings[a], a)): lib.echo("- %s (%s)" % (item_, exc.bindings[item_])) sys.exit(lib.USER_ERROR) else: # FIXED topic_syntax development_dir = _format.fixed_development_directory( templates, inventory, topics, as_) context["BE_DEVELOPMENTDIR"] = development_dir tempdir = (tempfile.mkdtemp() if not os.environ.get("BE_TEMPDIR") else os.environ["BE_TEMPDIR"]) context["BE_TEMPDIR"] = tempdir # Should it be entered? if enter and not os.path.exists(development_dir): create = False if yes: create = True else: sys.stdout.write("No development directory found. Create? [Y/n]: ") if raw_input().lower() in ("", "y", "yes"): create = True if create: ctx.invoke(mkdir, dir=development_dir) else: sys.stdout.write("Cancelled") sys.exit(lib.NORMAL) # Parse be.yaml if "script" in be: context["BE_SCRIPT"] = _extern.write_script( be["script"], tempdir) if "python" in be: script = "\n".join(be["python"]) context["BE_PYTHON"] = script try: exec script in {"__name__": __name__} except Exception as e: lib.echo("ERROR: %s" % e) invalids = [v for v in context.values() if not isinstance(v, str)] assert all(isinstance(v, str) for v in context.values()), invalids # Create aliases aliases_dir = _extern.write_aliases( be.get("alias", {}), tempdir) context["PATH"] = (aliases_dir + os.pathsep + context.get("PATH", "")) context["BE_ALIASDIR"] = aliases_dir # Parse redirects _format.parse_redirect( be.get("redirect", {}), topics, context) # Override inherited context # with that coming from be.yaml. if "environment" in be: parsed = _format.parse_environment( fields=be["environment"], context=context, topics=topics) context["BE_ENVIRONMENT"] = " ".join(parsed.keys()) context.update(parsed) if "BE_TESTING" in context: os.chdir(development_dir) os.environ.update(context) else: parent = lib.parent() cmd = lib.cmd(parent) # Store reference to calling shell context["BE_SHELL"] = parent try: sys.exit(subprocess.call(cmd, env=context)) finally: import shutil shutil.rmtree(tempdir)