Skip to content

Commit

Permalink
fix bug in package building config, decouple uoft_core.prompt.Prompt …
Browse files Browse the repository at this point in the history
…from uoft_core.Util, add fuzzy completion flag to uoft_core.prompt.Prompt's get_from_choices and get_path methods, add invoke tasks for inspecting the contents of built packages
  • Loading branch information
alextremblay committed Nov 7, 2022
1 parent dc08b41 commit 12c18bb
Show file tree
Hide file tree
Showing 9 changed files with 90 additions and 20 deletions.
5 changes: 4 additions & 1 deletion projects/aruba/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ version = "0.0" # This field will be auto-populated by pyproject.py
description = "Collection of utilities for interacting with Aruba infrastructure"
authors = [
{ name = "Kyle Fozo", email = "[email protected]" },
{ name = "University of Toronto Governing Council", email = "governing.council@utoronto.ca" },
{ name = "University of Toronto", email = "alex.tremblay@utoronto.ca" },
]
requires-python = ">=3.10"
readme = "README.md"
Expand All @@ -25,3 +25,6 @@ build-backend = "hatchling.build"

[tool.hatch.metadata.hooks.custom]
path = "pyproject.py"

[tool.hatch.build]
only-packages = true
5 changes: 4 additions & 1 deletion projects/core/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description = "an opinionated set of utilities designed to be easily included in
readme = "README.md"
authors = [
{ name = "Alex Tremblay", email = "[email protected]" },
{ name = "University of Toronto", email = "" }
{ name = "University of Toronto", email = "[email protected]" }
]
license = "MIT"
requires-python = ">=3.10"
Expand Down Expand Up @@ -33,3 +33,6 @@ build-backend = "hatchling.build"

[tool.hatch.metadata.hooks.custom]
path = "pyproject.py"

[tool.hatch.build]
only-packages = true
2 changes: 1 addition & 1 deletion projects/core/uoft_core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1011,7 +1011,7 @@ def prompt_for_missing_values(cls, values):
# Return values as is and let pydantic report validation errors on missing fields
return values

p = Prompt(cls.__config__.util())
p = Prompt(cls.__config__.util().history_cache)
for key in missing_keys:
field = cls.__fields__[key]
values[key] = p.from_model_field(key, field)
Expand Down
3 changes: 2 additions & 1 deletion projects/core/uoft_core/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ def cli():
from importlib.util import find_spec
from .prompt import Prompt, Validator

p = Prompt(util)
history_cache = util.history_cache
p = Prompt(history_cache)
v = Validator.from_callable(
lambda n: bool(find_spec(n)),
"no such module exists in the current python installation",
Expand Down
26 changes: 17 additions & 9 deletions projects/core/uoft_core/prompt.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@
import sys
from base64 import b64encode

from . import Util

from prompt_toolkit import PromptSession
from prompt_toolkit.history import FileHistory
from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
from prompt_toolkit.formatted_text import HTML
from prompt_toolkit.completion import WordCompleter, PathCompleter
from prompt_toolkit.completion import WordCompleter, PathCompleter, FuzzyCompleter
from prompt_toolkit.validation import Validator, ValidationError
from prompt_toolkit.key_binding import KeyBindings
from prompt_toolkit.document import Document
Expand Down Expand Up @@ -39,9 +37,9 @@ def _hash(s: str) -> str:


class Prompt:
def __init__(self, util: Util):
def __init__(self, history_cache: Path):

self.history_cache = util.history_cache
self.history_cache = history_cache
if not self.history_cache.exists():
self.history_cache.mkdir(parents=True)

Expand Down Expand Up @@ -87,6 +85,8 @@ def get_from_choices(
choices: Sequence[str],
description: str | None,
default_value: str | None = None,
completer_opts: dict | None = None,
fuzzy_search: bool = False,
**kwargs,
) -> str:

Expand All @@ -95,8 +95,12 @@ def get_from_choices(
error_message=f"Choice must be one of {', '.join(choices)}",
)

completer_opts = completer_opts or {}
completer = WordCompleter(list(choices), **completer_opts)
if fuzzy_search:
completer = FuzzyCompleter(completer)
opts = dict(
completer=WordCompleter(list(choices)),
completer=completer,
complete_while_typing=True,
rprompt=HTML(f"Valid options are: <b>{', '.join(choices)}</b>"),
validator=validator,
Expand All @@ -111,13 +115,17 @@ def get_path( # pylint: disable=too-many-arguments
default_value: str | None = None,
only_directories=False,
completer_opts: dict | None = None,
fuzzy_search: bool = False,
**kwargs,
) -> Path:
completer_opts = completer_opts or {}
completer = PathCompleter(
only_directories=only_directories, **completer_opts
)
if fuzzy_search:
completer = FuzzyCompleter(completer)
opts = dict(
completer=PathCompleter(
only_directories=only_directories, **completer_opts
),
completer=completer,
complete_while_typing=True,
)
opts.update(kwargs)
Expand Down
4 changes: 2 additions & 2 deletions projects/nautobot/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description = "A collection of UofT-specific modifications and extensions to Nau
readme = "README.md"
authors = [
{ name = "Alex Tremblay", email = "[email protected]" },
{ name = "University of Toronto Governing Council", email = "governing.council@utoronto.ca" },
{ name = "University of Toronto", email = "alex.tremblay@utoronto.ca" },
]
license = "MIT"
requires-python = ">=3.10"
Expand Down Expand Up @@ -34,4 +34,4 @@ build-backend = "hatchling.build"
path = "pyproject.py"

[tool.hatch.build]
packages = ["uoft_nautobot"]
only-packages = true
5 changes: 4 additions & 1 deletion projects/scripts/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description = "a collection of scripts and one-off tools"
readme = "README.md"
authors = [
{ name = "Alex Tremblay", email = "[email protected]" },
{ name = "University of Toronto Governing Council", email = "governing.council@utoronto.ca" },
{ name = "University of Toronto", email = "alex.tremblay@utoronto.ca" },
]
license = "MIT"
requires-python = ">=3.10"
Expand All @@ -27,3 +27,6 @@ build-backend = "hatchling.build"

[tool.hatch.metadata.hooks.custom]
path = "pyproject.py"

[tool.hatch.build]
only-packages = true
7 changes: 5 additions & 2 deletions projects/switchconfig/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description = "A tool to easily provision switches on the bench"
readme = "README.md"
authors = [
{ name = "Alex Tremblay", email = "[email protected]" },
{ name = "University of Toronto Governing Council", email = "governing.council@utoronto.ca" },
{ name = "University of Toronto", email = "alex.tremblay@utoronto.ca" },
]
license = "MIT"
requires-python = ">=3.10"
Expand All @@ -30,4 +30,7 @@ requires = ["hatchling >= 1.6.0", "setuptools_scm"]
build-backend = "hatchling.build"

[tool.hatch.metadata.hooks.custom]
path = "pyproject.py"
path = "pyproject.py"

[tool.hatch.build]
only-packages = true
53 changes: 51 additions & 2 deletions tasks/common.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
"""common tasks for all projects in the repo"""
import os

from invoke import task, Context

from . import ROOT
Expand All @@ -24,11 +26,13 @@ def build(c: Context, project: str):
"""build sdist and wheel packages for a given project"""
print(f"building {project} from projects/{project}")
assert (ROOT / f"projects/{project}").exists(), f"Project {project} does not exist"
r = c.run(f"python -m build -o {ROOT}/dist/ projects/{project}")
c.run(f"python -m build --sdist --outdir {ROOT}/dist/ projects/{project}")
c.run(f"python -m build --wheel --outdir {ROOT}/dist/ projects/{project}")

@task()
def build_all(c: Context):
"""build sdist and wheel packages for all projects"""
c.run("rm dist/*")
for project in all_projects():
build(c, project.name)

Expand Down Expand Up @@ -99,4 +103,49 @@ def version_next(c: Context, minor: bool = False ):
else:
segments[2] += 1
new_version = Version('.'.join(map(str, segments)))
print(f"suggested command: \n\ngit tag --sign --message 'Version {new_version}' {new_version}\ngit push --tags\n")
print(f"suggested command: \n\ngit tag --sign --message 'Version {new_version}' {new_version}\ngit push --tags\n")

@task()
def package_inspect(c: Context):
"""list the contents of an sdist or wheel file in the dist/ directory"""
from . import ROOT
from uoft_core import Util
from uoft_core.prompt import Prompt
prompt = Prompt(Util('uoft-tools').history_cache)
os.chdir(ROOT / 'dist')
package = prompt.get_path("package", "Enter a filename for a package to inspect", fuzzy_search=True)
if package.name.endswith('.tar.gz'):
c.run(f"tar -tvf {package}")
elif package.name.endswith('.whl'):
c.run(f"unzip -l {package}")
else:
raise Exception(f"Unknown package type: {package}")

@task()
def package_peek(c: Context):
"""print out the contents of a file in an sdist or wheel file in the dist/ directory"""
from . import ROOT
from uoft_core import Util
from uoft_core.prompt import Prompt
prompt = Prompt(Util('uoft-tools').history_cache)
os.chdir(ROOT / 'dist')
package = prompt.get_path("package", "Enter a filename for a package to inspect", fuzzy_search=True)
names = []
if package.name.endswith('.tar.gz'):
import tarfile
with tarfile.open(package) as tar:
names = tar.getnames()
filename = prompt.get_from_choices("filename", choices=names, description="Which file to peek at?", fuzzy_search=True)
embedded_file = tar.extractfile(filename)
assert embedded_file, f"Could not find file {filename} in {package}"
with embedded_file as f:
print(f.read().decode('utf-8'))
elif package.name.endswith(('.whl', '.zip', '.pex')):
import zipfile
with zipfile.ZipFile(package) as zip:
names = zip.namelist()
filename = prompt.get_from_choices("filename", choices=names, description="Which file to peek at?", fuzzy_search=True)
with zip.open(filename) as f:
print(f.read().decode('utf-8'))
else:
raise Exception(f"Unknown package type: {package}")

0 comments on commit 12c18bb

Please sign in to comment.