fix: minor comments, TODO items and formatting
This has almost no impact, outside of rewording some items.
This commit is contained in:
parent
097be3e3fe
commit
b60655ed54
@ -17,8 +17,8 @@ from quart import (
|
|||||||
request,
|
request,
|
||||||
url_for,
|
url_for,
|
||||||
)
|
)
|
||||||
from quart.helpers import WerkzeugResponse
|
|
||||||
from quart.typing import ResponseTypes
|
from quart.typing import ResponseTypes
|
||||||
|
from werkzeug.sansio.response import Response as BaseResponse
|
||||||
from tutor.plugins.v1 import discover_package
|
from tutor.plugins.v1 import discover_package
|
||||||
|
|
||||||
from tutordeck.server.utils import current_page_plugins, pagination_context
|
from tutordeck.server.utils import current_page_plugins, pagination_context
|
||||||
@ -80,7 +80,7 @@ async def plugin_store_list() -> str:
|
|||||||
"name": p.name,
|
"name": p.name,
|
||||||
"url": p.url,
|
"url": p.url,
|
||||||
"index": p.index,
|
"index": p.index,
|
||||||
"author": p.author.split("<")[0].strip(),
|
"author": tutorclient.Client.get_plugin_author(p),
|
||||||
"description": p.short_description,
|
"description": p.short_description,
|
||||||
"is_installed": p.name in g.installed_plugins,
|
"is_installed": p.name in g.installed_plugins,
|
||||||
"is_enabled": p.name in g.enabled_plugins,
|
"is_enabled": p.name in g.enabled_plugins,
|
||||||
@ -102,13 +102,16 @@ async def plugin_store_list() -> str:
|
|||||||
|
|
||||||
@app.get("/plugin/installed/list")
|
@app.get("/plugin/installed/list")
|
||||||
async def plugin_installed_list() -> str:
|
async def plugin_installed_list() -> str:
|
||||||
|
# TODO IMPORTANT this displays only the plugins that are in the store. When a plugin
|
||||||
|
# is installed locally but not in the store, we must display it here anyway.
|
||||||
|
# TODO this is duplicated code from plugin_store_list
|
||||||
search_query = request.args.get("search", "")
|
search_query = request.args.get("search", "")
|
||||||
plugins: list[dict[str, t.Any]] = [
|
plugins: list[dict[str, t.Any]] = [
|
||||||
{
|
{
|
||||||
"name": p.name,
|
"name": p.name,
|
||||||
"url": p.url,
|
"url": p.url,
|
||||||
"index": p.index,
|
"index": p.index,
|
||||||
"author": p.author.split("<")[0].strip(),
|
"author": tutorclient.Client.get_plugin_author(p),
|
||||||
"description": p.short_description,
|
"description": p.short_description,
|
||||||
"is_enabled": p.name in g.enabled_plugins,
|
"is_enabled": p.name in g.enabled_plugins,
|
||||||
}
|
}
|
||||||
@ -129,15 +132,16 @@ async def plugin(name: str) -> Response:
|
|||||||
if not index_entry:
|
if not index_entry:
|
||||||
return Response("Plugin not found", status=404)
|
return Response("Plugin not found", status=404)
|
||||||
|
|
||||||
|
# TODO this seq_command_executed argument is confusing and causing issues, for
|
||||||
|
# instance with the "unset" button. We need to get rid of it.
|
||||||
seq_command_executed = request.args.get("seq_command_executed")
|
seq_command_executed = request.args.get("seq_command_executed")
|
||||||
author = index_entry.author.split("<")[0].strip()
|
|
||||||
description = markdown(index_entry.description)
|
description = markdown(index_entry.description)
|
||||||
rendered_template = await render_template(
|
rendered_template = await render_template(
|
||||||
"plugin.html",
|
"plugin.html",
|
||||||
plugin_name=name,
|
plugin_name=name,
|
||||||
is_enabled=name in g.enabled_plugins,
|
is_enabled=name in g.enabled_plugins,
|
||||||
is_installed=name in g.installed_plugins,
|
is_installed=name in g.installed_plugins,
|
||||||
author_name=author,
|
author_name=tutorclient.Client.get_plugin_author(index_entry),
|
||||||
plugin_description=description,
|
plugin_description=description,
|
||||||
seq_command_executed=seq_command_executed,
|
seq_command_executed=seq_command_executed,
|
||||||
plugin_config_unique=tutorclient.Client.plugin_config_unique(name),
|
plugin_config_unique=tutorclient.Client.plugin_config_unique(name),
|
||||||
@ -146,6 +150,7 @@ async def plugin(name: str) -> Response:
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Redirect to plugin page
|
# Redirect to plugin page
|
||||||
|
# TODO this is useful only after a POST to plugin/<name>/update. I don't think these two things should be handled in the same place.
|
||||||
response = Response(rendered_template, status=200, content_type="text/html")
|
response = Response(rendered_template, status=200, content_type="text/html")
|
||||||
response.headers["HX-Redirect"] = url_for(
|
response.headers["HX-Redirect"] = url_for(
|
||||||
"plugin", name=name, seq_command_executed=seq_command_executed
|
"plugin", name=name, seq_command_executed=seq_command_executed
|
||||||
@ -188,11 +193,12 @@ async def plugin_toggle(name: str) -> Response:
|
|||||||
|
|
||||||
|
|
||||||
@app.post("/plugin/<name>/install")
|
@app.post("/plugin/<name>/install")
|
||||||
async def plugin_install(name: str) -> WerkzeugResponse:
|
async def plugin_install(name: str) -> BaseResponse:
|
||||||
async def bg_install_and_reload() -> None:
|
async def bg_install_and_reload() -> None:
|
||||||
tutorclient.CliPool.run_parallel(app, ["plugins", "install", name])
|
tutorclient.CliPool.run_parallel(app, ["plugins", "install", name])
|
||||||
while tutorclient.CliPool.THREAD and tutorclient.CliPool.THREAD.is_alive():
|
while tutorclient.CliPool.THREAD and tutorclient.CliPool.THREAD.is_alive():
|
||||||
await asyncio.sleep(0.1)
|
await asyncio.sleep(0.1)
|
||||||
|
# TODO this is hackish. How can we improve?
|
||||||
discover_package(importlib_metadata.entry_points().__getitem__(name))
|
discover_package(importlib_metadata.entry_points().__getitem__(name))
|
||||||
|
|
||||||
asyncio.create_task(bg_install_and_reload())
|
asyncio.create_task(bg_install_and_reload())
|
||||||
@ -205,7 +211,7 @@ async def plugin_install(name: str) -> WerkzeugResponse:
|
|||||||
|
|
||||||
|
|
||||||
@app.post("/plugin/<name>/upgrade")
|
@app.post("/plugin/<name>/upgrade")
|
||||||
async def plugin_upgrade(name: str) -> WerkzeugResponse:
|
async def plugin_upgrade(name: str) -> BaseResponse:
|
||||||
tutorclient.CliPool.run_parallel(app, ["plugins", "upgrade", name])
|
tutorclient.CliPool.run_parallel(app, ["plugins", "upgrade", name])
|
||||||
return redirect(
|
return redirect(
|
||||||
url_for(
|
url_for(
|
||||||
@ -344,7 +350,7 @@ async def suggest() -> Response:
|
|||||||
|
|
||||||
|
|
||||||
@app.post("/command")
|
@app.post("/command")
|
||||||
async def command() -> WerkzeugResponse:
|
async def command() -> BaseResponse:
|
||||||
form = await request.form
|
form = await request.form
|
||||||
command_string = form.get("command", "")
|
command_string = form.get("command", "")
|
||||||
command_args = command_string.split()
|
command_args = command_string.split()
|
||||||
|
|||||||
@ -8,16 +8,12 @@ Developer Mode
|
|||||||
Search for any tutor command and execute it with a single click.
|
Search for any tutor command and execute it with a single click.
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block page_button %}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block searchbar %}
|
{% block searchbar %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block warning %}
|
{% block warning %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
{% set sidebar_active_tab = "advanced" %}
|
{% set sidebar_active_tab = "advanced" %}
|
||||||
|
|
||||||
{% block workspace_content %}
|
{% block workspace_content %}
|
||||||
|
|||||||
@ -40,7 +40,7 @@
|
|||||||
{% else %}
|
{% else %}
|
||||||
<p>N/A</p>
|
<p>N/A</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<button type="submit">Update All</button>
|
<button type="submit">Save changes</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@ -79,6 +79,7 @@
|
|||||||
bar.style.display = isPluginInstalled ? 'flex' : 'none';
|
bar.style.display = isPluginInstalled ? 'flex' : 'none';
|
||||||
}
|
}
|
||||||
async function checkIfPluginInstalled(pluginName) {
|
async function checkIfPluginInstalled(pluginName) {
|
||||||
|
// TODO let's avoid hard-coded urls
|
||||||
const response = await fetch(`/plugin/${pluginName}/is-installed`);
|
const response = await fetch(`/plugin/${pluginName}/is-installed`);
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
return data.installed;
|
return data.installed;
|
||||||
|
|||||||
@ -114,7 +114,8 @@ class Cli:
|
|||||||
self.log_to_file(e.args[0])
|
self.log_to_file(e.args[0])
|
||||||
self.log_to_file("\nCancelled!\n")
|
self.log_to_file("\nCancelled!\n")
|
||||||
except SystemExit:
|
except SystemExit:
|
||||||
# TODO Is there a better way to notify command completion???
|
# TODO Is there a better way to notify command completion??? The
|
||||||
|
# frontend relies on this hard-coded string to detect launch completion.
|
||||||
self.log_to_file("\nSuccess!")
|
self.log_to_file("\nSuccess!")
|
||||||
|
|
||||||
def stop(self) -> None:
|
def stop(self) -> None:
|
||||||
@ -326,9 +327,7 @@ class Client:
|
|||||||
@classmethod
|
@classmethod
|
||||||
def plugins_matching_pattern(cls, pattern: str) -> list[str]:
|
def plugins_matching_pattern(cls, pattern: str) -> list[str]:
|
||||||
return [
|
return [
|
||||||
plugin._data["name"]
|
plugin.name for plugin in cls.plugins_in_store() if plugin.match(pattern)
|
||||||
for plugin in cls.plugins_in_store()
|
|
||||||
if plugin.match(pattern)
|
|
||||||
]
|
]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -356,19 +355,25 @@ class Client:
|
|||||||
key: user_config.get(key, value) for key, value in config_defaults.items()
|
key: user_config.get(key, value) for key, value in config_defaults.items()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_plugin_author(cls, index_entry: tutor.plugins.indexes.IndexEntry) -> str:
|
||||||
|
return index_entry.author.split("<")[0].strip()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def autocomplete(cls, partial_command: str) -> list[dict[str, str]]:
|
def autocomplete(cls, partial_command: str) -> list[dict[str, str]]:
|
||||||
|
"""
|
||||||
|
Handle CLI command completion via click_repl.ClickCompleter
|
||||||
|
https://github.com/click-contrib/click-repl/blob/master/click_repl/_completer.py
|
||||||
|
"""
|
||||||
cli = tutor.commands.cli.cli
|
cli = tutor.commands.cli.cli
|
||||||
ctx = click.Context(cli, info_name=cli.name, parent=None)
|
ctx = click.Context(cli, info_name=cli.name, parent=None)
|
||||||
completer = click_repl.ClickCompleter(cli, ctx)
|
completer = click_repl.ClickCompleter(cli, ctx)
|
||||||
document = Document(partial_command, len(partial_command))
|
document = Document(partial_command, len(partial_command))
|
||||||
completions = list(completer.get_completions(document, None))
|
completions = list(completer.get_completions(document, None))
|
||||||
suggestions = []
|
return [
|
||||||
for completion in completions:
|
|
||||||
suggestions.append(
|
|
||||||
{
|
{
|
||||||
"text": completion.text,
|
"text": completion.text,
|
||||||
"display": completion.display,
|
"display": completion.display,
|
||||||
}
|
}
|
||||||
)
|
for completion in completions
|
||||||
return suggestions
|
]
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user