-
Notifications
You must be signed in to change notification settings - Fork 0
0.3.0 Release -- Major refactor and stability branch #8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
birdcar
wants to merge
24
commits into
main
Choose a base branch
from
refactor-for-beta-release
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
a4ea73c
Add miniconda as a pyenv version for testing
birdcar 0a0c8a7
Disable wordwrap my default for non python files
birdcar 78c3d51
Create a managers subpackage and a base manager class
birdcar 7af93c1
Add tests for the forthcoming venv-based manager
birdcar 4593c21
Create the venv-based manager, based on the base manager API
birdcar 7e991c2
Skip initial version of dependency installation tests
birdcar 88edf4e
Add stubs for new (sub)package organization
birdcar d9ca084
Add module and package docstrings to silence linter warnings
birdcar 14003bc
Add tox-pyenv as a plugin/dependency for testing
birdcar 9b5ee1e
Configure tox-pyenv with a conda specific test environment
birdcar 19eb04b
Change the kwarg on install_dependencies from 'quiet' to 'verbose'
birdcar 39350ad
Update local variables in VenvManager to match CondaManager style
birdcar 6b1550f
Remove custom pytest fixture in favor of tmp_path
birdcar fb9d5df
Make docstring for the devwrangler.managers.venv module more consistent
birdcar 48e817d
Write initial test for the devwrangler.managers.conda:CondaManager class
birdcar 0f1e09d
Implement the Anaconda based environment manager
birdcar f89fcaf
Configure logging for devwrangler and pydev
birdcar 1f6183e
Refactor shell:run_command utility for better logging and flexibility
birdcar 5a938bb
Add current working directory as default work_dir in Base manager
birdcar eb0e762
Add display utilities using Rich
birdcar eb2dcd9
Create first pass on new CLI api
birdcar 5e53592
Erase old CLI code and expose the new typer app in the CLI module
birdcar 7f9dd52
Add basic ergonomic usage example
birdcar 9cf9a8a
Replace the application specified by pyproject.toml
birdcar File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,3 +2,4 @@ | |
| 3.9.7 | ||
| 3.8.12 | ||
| 3.7.12 | ||
| miniconda3-4.7.12 | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,39 +1,5 @@ | ||
| """Typer-based CLI for devwrangler.""" | ||
| from pathlib import Path | ||
|
|
||
| import typer | ||
|
|
||
| from .devwrangler import ( | ||
| create_virtual_environment, | ||
| parse_config_file, | ||
| set_workspace_settings, | ||
| ) | ||
|
|
||
| APP_NAME = 'devwrangler' | ||
|
|
||
| PROJECT_ROOT = Path.cwd() | ||
| VENV_PATH = PROJECT_ROOT / ".venv" | ||
|
|
||
|
|
||
| def main( | ||
| req_file: str = typer.Argument('requirements-dev.txt'), | ||
| dev: bool = typer.Argument(True), | ||
| ): | ||
| """CLI main function.""" | ||
| app_dir = typer.get_app_dir(APP_NAME, force_posix=True) | ||
| config_file_path: Path = Path(app_dir) / 'config.json' | ||
|
|
||
| # check if config data exists, if not, proceed with default config | ||
| if not config_file_path.exists(): | ||
| typer.echo(f"Config file not found at {config_file_path}") | ||
| typer.echo("Using our default configuration") | ||
| config_data = parse_config_file() | ||
| else: | ||
| config_data = parse_config_file(config_file_path) | ||
|
|
||
| create_virtual_environment(VENV_PATH, logger=typer.echo) | ||
| set_workspace_settings(config_data, workspace_path=(PROJECT_ROOT / '.vscode')) | ||
|
|
||
| from .commands import app | ||
|
|
||
| if __name__ == '__main__': | ||
| main() | ||
| app() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| """Devwrangler's CLI package: pydev.""" | ||
| import typer | ||
|
|
||
| from devwrangler.commands.configure import config_app | ||
| from devwrangler.commands.create import create_app | ||
| from devwrangler.utilities.display import STD_ERR, STD_OUT | ||
|
|
||
| app = typer.Typer(name="devwrangler") | ||
| app.add_typer(create_app, name='create', invoke_without_command=True) | ||
| app.add_typer(config_app, name="configure", invoke_without_command=True) | ||
|
|
||
|
|
||
| @app.callback(invoke_without_command=True) | ||
| def main(ctx: typer.Context): | ||
| """Bringing Peace, Justice, and Security to your Python empire.""" | ||
| if ctx.invoked_subcommand is None: | ||
| with STD_OUT.status("Generating environment..."): | ||
| STD_OUT.print("Gathering configuration from environment...") | ||
| STD_ERR.print("NO CONFIGURATION FOUND") | ||
| ctx.invoke(app.registered_groups) | ||
| ctx.invoke(config_app.registered_callback) | ||
|
|
||
|
|
||
| if __name__ == '__main__': | ||
| app() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| """Typer command module for the `configure` command.""" | ||
| from enum import Enum | ||
|
|
||
| import typer | ||
|
|
||
| from ..utilities.display import STD_OUT | ||
|
|
||
| config_app = typer.Typer() | ||
|
|
||
|
|
||
| class Editor(Enum): | ||
| """Enum of valid editor options.""" | ||
|
|
||
| vscode = "vscode" | ||
|
|
||
|
|
||
| def parse_extras(extras: str) -> tuple: | ||
| """Parse a comma separated options list provided by the user.""" | ||
| return tuple(s.strip() for s in extras.split(',')) | ||
|
|
||
|
|
||
| @config_app.callback('configure') | ||
| def configure( | ||
| editor: Editor = typer.Option( | ||
| 'vscode', | ||
| metavar="e", | ||
| help="The editor you'd like configured for development", | ||
| ), | ||
| extras: str = typer.Option( | ||
| "black,bandit,flake8,jinja2,mypy,isort", | ||
| metavar="x", | ||
| help="Extras to enable and configure in your editor (see docs for supported options)", | ||
| callback=parse_extras, | ||
| ), | ||
| ): | ||
| """Configure an editor to use an already configured dev environment.""" | ||
| STD_OUT.print("Configuring VS Code...") | ||
| STD_OUT.print(f"Configuring extras {extras} in {editor.value}") | ||
|
|
||
|
|
||
| if __name__ == '__main__': | ||
| config_app() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| """Typer command module for the Create command.""" | ||
| from enum import Enum | ||
| from pathlib import Path | ||
|
|
||
| import typer | ||
|
|
||
| from ..managers import CondaManager, VenvManager | ||
| from ..utilities.display import STD_OUT | ||
|
|
||
| PROJECT_ROOT = Path.cwd() | ||
| VENV_PATH = PROJECT_ROOT / ".venv" | ||
|
|
||
| create_app = typer.Typer() | ||
|
|
||
|
|
||
| class Manager(Enum): | ||
| """An Enum containing the valid managers a user may pick from.""" | ||
|
|
||
| conda = "conda" | ||
| venv = "venv" | ||
|
|
||
|
|
||
| @create_app.callback() | ||
| def main( | ||
| env: Manager = typer.Option( | ||
| 'venv', | ||
| metavar="e", | ||
| ) | ||
| ): | ||
| """Create a developer environment.""" | ||
| STD_OUT.print(f"[bold green]Creating {env.value} environment...[/]") | ||
| if env == Manager.venv: | ||
| venv = VenvManager() | ||
| venv.create() | ||
| venv.install_dependencies() | ||
| elif env == Manager.conda: | ||
| conda = CondaManager() | ||
| conda.create() | ||
| conda.install_dependencies() | ||
|
|
||
|
|
||
| if __name__ == '__main__': | ||
| create_app() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| """Managers exposed for use by devwrangler's CLI: pydev.""" | ||
| from .conda import CondaManager | ||
| from .venv import VenvManager |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| """Defines an Abstract Base Class (ABC) to Standardize the API for various environment managers.""" | ||
| import abc | ||
| import platform | ||
| from pathlib import Path | ||
|
|
||
| from ..utilities.shell import run_command | ||
|
|
||
|
|
||
| class BaseManager(abc.ABC): | ||
| """A standard API for various environment managers.""" | ||
|
|
||
| def __init__(self, work_dir: Path = Path.cwd()): | ||
| """Initialize a virtual environment model with venv.""" | ||
| self.prefixes = { | ||
| 'windows': 'Scripts/python.exe', | ||
| } | ||
| self.venv_path = work_dir / ".venv" | ||
| self.cmd = run_command | ||
|
|
||
| @property | ||
| def prefix(self) -> Path: | ||
| """Return the path to the python executable for the virtual environment.""" | ||
| return self.venv_path.joinpath( | ||
| self.prefixes.get(platform.system().lower(), "bin/python") | ||
| ) | ||
|
|
||
| @abc.abstractmethod | ||
| def create(self): | ||
| """Create a sandboxed virtual environment with the specific manager.""" | ||
| pass | ||
|
|
||
| @abc.abstractmethod | ||
| def install_dependencies(self, verbose: bool = False): | ||
| """Install dependencies into a created environment.""" | ||
| pass |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| """A wrapper for creating an Anaconda-based dev environment.""" | ||
| import shutil as sh | ||
| from pathlib import Path | ||
|
|
||
| from .base import BaseManager | ||
|
|
||
|
|
||
| class CondaManager(BaseManager): | ||
| """A manager for conda and it's environment.""" | ||
|
|
||
| def create(self): | ||
| """Create a conda environment in the location specified by venv_path.""" | ||
| if not sh.which("conda"): | ||
| raise FileNotFoundError("No conda executable found in your $PATH") | ||
|
|
||
| self.cmd( | ||
| [ | ||
| "conda", | ||
| "create", | ||
| "-y", | ||
| "--quiet", | ||
| "--prefix", | ||
| str(self.venv_path), | ||
| "python", | ||
| ] | ||
| ) | ||
|
|
||
| def install_dependencies(self, verbose: bool = False): | ||
| """Install dependencies from conda's environment.yml file in the root of your project.""" | ||
| if not sh.which("conda"): | ||
| raise FileNotFoundError("No conda executable found in your $PATH") | ||
|
|
||
| if not (Path.cwd() / "environment.yml").exists(): | ||
| raise FileNotFoundError( | ||
| "No environment.yml file round in the project directory" | ||
| ) | ||
|
|
||
| CONDA_CMD = [ | ||
| "conda", | ||
| "env", | ||
| "update", | ||
| "--prefix", | ||
| str(self.venv_path), | ||
| "--file", | ||
| "environment.yml", | ||
| "--prune", | ||
| ] | ||
|
|
||
| if not verbose: | ||
| CONDA_CMD.append("--quiet") | ||
|
|
||
| self.cmd(CONDA_CMD, critical=True) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| """A wrapper for creating a venv-based dev environment.""" | ||
| import venv | ||
|
|
||
| from .base import BaseManager | ||
|
|
||
|
|
||
| class VenvManager(BaseManager): | ||
| """Manage virtual environments with Python's 'venv' module.""" | ||
|
|
||
| def create(self): | ||
| """Create a virtual environment using venv.""" | ||
| venv.create( | ||
| self.venv_path, | ||
| with_pip=True, | ||
| prompt=self.venv_path.parent.name, | ||
| ) | ||
|
|
||
| def install_dependencies(self, verbose: bool = False): | ||
| """Install environment dependencies.""" | ||
| PIP_CMD = [ | ||
| str(self.prefix), | ||
| "-m", | ||
| "pip", | ||
| "install", | ||
| "-U", | ||
| "pip", | ||
| "setuptools", | ||
| ] | ||
|
|
||
| if not verbose: | ||
| PIP_CMD.append("-qqq") | ||
|
|
||
| self.cmd(PIP_CMD, critical=True) |
Empty file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| -r base.txt | ||
| -r test.txt |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| -r base.txt | ||
| -r test.txt |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| -r base.txt |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| { | ||
| "recommendations": [ | ||
| "ms-python.python", | ||
| "ms-python.vscode-pylance", | ||
| "hbenl.vscode-test-explorer", | ||
| "littlefoxteam.vscode-python-test-adapter", | ||
| "ms-vscode.test-adapter-converter", | ||
| "samuelcolvin.jinjahtml", | ||
| "batisteo.vscode-django", | ||
| "bungcip.better-toml" | ||
| ] | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| { | ||
| "editor.formatOnSave": true, | ||
| "files.associations": { | ||
| "**/*.html": "html", | ||
| {% if config["use_django"] %} | ||
| "**/templates/**/*": "django-txt", | ||
| "**/templates/**/*.html": "django-html", | ||
| {% else %} | ||
| "**/templates/**/*": "jinja", | ||
| {% for ext, kind in config["jinja"]["types"].items() %} | ||
| "**/templates/**/*.html": "jinja-{{ kind }}", | ||
| {% endfor %} | ||
| {% endif %} | ||
| "**/requirements{/**,*}.{txt,in}": "pip-requirements" | ||
| }, | ||
| "python.analysis.diagnosticPublishDelay": 1000, | ||
| "python.analysis.disabled": [], | ||
| "python.analysis.errors": [ | ||
| "inherit-non-class", | ||
| "no-cls-argument", | ||
| "no-self-argument", | ||
| "parameter-already-specified", | ||
| "parameter-missing", | ||
| "positional-argument-after-keyword", | ||
| "positional-only-named", | ||
| "return-in-init", | ||
| "typing-generic-arguments", | ||
| "typing-typevar-arguments", | ||
| "typing-newtype-arguments", | ||
| "unresolved-import", | ||
| "undefined-variable" | ||
| ], | ||
| "python.analysis.warnings": [ | ||
| "unknown-parameter-name", | ||
| "variable-not-defined-globally", | ||
| "variable-not-defined-nonlocal" | ||
| ], | ||
| "python.analysis.information": [ | ||
| "too-many-function-arguments", | ||
| "too-many-positional-arguments-before-star", | ||
| "no-method-argument" | ||
| ], | ||
| "python.autoComplete.addBrackets": true, | ||
| "python.formatting.provider": "black", | ||
| "python.languageServer": "Pylance", | ||
| "python.linting.banditEnabled": true, | ||
| "python.linting.flake8Enabled": true, | ||
| "python.linting.flake8Args": ["--max-line-length", "88"], | ||
| "python.linting.mypyEnabled": false, | ||
| "python.sortImports.path": "isort", | ||
| "python.sortImports.args": ["--profile", "black"], | ||
| "[python]": { | ||
| "editor.insertSpaces": true, | ||
| "editor.tabSize": 4, | ||
| "editor.codeActionsOnSave": { | ||
| "source.organizeImports": true | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| """Functional utilities for devwrangler.""" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| """Configuration utility functions for devwrangler.""" |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a review comment