Merge pull request #148 from Adamkadaban/argcomplete-completion

add argcomplete bash/zsh completion
main
Alex 2023-12-24 14:20:28 +01:00 committed by GitHub
commit dcbb01a39e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 46 additions and 28 deletions

View File

@ -1,4 +1,4 @@
![Supported Python versions](https://img.shields.io/badge/python-3.7+-blue.svg) ![Supported Python versions](https://img.shields.io/badge/python-3.8+-blue.svg)
[![Twitter](https://img.shields.io/twitter/follow/al3xn3ff?label=al3x_n3ff&style=social)](https://twitter.com/intent/follow?screen_name=al3x_n3ff) [![Twitter](https://img.shields.io/twitter/follow/al3xn3ff?label=al3x_n3ff&style=social)](https://twitter.com/intent/follow?screen_name=al3x_n3ff)
[![Twitter](https://img.shields.io/twitter/follow/_zblurx?label=_zblurx&style=social)](https://twitter.com/intent/follow?screen_name=_zblurx) [![Twitter](https://img.shields.io/twitter/follow/_zblurx?label=_zblurx&style=social)](https://twitter.com/intent/follow?screen_name=_zblurx)
[![Twitter](https://img.shields.io/twitter/follow/MJHallenbeck?label=MJHallenbeck&style=social)](https://twitter.com/intent/follow?screen_name=MJHallenbeck) [![Twitter](https://img.shields.io/twitter/follow/MJHallenbeck?label=MJHallenbeck&style=social)](https://twitter.com/intent/follow?screen_name=MJHallenbeck)

View File

@ -1,6 +1,12 @@
import argparse import argparse
import argcomplete
import sys import sys
from argparse import RawTextHelpFormatter from argparse import RawTextHelpFormatter
from os import listdir
from os.path import dirname
from os.path import join as path_join
import nxc
from nxc.paths import NXC_PATH
from nxc.loaders.protocolloader import ProtocolLoader from nxc.loaders.protocolloader import ProtocolLoader
from nxc.helpers.logger import highlight from nxc.helpers.logger import highlight
from nxc.logger import nxc_logger from nxc.logger import nxc_logger
@ -41,7 +47,7 @@ def gen_cli_args():
# we do module arg parsing here so we can reference the module_list attribute below # we do module arg parsing here so we can reference the module_list attribute below
module_parser = argparse.ArgumentParser(add_help=False) module_parser = argparse.ArgumentParser(add_help=False)
mgroup = module_parser.add_mutually_exclusive_group() mgroup = module_parser.add_mutually_exclusive_group()
mgroup.add_argument("-M", "--module", action="append", metavar="MODULE", help="module to use") mgroup.add_argument("-M", "--module", choices=get_module_names(), action="append", metavar="MODULE", help="module to use")
module_parser.add_argument("-o", metavar="MODULE_OPTION", nargs="+", default=[], dest="module_options", help="module options") module_parser.add_argument("-o", metavar="MODULE_OPTION", nargs="+", default=[], dest="module_options", help="module options")
module_parser.add_argument("-L", "--list-modules", action="store_true", help="list available modules") module_parser.add_argument("-L", "--list-modules", action="store_true", help="list available modules")
module_parser.add_argument("--options", dest="show_module_options", action="store_true", help="display module options") module_parser.add_argument("--options", dest="show_module_options", action="store_true", help="display module options")
@ -81,14 +87,28 @@ def gen_cli_args():
except Exception as e: except Exception as e:
nxc_logger.exception(f"Error loading proto_args from proto_args.py file in protocol folder: {protocol} - {e}") nxc_logger.exception(f"Error loading proto_args from proto_args.py file in protocol folder: {protocol} - {e}")
argcomplete.autocomplete(parser)
args = parser.parse_args()
if len(sys.argv) == 1: if len(sys.argv) == 1:
parser.print_help() parser.print_help()
sys.exit(1) sys.exit(1)
args = parser.parse_args()
if args.version: if args.version:
print(f"{VERSION} - {CODENAME}") print(f"{VERSION} - {CODENAME}")
sys.exit(1) sys.exit(1)
return args return args
def get_module_names():
"""Get module names without initializing them"""
modules = []
modules_paths = [
path_join(dirname(nxc.__file__), "modules"),
path_join(NXC_PATH, "modules"),
]
for path in modules_paths:
modules.extend([module[:-3] for module in listdir(path) if module[-3:] == ".py" and module != "example_module.py"])
return sorted(modules, key=str.casefold)

View File

@ -24,6 +24,9 @@ class ModuleLoader:
if not hasattr(module, "name"): if not hasattr(module, "name"):
self.logger.fail(f"{module_path} missing the name variable") self.logger.fail(f"{module_path} missing the name variable")
module_error = True module_error = True
elif hasattr(module, "name") and module.name != module_path.split("/")[-1][:-3]:
self.logger.fail(f"{module_path} filename must match the module name {module.name}")
module_error = True
elif not hasattr(module, "description"): elif not hasattr(module, "description"):
self.logger.fail(f"{module_path} missing the description variable") self.logger.fail(f"{module_path} missing the description variable")
module_error = True module_error = True

38
poetry.lock generated
View File

@ -92,9 +92,6 @@ files = [
{file = "aiosqlite-0.19.0.tar.gz", hash = "sha256:95ee77b91c8d2808bd08a59fbebf66270e9090c3d92ffbf260dc0db0b979577d"}, {file = "aiosqlite-0.19.0.tar.gz", hash = "sha256:95ee77b91c8d2808bd08a59fbebf66270e9090c3d92ffbf260dc0db0b979577d"},
] ]
[package.dependencies]
typing_extensions = {version = ">=4.0", markers = "python_version < \"3.8\""}
[package.extras] [package.extras]
dev = ["aiounittest (==1.4.1)", "attribution (==1.6.2)", "black (==23.3.0)", "coverage[toml] (==7.2.3)", "flake8 (==5.0.4)", "flake8-bugbear (==23.3.12)", "flit (==3.7.1)", "mypy (==1.2.0)", "ufmt (==2.1.0)", "usort (==1.0.6)"] dev = ["aiounittest (==1.4.1)", "attribution (==1.6.2)", "black (==23.3.0)", "coverage[toml] (==7.2.3)", "flake8 (==5.0.4)", "flake8-bugbear (==23.3.12)", "flit (==3.7.1)", "mypy (==1.2.0)", "ufmt (==2.1.0)", "usort (==1.0.6)"]
docs = ["sphinx (==6.1.3)", "sphinx-mdinclude (==0.5.3)"] docs = ["sphinx (==6.1.3)", "sphinx-mdinclude (==0.5.3)"]
@ -147,6 +144,20 @@ files = [
{file = "arc4-0.4.0.tar.gz", hash = "sha256:d431b53d11b24d62521dbbd06d755bf9d6d11a03cc7bbbdf37a13a12ee0747b6"}, {file = "arc4-0.4.0.tar.gz", hash = "sha256:d431b53d11b24d62521dbbd06d755bf9d6d11a03cc7bbbdf37a13a12ee0747b6"},
] ]
[[package]]
name = "argcomplete"
version = "3.2.1"
description = "Bash tab completion for argparse"
optional = false
python-versions = ">=3.8"
files = [
{file = "argcomplete-3.2.1-py3-none-any.whl", hash = "sha256:30891d87f3c1abe091f2142613c9d33cac84a5e15404489f033b20399b691fec"},
{file = "argcomplete-3.2.1.tar.gz", hash = "sha256:437f67fb9b058da5a090df505ef9be0297c4883993f3f56cb186ff087778cfb4"},
]
[package.extras]
test = ["coverage", "mypy", "pexpect", "ruff", "wheel"]
[[package]] [[package]]
name = "asn1crypto" name = "asn1crypto"
version = "1.5.1" version = "1.5.1"
@ -220,9 +231,6 @@ files = [
{file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"}, {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"},
] ]
[package.dependencies]
importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
[package.extras] [package.extras]
cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] cov = ["attrs[tests]", "coverage[toml] (>=5.3)"]
dev = ["attrs[docs,tests]", "pre-commit"] dev = ["attrs[docs,tests]", "pre-commit"]
@ -522,7 +530,6 @@ files = [
[package.dependencies] [package.dependencies]
colorama = {version = "*", markers = "platform_system == \"Windows\""} colorama = {version = "*", markers = "platform_system == \"Windows\""}
importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
[[package]] [[package]]
name = "colorama" name = "colorama"
@ -649,7 +656,6 @@ files = [
] ]
[package.dependencies] [package.dependencies]
importlib-metadata = {version = ">=1.1.0,<4.3", markers = "python_version < \"3.8\""}
mccabe = ">=0.7.0,<0.8.0" mccabe = ">=0.7.0,<0.8.0"
pycodestyle = ">=2.9.0,<2.10.0" pycodestyle = ">=2.9.0,<2.10.0"
pyflakes = ">=2.5.0,<2.6.0" pyflakes = ">=2.5.0,<2.6.0"
@ -772,9 +778,6 @@ files = [
{file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"},
] ]
[package.dependencies]
typing-extensions = {version = "*", markers = "python_version < \"3.8\""}
[[package]] [[package]]
name = "idna" name = "idna"
version = "3.4" version = "3.4"
@ -825,7 +828,6 @@ files = [
] ]
[package.dependencies] [package.dependencies]
typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""}
zipp = ">=0.5" zipp = ">=0.5"
[package.extras] [package.extras]
@ -916,11 +918,9 @@ files = [
[package.dependencies] [package.dependencies]
attrs = ">=17.4.0" attrs = ">=17.4.0"
importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
importlib-resources = {version = ">=1.4.0", markers = "python_version < \"3.9\""} importlib-resources = {version = ">=1.4.0", markers = "python_version < \"3.9\""}
pkgutil-resolve-name = {version = ">=1.3.10", markers = "python_version < \"3.9\""} pkgutil-resolve-name = {version = ">=1.3.10", markers = "python_version < \"3.9\""}
pyrsistent = ">=0.14.0,<0.17.0 || >0.17.0,<0.17.1 || >0.17.1,<0.17.2 || >0.17.2" pyrsistent = ">=0.14.0,<0.17.0 || >0.17.0,<0.17.1 || >0.17.1,<0.17.2 || >0.17.2"
typing-extensions = {version = "*", markers = "python_version < \"3.8\""}
[package.extras] [package.extras]
format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"]
@ -1090,7 +1090,6 @@ files = [
[package.dependencies] [package.dependencies]
mdurl = ">=0.1,<1.0" mdurl = ">=0.1,<1.0"
typing_extensions = {version = ">=3.7.4", markers = "python_version < \"3.8\""}
[package.extras] [package.extras]
benchmarking = ["psutil", "pytest", "pytest-benchmark"] benchmarking = ["psutil", "pytest", "pytest-benchmark"]
@ -1521,9 +1520,6 @@ files = [
{file = "pluggy-1.2.0.tar.gz", hash = "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3"}, {file = "pluggy-1.2.0.tar.gz", hash = "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3"},
] ]
[package.dependencies]
importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
[package.extras] [package.extras]
dev = ["pre-commit", "tox"] dev = ["pre-commit", "tox"]
testing = ["pytest", "pytest-benchmark"] testing = ["pytest", "pytest-benchmark"]
@ -1866,7 +1862,6 @@ files = [
[package.dependencies] [package.dependencies]
colorama = {version = "*", markers = "sys_platform == \"win32\""} colorama = {version = "*", markers = "sys_platform == \"win32\""}
exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
iniconfig = "*" iniconfig = "*"
packaging = "*" packaging = "*"
pluggy = ">=0.12,<2.0" pluggy = ">=0.12,<2.0"
@ -2185,7 +2180,6 @@ files = [
[package.dependencies] [package.dependencies]
greenlet = {version = "!=0.4.17", markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\""} greenlet = {version = "!=0.4.17", markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\""}
importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
typing-extensions = ">=4.2.0" typing-extensions = ">=4.2.0"
[package.extras] [package.extras]
@ -2393,5 +2387,5 @@ testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more
[metadata] [metadata]
lock-version = "2.0" lock-version = "2.0"
python-versions = "^3.7.0" python-versions = "^3.8.0"
content-hash = "1ff7892bac10d1469e83c63d338eeca5964a19f39704651cb71a90e045ebb16b" content-hash = "912d573a68ba30b528b05d95f2ec67b2d569e01e32e170ab5551ab2b9422f417"

View File

@ -33,7 +33,7 @@ NetExec = 'nxc.netexec:main'
nxcdb = 'nxc.nxcdb:main' nxcdb = 'nxc.nxcdb:main'
[tool.poetry.dependencies] [tool.poetry.dependencies]
python = "^3.7.0" python = "^3.8.0"
requests = ">=2.27.1" requests = ">=2.27.1"
beautifulsoup4 = ">=4.11,<5" beautifulsoup4 = ">=4.11,<5"
lsassy = ">=3.1.8" lsassy = ">=3.1.8"
@ -65,6 +65,7 @@ resource = "^0.2.1"
oscrypto = { git = "https://github.com/Pennyw0rth/oscrypto" } # Pypi version currently broken, see: https://github.com/wbond/oscrypto/issues/78 (as of 9/23) oscrypto = { git = "https://github.com/Pennyw0rth/oscrypto" } # Pypi version currently broken, see: https://github.com/wbond/oscrypto/issues/78 (as of 9/23)
pyreadline = "^2.1" # for the build - impacket imports its hidden from the builder so an error occurs pyreadline = "^2.1" # for the build - impacket imports its hidden from the builder so an error occurs
ruff = "=0.0.292" ruff = "=0.0.292"
argcomplete = "3.2.1"
[tool.poetry.group.dev.dependencies] [tool.poetry.group.dev.dependencies]
flake8 = "*" flake8 = "*"
@ -123,4 +124,4 @@ target-version = "py37"
[tool.ruff.flake8-quotes] [tool.ruff.flake8-quotes]
docstring-quotes = "double" docstring-quotes = "double"
inline-quotes = "double" inline-quotes = "double"
multiline-quotes = "double" multiline-quotes = "double"