[Pkg-privacy-commits] [onionshare] 23/53: Add docstrings to all classes and methods (fix #198)

Ulrike Uhlig u-guest at moszumanska.debian.org
Wed Dec 30 00:20:12 UTC 2015


This is an automated email from the git hooks/post-receive script.

u-guest pushed a commit to branch debian
in repository onionshare.

commit dc589211879ac7d32c67d6ea0502dfe12eb91400
Author: Micah Lee <micah at micahflee.com>
Date:   Sun Nov 15 19:01:20 2015 -0800

    Add docstrings to all classes and methods (fix #198)
---
 onionshare/helpers.py            | 17 +++++++++++++
 onionshare/hs.py                 | 36 +++++++++++++++++++++++++++
 onionshare/onionshare.py         | 17 +++++++++++++
 onionshare/web.py                | 41 +++++++++++++++++++++++++++++++
 onionshare_gui/downloads.py      | 13 ++++++++++
 onionshare_gui/file_selection.py | 53 ++++++++++++++++++++++++++++++++++++++++
 onionshare_gui/onionshare_gui.py | 38 ++++++++++++++++++++++++++++
 onionshare_gui/options.py        |  6 +++++
 onionshare_gui/server_status.py  | 24 ++++++++++++++++++
 9 files changed, 245 insertions(+)

diff --git a/onionshare/helpers.py b/onionshare/helpers.py
index 250ef8d..1a48147 100644
--- a/onionshare/helpers.py
+++ b/onionshare/helpers.py
@@ -120,6 +120,9 @@ def is_root():
 
 
 def dir_size(start_path):
+    """
+    Calculates the total size, in bytes, of all of the files in a directory.
+    """
     total_size = 0
     for dirpath, dirnames, filenames in os.walk(start_path):
         for f in filenames:
@@ -130,6 +133,11 @@ def dir_size(start_path):
 
 
 class ZipWriter(object):
+    """
+    ZipWriter accepts files and directories and compresses them into a zip file
+    with. If a zip_filename is not passed in, it will use the default onionshare
+    filename.
+    """
     def __init__(self, zip_filename=None):
         if zip_filename:
             self.zip_filename = zip_filename
@@ -139,9 +147,15 @@ class ZipWriter(object):
         self.z = zipfile.ZipFile(self.zip_filename, 'w', allowZip64=True)
 
     def add_file(self, filename):
+        """
+        Add a file to the zip archive.
+        """
         self.z.write(filename, os.path.basename(filename), zipfile.ZIP_DEFLATED)
 
     def add_dir(self, filename):
+        """
+        Add a directory, and all of its children, to the zip archive.
+        """
         dir_to_strip = os.path.dirname(filename.rstrip('/'))+'/'
         for dirpath, dirnames, filenames in os.walk(filename):
             for f in filenames:
@@ -151,4 +165,7 @@ class ZipWriter(object):
                     self.z.write(full_filename, arc_filename, zipfile.ZIP_DEFLATED)
 
     def close(self):
+        """
+        Close the zip archive.
+        """
         self.z.close()
diff --git a/onionshare/hs.py b/onionshare/hs.py
index 368a866..8897ec0 100644
--- a/onionshare/hs.py
+++ b/onionshare/hs.py
@@ -25,12 +25,35 @@ import socks
 import helpers, strings
 
 class NoTor(Exception):
+    """
+    This exception is raised if onionshare can't find a Tor control port
+    to connect to, or if it can't find a Tor socks5 proxy to proxy though.
+    """
     pass
 
 class HSDirError(Exception):
+    """
+    This exception is raised when onionshare tries create a non-ephemeral
+    hidden service and does not have permission to create or write to
+    the hidden service directory.
+    """
     pass
 
 class HS(object):
+    """
+    HS is an abstraction layer for connecting to the Tor control port and
+    creating hidden services. Onionshare supports creating hidden services
+    using two methods:
+
+    - Modifying the Tor configuration through the control port is the old
+      method, and will be deprecated in favor of ephemeral hidden services.
+    - Using the control port to create ephemeral hidden servers is the
+      preferred method.
+
+    This class detects the versions of Tor and stem to determine if ephemeral
+    hidden services are supported. If not, it falls back to modifying the
+    Tor configuration.
+    """
     def __init__(self, transparent_torification=False):
         self.transparent_torification = transparent_torification
 
@@ -57,6 +80,10 @@ class HS(object):
         self.supports_ephemeral = callable(list_ephemeral_hidden_services) and tor_version >= '0.2.7.1'
 
     def start(self, port):
+        """
+        Start a hidden service on port 80, pointing to the given port, and
+        return the onion hostname.
+        """
         print strings._("connecting_ctrlport").format(int(port))
         if self.supports_ephemeral:
             print strings._('using_ephemeral')
@@ -104,6 +131,11 @@ class HS(object):
             return onion_host
 
     def wait_for_hs(self, onion_host):
+        """
+        This function is only required when using non-ephemeral hidden services. After
+        creating a hidden service, continually attempt to connect to it until it
+        successfully connects..
+        """
         # legacy only, this function is no longer required with ephemeral hidden services
         print strings._('wait_for_hs')
 
@@ -148,6 +180,10 @@ class HS(object):
         return True
 
     def cleanup(self):
+        """
+        Stop hidden services that were created earlier, and delete any temporary
+        files that were created.
+        """
         if self.supports_ephemeral:
             # cleanup the ephemeral hidden service
             if self.service_id:
diff --git a/onionshare/onionshare.py b/onionshare/onionshare.py
index 3e30567..aa50031 100644
--- a/onionshare/onionshare.py
+++ b/onionshare/onionshare.py
@@ -22,6 +22,10 @@ import os, sys, subprocess, time, argparse, inspect, shutil, socket, threading
 import strings, helpers, web, hs
 
 class OnionShare(object):
+    """
+    OnionShare is the main application class. Pass in options and run
+    start_hidden_service and it will do the magic.
+    """
     def __init__(self, debug=False, local_only=False, stay_open=False, transparent_torification=False):
         self.port = None
         self.hs = None
@@ -45,6 +49,9 @@ class OnionShare(object):
         self.transparent_torification = transparent_torification
 
     def choose_port(self):
+        """
+        Pick an un-used port to bind to.
+        """
         # let the OS choose a port
         tmpsock = socket.socket()
         tmpsock.bind(("127.0.0.1", 0))
@@ -52,6 +59,9 @@ class OnionShare(object):
         tmpsock.close()
 
     def start_hidden_service(self, gui=False):
+        """
+        Start the onionshare hidden service.
+        """
         if not self.port:
             self.choose_port()
 
@@ -65,6 +75,9 @@ class OnionShare(object):
         self.onion_host = self.hs.start(self.port)
 
     def cleanup(self):
+        """
+        Shut everything down and clean up temporary files, etc.
+        """
         # cleanup files
         for filename in self.cleanup_filenames:
             if os.path.isfile(filename):
@@ -79,6 +92,10 @@ class OnionShare(object):
 
 
 def main(cwd=None):
+    """
+    The main() function implements all of the logic that the command-line version of
+    onionshare uses.
+    """
     strings.load_strings()
 
     # onionshare CLI in OSX needs to change current working directory (#132)
diff --git a/onionshare/web.py b/onionshare/web.py
index db52c04..8706c4d 100644
--- a/onionshare/web.py
+++ b/onionshare/web.py
@@ -31,6 +31,11 @@ zip_filesize = None
 
 
 def set_file_info(filenames):
+    """
+    Using the list of filenames being shared, fill in details that the web
+    page will need to display. This includes zipping up the file in order to
+    get the zip file's name and size.
+    """
     global file_info, zip_filename, zip_filesize
 
     # build file info list
@@ -71,6 +76,9 @@ q = Queue.Queue()
 
 
 def add_request(request_type, path, data=None):
+    """
+    Add a request to the queue, to communicate with the GUI.
+    """
     global q
     q.put({
         'type': request_type,
@@ -84,19 +92,34 @@ download_count = 0
 
 stay_open = False
 def set_stay_open(new_stay_open):
+    """
+    Set stay_open variable.
+    """
     global stay_open
     stay_open = new_stay_open
 def get_stay_open():
+    """
+    Get stay_open variable.
+    """
     return stay_open
 
 transparent_torification = False
 def set_transparent_torification(new_transparent_torification):
+    """
+    Set transparent_torification variable.
+    """
     global transparent_torification
     stay_open = new_transparent_torification
 def get_transparent_torification():
+    """
+    Get transparent_torification variable."
+    """
     return transparent_torification
 
 def debug_mode():
+    """
+    Turn on debugging mode, which will log flask errors to a debug file.
+    """
     import logging
 
     if platform.system() == 'Windows':
@@ -111,6 +134,9 @@ def debug_mode():
 
 @app.route("/<slug_candidate>")
 def index(slug_candidate):
+    """
+    Render the template for the onionshare landing page.
+    """
     if not helpers.constant_time_compare(slug.encode('ascii'), slug_candidate.encode('ascii')):
         abort(404)
 
@@ -128,6 +154,9 @@ def index(slug_candidate):
 
 @app.route("/<slug_candidate>/download")
 def download(slug_candidate):
+    """
+    Download the zip file.
+    """
     global download_count
     if not helpers.constant_time_compare(slug.encode('ascii'), slug_candidate.encode('ascii')):
         abort(404)
@@ -205,6 +234,9 @@ def download(slug_candidate):
 
 @app.errorhandler(404)
 def page_not_found(e):
+    """
+    404 error page.
+    """
     add_request(REQUEST_OTHER, request.path)
     return render_template_string(open(helpers.get_html_path('404.html')).read())
 
@@ -214,6 +246,9 @@ shutdown_slug = helpers.random_string(16)
 
 @app.route("/<shutdown_slug_candidate>/shutdown")
 def shutdown(shutdown_slug_candidate):
+    """
+    Stop the flask web server.
+    """
     if not helpers.constant_time_compare(shutdown_slug.encode('ascii'), shutdown_slug_candidate.encode('ascii')):
         abort(404)
 
@@ -227,12 +262,18 @@ def shutdown(shutdown_slug_candidate):
 
 
 def start(port, stay_open=False, transparent_torification=False):
+    """
+    Start the flask web server.
+    """
     set_stay_open(stay_open)
     set_transparent_torification(transparent_torification)
     app.run(port=port, threaded=True)
 
 
 def stop(port):
+    """
+    Stop the flask web server by loading /shutdown.
+    """
     # to stop flask, load http://127.0.0.1:<port>/<shutdown_slug>/shutdown
     if transparent_torification:
         import socket
diff --git a/onionshare_gui/downloads.py b/onionshare_gui/downloads.py
index 85c25aa..0ecb49f 100644
--- a/onionshare_gui/downloads.py
+++ b/onionshare_gui/downloads.py
@@ -24,6 +24,10 @@ from onionshare import strings, helpers
 
 
 class Downloads(QtGui.QVBoxLayout):
+    """
+    The downloads chunk of the GUI. This lists all of the active download
+    progress bars.
+    """
     def __init__(self):
         super(Downloads, self).__init__()
 
@@ -37,6 +41,9 @@ class Downloads(QtGui.QVBoxLayout):
         self.addWidget(self.downloads_label)
 
     def add_download(self, download_id, total_bytes):
+        """
+        Add a new download progress bar.
+        """
         self.downloads_label.show()
 
         # make a new progress bar
@@ -57,6 +64,9 @@ class Downloads(QtGui.QVBoxLayout):
         self.update_download(download_id, total_bytes, 0)
 
     def update_download(self, download_id, total_bytes, downloaded_bytes):
+        """
+        Update the progress of a download progress bar.
+        """
         if download_id not in self.progress_bars:
             self.add_download(download_id, total_bytes)
 
@@ -68,5 +78,8 @@ class Downloads(QtGui.QVBoxLayout):
             pb.setFormat("{0:s}, %p%".format(helpers.human_readable_filesize(downloaded_bytes)))
 
     def cancel_download(self, download_id):
+        """
+        Update a download progress bar to show that it has been canceled.
+        """
         pb = self.progress_bars[download_id]
         pb.setFormat(strings._('gui_canceled'))
diff --git a/onionshare_gui/file_selection.py b/onionshare_gui/file_selection.py
index 03127a2..441b3c9 100644
--- a/onionshare_gui/file_selection.py
+++ b/onionshare_gui/file_selection.py
@@ -25,6 +25,9 @@ from onionshare import strings, helpers
 
 
 class FileList(QtGui.QListWidget):
+    """
+    The list of files and folders in the GUI.
+    """
     files_dropped = QtCore.pyqtSignal()
     files_updated = QtCore.pyqtSignal()
 
@@ -35,6 +38,10 @@ class FileList(QtGui.QListWidget):
         self.setSortingEnabled(True)
 
         class DropHereLabel(QtGui.QLabel):
+            """
+            When there are no files or folders in the FileList yet, display the
+            'drop files here' message and graphic.
+            """
             def __init__(self, parent, image=False):
                 self.parent = parent
                 super(DropHereLabel, self).__init__(parent=parent)
@@ -61,6 +68,9 @@ class FileList(QtGui.QListWidget):
         self.update()
 
     def update(self):
+        """
+        Update the GUI elements based on the current state.
+        """
         # file list should have a background image if empty
         if len(self.filenames) == 0:
             self.drop_here_image.show()
@@ -70,20 +80,32 @@ class FileList(QtGui.QListWidget):
             self.drop_here_text.hide()
 
     def resizeEvent(self, event):
+        """
+        When the widget is resized, resize the drop files image and text.
+        """
         self.drop_here_image.setGeometry(0, 0, self.width(), self.height())
         self.drop_here_text.setGeometry(0, 0, self.width(), self.height())
 
     def dragEnterEvent(self, event):
+        """
+        dragEnterEvent for dragging files and directories into the widget.
+        """
         if event.mimeData().hasUrls:
             event.accept()
         else:
             event.ignore()
 
     def dragLeaveEvent(self, event):
+        """
+        dragLeaveEvent for dragging files and directories into the widget.
+        """
         event.accept()
         self.update()
 
     def dragMoveEvent(self, event):
+        """
+        dragMoveEvent for dragging files and directories into the widget.
+        """
         if event.mimeData().hasUrls:
             event.setDropAction(QtCore.Qt.CopyAction)
             event.accept()
@@ -91,6 +113,9 @@ class FileList(QtGui.QListWidget):
             event.ignore()
 
     def dropEvent(self, event):
+        """
+        dropEvent for dragging files and directories into the widget.
+        """
         if event.mimeData().hasUrls:
             event.setDropAction(QtCore.Qt.CopyAction)
             event.accept()
@@ -102,6 +127,9 @@ class FileList(QtGui.QListWidget):
         self.files_dropped.emit()
 
     def add_file(self, filename):
+        """
+        Add a file or directory to this widget.
+        """
         if filename not in self.filenames:
             # make filenames unicode-safe for Qt (#141)
             filename = filename.encode('utf-8').decode('utf-8', 'replace')
@@ -128,6 +156,10 @@ class FileList(QtGui.QListWidget):
 
 
 class FileSelection(QtGui.QVBoxLayout):
+    """
+    The list of files and folders in the GUI, as well as buttons to add and
+    delete the files and folders.
+    """
     def __init__(self):
         super(FileSelection, self).__init__()
         self.server_on = False
@@ -156,6 +188,9 @@ class FileSelection(QtGui.QVBoxLayout):
         self.update()
 
     def update(self):
+        """
+        Update the GUI elements based on the current state.
+        """
         # all buttons should be disabled if the server is on
         if self.server_on:
             self.add_files_button.setEnabled(False)
@@ -176,6 +211,9 @@ class FileSelection(QtGui.QVBoxLayout):
         self.file_list.update()
 
     def add_files(self):
+        """
+        Add files button clicked.
+        """
         filenames = QtGui.QFileDialog.getOpenFileNames(
             caption=strings._('gui_choose_files', True), options=QtGui.QFileDialog.ReadOnly)
         if filenames:
@@ -184,6 +222,9 @@ class FileSelection(QtGui.QVBoxLayout):
         self.update()
 
     def add_dir(self):
+        """
+        Add folder button clicked.
+        """
         filename = QtGui.QFileDialog.getExistingDirectory(
             caption=strings._('gui_choose_folder', True), options=QtGui.QFileDialog.ReadOnly)
         if filename:
@@ -191,20 +232,32 @@ class FileSelection(QtGui.QVBoxLayout):
         self.update()
 
     def delete_file(self):
+        """
+        Delete button clicked
+        """
         current_row = self.file_list.currentRow()
         self.file_list.filenames.pop(current_row)
         self.file_list.takeItem(current_row)
         self.update()
 
     def server_started(self):
+        """
+        Gets called when the server starts.
+        """
         self.server_on = True
         self.file_list.setAcceptDrops(False)
         self.update()
 
     def server_stopped(self):
+        """
+        Gets called when the server stops.
+        """
         self.server_on = False
         self.file_list.setAcceptDrops(True)
         self.update()
 
     def get_num_files(self):
+        """
+        Returns the total number of files and folders in the list.
+        """
         return len(self.file_list.filenames)
diff --git a/onionshare_gui/onionshare_gui.py b/onionshare_gui/onionshare_gui.py
index ee5d146..dc33a5b 100644
--- a/onionshare_gui/onionshare_gui.py
+++ b/onionshare_gui/onionshare_gui.py
@@ -37,6 +37,10 @@ from options import Options
 
 
 class Application(QtGui.QApplication):
+    """
+    This is Qt's QApplication class. It has been overridden to support threads
+    and the quick keyboard shortcut.
+    """
     def __init__(self):
         platform = helpers.get_platform()
         if platform == 'Linux':
@@ -53,6 +57,10 @@ class Application(QtGui.QApplication):
 
 
 class OnionShareGui(QtGui.QWidget):
+    """
+    OnionShareGui is the main window for the GUI that contains all of the
+    GUI elements.
+    """
     start_server_finished = QtCore.pyqtSignal()
     stop_server_finished = QtCore.pyqtSignal()
     starting_server_step2 = QtCore.pyqtSignal()
@@ -66,6 +74,10 @@ class OnionShareGui(QtGui.QWidget):
         self.setWindowIcon(window_icon)
 
     def send_files(self, filenames=None):
+        """
+        Build the GUI in send files mode.
+        Note that this is the only mode currently implemented.
+        """
         # file selection
         self.file_selection = FileSelection()
         if filenames:
@@ -117,12 +129,20 @@ class OnionShareGui(QtGui.QWidget):
         self.timer.start(500)
 
     def start_server_step2(self):
+        """
+        Step 2 in starting the onionshare server. This displays the large filesize
+        warning, if applicable.
+        """
         # warn about sending large files over Tor
         if web.zip_filesize >= 157286400:  # 150mb
             self.filesize_warning.setText(strings._("large_filesize", True))
             self.filesize_warning.show()
 
     def start_server(self):
+        """
+        Start the onionshare server. This uses multiple threads to start the Tor hidden
+        server and the web app.
+        """
         # start the hidden service
         self.status_bar.showMessage(strings._('gui_starting_server1', True))
         self.app.choose_port()
@@ -162,6 +182,9 @@ class OnionShareGui(QtGui.QWidget):
         t.start()
 
     def stop_server(self):
+        """
+        Stop the onionshare server.
+        """
         if self.server_status.status == self.server_status.STATUS_STARTED:
             web.stop(self.app.port)
         self.app.cleanup()
@@ -169,6 +192,9 @@ class OnionShareGui(QtGui.QWidget):
         self.stop_server_finished.emit()
 
     def check_for_requests(self):
+        """
+        Check for messages communicated from the web app, and update the GUI accordingly.
+        """
         self.update()
         # only check for requests if the server is running
         if self.server_status.status != self.server_status.STATUS_STARTED:
@@ -207,13 +233,22 @@ class OnionShareGui(QtGui.QWidget):
                 self.status_bar.showMessage('{0:s}: {1:s}'.format(strings._('other_page_loaded', True), event["path"]))
 
     def copy_url(self):
+        """
+        When the URL gets copied to the clipboard, display this in the status bar.
+        """
         self.status_bar.showMessage(strings._('gui_copied_url', True), 2000)
 
     def clear_message(self):
+        """
+        Clear messages from the status bar.
+        """
         self.status_bar.clearMessage()
 
 
 def alert(msg, icon=QtGui.QMessageBox.NoIcon):
+    """
+    Pop up a message in a dialog window.
+    """
     dialog = QtGui.QMessageBox()
     dialog.setWindowTitle("OnionShare")
     dialog.setWindowIcon(window_icon)
@@ -223,6 +258,9 @@ def alert(msg, icon=QtGui.QMessageBox.NoIcon):
 
 
 def main():
+    """
+    The main() function implements all of the logic that the GUI version of onionshare uses.
+    """
     strings.load_strings()
 
     # start the Qt app
diff --git a/onionshare_gui/options.py b/onionshare_gui/options.py
index 9a098c8..f3a91d2 100644
--- a/onionshare_gui/options.py
+++ b/onionshare_gui/options.py
@@ -24,6 +24,9 @@ from onionshare import strings, helpers
 
 
 class Options(QtGui.QHBoxLayout):
+    """
+    The extra onionshare options in the GUI.
+    """
     def __init__(self, web):
         super(Options, self).__init__()
 
@@ -42,6 +45,9 @@ class Options(QtGui.QHBoxLayout):
         self.addWidget(self.close_automatically)
 
     def stay_open_changed(self, state):
+        """
+        When the 'close automatically' checkbox is toggled, let the web app know.
+        """
         if state > 0:
             self.web.set_stay_open(False)
         else:
diff --git a/onionshare_gui/server_status.py b/onionshare_gui/server_status.py
index 6d34b55..9753895 100644
--- a/onionshare_gui/server_status.py
+++ b/onionshare_gui/server_status.py
@@ -25,6 +25,9 @@ from onionshare import strings, helpers
 
 
 class ServerStatus(QtGui.QVBoxLayout):
+    """
+    The server status chunk of the GUI.
+    """
     server_started = QtCore.pyqtSignal()
     server_stopped = QtCore.pyqtSignal()
     url_copied = QtCore.pyqtSignal()
@@ -73,6 +76,9 @@ class ServerStatus(QtGui.QVBoxLayout):
         self.update()
 
     def update(self):
+        """
+        Update the GUI elements based on the current state.
+        """
         # set the status image
         if self.status == self.STATUS_STOPPED:
             self.status_image_label.setPixmap(QtGui.QPixmap.fromImage(self.status_image_stopped))
@@ -110,31 +116,49 @@ class ServerStatus(QtGui.QVBoxLayout):
                 self.server_button.setText(strings._('gui_please_wait'))
 
     def server_button_clicked(self):
+        """
+        Toggle starting or stopping the server.
+        """
         if self.status == self.STATUS_STOPPED:
             self.start_server()
         elif self.status == self.STATUS_STARTED:
             self.stop_server()
 
     def start_server(self):
+        """
+        Start the server.
+        """
         self.status = self.STATUS_WORKING
         self.update()
         self.server_started.emit()
 
     def start_server_finished(self):
+        """
+        The server has finished starting.
+        """
         self.status = self.STATUS_STARTED
         self.copy_url()
         self.update()
 
     def stop_server(self):
+        """
+        Stop the server.
+        """
         self.status = self.STATUS_WORKING
         self.update()
         self.server_stopped.emit()
 
     def stop_server_finished(self):
+        """
+        The server has finished stopping.
+        """
         self.status = self.STATUS_STOPPED
         self.update()
 
     def copy_url(self):
+        """
+        Copy the onionshare URL to the clipboard.
+        """
         url = 'http://{0:s}/{1:s}'.format(self.app.onion_host, self.web.slug)
 
         if platform.system() == 'Windows':

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-privacy/packages/onionshare.git



More information about the Pkg-privacy-commits mailing list