[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