Bug 1951578: remove mach pastebin. r=sergesanspaille
Adds a new "hidden" argument to mach decorators that allows the command to execute but will not be visible in `mach help`. Removes `mach pastebin` functionality, marks it as "hidden", and displays a notice that pastebin.mozilla.org has been decommissioned. Differential Revision: https://phabricator.services.mozilla.com/D240280
This commit is contained in:
@@ -45,6 +45,8 @@ class _MachCommand:
|
||||
"decl_order",
|
||||
# Whether to disable automatic logging to last_log.json for the command.
|
||||
"no_auto_log",
|
||||
# Whether to hide this command from help.
|
||||
"hidden",
|
||||
)
|
||||
|
||||
def __init__(
|
||||
@@ -59,6 +61,7 @@ class _MachCommand:
|
||||
virtualenv_name=None,
|
||||
ok_if_tests_disabled=False,
|
||||
no_auto_log=False,
|
||||
hidden=False,
|
||||
):
|
||||
self.name = name
|
||||
self.subcommand = subcommand
|
||||
@@ -70,6 +73,7 @@ class _MachCommand:
|
||||
self.argument_group_names = []
|
||||
self.virtualenv_name = virtualenv_name
|
||||
self.order = order
|
||||
self.hidden = hidden
|
||||
if ok_if_tests_disabled and category != "testing":
|
||||
raise ValueError(
|
||||
"ok_if_tests_disabled should only be set for " "`testing` mach commands"
|
||||
|
||||
@@ -259,6 +259,9 @@ class CommandAction(argparse.Action):
|
||||
for command in sorted(r.commands_by_category[category]):
|
||||
handler = r.command_handlers[command]
|
||||
|
||||
if handler.hidden:
|
||||
continue
|
||||
|
||||
# Instantiate a handler class to see if it should be filtered
|
||||
# out for the current context or not. Condition functions can be
|
||||
# applied to the command's decorator.
|
||||
|
||||
20
python/mach/mach/test/providers/definitions.py
Normal file
20
python/mach/mach/test/providers/definitions.py
Normal file
@@ -0,0 +1,20 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
from mach.decorators import Command
|
||||
|
||||
|
||||
@Command("cmd_default_visible", category="testing")
|
||||
def run_default_visible(self, command_context):
|
||||
pass
|
||||
|
||||
|
||||
@Command("cmd_not_hidden", category="testing")
|
||||
def run_not_hidden(self, command_context, hidden=False):
|
||||
pass
|
||||
|
||||
|
||||
@Command("cmd_hidden", category="testing", hidden=True)
|
||||
def run_hidden(self, command_context):
|
||||
pass
|
||||
@@ -6,6 +6,8 @@ subsuite = "mach"
|
||||
["test_conditions.py"]
|
||||
skip-if = ["true"]
|
||||
|
||||
["test_definitions.py"]
|
||||
|
||||
["test_config.py"]
|
||||
|
||||
["test_decorators.py"]
|
||||
|
||||
28
python/mach/mach/test/test_definitions.py
Normal file
28
python/mach/mach/test/test_definitions.py
Normal file
@@ -0,0 +1,28 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from mozunit import main
|
||||
|
||||
from mach.test.conftest import TestBase
|
||||
|
||||
|
||||
class TestConditions(TestBase):
|
||||
"""Tests for definitions provided to the @Command decorator."""
|
||||
|
||||
def _run(self, args):
|
||||
return self._run_mach(args, Path("definitions.py"))
|
||||
|
||||
def test_help_message(self):
|
||||
"""Test that commands that are hidden do not show up in help."""
|
||||
|
||||
result, stdout, stderr = self._run(["help"])
|
||||
self.assertIn("cmd_default_visible", stdout)
|
||||
self.assertIn("cmd_not_hidden", stdout)
|
||||
self.assertNotIn("cmd_hidden", stdout)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -110,246 +110,28 @@ def busted_file(command_context, against):
|
||||
webbrowser.open_new_tab(uri)
|
||||
|
||||
|
||||
MACH_PASTEBIN_DURATIONS = {
|
||||
"onetime": "onetime",
|
||||
"hour": "3600",
|
||||
"day": "86400",
|
||||
"week": "604800",
|
||||
"month": "2073600",
|
||||
}
|
||||
|
||||
EXTENSION_TO_HIGHLIGHTER = {
|
||||
".hgrc": "ini",
|
||||
"Dockerfile": "docker",
|
||||
"Makefile": "make",
|
||||
"applescript": "applescript",
|
||||
"arduino": "arduino",
|
||||
"bash": "bash",
|
||||
"bat": "bat",
|
||||
"c": "c",
|
||||
"clojure": "clojure",
|
||||
"cmake": "cmake",
|
||||
"coffee": "coffee-script",
|
||||
"console": "console",
|
||||
"cpp": "cpp",
|
||||
"cs": "csharp",
|
||||
"css": "css",
|
||||
"cu": "cuda",
|
||||
"cuda": "cuda",
|
||||
"dart": "dart",
|
||||
"delphi": "delphi",
|
||||
"diff": "diff",
|
||||
"django": "django",
|
||||
"docker": "docker",
|
||||
"elixir": "elixir",
|
||||
"erlang": "erlang",
|
||||
"go": "go",
|
||||
"h": "c",
|
||||
"handlebars": "handlebars",
|
||||
"haskell": "haskell",
|
||||
"hs": "haskell",
|
||||
"html": "html",
|
||||
"ini": "ini",
|
||||
"ipy": "ipythonconsole",
|
||||
"ipynb": "ipythonconsole",
|
||||
"irc": "irc",
|
||||
"j2": "django",
|
||||
"java": "java",
|
||||
"js": "js",
|
||||
"json": "json",
|
||||
"jsx": "jsx",
|
||||
"kt": "kotlin",
|
||||
"less": "less",
|
||||
"lisp": "common-lisp",
|
||||
"lsp": "common-lisp",
|
||||
"lua": "lua",
|
||||
"m": "objective-c",
|
||||
"make": "make",
|
||||
"matlab": "matlab",
|
||||
"md": "_markdown",
|
||||
"nginx": "nginx",
|
||||
"numpy": "numpy",
|
||||
"patch": "diff",
|
||||
"perl": "perl",
|
||||
"php": "php",
|
||||
"pm": "perl",
|
||||
"postgresql": "postgresql",
|
||||
"py": "python",
|
||||
"rb": "rb",
|
||||
"rs": "rust",
|
||||
"rst": "rst",
|
||||
"sass": "sass",
|
||||
"scss": "scss",
|
||||
"sh": "bash",
|
||||
"sol": "sol",
|
||||
"sql": "sql",
|
||||
"swift": "swift",
|
||||
"tex": "tex",
|
||||
"typoscript": "typoscript",
|
||||
"vim": "vim",
|
||||
"xml": "xml",
|
||||
"xslt": "xslt",
|
||||
"yaml": "yaml",
|
||||
"yml": "yaml",
|
||||
}
|
||||
|
||||
|
||||
def guess_highlighter_from_path(path):
|
||||
"""Return a known highlighter from a given path
|
||||
|
||||
Attempt to select a highlighter by checking the file extension in the mapping
|
||||
of extensions to highlighter. If that fails, attempt to pass the basename of
|
||||
the file. Return `_code` as the default highlighter if that fails.
|
||||
"""
|
||||
import os
|
||||
|
||||
_name, ext = os.path.splitext(path)
|
||||
|
||||
if ext.startswith("."):
|
||||
ext = ext[1:]
|
||||
|
||||
if ext in EXTENSION_TO_HIGHLIGHTER:
|
||||
return EXTENSION_TO_HIGHLIGHTER[ext]
|
||||
|
||||
basename = os.path.basename(path)
|
||||
|
||||
return EXTENSION_TO_HIGHLIGHTER.get(basename, "_code")
|
||||
|
||||
|
||||
PASTEMO_MAX_CONTENT_LENGTH = 250 * 1024 * 1024
|
||||
|
||||
PASTEMO_URL = "https://paste.mozilla.org/api/"
|
||||
def pastebin_create_parser():
|
||||
# Accept all args so they can be promptly ignored.
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("argv", nargs=argparse.REMAINDER, help=argparse.SUPPRESS)
|
||||
return parser
|
||||
|
||||
|
||||
@Command(
|
||||
"pastebin",
|
||||
category="misc",
|
||||
description="Command line interface to paste.mozilla.org.",
|
||||
hidden=True,
|
||||
parser=pastebin_create_parser,
|
||||
)
|
||||
@CommandArgument(
|
||||
"--list-highlighters",
|
||||
action="store_true",
|
||||
help="List known highlighters and exit",
|
||||
)
|
||||
@CommandArgument(
|
||||
"--highlighter", default=None, help="Syntax highlighting to use for paste"
|
||||
)
|
||||
@CommandArgument(
|
||||
"--expires",
|
||||
default="week",
|
||||
choices=sorted(MACH_PASTEBIN_DURATIONS.keys()),
|
||||
help="Expire paste after given time duration (default: %(default)s)",
|
||||
)
|
||||
@CommandArgument(
|
||||
"--verbose",
|
||||
action="store_true",
|
||||
help="Print extra info such as selected syntax highlighter",
|
||||
)
|
||||
@CommandArgument(
|
||||
"path",
|
||||
nargs="?",
|
||||
default=None,
|
||||
help="Path to file for upload to paste.mozilla.org",
|
||||
)
|
||||
def pastebin(command_context, list_highlighters, highlighter, expires, verbose, path):
|
||||
"""Command line interface to `paste.mozilla.org`.
|
||||
def pastebin(command_context, argv):
|
||||
"""Obsolete command line interface to `paste.mozilla.org`."""
|
||||
|
||||
Takes either a filename whose content should be pasted, or reads
|
||||
content from standard input. If a highlighter is specified it will
|
||||
be used, otherwise the file name will be used to determine an
|
||||
appropriate highlighter.
|
||||
"""
|
||||
|
||||
import requests
|
||||
|
||||
def verbose_print(*args, **kwargs):
|
||||
"""Print a string if `--verbose` flag is set"""
|
||||
if verbose:
|
||||
print(*args, **kwargs)
|
||||
|
||||
# Show known highlighters and exit.
|
||||
if list_highlighters:
|
||||
lexers = set(EXTENSION_TO_HIGHLIGHTER.values())
|
||||
print("Available lexers:\n - %s" % "\n - ".join(sorted(lexers)))
|
||||
return 0
|
||||
|
||||
# Get a correct expiry value.
|
||||
try:
|
||||
verbose_print("Setting expiry from %s" % expires)
|
||||
expires = MACH_PASTEBIN_DURATIONS[expires]
|
||||
verbose_print("Using %s as expiry" % expires)
|
||||
except KeyError:
|
||||
print(
|
||||
"%s is not a valid duration.\n"
|
||||
"(hint: try one of %s)"
|
||||
% (expires, ", ".join(MACH_PASTEBIN_DURATIONS.keys()))
|
||||
"pastebin.mozilla.org has been decommissioned.\n"
|
||||
"Please use your favorite search engine to find alternatives."
|
||||
)
|
||||
return 1
|
||||
|
||||
data = {
|
||||
"format": "json",
|
||||
"expires": expires,
|
||||
}
|
||||
|
||||
# Get content to be pasted.
|
||||
if path:
|
||||
verbose_print("Reading content from %s" % path)
|
||||
try:
|
||||
with open(path, "r") as f:
|
||||
content = f.read()
|
||||
except IOError:
|
||||
print("ERROR. No such file %s" % path)
|
||||
return 1
|
||||
|
||||
lexer = guess_highlighter_from_path(path)
|
||||
if lexer:
|
||||
data["lexer"] = lexer
|
||||
else:
|
||||
verbose_print("Reading content from stdin")
|
||||
content = sys.stdin.read()
|
||||
|
||||
# Assert the length of content to be posted does not exceed the maximum.
|
||||
content_length = len(content)
|
||||
verbose_print("Checking size of content is okay (%d)" % content_length)
|
||||
if content_length > PASTEMO_MAX_CONTENT_LENGTH:
|
||||
print(
|
||||
"Paste content is too large (%d, maximum %d)"
|
||||
% (content_length, PASTEMO_MAX_CONTENT_LENGTH)
|
||||
)
|
||||
return 1
|
||||
|
||||
data["content"] = content
|
||||
|
||||
# Highlight as specified language, overwriting value set from filename.
|
||||
if highlighter:
|
||||
verbose_print("Setting %s as highlighter" % highlighter)
|
||||
data["lexer"] = highlighter
|
||||
|
||||
try:
|
||||
verbose_print("Sending request to %s" % PASTEMO_URL)
|
||||
resp = requests.post(PASTEMO_URL, data=data)
|
||||
|
||||
# Error code should always be 400.
|
||||
# Response content will include a helpful error message,
|
||||
# so print it here (for example, if an invalid highlighter is
|
||||
# provided, it will return a list of valid highlighters).
|
||||
if resp.status_code >= 400:
|
||||
print("Error code %d: %s" % (resp.status_code, resp.content))
|
||||
return 1
|
||||
|
||||
verbose_print("Pasted successfully")
|
||||
|
||||
response_json = resp.json()
|
||||
|
||||
verbose_print("Paste highlighted as %s" % response_json["lexer"])
|
||||
print(response_json["url"])
|
||||
|
||||
return 0
|
||||
except Exception as e:
|
||||
print("ERROR. Paste failed.")
|
||||
print("%s" % e)
|
||||
return 1
|
||||
|
||||
|
||||
class PypiBasedTool:
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user