def run(self, parsed_args): """Run the command.""" lib_name = parsed_args.name valid_all_chars = set(string.ascii_lowercase + string.digits + '_') valid_first_char = string.ascii_lowercase if set(lib_name) - valid_all_chars or not lib_name or lib_name[0] not in valid_first_char: raise CommandError( "Invalid library name. Must only use lowercase alphanumeric " "characters and underscore, starting with alpha.") charm_name = get_name_from_metadata() if charm_name is None: raise CommandError( "Cannot find a valid charm name in metadata.yaml. Check you are in a charm " "directory with metadata.yaml.") # '-' is valid in charm names, but not in a python import # mutate the name so the path is a valid import importable_charm_name = create_importable_name(charm_name) # all libraries born with API version 0 full_name = 'charms.{}.v0.{}'.format(importable_charm_name, lib_name) lib_data = _get_lib_info(full_name=full_name) lib_path = lib_data.path if lib_path.exists(): raise CommandError('This library already exists: {}'.format(lib_path)) store = Store(self.config.charmhub) lib_id = store.create_library_id(charm_name, lib_name) # create the new library file from the template env = get_templates_environment('charmlibs') template = env.get_template('new_library.py.j2') context = dict(lib_id=lib_id) try: lib_path.parent.mkdir(parents=True, exist_ok=True) lib_path.write_text(template.render(context)) except OSError as exc: raise CommandError( "Error writing the library in {}: {!r}.".format(lib_path, exc)) logger.info("Library %s created with id %s.", full_name, lib_id) logger.info("Consider 'git add %s'.", lib_path)
def run(self, args): """Execute command's actual functionality.""" if any(self.config.project.dirpath.iterdir()) and not args.force: raise CommandError( "{} is not empty (consider using --force to work on nonempty directories)" .format(self.config.project.dirpath)) logger.debug("Using project directory '%s'", self.config.project.dirpath) if args.author is None: gecos = pwd.getpwuid(os.getuid()).pw_gecos.split(",", 1)[0] if not gecos: raise CommandError( "Author not given, and nothing in GECOS field") logger.debug("Setting author to %r from GECOS field", gecos) args.author = gecos if not args.name: args.name = self.config.project.dirpath.name logger.debug("Set project name to '%s'", args.name) if not re.match(r"[a-z][a-z0-9-]*[a-z0-9]$", args.name): raise CommandError("{} is not a valid charm name".format( args.name)) context = { "name": args.name, "author": args.author, "year": date.today().year, "class_name": "".join(re.split(r"\W+", args.name.title())) + "Charm", } env = get_templates_environment("init") _todo_rx = re.compile("TODO: (.*)") todos = [] executables = ["run_tests", "src/charm.py"] for template_name in env.list_templates(): if not template_name.endswith(".j2"): continue template = env.get_template(template_name) template_name = template_name[:-3] logger.debug("Rendering %s", template_name) path = self.config.project.dirpath / template_name if path.exists(): continue path.parent.mkdir(parents=True, exist_ok=True) with path.open("wt", encoding="utf8") as fh: out = template.render(context) fh.write(out) for todo in _todo_rx.findall(out): todos.append((template_name, todo)) if template_name in executables: make_executable(fh) logger.debug(" made executable") logger.info( "Charm operator package file and directory tree initialized.") if todos: logger.info("TODO:") logger.info("") w = max(len(i[0]) for i in todos) for fn, todo in todos: logger.info("%*s: %s", w + 2, fn, todo)
def run(self, args): """Execute command's actual functionality.""" init_dirpath = self.config.project.dirpath if not init_dirpath.exists(): init_dirpath.mkdir(parents=True) elif any(init_dirpath.iterdir()) and not args.force: tpl = "{!r} is not empty (consider using --force to work on nonempty directories)" raise CommandError(tpl.format(str(init_dirpath))) emit.trace(f"Using project directory {str(init_dirpath)!r}") if args.author is None and pwd is not None: args.author = _get_users_full_name_gecos() if not args.author: raise CommandError( "Unable to automatically determine author's name, specify it with --author" ) if not args.name: args.name = init_dirpath.name emit.trace(f"Set project name to '{args.name}'") if not re.match(r"[a-z][a-z0-9-]*[a-z0-9]$", args.name): raise CommandError("{} is not a valid charm name".format( args.name)) context = { "name": args.name, "author": args.author, "year": date.today().year, "class_name": "".join(re.split(r"\W+", args.name.title())) + "Charm", } env = get_templates_environment("init") _todo_rx = re.compile("TODO: (.*)") todos = [] executables = ["run_tests", "src/charm.py"] for template_name in env.list_templates(): if not template_name.endswith(".j2"): continue template = env.get_template(template_name) template_name = template_name[:-3] emit.trace(f"Rendering {template_name}") path = init_dirpath / template_name if path.exists(): continue path.parent.mkdir(parents=True, exist_ok=True) with path.open("wt", encoding="utf8") as fh: out = template.render(context) fh.write(out) for todo in _todo_rx.findall(out): todos.append((template_name, todo)) if template_name in executables and os.name == "posix": make_executable(fh) emit.trace(" made executable") emit.message( "Charm operator package file and directory tree initialized.") if todos: emit.message("TODO:") emit.message("") width = max(len(i[0]) for i in todos) + 2 for fn, todo in todos: emit.message(f"{fn:>{width}s}: {todo}")