From 0268cd426b7ee22ac3106245f6db4f2db66550b9 Mon Sep 17 00:00:00 2001 From: Solderpunk Date: Sat, 25 Nov 2023 16:12:46 +0100 Subject: [PATCH] Further splitting up and renaming of files. Now that everything lives in src/av98/ as per the latest Python fashion, it's a problem to have a file named av98.py. So split it out into main.py (which just implements the argument parsing) and client.py. The old clientcerts.py has become certmanager.py so that tab completion for client.py is quick and easy. --- pyproject.toml | 2 +- src/av98/{clientcerts.py => certmanager.py} | 0 src/av98/{av98.py => client.py} | 115 +---------------- src/av98/main.py | 130 ++++++++++++++++++++ 4 files changed, 132 insertions(+), 115 deletions(-) rename src/av98/{clientcerts.py => certmanager.py} (100%) rename src/av98/{av98.py => client.py} (92%) create mode 100755 src/av98/main.py diff --git a/pyproject.toml b/pyproject.toml index 55a3245..69a4e49 100755 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,7 +18,7 @@ classifiers = [ Homepage = "https://tildegit.org/solderpunk/AV-98/" Issues = "https://tildegit.org/solderpunk/AV-98/issues" [project.scripts] -av98 = "av98.av98:main" +av98 = "av98.main:main" [project.optional-dependencies] tofu = ["cryptography"] colour = ["ansiwrap"] diff --git a/src/av98/clientcerts.py b/src/av98/certmanager.py similarity index 100% rename from src/av98/clientcerts.py rename to src/av98/certmanager.py diff --git a/src/av98/av98.py b/src/av98/client.py similarity index 92% rename from src/av98/av98.py rename to src/av98/client.py index 1c9eb1a..d28f4d8 100755 --- a/src/av98/av98.py +++ b/src/av98/client.py @@ -13,7 +13,6 @@ # - rmgr # - Aleksey Ryndin -import argparse import cmd import cgi import codecs @@ -43,11 +42,9 @@ except ModuleNotFoundError: from av98 import __version__ from av98.cache import Cache from av98.tofu import TofuStore -from av98.clientcerts import ClientCertificateManager +from av98.certmanager import ClientCertificateManager import av98.util as util -_VERSION = "1.1.0dev" - _MAX_REDIRECTS = 5 # Command abbreviations @@ -1398,113 +1395,3 @@ current gemini browsing session.""" self._stop = True do_exit = do_quit - -# Main function -def main(): - - # Parse args - parser = argparse.ArgumentParser(description='A command line gemini client.') - parser.add_argument('--bookmarks', action='store_true', - help='start with your list of bookmarks') - parser.add_argument('--dl', '--download', action='store_true', - help='download a single URL and quit') - parser.add_argument('-o', '--output', metavar='FILE', - help='filename to save --dl URL to') - parser.add_argument('--tls-cert', metavar='FILE', help='TLS client certificate file') - parser.add_argument('--tls-key', metavar='FILE', help='TLS client certificate private key file') - parser.add_argument('--restricted', action="store_true", help='Disallow shell, add, and save commands') - parser.add_argument('--version', action='store_true', - help='display version information and quit') - parser.add_argument('url', metavar='URL', nargs='*', - help='start with this URL') - args = parser.parse_args() - - # Handle --version - if args.version: - print("AV-98 " + _VERSION) - sys.exit() - - # Instantiate client - gc = GeminiClient(args.restricted) - - # Activate client certs now in case they are needed for --download below - if args.tls_cert and args.tls_key: - gc.client_cert_manager._activate_client_cert(args.tls_cert, args.tls_key) - for url in args.url: - gi = GeminiItem(url) - gc.client_cert_manager.active_cert_domains.append(gi.host) - - # Handle --download - if args.dl: - gc.onecmd("set debug True") - # Download - gi = GeminiItem(args.url[0]) - gi, mime = gc._fetch_over_network(gi) - # Decide on a filename - if args.output: - filename = args.output - else: - if mime == "text/gemini": - # Parse gemtext in the hopes of getting a gi.name for the filename - gc.active_raw_file = gc.raw_file_buffer - gc._handle_gemtext(gi) - filename = gi.derive_filename(mime) - # Copy from temp file to pwd with a nice name - shutil.copyfile(gc.raw_file_buffer, filename) - size = os.path.getsize(filename) - # Notify user where the file ended up - print("Wrote %d byte %s response to %s." % (size, mime, filename)) - gc.do_quit() - sys.exit() - - # Process config file - rcfile = os.path.join(gc.config_dir, "av98rc") - if os.path.exists(rcfile): - print("Using config %s" % rcfile) - with open(rcfile, "r") as fp: - for line in fp: - line = line.strip() - if ((args.bookmarks or args.url) and - any((line.startswith(x) for x in ("go", "g", "tour", "t"))) - ): - if args.bookmarks: - print("Skipping rc command \"%s\" due to --bookmarks option." % line) - else: - print("Skipping rc command \"%s\" due to provided URLs." % line) - continue - gc.cmdqueue.append(line) - - # Say hi - print("Welcome to AV-98!") - if args.restricted: - print("Restricted mode engaged!") - print("Enjoy your patrol through Geminispace...") - - # Add commands to the queue based on command line arguments - if args.bookmarks: - gc.cmdqueue.append("bookmarks") - elif args.url: - if len(args.url) == 1: - gc.cmdqueue.append("go %s" % args.url[0]) - else: - for url in args.url: - if not url.startswith("gemini://"): - url = "gemini://" + url - gc.cmdqueue.append("tour %s" % url) - gc.cmdqueue.append("tour") - - # Endless interpret loop until user quits - while True: - try: - gc.cmdloop() - break - except KeyboardInterrupt: - print("") - - # Say goodbye - print() - print("Thank you for patrolling with AV-98!") - sys.exit() - -if __name__ == '__main__': - main() diff --git a/src/av98/main.py b/src/av98/main.py new file mode 100755 index 0000000..a5f4ae8 --- /dev/null +++ b/src/av98/main.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python3 +# AV-98 Gemini client +# Dervied from VF-1 (https://github.com/solderpunk/VF-1), +# (C) 2019, 2020, 2023 Solderpunk +# With contributions from: +# - danceka +# - +# - +# - Klaus Alexander Seistrup +# - govynnus +# - Nik +# - +# - rmgr +# - Aleksey Ryndin +import argparse +import os.path +import shutil +import sys + +from av98 import __version__ +from av98.client import GeminiClient + +def main(): + + # Parse args + parser = argparse.ArgumentParser(description='A command line gemini client.') + parser.add_argument('--bookmarks', action='store_true', + help='start with your list of bookmarks') + parser.add_argument('--dl', '--download', action='store_true', + help='download a single URL and quit') + parser.add_argument('-o', '--output', metavar='FILE', + help='filename to save --dl URL to') + parser.add_argument('--tls-cert', metavar='FILE', help='TLS client certificate file') + parser.add_argument('--tls-key', metavar='FILE', help='TLS client certificate private key file') + parser.add_argument('--restricted', action="store_true", help='Disallow shell, add, and save commands') + parser.add_argument('--version', action='store_true', + help='display version information and quit') + parser.add_argument('url', metavar='URL', nargs='*', + help='start with this URL') + args = parser.parse_args() + + # Handle --version + if args.version: + print("AV-98 " + __version__) + sys.exit() + + # Instantiate client + gc = GeminiClient(args.restricted) + + # Activate client certs now in case they are needed for --download below + if args.tls_cert and args.tls_key: + gc.client_cert_manager._activate_client_cert(args.tls_cert, args.tls_key) + for url in args.url: + gi = GeminiItem(url) + gc.client_cert_manager.active_cert_domains.append(gi.host) + + # Handle --download + if args.dl: + gc.onecmd("set debug True") + # Download + gi = GeminiItem(args.url[0]) + gi, mime = gc._fetch_over_network(gi) + # Decide on a filename + if args.output: + filename = args.output + else: + if mime == "text/gemini": + # Parse gemtext in the hopes of getting a gi.name for the filename + gc.active_raw_file = gc.raw_file_buffer + gc._handle_gemtext(gi) + filename = gi.derive_filename(mime) + # Copy from temp file to pwd with a nice name + shutil.copyfile(gc.raw_file_buffer, filename) + size = os.path.getsize(filename) + # Notify user where the file ended up + print("Wrote %d byte %s response to %s." % (size, mime, filename)) + gc.do_quit() + sys.exit() + + # Process config file + rcfile = os.path.join(gc.config_dir, "av98rc") + if os.path.exists(rcfile): + print("Using config %s" % rcfile) + with open(rcfile, "r") as fp: + for line in fp: + line = line.strip() + if ((args.bookmarks or args.url) and + any((line.startswith(x) for x in ("go", "g", "tour", "t"))) + ): + if args.bookmarks: + print("Skipping rc command \"%s\" due to --bookmarks option." % line) + else: + print("Skipping rc command \"%s\" due to provided URLs." % line) + continue + gc.cmdqueue.append(line) + + # Say hi + print("Welcome to AV-98!") + if args.restricted: + print("Restricted mode engaged!") + print("Enjoy your patrol through Geminispace...") + + # Add commands to the queue based on command line arguments + if args.bookmarks: + gc.cmdqueue.append("bookmarks") + elif args.url: + if len(args.url) == 1: + gc.cmdqueue.append("go %s" % args.url[0]) + else: + for url in args.url: + if not url.startswith("gemini://"): + url = "gemini://" + url + gc.cmdqueue.append("tour %s" % url) + gc.cmdqueue.append("tour") + + # Endless interpret loop until user quits + while True: + try: + gc.cmdloop() + break + except KeyboardInterrupt: + print("") + + # Say goodbye + print() + print("Thank you for patrolling with AV-98!") + sys.exit() + +if __name__ == '__main__': + main()