diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 0d3930e1..3f83f4d2 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -8,6 +8,9 @@ on: branches: - "master" +env: + FORCE_COLOR: "true" + jobs: build-examples-templates: runs-on: ubuntu-latest diff --git a/cookiecutter/README.md b/cookiecutter/README.md index efaa1d67..00f53cbc 100644 --- a/cookiecutter/README.md +++ b/cookiecutter/README.md @@ -1,10 +1,10 @@ -# Streamlit template for CookieCutter +# Streamlit template for ``cookiecutter`` Template for creating a streamlit component ## Usage -Make sure you have [https://pypi.org/project/cookiecutter/](cookiecutter) installed. To install it, you can use [pipx](https://pypa.github.io/pipx/): +Make sure you have [cookiecutter](https://pypi.org/project/cookiecutter/) installed. To install it, you can use [pipx](https://pypa.github.io/pipx/): ```sh pipx install cookiecutter ``` diff --git a/cookiecutter/cookiecutter.json b/cookiecutter/cookiecutter.json index f78feb0b..35822be7 100644 --- a/cookiecutter/cookiecutter.json +++ b/cookiecutter/cookiecutter.json @@ -14,7 +14,17 @@ "Not open source" ], "framework": [ - "React + Typescript", - "Pure Typescript" - ] + "Pure Typescript", + "React + Typescript" + ], + "__prompts__": { + "author_name": "Your name", + "author_email": "Your e-mail", + "project_name": "Project name", + "package_name": "Package name", + "import_name": "The name of the function that will initialize component", + "description": "Description", + "open_source_license": "Select Open Source License", + "framework": "Which framework you want to use?" + } } diff --git a/cookiecutter/hooks/post_gen_project.py b/cookiecutter/hooks/post_gen_project.py index 1ca13120..01a549c8 100644 --- a/cookiecutter/hooks/post_gen_project.py +++ b/cookiecutter/hooks/post_gen_project.py @@ -1,14 +1,31 @@ import shutil from pathlib import Path +import subprocess project_dir = Path("{{ cookiecutter.import_name }}").absolute() framework = "{{ cookiecutter.framework }}" +frontend_dir = project_dir / "frontend" + if framework == "React + Typescript": - shutil.move(str(project_dir / "frontend-react"), str(project_dir / "frontend")) + shutil.move(str(project_dir / "frontend-react"), str(frontend_dir)) shutil.rmtree(str(project_dir / "frontend-reactless")) elif framework == "Pure Typescript": - shutil.move(str(project_dir / "frontend-reactless"), str(project_dir / "frontend")) + shutil.move(str(project_dir / "frontend-reactless"), str(frontend_dir)) shutil.rmtree(str(project_dir / "frontend-react")) else: raise Exception(f"Unsupported option: {framework!r}") + +print("Compiling frontend") +subprocess.run(["npm", "install"], cwd=frontend_dir) + + +print() +print("Project is ready") +print("To starts development: ") +print("1. Go to new created project:") +print(f" $ cd {project_dir.relative_to(Path.cwd().parent)}") +print() +print("2. Open two terminal and run commands:") +print(" Terminal 1: $ npm run start") +print(f" Terminal 2: $ streamlit run {project_dir.relative_to(Path.cwd())}/__init__.py") diff --git a/cookiecutter/hooks/pre_gen_project.py b/cookiecutter/hooks/pre_gen_project.py new file mode 100644 index 00000000..0ac1b21e --- /dev/null +++ b/cookiecutter/hooks/pre_gen_project.py @@ -0,0 +1,46 @@ +import subprocess +import shutil +import re +import typing + +# Regexp to parse semantic versioning to avoid dependency on external libraries +# For details, see:https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string +SEMVER_REGEXP = re.compile( + r"^(?P0|[1-9]\d*)\." + r"(?P0|[1-9]\d*)\." + r"(?P0|[1-9]\d*)" + r"(?:-(?P(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?" + r"(?:\+(?P[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$" +) + +VersionType = typing.Tuple[int, int, int] + + +def _version_str_to_tuple(version_str) -> VersionType: + result = SEMVER_REGEXP.match(version_str) + return int(result['major']), int(result['minor']), int(result['patch']) + + +def _get_installed_node_version() -> VersionType: + """Return the node version installed on the device.""" + local_node_version = ( + subprocess.check_output(["node", "--version"]).strip().decode().lstrip("v") + ) + return _version_str_to_tuple(local_node_version) + + +def is_node_installed() -> bool: + """Checks if node is installed on the device.""" + return shutil.which("node") is not None + + +if not is_node_installed(): + raise SystemExit("Node is not installed.") + +MIN_NODE_VERSION = _version_str_to_tuple('16.0.0') +local_node_version = _get_installed_node_version() + +if local_node_version < MIN_NODE_VERSION: + raise SystemExit( + f"Node version too old. Current version: {local_node_version}. Max supported version: {MIN_NODE_VERSION}." + ) diff --git a/dev.py b/dev.py index 3b5c812c..11791371 100755 --- a/dev.py +++ b/dev.py @@ -141,12 +141,12 @@ def cmd_check_templates_using_cookiecutter(args): ) run_verbose( [ - "git", - "--no-pager", "diff", - "--no-index", + "-qr", str(output_template), str(cookiecutter_variant.repo_directory), + '--exclude=node_modules', + '--exclude=package-lock.json' ] ) except subprocess.CalledProcessError: