Skip to content

Commit

Permalink
add support for deploy attribute on <target/> (#743)
Browse files Browse the repository at this point in the history
* add support for deploy attribute

* improved `to_deploy` logic

* test deploy/deploy-dir logic

* revert elaborate example, create project to test deploy stuff programmatically
  • Loading branch information
StevenClontz authored Jun 17, 2024
1 parent 6adc156 commit 4e4e0b3
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 12 deletions.
34 changes: 22 additions & 12 deletions pretext/project/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,22 @@ class Target(pxml.BaseXmlModel, tag="target", search_mode=SearchMode.UNORDERED):
name="braille-mode", default=BrailleMode.EMBOSS
)
stringparams: t.Dict[str, str] = pxml.element(default={})
# A path to the subdirectory of your deployment where this target will live.

# Specify whether this target should be included in a deployment
deploy: t.Optional[str] = pxml.attr(name="deploy", default=None)
# A non-default path to the subdirectory of your deployment where this target will live.
deploy_dir: t.Optional[Path] = pxml.attr(name="deploy-dir", default=None)

# Case-check different combos of `deploy` / `deploy-dir`
def to_deploy(self) -> bool:
deploy = self.deploy
if deploy is None:
# didn't specify `deploy`, so deploy iff there's a `deploy_dir`
return self.deploy_dir is not None
else:
# specified `deploy` attr, so deploy iff choice isn't "no"
return deploy.lower() != "no"

# These attributes have complex validators.
# Note that in each case, since we may not have validated the properties we refer to in values, we should use `values.get` instead of `values[]`.
#
Expand Down Expand Up @@ -329,14 +342,14 @@ def output_dir_abspath(self) -> Path:
def output_dir_relpath(self) -> Path:
return self._project.output_dir / self.output_dir

def deploy_dir_abspath(self) -> t.Optional[Path]:
def deploy_dir_abspath(self) -> Path:
if self.deploy_dir is None:
return None
return self._project.stage_abspath() / self.name
return self._project.stage_abspath() / self.deploy_dir

def deploy_dir_relpath(self) -> t.Optional[Path]:
def deploy_dir_relpath(self) -> Path:
if self.deploy_dir is None:
return None
return self._project.stage / self.name
return self._project.stage / self.deploy_dir

def xsl_abspath(self) -> t.Optional[Path]:
Expand Down Expand Up @@ -1045,6 +1058,7 @@ def server_validator(cls, v: t.List[Server]) -> t.List[Server]:
return v

# This validator sets the `_path`, which is provided in the validation context. It can't be loaded from the XML, since this is metadata about the XML (the location of the file it was loaded from).
# (It's unclear why the typing of the next line is causing issues.)
@model_validator(mode="after")
def set_metadata(self, info: ValidationInfo) -> "Project":
c = info.context
Expand Down Expand Up @@ -1287,7 +1301,7 @@ def init_core(self) -> None:
core.set_executables(exec_dict)

def deploy_targets(self) -> t.List[Target]:
return [target for target in self.targets if target.deploy_dir is not None]
return [tgt for tgt in self.targets if tgt.to_deploy()]

def stage_deployment(self) -> None:
# First empty the stage directory (as long as it is safely in the project directory).
Expand All @@ -1301,8 +1315,6 @@ def stage_deployment(self) -> None:
self.stage_abspath().mkdir(parents=True, exist_ok=True)
# Stage all configured targets for deployment
for target in self.deploy_targets():
deploy_dir = target.deploy_dir
assert deploy_dir is not None
if not target.output_dir_abspath().exists():
log.warning(
f"No build for `{target.name}` was found in the directory `{target.output_dir_abspath()}`."
Expand All @@ -1312,12 +1324,10 @@ def stage_deployment(self) -> None:
else:
shutil.copytree(
target.output_dir_abspath(),
(self.stage_abspath() / deploy_dir).resolve(),
target.deploy_dir_abspath(),
dirs_exist_ok=True,
)
log.info(
f"Staging `{target.name}` at `{self.stage_abspath() / deploy_dir}`."
)
log.info(f"Staging `{target.name}` at `{target.deploy_dir_abspath()}`.")
# If no target is configured to deploy, stage the default target
if len(self.deploy_targets()) == 0:
target = self.get_target()
Expand Down
55 changes: 55 additions & 0 deletions tests/test_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -364,12 +364,67 @@ def test_asset_table(tmp_path: Path) -> None:


def test_deploy(tmp_path: Path) -> None:
# check permutations of deploy / deploy-dir
project = pr.Project(ptx_version="2")

t = project.new_target(
name="none-deploy-none-dir",
format="html",
)
assert not t.to_deploy()
assert t.deploy_dir_relpath().name == t.name

t = project.new_target(
name="no-deploy-none-dir",
format="html",
deploy="no",
)
assert not t.to_deploy()
assert t.deploy_dir_relpath().name == t.name

t = project.new_target(
name="yes-deploy-none-dir",
format="html",
deploy="yes",
)
assert t.to_deploy()
assert t.deploy_dir_relpath().name == t.name

t = project.new_target(
name="none-deploy-custom-dir",
format="html",
deploy_dir="custom",
)
assert t.to_deploy()
assert t.deploy_dir_relpath().name == "custom"

t = project.new_target(
name="no-deploy-custom-dir",
format="html",
deploy="no",
deploy_dir="custom",
)
assert not t.to_deploy()
assert t.deploy_dir_relpath().name == "custom"

t = project.new_target(
name="yes-deploy-custom-dir",
format="html",
deploy="yes",
deploy_dir="custom",
)
assert t.to_deploy()
assert t.deploy_dir_relpath().name == "custom"

# check elaborate settings
prj_path = tmp_path / "elaborate"
shutil.copytree(
EXAMPLES_DIR / "projects" / "project_refactor" / "elaborate", prj_path
)
with utils.working_directory(prj_path):
project = pr.Project.parse()
assert project.get_target("web").to_deploy()
assert not project.get_target("print").to_deploy()
project.get_target("web").build()
assert (prj_path / "build" / "here" / "web" / "index.html").exists()
project.deploy(stage_only=True)
Expand Down

0 comments on commit 4e4e0b3

Please sign in to comment.