import sys
import pathlib
import os
import shutil
import re
import subprocess
from itertools import count
from glob import iglob
from dataclasses import dataclass
from configparser import ConfigParser
from typing import Optional
@dataclass(init=False)
class ScriptInfo:
name_target: Optional[str] = None
name_original: Optional[str] = None
git_org: Optional[str] = None
path_original: Optional[pathlib.Path] = None
path_target: Optional[pathlib.Path] = None
new_created: bool = False
is_service: bool = False
@staticmethod
def config_path() -> pathlib.Path:
return pathlib.Path("./setup.cfg").absolute()
def load_cfg(config_path: pathlib.Path) -> ConfigParser:
config = ConfigParser()
config.read(str(config_path))
return config
def load_target_name(script_info: ScriptInfo) -> None:
try:
script_info.name_target = sys.argv[1]
except IndexError:
raise ValueError("new name must be passed with name=[name] param")
if "service" in sys.argv:
script_info.is_service = True
if not script_info.name_target:
raise ValueError("new name must be passed with name=[name] param")
def make_new_directory(script_info: ScriptInfo) -> None:
script_info.path_original = pathlib.Path(".").absolute()
script_info.path_target = (
script_info.path_original.parent / f"{script_info.name_target}-go"
)
if script_info.path_target.exists():
raise FileExistsError(f"directory {script_info.path_target} exists")
shutil.copytree(str(script_info.path_original), str(script_info.path_target))
assert script_info.path_target.exists()
script_info.new_created = True
def edit_cfg(script_info: ScriptInfo) -> str:
target_name = script_info.name_target
config = load_cfg(script_info.config_path())
script_info.git_org = config.get("metadata", "git_org")
old_name = config.get("metadata", "name")
config.set("metadata", "name", target_name)
config.set("build_sphinx", "project", target_name)
with open(str(script_info.config_path()), mode="w") as f:
config.write(f)
return old_name
def rewrite_sphinx_conf(target_name: str) -> None:
template_path = pathlib.Path("./zdocs/source/conf-template").absolute()
conf_path = pathlib.Path("./zdocs/source/conf.py").absolute()
template_text = template_path.read_text()
conf_text = template_text.replace("{lib-name-goes-here}", target_name)
conf_path.write_text(conf_text)
def rename_packages(
old_name: str, target_name: str, is_service: bool, git_org: str
) -> None:
search_pattern = "./**/*.go"
go_mod_path = pathlib.Path("./go.mod")
package_regex = re.compile(r"(package) \S+", flags=re.IGNORECASE)
os.remove(str(go_mod_path))
process = subprocess.Popen(["go", "mod", "init", f"{git_org}/{target_name}-go"])
if process.wait(timeout=5) != 0:
raise RuntimeError("could not init gomod")
if is_service:
return
i = 0
for gofile_path_str, i in zip(iglob(search_pattern, recursive=True), count(1)):
gofile_path = pathlib.Path(gofile_path_str)
parent_path: pathlib.Path = pathlib.Path(gofile_path).parent
parent_name = parent_path.name
if parent_name.lower() == "zdevelop":
continue
gofile_content = gofile_path.read_text()
with gofile_path.open(mode="w") as f:
gofile_content = package_regex.sub(f"package {target_name}", gofile_content)
f.write(gofile_content)
i += 1
if i == 0:
raise FileNotFoundError("no packages found in library")
def alter_new(script_info: ScriptInfo) -> None:
old_name = edit_cfg(script_info)
assert script_info.name_target is not None
rewrite_sphinx_conf(script_info.name_target)
path_egg = f"{old_name}.egg-info"
try:
shutil.rmtree(path_egg)
except PermissionError:
os.chmod(path_egg, mode=0o007)
shutil.rmtree(path_egg)
except FileNotFoundError:
pass
assert script_info.git_org is not None
rename_packages(
old_name, script_info.name_target, script_info.is_service, script_info.git_org
)
def main() -> None:
script_info = ScriptInfo()
try:
load_target_name(script_info)
make_new_directory(script_info)
os.chdir(str(script_info.path_target))
alter_new(script_info)
sys.stdout.write(str(script_info.path_target))
except BaseException as this_error:
if script_info.new_created:
shutil.rmtree(str(script_info.path_target))
raise this_error
else:
shutil.rmtree(str(script_info.path_original))
if __name__ == "__main__":
try:
main()
except BaseException as error:
sys.stdout.write("0")
raise error