From 5cd9047165800abe6223ed61ca3395691593357e Mon Sep 17 00:00:00 2001 From: joncrall Date: Thu, 8 Aug 2024 11:55:51 -0400 Subject: [PATCH 01/11] Lint --- instant_rst/args.py | 4 +++- instant_rst/main.py | 8 ++++---- instant_rst/server.py | 37 ++++++++++++++++++++++--------------- 3 files changed, 29 insertions(+), 20 deletions(-) diff --git a/instant_rst/args.py b/instant_rst/args.py index 4dbe1ea..d8f5a50 100644 --- a/instant_rst/args.py +++ b/instant_rst/args.py @@ -4,6 +4,7 @@ from instant_rst.settings import DEFAULT_FILE, PORT, BROWSER, \ FLASK_TEMPLATE_FOLDER, FLASK_STATIC_FOLDER + def setup(_args): settings.FLASK_TEMPLATE_FOLDER = _args.template_dir settings.FLASK_STATIC_FOLDER = _args.static_dir @@ -11,6 +12,7 @@ def setup(_args): settings.ADDITIONAL_DIRS = _args.additional_dirs settings.PORT = _args.port + def parse(): parser = argparse.ArgumentParser(description='Preview rst instantly.') parser.add_argument('-f', '--file', dest='filename', @@ -41,7 +43,7 @@ def parse(): default=False, help='debug mode or not') - _args = parser.parse_args() + _args = parser.parse_args() setup(_args) diff --git a/instant_rst/main.py b/instant_rst/main.py index 5e9ebd0..9f72cb6 100644 --- a/instant_rst/main.py +++ b/instant_rst/main.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 -from multiprocessing import Process from threading import Thread import socket -import sys +import sys from instant_rst.server import sock, app from instant_rst import util, args, settings @@ -19,16 +18,17 @@ settings.URL = f"http://{settings.HOST}:{settings.PORT}" + def run(): settings._p1 = Thread(target=util.delay, args=(1, "browseAndPost", [_args.browser, settings.URL])) - settings._p2 = Thread(target=sock.run, args=(app,), kwargs={'host':APP_HOST,'port':settings.PORT}) + settings._p2 = Thread(target=sock.run, args=(app,), kwargs={'host': APP_HOST, 'port': settings.PORT}) try: if not _args.debug: settings._p1.start() # sock.run(app, host=APP_HOST, port=settings.PORT) settings._p2.start() - except: + except Exception: print('\nSome error/exception occurred.') print(sys.exc_info()) settings._p1.terminate() diff --git a/instant_rst/server.py b/instant_rst/server.py index ba9f05d..30ca778 100644 --- a/instant_rst/server.py +++ b/instant_rst/server.py @@ -1,7 +1,8 @@ -from flask import Flask, escape, request, render_template, jsonify, send_from_directory +from flask import Flask, request, render_template, jsonify, send_from_directory from flask_socketio import SocketIO -import os, sys, time +import os +import sys from instant_rst.rst import html_body from instant_rst import settings, util @@ -14,28 +15,31 @@ # ROUTE + @app.route('/', methods=['GET']) def index_get(): _file = request.args.get('rst', '') if os.path.isfile(_file): - with open(_file,'r') as _fo: + with open(_file, 'r') as _fo: _doc = html_body(_fo.read()) return render_template('index.html', HTML=_doc) else: return render_template('index.html') + @app.route('/', methods=['POST', 'PUT']) def index_post(): print(str(request.form)) - if util.emit_doc(sock, - request.form.get('dir',''), - request.form.get('file',''), - request.form.get('pos', '-1')): + if util.emit_doc(sock, + request.form.get('dir', ''), + request.form.get('file', ''), + request.form.get('pos', '-1')): return jsonify(code=0, msg='success') else: return jsonify(code=2, msg='file not exist', file=request.form.get('file')) return 'error', 502 + @app.route('/', methods=['DELETE']) def index_delete(): sock.emit('die', {'exit': 1}) @@ -44,6 +48,7 @@ def index_delete(): # FILES + # serve static with additional directories @app.route("//") def serve_additional_file(directory, filename): @@ -71,7 +76,7 @@ def serve_static_file(filename): print("serve", settings.STATIC_DIR) if settings.STATIC_DIR and filename: return send_from_directory( - settings.STATIC_DIR, + settings.STATIC_DIR, filename) else: return '', 404 @@ -80,12 +85,13 @@ def serve_static_file(filename): # SOCKET @sock.on('file') -def handler(detail): +def file_handler(detail): print('received file: ' + str(detail)) - util.emit_doc(sock, - detail.get('dir',''), - detail.get('file',''), - detail.get('pos', '')) + util.emit_doc(sock, + detail.get('dir', ''), + detail.get('file', ''), + detail.get('pos', '')) + @sock.on('message') def handler(message): @@ -98,11 +104,14 @@ def handler(message): def page_not_found(e): return render_template('404.html'), 404 + @app.errorhandler(500) def server_error(e): return render_template('500.html', err=e), 500 + def shutdown_server(): + # import time # time.sleep(0.5) # settings._p2.terminate() # settings._p2.join() @@ -111,5 +120,3 @@ def shutdown_server(): sys.exit() else: exit() - - From 20340c222ed023f0a9b97f02161381f06975d2dc Mon Sep 17 00:00:00 2001 From: joncrall Date: Thu, 8 Aug 2024 11:56:12 -0400 Subject: [PATCH 02/11] Add dunder main to module --- instant_rst/__main__.py | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 instant_rst/__main__.py diff --git a/instant_rst/__main__.py b/instant_rst/__main__.py new file mode 100644 index 0000000..62b57e6 --- /dev/null +++ b/instant_rst/__main__.py @@ -0,0 +1,5 @@ +#!/usr/bin/env python3 +from instant_rst.main import run + +if __name__ == '__main__': + run() From 24f1adb62fe5cd2b2003e4018f090a927095df2f Mon Sep 17 00:00:00 2001 From: joncrall Date: Wed, 28 Aug 2024 19:39:37 -0400 Subject: [PATCH 03/11] testing --- README.rst | 28 ++++++++++++++-------------- instant_rst/main.py | 1 + 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/README.rst b/README.rst index ea26335..799ffc8 100644 --- a/README.rst +++ b/README.rst @@ -46,7 +46,7 @@ usage: instantRst [-h] [-f FILENAME] [-b BROWSER] [-p PORT] [-s STATIC_DIR] [-t optional arguments: --h, --help +-h, --help show this help message and exit -f FILENAME, --file FILENAME The local filename for Converting @@ -55,16 +55,16 @@ optional arguments: Default is '' for using system default -p PORT, --port PORT The port for server to use Default is '5676' --t TEMPLATE_DIR, --template-dir TEMPLATE_DIR - Directory containing a template to - be used when rendering the output. +-t TEMPLATE_DIR, --template-dir TEMPLATE_DIR + Directory containing a template to + be used when rendering the output. Defaults to a bundled rhythm.css_ --s STATIC_DIR, --static-dir STATIC_DIR - The directory containing static +-s STATIC_DIR, --static-dir STATIC_DIR + The directory containing static files used by the template. Defaults to a bundled rhythm.css_ --l, --localhost-only - Only use localhost, disable lan ip +-l, --localhost-only + Only use localhost, disable lan ip default: False -d, --additional-dir @@ -130,7 +130,7 @@ STATIC FILES 0. Default Static file: the ``static/main.css|js`` is served there - + The instant rst's default theme is set there. You can pass the ``-s`` for default static directory. @@ -154,7 +154,7 @@ STATIC FILES When using with dynamic files, you can post with '-dir=DYN_DIR_NAME' to update the ``DYN_STATIC_DIR`` e.g.: - + You have a file named ``test/test.jpg`` When you start instantRst ``instantRst -f test/test.rst`` @@ -162,7 +162,7 @@ STATIC FILES The file is served with ``localhost:5676/_static/test.jpg`` When you switch to another file like ``test1/test.rst`` - Then you can post with ``dir=test1`` or ``dir=~/rst/test1`` to change + Then you can post with ``dir=test1`` or ``dir=~/rst/test1`` to change the static dir. Develop @@ -171,8 +171,8 @@ Develop Contribution are welcomed. git clone the project:: - - git clone + + git clone install local package:: @@ -181,7 +181,7 @@ install local package:: start test with local package:: # localhost:5676 - python scripts/instantRst --debug -f test/test.rst + python -m instant_rst --debug -f README.rst change to static/template file should change setup.py and manifest.in diff --git a/instant_rst/main.py b/instant_rst/main.py index 9f72cb6..98460cd 100644 --- a/instant_rst/main.py +++ b/instant_rst/main.py @@ -20,6 +20,7 @@ def run(): + print(settings.URL) settings._p1 = Thread(target=util.delay, args=(1, "browseAndPost", [_args.browser, settings.URL])) settings._p2 = Thread(target=sock.run, args=(app,), kwargs={'host': APP_HOST, 'port': settings.PORT}) From e368c57c6025ee537d5a0da9fbbd395b46b1e3fd Mon Sep 17 00:00:00 2001 From: joncrall Date: Wed, 28 Aug 2024 19:53:43 -0400 Subject: [PATCH 04/11] Consolidate args and main --- README.rst | 8 +++--- instant_rst/args.py | 50 -------------------------------- instant_rst/main.py | 64 ++++++++++++++++++++++++++++++++++------- instant_rst/settings.py | 13 +++++---- 4 files changed, 66 insertions(+), 69 deletions(-) delete mode 100644 instant_rst/args.py diff --git a/README.rst b/README.rst index 799ffc8..a961ee9 100644 --- a/README.rst +++ b/README.rst @@ -58,11 +58,11 @@ optional arguments: -t TEMPLATE_DIR, --template-dir TEMPLATE_DIR Directory containing a template to be used when rendering the output. - Defaults to a bundled rhythm.css_ + Defaults to a bundled ``rhythm.css_`` -s STATIC_DIR, --static-dir STATIC_DIR The directory containing static files used by the template. - Defaults to a bundled rhythm.css_ + Defaults to a bundled ``rhythm.css_`` -l, --localhost-only Only use localhost, disable lan ip default: False @@ -180,8 +180,8 @@ install local package:: start test with local package:: - # localhost:5676 - python -m instant_rst --debug -f README.rst + # localhost:5000 + python -m instant_rst -f README.rst change to static/template file should change setup.py and manifest.in diff --git a/instant_rst/args.py b/instant_rst/args.py deleted file mode 100644 index d8f5a50..0000000 --- a/instant_rst/args.py +++ /dev/null @@ -1,50 +0,0 @@ -import argparse - -from instant_rst import settings -from instant_rst.settings import DEFAULT_FILE, PORT, BROWSER, \ - FLASK_TEMPLATE_FOLDER, FLASK_STATIC_FOLDER - - -def setup(_args): - settings.FLASK_TEMPLATE_FOLDER = _args.template_dir - settings.FLASK_STATIC_FOLDER = _args.static_dir - settings.DEFAULT_FILE = _args.filename - settings.ADDITIONAL_DIRS = _args.additional_dirs - settings.PORT = _args.port - - -def parse(): - parser = argparse.ArgumentParser(description='Preview rst instantly.') - parser.add_argument('-f', '--file', dest='filename', - default=DEFAULT_FILE, - help='The local filename for Converting') - parser.add_argument('-b', '--browser', dest='browser', - default=BROWSER, - help='The browser command for viewing, empty will use default') - parser.add_argument('-p', '--port', dest='port', - default=PORT, - help='The port for server to use') - parser.add_argument('-s', '--static-dir', dest='static_dir', - default=FLASK_STATIC_FOLDER, - help='Directory with static files for rendering') - parser.add_argument('-t', '--template-dir', dest='template_dir', - default=FLASK_TEMPLATE_FOLDER, - help='Directory with template files for rendering') - parser.add_argument('-l', '--localhost-only', dest='localhost_only', - action='store_true', - help='Only use localhost, disable lan. default: False') - parser.add_argument('-d', '--aditional-dir', dest='additional_dirs', - action='append', - default=[], - help='Additional directories to serve') - - parser.add_argument('--debug', - action='store_true', - default=False, - help='debug mode or not') - - _args = parser.parse_args() - - setup(_args) - - return _args diff --git a/instant_rst/main.py b/instant_rst/main.py index 98460cd..16c0e16 100644 --- a/instant_rst/main.py +++ b/instant_rst/main.py @@ -1,25 +1,69 @@ #!/usr/bin/env python3 from threading import Thread +import argparse import socket import sys from instant_rst.server import sock, app -from instant_rst import util, args, settings +from instant_rst import util +from instant_rst import settings -_args = args.parse() -if _args.localhost_only: - settings.HOST = "localhost" - APP_HOST = "127.0.0.1" -else: - # get hostname of local LAN IP - settings.HOST = socket.gethostbyname(socket.gethostname()) - APP_HOST = "0.0.0.0" +def parse(): + parser = argparse.ArgumentParser(description='Preview rst instantly.') + parser.add_argument('-f', '--file', dest='filename', + default=settings.DEFAULT_FILE, + help='The local filename for Converting') + parser.add_argument('-b', '--browser', dest='browser', + default=settings.BROWSER, + help='The browser command for viewing, empty will use default') + parser.add_argument('-p', '--port', dest='port', + default=settings.PORT, + help='The port for server to use') + parser.add_argument('-s', '--static-dir', dest='static_dir', + default=settings.FLASK_STATIC_FOLDER, + help='Directory with static files for rendering') + parser.add_argument('-t', '--template-dir', dest='template_dir', + default=settings.FLASK_TEMPLATE_FOLDER, + help='Directory with template files for rendering') + parser.add_argument('-l', '--localhost-only', dest='localhost_only', + action='store_true', + help='Only use localhost, disable lan. default: False') + parser.add_argument('-d', '--aditional-dir', dest='additional_dirs', + action='append', + default=[], + help='Additional directories to serve') -settings.URL = f"http://{settings.HOST}:{settings.PORT}" + parser.add_argument('--debug', + action='store_true', + default=False, + help='debug mode or not') + + _args = parser.parse_args() + + return _args def run(): + + _args = parse() + + settings.FLASK_TEMPLATE_FOLDER = _args.template_dir + settings.FLASK_STATIC_FOLDER = _args.static_dir + settings.DEFAULT_FILE = _args.filename + settings.ADDITIONAL_DIRS = _args.additional_dirs + settings.PORT = _args.port + + if _args.localhost_only: + settings.HOST = "localhost" + APP_HOST = "127.0.0.1" + else: + # get hostname of local LAN IP + settings.HOST = socket.gethostbyname(socket.gethostname()) + APP_HOST = "0.0.0.0" + + settings.URL = f"http://{settings.HOST}:{settings.PORT}" + print(settings.URL) settings._p1 = Thread(target=util.delay, args=(1, "browseAndPost", [_args.browser, settings.URL])) settings._p2 = Thread(target=sock.run, args=(app,), kwargs={'host': APP_HOST, 'port': settings.PORT}) diff --git a/instant_rst/settings.py b/instant_rst/settings.py index 8b25bc1..c6667b9 100644 --- a/instant_rst/settings.py +++ b/instant_rst/settings.py @@ -2,16 +2,19 @@ ADDITIONAL_DIRS = [] -STATIC_DIR = os.path.join( os.path.dirname(os.path.realpath(__file__)),'templates') -DEFAULT_FILE = os.path.join( os.path.dirname(os.path.realpath(__file__)),'templates', "index.rst") +mod_dpath = os.path.dirname(os.path.abspath(__file__)) + +STATIC_DIR = os.path.join(mod_dpath, 'templates') +DEFAULT_FILE = os.path.join(mod_dpath, 'templates', "index.rst") HOST = "127.0.0.1" PORT = 5000 URL = "http://127.0.0.1:5000" -BROWSER = 'firefox' +# BROWSER = 'firefox' +BROWSER = '' SECRET = 'JO34h#F*$HFHA@#&(' -FLASK_STATIC_FOLDER = os.path.join( os.path.dirname(os.path.realpath(__file__)),'static') -FLASK_TEMPLATE_FOLDER = os.path.join( os.path.dirname(os.path.realpath(__file__)),'templates') +FLASK_STATIC_FOLDER = os.path.join(mod_dpath, 'static') +FLASK_TEMPLATE_FOLDER = os.path.join(mod_dpath, 'templates') _p1 = None From f75aba8fe7420266313a4b2294817d1a074d27de Mon Sep 17 00:00:00 2001 From: joncrall Date: Wed, 28 Aug 2024 19:55:36 -0400 Subject: [PATCH 05/11] Remove scripts in favor of entry points in setup --- scripts/instantRst | 6 ------ setup.py | 15 ++++++++++----- 2 files changed, 10 insertions(+), 11 deletions(-) delete mode 100755 scripts/instantRst diff --git a/scripts/instantRst b/scripts/instantRst deleted file mode 100755 index a6ef087..0000000 --- a/scripts/instantRst +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -from instant_rst.main import run - -run() diff --git a/setup.py b/setup.py index 0f40047..683f232 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,4 @@ -from setuptools import setup, find_packages # Always prefer setuptools over distutils +from setuptools import setup # Always prefer setuptools over distutils from codecs import open # To use a consistent encoding from os import path @@ -51,7 +51,7 @@ # now require 3.6+ python_requires='>=3.6', - + # What does your project relate to? keywords='rst docutils preview', @@ -66,7 +66,7 @@ # project is installed. For an analysis of "install_requires" vs pip's # requirements files see: # https://packaging.python.org/en/latest/technical.html#install-requires-vs-requirements-files - install_requires=['flask>=2.1.1','docutils', 'pygments','flask-socketio>=5.1.1'], + install_requires=['flask>=2.1.1', 'docutils', 'pygments', 'flask-socketio>=5.1.1'], # If there are data files included in your packages that need to be # installed, specify them here. If using Python 2.6 or less, then these @@ -75,7 +75,7 @@ # 'scripts': ['scripts/instantRst.py'], # }, package_data={'static': ['*.css', '*.js'], - 'templates':['*.html', '*.rst']}, + 'templates': ['*.html', '*.rst']}, # package_data = { # '': ['*.txt', '*.rst','*.css','*.html'], # }, @@ -88,7 +88,12 @@ # 'instant_rst/templates/index.rst'])], include_package_data=True, - scripts=['scripts/instantRst'], + + entry_points={ + 'console_scripts': [ + 'instantRst= instant_rst.main:run', + ], + }, # To provide executable scripts, use entry points in preference to the # "scripts" keyword. Entry points provide cross-platform support and allow From ad1172d0dda8ee8b79cf0ae69e3376defeb1cfc3 Mon Sep 17 00:00:00 2001 From: joncrall Date: Wed, 28 Aug 2024 19:56:50 -0400 Subject: [PATCH 06/11] lint --- instant_rst/rst.py | 5 +++-- instant_rst/util.py | 24 +++++++++++++----------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/instant_rst/rst.py b/instant_rst/rst.py index feb5c4b..2fe6f7b 100644 --- a/instant_rst/rst.py +++ b/instant_rst/rst.py @@ -1,6 +1,7 @@ -from docutils import core, io +from docutils import core -def html_parts(input_string, source_path=None, + +def html_parts(input_string, source_path=None, destination_path=None, input_encoding='unicode', doctitle=True, initial_header_level=1): diff --git a/instant_rst/util.py b/instant_rst/util.py index cde2b47..61a50de 100644 --- a/instant_rst/util.py +++ b/instant_rst/util.py @@ -1,10 +1,11 @@ -from flask import jsonify import time -import os, sys - +import os +import sys +from urllib import request, parse from instant_rst.rst import html_body from instant_rst import settings + def which(program): def is_exe(fpath): return os.path.isfile(fpath) and os.access(fpath, os.X_OK) @@ -22,11 +23,12 @@ def is_exe(fpath): return None + def delay(t, func, args): time.sleep(t) # call function in globals with unzipped args[] globals()[func](*args) - + def browse(browser, url): if sys.platform.startswith('darwin'): @@ -40,7 +42,7 @@ def browse(browser, url): else: os.system(f'start {url}') elif os.name == 'posix': - linux = ['xdg-open','kioclient', 'exo-open', 'gnome-open', 'cygstart'] + linux = ['xdg-open', 'kioclient', 'exo-open', 'gnome-open', 'cygstart'] for _open in linux: if which(_open): if browser: @@ -50,19 +52,19 @@ def browse(browser, url): os.system(f'{_open} {url} &') break + def browseAndPost(browser, url): browse(browser, url) time.sleep(1) # print('post', settings.DEFAULT_FILE, settings.STATIC_DIR ) - post(url, {'file':settings.DEFAULT_FILE, 'dir':settings.STATIC_DIR}) + post(url, {'file': settings.DEFAULT_FILE, 'dir': settings.STATIC_DIR}) time.sleep(1) # settings._p1.terminate() def getDir(_dir): - return _dir if os.path.isabs(_dir) else os.path.join(os.getcwd(), os.path.dirname(_dir)) + return _dir if os.path.isabs(_dir) else os.path.join(os.getcwd(), os.path.dirname(_dir)) -from urllib import request, parse def post(url, data): data = parse.urlencode(data).encode('utf-8') @@ -84,13 +86,13 @@ def emit_doc(sock, _dir='', _file='', _pos='-1'): if os.path.isfile(_file): settings.DEFAULT_FILE = _file - with open(_file,'r') as _fo: + with open(_file, 'r') as _fo: _doc = html_body(_fo.read()) - sock.emit('updatingContent', {'HTML': _doc, 'pos':_pos}) + sock.emit('updatingContent', {'HTML': _doc, 'pos': _pos}) return True elif _pos != '-1': - sock.emit('updatingContent', {'pos':_pos}) + sock.emit('updatingContent', {'pos': _pos}) return True return False From b4ccba85a7316ec7a77aac635d1ea2d7cd64dc60 Mon Sep 17 00:00:00 2001 From: joncrall Date: Thu, 29 Aug 2024 17:55:58 -0400 Subject: [PATCH 07/11] scriptconfig --- instant_rst/main.py | 55 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 6 deletions(-) diff --git a/instant_rst/main.py b/instant_rst/main.py index 16c0e16..3388da9 100644 --- a/instant_rst/main.py +++ b/instant_rst/main.py @@ -8,8 +8,49 @@ from instant_rst import util from instant_rst import settings +import ubelt as ub +import scriptconfig as scfg -def parse(): + +class InstantRST_CLI(scfg.DataConfig): + """ + Preview rst instantly. + """ + filename = scfg.Value( + settings.DEFAULT_FILE, + alias=['file'], short_alias=['f'], + help='The local filename for Converting', + position=1) + browser = scfg.Value(settings.BROWSER, short_alias=['b'], help=ub.paragraph( + ''' + The browser command for viewing, empty will use default + ''')) + port = scfg.Value(settings.PORT, short_alias=['p'], help='The port for server to use') + static_dir = scfg.Value(settings.FLASK_TEMPLATE_FOLDER, short_alias=['s'], help=ub.paragraph( + ''' + Directory with static files for rendering + ''')) + template_dir = scfg.Value(settings.FLASK_STATIC_FOLDER, short_alias=['t'], help=ub.paragraph( + ''' + Directory with template files for rendering + ''')) + localhost_only = scfg.Value(False, isflag=True, short_alias=['l'], help=ub.paragraph( + ''' + Only use localhost, disable lan. default: False + ''')) + additional_dirs = scfg.Value([], alias=['aditional_dir'], short_alias=['d'], help='Additional directories to serve') + debug = scfg.Value(False, isflag=True, help='debug mode or not') + + +def make_argparse(): + """ + Ignore: + from instant_rst.main import * # NOQA + import scriptconfig + parser = make_argparse() + print(scriptconfig.DataConfig.port_from_argparse(parser, name='InstantRST_CLI')) + + """ parser = argparse.ArgumentParser(description='Preview rst instantly.') parser.add_argument('-f', '--file', dest='filename', default=settings.DEFAULT_FILE, @@ -39,15 +80,17 @@ def parse(): default=False, help='debug mode or not') - _args = parser.parse_args() - - return _args + return parser def run(): + try: + _args = InstantRST_CLI.cli(strict=True) + except Exception: + parser = make_argparse() + _args = parser.parse_args() - _args = parse() - + # Settings are stored in a global module, might be best to change this. settings.FLASK_TEMPLATE_FOLDER = _args.template_dir settings.FLASK_STATIC_FOLDER = _args.static_dir settings.DEFAULT_FILE = _args.filename From 4a6521f93356801f9ea0b305465c26aabe07cc13 Mon Sep 17 00:00:00 2001 From: joncrall Date: Thu, 29 Aug 2024 17:56:19 -0400 Subject: [PATCH 08/11] wip --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 683f232..ecf8061 100644 --- a/setup.py +++ b/setup.py @@ -66,7 +66,7 @@ # project is installed. For an analysis of "install_requires" vs pip's # requirements files see: # https://packaging.python.org/en/latest/technical.html#install-requires-vs-requirements-files - install_requires=['flask>=2.1.1', 'docutils', 'pygments', 'flask-socketio>=5.1.1'], + install_requires=['flask>=2.1.1', 'docutils', 'pygments', 'flask-socketio>=5.1.1', 'scriptconfig'], # If there are data files included in your packages that need to be # installed, specify them here. If using Python 2.6 or less, then these From ac61b9e800e31b08f9214693bed1057c6769e189 Mon Sep 17 00:00:00 2001 From: joncrall Date: Fri, 19 Sep 2025 14:34:57 -0400 Subject: [PATCH 09/11] Update reqs --- setup.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index ecf8061..efac3cc 100644 --- a/setup.py +++ b/setup.py @@ -66,7 +66,13 @@ # project is installed. For an analysis of "install_requires" vs pip's # requirements files see: # https://packaging.python.org/en/latest/technical.html#install-requires-vs-requirements-files - install_requires=['flask>=2.1.1', 'docutils', 'pygments', 'flask-socketio>=5.1.1', 'scriptconfig'], + install_requires=[ + 'flask>=2.0.1', + 'docutils', + 'pygments', + 'flask-socketio>=5.1.1', + 'scriptconfig' + ], # If there are data files included in your packages that need to be # installed, specify them here. If using Python 2.6 or less, then these @@ -91,7 +97,8 @@ entry_points={ 'console_scripts': [ - 'instantRst= instant_rst.main:run', + 'instantRst = instant_rst.main:run', + 'instant-rst = instant_rst.main:run', ], }, From f7ec71bc5f02dcf5c40e8c1cd4e2cc6a5b7a8bdb Mon Sep 17 00:00:00 2001 From: joncrall Date: Fri, 19 Sep 2025 14:48:43 -0400 Subject: [PATCH 10/11] remove hardcoded secret, change default port --- instant_rst/server.py | 3 ++- instant_rst/settings.py | 48 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/instant_rst/server.py b/instant_rst/server.py index 30ca778..31a9620 100644 --- a/instant_rst/server.py +++ b/instant_rst/server.py @@ -10,7 +10,8 @@ app = Flask(__name__, static_folder=settings.FLASK_STATIC_FOLDER, template_folder=settings.FLASK_TEMPLATE_FOLDER) -app.config['SECRET_KEY'] = settings.SECRET + +app.config['SECRET_KEY'] = settings.get_secret() sock = SocketIO(app) # ROUTE diff --git a/instant_rst/settings.py b/instant_rst/settings.py index c6667b9..fe22d3e 100644 --- a/instant_rst/settings.py +++ b/instant_rst/settings.py @@ -1,4 +1,7 @@ import os +import secrets +import stat +import ubelt as ub ADDITIONAL_DIRS = [] @@ -7,15 +10,54 @@ STATIC_DIR = os.path.join(mod_dpath, 'templates') DEFAULT_FILE = os.path.join(mod_dpath, 'templates', "index.rst") HOST = "127.0.0.1" -PORT = 5000 -URL = "http://127.0.0.1:5000" +# PORT = 5000 +PORT = 58772 # Picking a random non-dev port +URL = f"http://127.0.0.1:{PORT}" # BROWSER = 'firefox' BROWSER = '' -SECRET = 'JO34h#F*$HFHA@#&(' +# SECRET = 'JO34h#F*$HFHA@#&(' FLASK_STATIC_FOLDER = os.path.join(mod_dpath, 'static') FLASK_TEMPLATE_FOLDER = os.path.join(mod_dpath, 'templates') +APP_NAME = "instant-rst" + + +def _secret_file(): + config_dpath = ub.Path.appdir(APP_NAME).ensuredir() + return config_dpath / "secret_key" + + +def get_secret(env_var="SECRET_KEY", allow_generate=True, dev_mode=False) -> str: + # 1) Environment takes precedence + val = os.getenv(env_var) + if val: + return val + + # 2) Persistent file-based secret + fpath = _secret_file() + if fpath.exists(): + return fpath.read_text().strip() + + # 3) Generate new one and save securely + if allow_generate: + secret = secrets.token_urlsafe(32) + fpath.write_text(secret) + + # Lock down permissions on POSIX + try: + os.chmod(fpath, stat.S_IRUSR | stat.S_IWUSR) + except Exception: + pass + return secret + + # 4) Dev fallback: ephemeral + if dev_mode: + return secrets.token_urlsafe(32) + + raise RuntimeError(f"{env_var} is required in production") + + _p1 = None _p2 = None From 5a85331c8420defc5a9c0aaa7b371875a8da44a7 Mon Sep 17 00:00:00 2001 From: joncrall Date: Fri, 19 Sep 2025 14:55:01 -0400 Subject: [PATCH 11/11] wip [skip ci] --- instant_rst/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instant_rst/main.py b/instant_rst/main.py index 3388da9..9c5827b 100644 --- a/instant_rst/main.py +++ b/instant_rst/main.py @@ -85,7 +85,7 @@ def make_argparse(): def run(): try: - _args = InstantRST_CLI.cli(strict=True) + _args = InstantRST_CLI.cli(strict=True, verbose='auto') except Exception: parser = make_argparse() _args = parser.parse_args()