Skip to content

Commit

Permalink
fix sync then check command
Browse files Browse the repository at this point in the history
  • Loading branch information
carderne committed Aug 18, 2024
1 parent a325e36 commit 7cb54bf
Show file tree
Hide file tree
Showing 11 changed files with 53 additions and 38 deletions.
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
# una
**Warning: this is pre-alpha and probably doesn't work at all. You'll probably just get frustrated if you even try to use it.**

una is a tool to make Python monorepos with Rye easier. It is a CLI tool and a Hatch plugin that does the following things:
1. Enable builds of individual apps or projects within a monorepo.
2. Ensure that internal and external dependencies are correctly specified.
Expand All @@ -20,8 +18,8 @@ Within this context, we use the following words frequently:

## Examples
You can see examples for each of the two styles here:
- [carderne/una-example-packages](https://github.com/carderne/una-example-packages)
- [carderne/una-example-modules](https://github.com/carderne/una-example-modules)
- [una-example-packages](https://github.com/carderne/una-example-packages)
- [una-example-modules](https://github.com/carderne/una-example-modules)

## Quickstart
This will give you a quick view of how this all works.
Expand Down
7 changes: 5 additions & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# una

**Warning: this is pre-alpha and probably doesn't work at all. You'll probably just get frustrated if you even try to use it.**

una is a tool to make Python monorepos with Rye easier. It is a CLI tool and a Hatch plugin that does the following things:

1. Enable builds of individual apps or projects within a monorepo.
Expand All @@ -21,3 +19,8 @@ Within this context, we use the following words frequently:
- `lib`: a module or package that will be imported but not run.
- `app`: a module or package that will be run but never imported.
- `project`: a package with no code but only dependencies (only used in the `modules` style)

## Examples
You can see examples for each of the two styles here:
- [una-example-packages](https://github.com/carderne/una-example-packages)
- [una-example-modules](https://github.com/carderne/una-example-modules)
4 changes: 4 additions & 0 deletions docs/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,7 @@ And run it:
docker build --tag unarepo-printer .
docker run --rm -it unarepo-printer python -c 'from unarepo.printer import run; run()'
```

## Example
After running through the steps above, the result will be similar to the Projects style example repo:
- [una-example-packages](https://github.com/carderne/una-example-packages)
4 changes: 4 additions & 0 deletions docs/style-modules.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
# Style: Modules

You can see an example of the Modules style here:
- [una-example-modules](https://github.com/carderne/una-example-modules)

This approach is inspired by [Polylith](https://davidvujic.github.io/python-polylith-docs/).
You don't use a Rye workspace (and indeed this approach will work with just Hatch), and there's only a single `pyproject.toml`.

Expand Down
4 changes: 4 additions & 0 deletions docs/style-packages.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
# Style: Packages

You can see an example of the Modules style here:
- [una-example-packages](https://github.com/carderne/una-example-packages)

In this setup, we use Rye's built-in workspace support. The structure will look something like this:
```bash
.
Expand Down
13 changes: 13 additions & 0 deletions una/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,19 @@ def with_ext_deps_from_lock_file(project: Proj) -> Proj:
return project


def enriched_with_lock_file_data(project: Proj, is_verbose: bool) -> Proj:
try:
return with_ext_deps_from_lock_file(project)
except ValueError as e:
if is_verbose:
print(f"{project.name}: {e}")
return project


def enriched_with_lock_files_data(projects: list[Proj], is_verbose: bool) -> list[Proj]:
return [enriched_with_lock_file_data(p, is_verbose) for p in projects]


def collect_known_aliases(project: Proj, options: Options) -> set[str]:
return distributions.known_aliases_and_sub_dependencies(project.ext_deps, options.alias)

Expand Down
37 changes: 12 additions & 25 deletions una/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from typer import Argument, Exit, Option, Typer

from una import check, config, defaults, differ, external_deps, files, internal_deps, sync
from una.types import Options, Proj, Style
from una.types import Options, Style

app = Typer(name="una", no_args_is_help=True, add_completion=False)
create = Typer(no_args_is_help=True)
Expand All @@ -20,24 +20,6 @@
option_quiet = Option(help="Do not output any messages.") # type: ignore[reportAny]


def filtered_projects_data(projects: list[Proj]) -> list[Proj]:
dir_path = Path.cwd().name
return [p for p in projects if dir_path in p.path.as_posix()]


def enriched_with_lock_file_data(project: Proj, is_verbose: bool) -> Proj:
try:
return check.with_ext_deps_from_lock_file(project)
except ValueError as e:
if is_verbose:
print(f"{project.name}: {e}")
return project


def enriched_with_lock_files_data(projects: list[Proj], is_verbose: bool) -> list[Proj]:
return [enriched_with_lock_file_data(p, is_verbose) for p in projects]


@app.command("info")
def info_command(
alias: Annotated[str, option_alias] = "",
Expand All @@ -53,8 +35,8 @@ def info_command(

# Deps on external libraries
projects = internal_deps.get_projects_data(root, ns)
filtered_projects = filtered_projects_data(projects)
merged_projects_data = enriched_with_lock_files_data(filtered_projects, False)
filtered_projects = internal_deps.filtered_projects_data(projects)
merged_projects_data = check.enriched_with_lock_files_data(filtered_projects, False)
results = external_deps.external_deps_from_all(root, ns, merged_projects_data, options)
external_deps.print_libs_in_projects(filtered_projects, options)
if not all(results):
Expand All @@ -80,19 +62,24 @@ def sync_command(
"""Update pyproject.toml with missing int_deps."""
root = config.get_workspace_root()
ns = config.get_ns(root)
projects = internal_deps.get_projects_data(root, ns)
options = Options(
quiet=quiet,
verbose=verbose,
alias=str.split(alias, ",") if alias else [],
)
filtered_projects = filtered_projects_data(projects)
enriched_projects = enriched_with_lock_files_data(filtered_projects, verbose)

if not check_only:
projects = internal_deps.get_projects_data(root, ns)
filtered_projects = internal_deps.filtered_projects_data(projects)
enriched_projects = check.enriched_with_lock_files_data(filtered_projects, verbose)
for p in filtered_projects:
sync.sync_project_int_deps(root, ns, p, options)
config.clear_conf_cache()

# reload projects so any changes made by sync are picked up
projects = internal_deps.get_projects_data(root, ns)
filtered_projects = internal_deps.filtered_projects_data(projects)
enriched_projects = check.enriched_with_lock_files_data(filtered_projects, verbose)
results = {check.check_int_ext_deps(root, ns, p, options) for p in enriched_projects}
if not all(results):
raise Exit(code=1)
Expand Down Expand Up @@ -141,7 +128,7 @@ def project_command(
console = Console(theme=defaults.una_theme)
if style == Style.packages:
console.print("You can't create projects in a Packages style workspace")
exit(1)
raise Exit(code=1)

files.create_project(root, name, "", from_app)
console.print("Success!")
Expand Down
4 changes: 4 additions & 0 deletions una/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ def _load_conf(path: Path) -> Conf:
return load_conf_from_str(f.read())


def clear_conf_cache() -> None:
_load_conf.cache_clear()


def load_conf(path: Path) -> Conf:
fullpath = (path / defaults.pyproj).resolve()
return _load_conf(fullpath)
Expand Down
2 changes: 1 addition & 1 deletion una/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ def create_package(path: Path, name: str, top_dir: str, content: str, dependenci
create_file(
app_dir,
defaults.pyproj,
content,
pyproj_content,
)


Expand Down
4 changes: 4 additions & 0 deletions una/internal_deps.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,10 @@ def get_projects_data(root: Path, ns: str) -> list[Proj]:
return get_int_deps_in_projects(root, lib_names, app_names, ns)


def filtered_projects_data(projects: list[Proj]) -> list[Proj]:
return [p for p in projects if Path.cwd().name in p.path.as_posix()]


def int_dep_status_projects(int_dep: str, int_deps: list[str], for_info: bool) -> str:
emoji = ":heavy_check_mark:" if for_info else ":gear:"
status = emoji if int_dep in int_deps else "-"
Expand Down
6 changes: 0 additions & 6 deletions una/sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,10 @@ def print_summary(diff: Diff) -> None:
name = diff.name
apps_pkgs = diff.apps
libs_pkgs = diff.libs
anything_to_sync = apps_pkgs or libs_pkgs
emoji = ":point_right:" if anything_to_sync else ":heavy_check_mark:"
printable_name = f"[proj]{name}[/]"
console.print(f"{emoji} {printable_name}")
for b in apps_pkgs:
console.print(f"adding [app]{b}[/] app to [proj]{name}[/]")
for c in libs_pkgs:
console.print(f"adding [lib]{c}[/] lib to [proj]{name}[/]")
if anything_to_sync:
console.print("")


def to_package(ns: str, name: str, int_dep_root: str, style: Style) -> Include:
Expand Down

0 comments on commit 7cb54bf

Please sign in to comment.