Skip to content
Open

Lux cli #1977

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file.
Empty file.
67 changes: 67 additions & 0 deletions mpcontribs-lux/mpcontribs/lux/cli/display/tree.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import pathlib
import tempfile

from rich import print
from rich.markup import escape
from rich.text import Text
from rich.tree import Tree

from mpcontribs.lux.cli.project.utils import build_scaffold


# github.com/textualize/rich/blob/master/examples/tree.py
def walk_directory(directory: pathlib.Path, tree: Tree) -> None:
"""Recursively build a Tree with directory contents."""
paths = sorted(
pathlib.Path(directory).iterdir(),
key=lambda path: (path.is_file(), path.name.lower()),
)
for path in paths:
if path.name.startswith("."):
continue
if path.is_dir():
style = "dim" if path.name.startswith("__") else ""
branch = tree.add(
f"[bold bright_blue] [link file://{path}]{escape(path.name)}",
style=style,
guide_style=style,
)
walk_directory(path, branch)
else:
text_filename = Text(path.name, "white")
text_filename.stylize(f"link file://{path}")
tree.add(text_filename)


def visualize_scaffold(
user_space: str,
projects: set[str],
structure: str,
include_analysis: bool,
include_pipeline: bool,
include_readme: bool,
extra_reqs: bool,
):
tree = Tree(
f"[bold bright_blue] [link file://{user_space}]{user_space}",
guide_style="white",
)

user_space_root = pathlib.Path(__file__).parent.parent.parent.joinpath(
"projects", user_space
)

with tempfile.TemporaryDirectory(prefix=str(user_space_root)) as tmpdir:
build_scaffold(
pathlib.Path(tmpdir),
user_space,
projects,
structure,
include_analysis,
include_pipeline,
include_readme,
extra_reqs,
)

walk_directory(pathlib.Path(tmpdir), tree)
print(tree)
12 changes: 12 additions & 0 deletions mpcontribs-lux/mpcontribs/lux/cli/entry_point.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import click

from mpcontribs.lux.cli.project import project
from mpcontribs.lux.cli.schema import schema


@click.group()
def lux(): ...


lux.add_command(project)
lux.add_command(schema)
10 changes: 10 additions & 0 deletions mpcontribs-lux/mpcontribs/lux/cli/project/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import click

from mpcontribs.lux.cli.project.scaffold import scaffold


@click.group()
def project(): ...


project.add_command(scaffold)
72 changes: 72 additions & 0 deletions mpcontribs-lux/mpcontribs/lux/cli/project/scaffold.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import pathlib

import click

from mpcontribs.lux.cli.display.tree import visualize_scaffold
from mpcontribs.lux.cli.project.utils import build_scaffold


@click.command()
@click.option("--user-space", default=None)
@click.option("--projects", multiple=True, default=None)
@click.option("--structure", type=click.Choice(["directory", "module"]), default=None)
@click.option("--include-analysis", is_flag=True, default=True)
@click.option("--include-pipeline", is_flag=True, default=True)
@click.option("--include-readme", is_flag=True, default=True)
@click.option("--extra-reqs", is_flag=True, default=True)
def scaffold(
user_space,
projects,
structure,
include_analysis,
include_pipeline,
include_readme,
extra_reqs,
):
if any([not x for x in (user_space, structure, projects)]):
user_space = click.prompt("Name space for user project")
structure = click.prompt("Structure of user project [directory, module]")
projects = click.prompt(
"Project names to scaffold in user project name space"
).split(" ")
include_analysis = click.confirm("Include analysis module?")
include_pipeline = click.confirm("Include pipeline module?")
include_readme = click.confirm("Include project README.md?")
extra_reqs = click.confirm(
"Include file for extra python requirements/libraries?"
)

projects = set(projects)

click.echo(
"The following project scaffold will be created in 'mpcontribs-lux.mpcontribs.projects':"
)
visualize_scaffold(
user_space,
projects,
structure,
include_analysis,
include_pipeline,
include_readme,
extra_reqs,
)
if click.confirm("Proceed? y/N", abort=True):
user_space_root = pathlib.Path(__file__).parent.parent.parent.joinpath(
"projects", user_space
)

user_space_root.mkdir()

build_scaffold(
user_space_root,
user_space,
projects,
structure,
include_analysis,
include_pipeline,
include_readme,
extra_reqs,
)
click.echo(
f"Project scaffold created at 'mpcontribs-lux.mpcontribs.projects.{user_space}'!"
)
50 changes: 50 additions & 0 deletions mpcontribs-lux/mpcontribs/lux/cli/project/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import pathlib


def build_scaffold(
root,
user_space,
projects,
structure,
include_analysis,
include_pipeline,
include_readme,
extra_reqs,
):
for proj in projects:
proj_dir = root / proj
proj_dir.mkdir()
pathlib.Path(proj_dir, "__init__.py").touch()

if include_readme:
pathlib.Path(proj_dir, "README.md").touch()
if extra_reqs:
pathlib.Path(proj_dir, "pip-extra-requirements.txt").touch()

match structure:
case "directory":
schema_dir = pathlib.Path(proj_dir) / "schemas"
schema_dir.mkdir()
pathlib.Path(schema_dir, "__init__.py").touch()
pathlib.Path(schema_dir, "schema_1.py").touch()

if include_analysis:
analysis_dir = pathlib.Path(proj_dir) / "analysis"
analysis_dir.mkdir()
pathlib.Path(analysis_dir, "__init__.py").touch()
pathlib.Path(analysis_dir, "analysis_1.py").touch()

if include_pipeline:
pipeline_dir = pathlib.Path(proj_dir) / "pipelines"
pipeline_dir.mkdir()
pathlib.Path(pipeline_dir, "__init__.py").touch()
pathlib.Path(pipeline_dir, "pipeline_1.py").touch()

case "module":
pathlib.Path(proj_dir, "schema_1.py").touch()

if include_analysis:
pathlib.Path(proj_dir, "analysis_1.py").touch()

if include_pipeline:
pathlib.Path(proj_dir, "pipeline_1.py").touch()
11 changes: 11 additions & 0 deletions mpcontribs-lux/mpcontribs/lux/cli/schema/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import click

from mpcontribs.lux.cli.schema.autogen import autogen


@click.group()
def schema():
pass


schema.add_command(autogen)
7 changes: 7 additions & 0 deletions mpcontribs-lux/mpcontribs/lux/cli/schema/autogen.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import click


@click.command()
def autogen():
# TODO: SchemaGenerator(file).pydantic_schema from --file, write output to --output-file (?)
...
7 changes: 7 additions & 0 deletions mpcontribs-lux/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,14 @@ authors = [
Homepage = "https://github.com/materialsproject/MPContribs"
Documentation = "https://docs.materialsproject.org/services/mpcontribs"

[project.scripts]
lux = "mpcontribs.lux.cli.entry_point:lux"

[project.optional-dependencies]
cli = [
"click",
"rich",
]
test = [
"pre-commit",
"pytest",
Expand Down
Loading