{"id":23003001,"url":"https://github.com/educationwarehouse/edwh","last_synced_at":"2025-10-25T10:34:30.217Z","repository":{"id":150778666,"uuid":"623519263","full_name":"educationwarehouse/edwh","owner":"educationwarehouse","description":"Education Warehouse environment management - swiss army knife","archived":false,"fork":false,"pushed_at":"2025-07-11T14:34:22.000Z","size":1077,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-08-02T21:19:58.770Z","etag":null,"topics":["edwh","hatch","invoke","python"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/edwh/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/educationwarehouse.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-04-04T14:30:22.000Z","updated_at":"2025-07-11T14:34:26.000Z","dependencies_parsed_at":null,"dependency_job_id":"fcff7a87-ec42-43e7-98e6-90df33b2987b","html_url":"https://github.com/educationwarehouse/edwh","commit_stats":null,"previous_names":[],"tags_count":246,"template":false,"template_full_name":null,"purl":"pkg:github/educationwarehouse/edwh","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/educationwarehouse%2Fedwh","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/educationwarehouse%2Fedwh/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/educationwarehouse%2Fedwh/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/educationwarehouse%2Fedwh/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/educationwarehouse","download_url":"https://codeload.github.com/educationwarehouse/edwh/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/educationwarehouse%2Fedwh/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270347431,"owners_count":24568569,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-13T02:00:09.904Z","response_time":66,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["edwh","hatch","invoke","python"],"created_at":"2024-12-15T07:13:12.203Z","updated_at":"2025-10-25T10:34:25.189Z","avatar_url":"https://github.com/educationwarehouse.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# edwh\n\n[![PyPI - Version](https://img.shields.io/pypi/v/edwh.svg)](https://pypi.org/project/edwh)\n[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/edwh.svg)](https://pypi.org/project/edwh)\n\n-----\n\n**Table of Contents**\n\n- [Installation](#installation)\n- [Usage](#usage)\n- [Plugins](#plugins)\n- [License](#license)\n- [Changelog](#changelog)\n\n## Installation\n\n```console\npipx install edwh\n# or: uvenv install edwh\n\n# or with all plugins:\npipx install[plugins]\n# or with specific plugins: \npipx install[multipass,restic]\n\n# managing plugins later:\nedwh plugins\nedwh plugin.add multipass\nedwh plugin.remove multipass\n```\n\n## Usage\n\n```console\n# to see all available commands:\new # or `edwh`\n# to see help about a specific namespace:\new help \u003cnamespace\u003e # e.g. `ew help plugin`\n# to see help about a specific command:\new help \u003ccommand\u003e # e.g. `ew help plugin.list` \n```\n\n## Task Load Order\n\nCommands are loaded in the following order:\n\n1. **EDWH Package**:\n    - Loaded into the global namespace and its own namespaces (like `ew plugins.`).\n\n2. **Plugins**:\n    - Loaded into their own namespaces (like `ew mp.`).\n\n3. **Current Directory**:\n    - Loaded into the `local.` namespace. If it doesn't exist, it traverses up the directory tree\n    - (e.g., `../tasks.py`, `../../tasks.py`).\n\n4. **Other Local Tasks**:\n    - Other local tasks with their own namespace are loaded (e.g., `namespace.tasks.py`) and can be invoked\n      with `edwh namespace.command`.\n\n5. **Personal Global Tasks**:\n    - Personal global tasks (e.g., `~/.config/edwh/tasks.py`) are also loaded into the **global** namespace, useful for\n      shortcuts, custom aliases, etc. (+ `add_alias`).\n\n6. **Personal Namespaced Tasks**:\n    - Personal tasks with their own namespace (e.g., `~/.config/edwh/namespace.tasks.py`). Similar to a plugin, but for\n      personal use.\n\n## Plugins\n\n### Multipass\n\n- pip name: [`edwh-multipass-plugin`](https://pypi.org/project/edwh-multipass-plugin/)\n- github: [`educationwarehouse/edwh-multipass-plugin`](https://github.com/educationwarehouse/edwh-multipass-plugin)\n- plugin name: `edwh[multipass]`\n- subcommand namespace: `mp`\n\n### Restic\n\n- pip name: [`edwh-restic-plugin`](https://pypi.org/project/edwh-restic-plugin/)\n- github: [`educationwarehouse/edwh-restic-plugin`](https://github.com/educationwarehouse/edwh-restic-plugin)\n- plugin name: `edwh[restic]`\n- subcommand namespace: `restic`\n\n### Pip Compile\n\n- pip name: [`edwh-pipcompile-plugin`](https://pypi.org/project/edwh-pipcompile-plugin/)\n- github: [`educationwarehouse/edwh-pipcompile-plugin`](https://github.com/educationwarehouse/edwh-pipcompile-plugin)\n- plugin name: `edwh[pip]`\n- subcommand namespace: `pip`\n\n### Bundler\n\n- pip name: [`edwh-bundler-plugin`](https://pypi.org/project/edwh-bundler-plugin/)\n- github: [`educationwarehouse/edwh-bundler-plugin`](https://github.com/educationwarehouse/edwh-bundler-plugin)\n- plugin name: `edwh[bundler]`\n- subcommand namespace: `bundle`\n\n### Server Provisioning\n\n- pip name: [`edwh-server-provisioning-plugin`](https://pypi.org/project/edwh-server-provisioning-plugin/)\n- github: [`educationwarehouse/server_provisioning`](https://github.com/educationwarehouse/server_provisioning)\n- plugin name: `edwh[server-provisioning]`\n- subcommand namespace: `remote`\n\n### b2\n\n- pip name: [`edwh-b2-plugin`](https://pypi.org/project/edwh-b2-plugin/)\n- github: [`educationwarehouse/edwh-b2-plugin`](https://github.com/educationwarehouse/edwh-b2-plugin)\n- plugin name: `edwh[b2]`\n- subcommand namespace: `b2`\n\n### Locust\n\n- pip name: [`edwh-locust-plugin`](https://pypi.org/project/edwh-locust-plugin/)\n- github: [`educationwarehouse/edwh-locust-plugin`](https://github.com/educationwarehouse/edwh-locust-plugin)\n- plugin name: `edwh[locust]`\n- subcommand namespace: `locust`\n\n### sshkey\n\n- pip name: [`edwh-sshkey-plugin`](https://pypi.org/project/edwh-sshkey-plugin)\n- github: [`educationwarehouse/edwh-sshkey-plugin`](https://github.com/educationwarehouse/edwh-sshkey-plugin)\n- plugin name `edwh[sshkey]`\n- subcommand namespace `sshkey`\n\n### sshfs\n\n- pip name: [`edwh-sshfs-plugin`](https://pypi.org/project/edwh-sshfs-plugin)\n- github: [`educationwarehouse/edwh-sshfs-plugin`](https://github.com/educationwarehouse/edwh-sshfs-plugin)\n- plugin name `edwh[sshfs]`\n- subcommand namespace `sshfs`\n\n### files\n\n- pip name: [`edwh-files-plugin`](https://pypi.org/project/edwh-files-plugin)\n- github: [`educationwarehouse/edwh-files-plugin`](https://github.com/educationwarehouse/edwh-files-plugin)\n- plugin name `edwh[files]`\n- subcommand namespace `file`\n\n### whitelabel\n\n- pip name: [`edwh-whitelabel-plugin`](https://pypi.org/project/edwh-whitelabel-plugin)\n- github: [`educationwarehouse/edwh-whitelabel-plugin`](https://github.com/educationwarehouse/edwh-whitelabel-plugin)\n- plugin name `edwh[whitelabel]`\n- subcommand namespace `wl`\n\n### devdb\n\n- pip name: [`edwh-devdb-plugin`](https://pypi.org/project/edwh-whitelabel-plugin)\n- github: [`educationwarehouse/edwh-devdb-plugin`](https://github.com/educationwarehouse/edwh-whitelabel-plugin)\n- plugin name `edwh[devdb]`\n- subcommand namespace `devdb`\n\n## Improvements to `@task`\n\nThe `edwh.improved_task` decorator enhances the functionality of the standard `@task` decorator from Invoke by\nintroducing additional features:\n\n- **Flags**: You can now specify custom flags for command line arguments. This allows you to define aliases, rename\n  arguments (e.g., using `--json` for an argument named `as_json`), and create custom short flags (e.g., `--exclude` can\n  also be represented as `-x`).\n\n- **Hookable**: The improved task supports hooks that allow you to run additional tasks after the main task\n  execution. If the `hookable` option is set to `True`, any tasks found across namespaces with the same name will be\n  executed in sequence, passing along the context and any provided arguments.\n\nThe return value of a hookable task will be available in the context under the key `result`.\nUsing a dictionary as the return value is recommended, as it allows you to merge the results of multiple cascading tasks.\n\n### Example Usage\n\n```python\nfrom edwh import improved_task as task\n\n\n@task(flags={'exclude': ['--exclude', '-x'], 'as_json': ['--json']}, hookable=True)\ndef process_data(ctx, exclude: str, as_json: bool = False):\n    # Task implementation here\n    return {\n        \"data\": [],\n    }\n\n\n# other plugin (or local tasks.py) can now also specify 'process_data':\n@task()\ndef process_data(ctx, exclude: str):\n    # the cascading function can choose whether to include the arguments `exclude` and `as_json` or not.\n    # this can be cherry-picked as long as the names match the arguments of the main function.\n    print(\n        ctx[\"result\"] # will contain {\"data\": []}\n    )\n```\n\n## License\n\n`edwh` is distributed under the terms of the [MIT](https://spdx.org/licenses/MIT.html) license.\n\n## Changelog\n\n[See CHANGELOG.md](CHANGELOG.md)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feducationwarehouse%2Fedwh","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feducationwarehouse%2Fedwh","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feducationwarehouse%2Fedwh/lists"}