]> git.phdru.name Git - m_librarian.git/commitdiff
Feat: Web UI
authorOleg Broytman <phd@phdru.name>
Sat, 31 Mar 2018 22:38:28 +0000 (01:38 +0300)
committerOleg Broytman <phd@phdru.name>
Sun, 1 Apr 2018 18:01:27 +0000 (21:01 +0300)
Start developing web UI using bottle microframework.
Implement simple server.

devscripts/requirements/requirements.txt
docs-ru/command_line.rst
docs/command_line.rst
m_librarian/web/__init__.py [new file with mode: 0644]
m_librarian/web/app.py [new file with mode: 0644]
m_librarian/web/server.py [new file with mode: 0644]
m_librarian/web/utils.py [new file with mode: 0644]
scripts/ml-web.py [new file with mode: 0755]
setup.py

index 93bfbe40135d0859cbad764df96bb0254e11bc8b..3c9963bac25e3cc7f4241bfd11b900cdccda0892 100644 (file)
@@ -5,3 +5,4 @@
 SQLObject>=2.2.1; python_version >= '2.7' and python_version < '3.0'
 SQLObject>=3.0.0; python_version >= '3.4'
 m_lib.defenc>=1.0
+bottle
index c646cde6f51e56f0462941d09498e2a184740c42..2a686610a0fe56a772b666e629e7b0baf979d132 100644 (file)
@@ -257,4 +257,21 @@ ml-search.py
 
 При использовании опции `-v` также выводится id из БД.
 
+
+ml-web.py
+------------
+
+Использование::
+
+    ml-web.py [-p port]
+
+Опции::
+
+    -p, --port port      Порт протокола HTTP
+
+Запускает web-сервер. Если указан порт, то используется указанный порт.
+Иначе выбирается случайный порт из числа свободных. Программа запускает
+браузер (или открывает новое окно уже запущенного web-обозревателя) с
+адресом, указывающим на сервер.
+
 .. vim: set tw=72 :
index 56824a93aae6ddcc849668887ceda1117fae5095..4bde53d9f3b354636c10df9afaa7026ccdee9870 100644 (file)
@@ -253,4 +253,20 @@ Options::
 
 With one option `-v` it also prints database id.
 
+
+ml-web.py
+------------
+
+Usage::
+
+    ml-web.py [-p port]
+
+Options::
+
+    -p, --port port      HTTP port to listen to
+
+Run a web server. If a port is given listen on the given port. Else
+choose a random port. Start a browser (or open a new window of a running
+browser) pointing it to the server.
+
 .. vim: set tw=72 :
diff --git a/m_librarian/web/__init__.py b/m_librarian/web/__init__.py
new file mode 100644 (file)
index 0000000..792d600
--- /dev/null
@@ -0,0 +1 @@
+#
diff --git a/m_librarian/web/app.py b/m_librarian/web/app.py
new file mode 100644 (file)
index 0000000..01b15dd
--- /dev/null
@@ -0,0 +1,6 @@
+from bottle import route
+
+
+@route('/')
+def hello():
+    return "Hello World!"
diff --git a/m_librarian/web/server.py b/m_librarian/web/server.py
new file mode 100644 (file)
index 0000000..bc8e552
--- /dev/null
@@ -0,0 +1,26 @@
+from bottle import run
+
+from wsgiref import simple_server
+from wsgiref.handlers import SimpleHandler
+from wsgiref.simple_server import WSGIServer
+from bottle import route
+
+simple_server.ServerHandler = SimpleHandler  # Stop logging to stdout
+
+
+class QuitWSGIServer(WSGIServer):
+    _quit_flag = False
+
+    def serve_forever(self):
+        while not self._quit_flag:
+            self.handle_request()
+
+
+@route('/quit')
+def quit():
+    QuitWSGIServer._quit_flag = True
+    return "The program has finished. Have a nice day!"
+
+
+def run_server(host='localhost', port=0):
+    run(host=host, port=port, server_class=QuitWSGIServer, debug=True)
diff --git a/m_librarian/web/utils.py b/m_librarian/web/utils.py
new file mode 100644 (file)
index 0000000..2efe724
--- /dev/null
@@ -0,0 +1,10 @@
+
+def get_open_port():
+    # https://stackoverflow.com/a/2838309/7976758
+    import socket
+    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    s.bind(("", 0))
+    # s.listen(1)
+    port = s.getsockname()[1]
+    s.close()
+    return port
diff --git a/scripts/ml-web.py b/scripts/ml-web.py
new file mode 100755 (executable)
index 0000000..f5a579e
--- /dev/null
@@ -0,0 +1,30 @@
+#! /usr/bin/env python
+
+import argparse
+import time
+import webbrowser
+
+from bottle import thread  # portable import
+
+import m_librarian.web.app  # noqa: F401 imported but unused
+from m_librarian.web.server import run_server
+from m_librarian.web.utils import get_open_port
+
+
+def start_browser(port):
+    time.sleep(1)  # A small timeout to allow the main thread to run the server
+    webbrowser.open_new('http://localhost:%d/' % port)
+
+
+if __name__ == '__main__':
+    parser = argparse.ArgumentParser(description='Init')
+    parser.add_argument('-p', '--port', help='HTTP server port')
+    args = parser.parse_args()
+
+    if args.port:
+        port = args.port
+    else:
+        port = get_open_port()
+
+    thread.start_new_thread(start_browser, (port,))
+    run_server(port=port)
index 29a8ec4e516a6b93076faade5471aad4b42919d8..d342061cd631375e121120fb80f50055f5db3bdf 100755 (executable)
--- a/setup.py
+++ b/setup.py
@@ -44,14 +44,14 @@ setup(name='m_librarian',
           'Programming Language :: Python :: 3.5',
           'Programming Language :: Python :: 3.6',
       ],
-      packages=['m_librarian'],
+      packages=['m_librarian', 'm_librarian.web'],
       package_data={'m_librarian': [
           'glst/*.txt', 'glst/genres_*.glst',
           'translations/*.mo'
           ]
       },
       scripts=['scripts/ml-import.py', 'scripts/ml-initdb.py',
-               'scripts/ml-search.py'],
+               'scripts/ml-search.py', 'scripts/ml-web.py'],
       python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*',
       install_requires=[
           'SQLObject>=2.2.1; python_version=="2.7"',
@@ -61,5 +61,7 @@ setup(name='m_librarian',
       extras_require={
           'm_lib': ['m_lib>=3.1'],
           'pbar': ['m_lib>=3.1'],
+          'web': ['bottle'],
+          'bottle': ['bottle'],
       },
       )