Alexandre Macabies avatar Alexandre Macabies committed d843cfe

Small UI changes; PEP8sation of sources

Comments (0)

Files changed (2)

 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+import datetime
+import json
 import logging
-import json
 import pprint
-import datetime
 import threading
-import os.path
 
+from urllib.error import HTTPError
+from urllib.parse import urlencode
+from urllib.parse import urlparse
 from urllib.request import urlopen, Request
-from urllib.parse import urlencode
-from urllib.error import HTTPError
-from urllib.parse import urlparse
 
 from http.client import HTTPConnection
 
 API_BASE = 'https://open.ge.tt/1/'
 API_KEY = 't05kormjprb2o6rm8f8wmts2thjjor'
 
+
 class APIError(Exception):
     pass
 
+
 def _post_request(path, **kwargs):
     qskeys = {}
     url = API_BASE + path
 
     return _request(request)
 
+
 def _get_request(path, **kwargs):
     url = API_BASE + path
 
     request = Request(url)
     return _request(request)
 
+
 def _request(req):
     logger.debug("%s request to %s", req.get_method(), req.full_url)
-    if req.data: logger.debug("data: %s", req.data.decode('utf-8'))
+    if req.data:
+        logger.debug("data: %s", req.data.decode('utf-8'))
 
     try:
         resp = urlopen(req)
         raw = resp.read()
     except HTTPError as ex:
         resp = ex
-        logger.debug("got %d error", resp.code) # urllib sucks
+        logger.debug("got %d error", resp.code)  # urllib sucks
         raw = ex.read()
 
     raw = raw.decode('utf-8')
 
     return result
 
+
 class User(object):
     def _load(self, result):
         self.atoken = result['accesstoken']
 
     def login_auth(self, email, password):
         logger.debug("Loging-in user %r", email)
-        result = _post_request('users/login', apikey=API_KEY, email=email, password=password)
+        result = _post_request('users/login',
+            apikey=API_KEY, email=email, password=password
+        )
         self._load(result)
 
     def login_token(self, rtoken):
     def list_shares(self, skip=None, limit=None):
         logger.debug("Listing shares")
         if skip is not None and limit is not None:
-            results = _get_request('shares', accesstoken=self.atoken, skip=str(skip), limit=str(limit))
+            results = _get_request('shares', accesstoken=self.atoken,
+                skip=str(skip), limit=str(limit)
+            )
         else:
             results = _get_request('shares', accesstoken=self.atoken)
 
         for share_result in results:
-             share = UserShare(self)
-             share._load(share_result)
-             yield share
+            share = UserShare(self)
+            share._load(share_result)
+            yield share
 
     def get_share(self, name):
         logger.debug("Getting share %r", name)
     def create_share(self, title=None):
         logger.debug("Creating share with title %r", title)
         if title is not None:
-            result = _post_request('shares/create', _accesstoken=self.atoken, title=title)
+            result = _post_request('shares/create',
+                _accesstoken=self.atoken, title=title
+            )
         else:
             result = _post_request('shares/create', _accesstoken=self.atoken)
 
 
         return share
 
+
 class Share(object):
     def __init__(self, name):
         self.name = name
         result = _get_request('shares/%s' % self.name)
         self._load(result)
 
+
 class UserShare(Share):
     def __init__(self, user):
         self.user = user
 
     def update(self, **fields):
         logger.debug("Updating user share %r", self.name)
-        result = _post_request('shares/%s/update' % self.name, _accesstoken=self.user.atoken, **fields)
+        result = _post_request('shares/%s/update' % self.name,
+            _accesstoken=self.user.atoken, **fields
+        )
         self._load(result)
 
     def destroy(self):
         logger.debug("Destroying user share %r", self.name)
-        _post_request('shares/%s/destroy' % self.name, _accesstoken=self.user.atoken)
+        _post_request('shares/%s/destroy' % self.name,
+            _accesstoken=self.user.atoken
+        )
 
     def create_file(self, filename, size=None):
         logger.debug("Creating file %r in user share %r", filename, self.name)
-        result = _post_request('files/%s/create' % self.name, _accesstoken=self.user.atoken, filename=filename)
+        result = _post_request('files/%s/create' % self.name,
+            _accesstoken=self.user.atoken, filename=filename
+        )
         file = File(self)
         file._load(result)
         file.size = size
         self.files[file.id] = file
         return file
 
+
 class File(object):
     def __init__(self, share):
         self.share = share
 
     def destroy(self):
         logger.debug("Destoying file %s/%s", self.share.name, self.id)
-        _post_request('files/%s/%s/destroy' % (self.share.name, self.id), _accesstoken=self.share.user.atoken)
+        _post_request('files/%s/%s/destroy' % (self.share.name, self.id),
+            _accesstoken=self.share.user.atoken
+        )
         del self.share.files[self.id]
 
     def refresh(self):
         result = _get_request('files/%s/%s' % (self.share.name,  self.id))
         self._load(result)
 
+
 class FileUpload(threading.Thread):
     def __init__(self, file, fp):
         super().__init__()
                 self.bytes_written += len(data)
                 self.percent_done = self.bytes_written * 100 / self.file_size
 
-            self.percent_done = 100 # needed when file_size is zero...
+            self.percent_done = 100  # needed when file_size is zero...
 
-            resp = conn.getresponse()
+            conn.getresponse()
+
         except Exception as ex:
             self.ex = ex
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-import sys, os, os.path
 import argparse
+import difflib
+import os
+import re
 import signal
-import re
+import sys
 import unicodedata
-import difflib
-import pprint
 
 from collections import defaultdict
 from itertools import chain
-from time import sleep
 
 from gett import *
 
 url_re = re.compile(r'^(?:http://ge\.tt/|/)?(\w+)(?:/(?:v/(\d+)/?)?)?$')
 DEFAULT_SIMILARITY_RATIO = .95
 
+
 def ascii_only(input_str):
     nkfd_form = unicodedata.normalize('NFKD', input_str)
     return ''.join([c for c in nkfd_form if not unicodedata.combining(c)])
 
+
 def similar(a, b, ratio_floor):
-        return difflib.SequenceMatcher(a=a, b=b).ratio() > ratio_floor
+    return difflib.SequenceMatcher(a=a, b=b).ratio() > ratio_floor
+
 
 def humansize(nbytes, pad=False):
     if nbytes is None:
         return ''
 
     for (exp, unit) in ((9, 'GB'), (6, 'MB'), (3, 'KB'), (0, ' B')):
-       if nbytes >= 10**exp:
-           break
+        if nbytes >= 10 ** exp:
+            break
 
     if pad:
-        return '%6.2f %-2s' % (nbytes / 10**exp, unit)
+        return '%6.2f %-2s' % (nbytes / 10 ** exp, unit)
     else:
-        return '%.2f %s' % (nbytes / 10**exp, unit)
+        return '%.2f %s' % (nbytes / 10 ** exp, unit)
+
 
 def shorten(filename, maxsize):
     base, ext = os.path.splitext(filename)
 
     return (base + ext).ljust(max_base + len(ext))
 
+
 def print_status(upload, index, count):
         name = shorten(upload.file.name, 22)
         bar_size = int(40 * upload.percent_done / 100)
         bar = '[' + (bar_size * '#') + ((40 - bar_size) * '-') + ']'
 
-        sys.stderr.write('\r%s (%3d/%d) %s %d %%' % (name, index, count, bar, upload.percent_done))
+        sys.stderr.write('\r%s (%3d/%d) %s %d %%' % \
+            (name, index, count, bar, upload.percent_done))
+
 
 def show_share(share):
-    print('--------------------------------------------------------------------------------')
-    print('Share: %s (%d file(s)) [%s]' % (share.title or 'Untitled', len(share.files), share.url))
-    print('--------------------------------------------------------------------------------')
+    print("--------------------------------------------------------------------------------")
+    print("Share: %s (%d file(s)) [%s]" % (share.title or "Untitled", len(share.files), share.url))
+    print("--------------------------------------------------------------------------------")
 
     if share.files:
         max_url = max(len(_.url) for _ in share.files.values())
         for file in share.files.values():
             print(' - %s  %s  %s  %s' % (shorten(file.name, 28), humansize(file.size, True), file.url.ljust(max_url), file.readystate))
     else:
-        print(' - No files')
+        print(" - No files")
 
     print()
 
+
 def entry_point():
     try:
         main()
     except APIError as ex:
-        logger.error('API error: %s', ex)
+        logger.error("API error: %s", ex)
+
 
 def pattern(string):
     import glob
                 ret.append(open(item, 'rb'))
 
     if not ret:
-        logger.warning('%s: no match', string)
+        logger.warning("%s: no match", string)
+
     return ret
 
+
 def main():
     signal.signal(signal.SIGINT, signal.SIG_DFL)
 
     parser = argparse.ArgumentParser(
             description="A command-line Ge.tt uploader and manager",
             epilog="Note that whenever http://ge.tt/<share_name>[/v/<fileid>] is expected, you can omit the http://ge.tt/ part.")
-    parser.add_argument('-D', dest='debug', action='store_true', help='Debug API calls (warning: very verbose)')
+    parser.add_argument('-D', dest='debug', action='store_true',
+        help="Debug API calls (warning: very verbose).")
 
     upload_group = parser.add_argument_group('Upload options')
-    upload_group.add_argument('file', nargs='*', type=pattern, help="Name of a file or a directory to upload. Patterns are allowed. This is not recursive.")
-    upload_group.add_argument('-t', dest='title', help='Title of the newly created share')
-    upload_group.add_argument('-s', dest='share', help='URL of the share to upload to (defaults to a newly created one)')
-    upload_group.add_argument('-P', dest='parallel_upload', action='store_true', help='Upload files in parallel rather than sequentially, the progress bars are displayed in ascending file size order')
+    upload_group.add_argument('file', nargs='*', type=pattern,
+        help="Name of a file or a directory to upload. Patterns are allowed. This is not recursive.")
+    upload_group.add_argument('-t', dest='title',
+        help="Title of the newly created share.")
+    upload_group.add_argument('-s', dest='share',
+        help="URL of the share to upload to (defaults to a newly created one).")
+    upload_group.add_argument('-P', dest='parallel_upload', action='store_true',
+        help="Upload files in parallel rather than sequentially. The progress bars are displayed in ascending file size order.")
 
     search_group = parser.add_argument_group('Search actions')
-    search_group.add_argument('-S', '--search', nargs='+', dest='search', metavar='SEARCH_TERM', help='Search in share titles and file names.')
-    search_group.add_argument('-R', '--similarity-ratio', default=DEFAULT_SIMILARITY_RATIO, type=float, dest='similarity_ratio', help='Similarity ratio (between 0 and 1) used for searching')
+    search_group.add_argument('-S', '--search', nargs='+', dest='search',
+        metavar='SEARCH_TERM', help="Search in share titles and file names.")
+    search_group.add_argument('-R', '--similarity-ratio',
+        default=DEFAULT_SIMILARITY_RATIO, type=float, dest='similarity_ratio',
+        help="Similarity ratio (between 0 and 1) used for searching. 1 means strict, 0 means very loose.")
 
-    other_group = parser.add_argument_group('Other actions')
-    other_group.add_argument('--delete', nargs='+', dest='delete', metavar='URL', help='Delete a share or a file')
-    other_group.add_argument('-l', '--list', nargs='*', dest='list', metavar='SHARE_URL', help='List the files in the specified share. If no share is specified, list all your shares.')
+    other_group = parser.add_argument_group("Other actions")
+    other_group.add_argument('--delete', nargs='+', dest='delete',
+        metavar='URL', help="Delete a share or a file.")
+    other_group.add_argument('-l', '--list', nargs='*', dest='list',
+        metavar='SHARE_URL', help="List the files in the specified share. If no share is specified, list all your shares.")
 
-    auth_group = parser.add_argument_group('Authentification')
-    auth_group.add_argument('-L', dest='ignore_token', action='store_true', help='Log-in with a different account than the stored one (if any)')
-    auth_group.add_argument('-e', dest='email', help='Email to login with')
-    auth_group.add_argument('-p', dest='password', help='Password to login with')
-    auth_group.add_argument('-k', dest='tokenfile', help='Ge.tt token file path (default: ~/.gett-token)', default=os.path.join(home, '.gett-token'))
+    auth_group = parser.add_argument_group("Authentification")
+    auth_group.add_argument('-L', dest='ignore_token', action='store_true',
+        help="Log-in with a different account than the stored one (if any).")
+    auth_group.add_argument('-e', dest='email', help="Email to login with.")
+    auth_group.add_argument('-p', dest='password', help="Password to login with.")
+    auth_group.add_argument('-k', dest='tokenfile',
+        default=os.path.join(home, '.gett-token'),
+        help="Ge.tt token file path (default: ~/.gett-token).")
 
     args = parser.parse_args()
 
 
     if not logged:
         if not args.email:
-            args.email = input('Please enter your Ge.tt email: ')
+            args.email = input("Please enter your Ge.tt email: ")
 
         if not args.password:
             import getpass
-            args.password = getpass.getpass('Please enter your Ge.tt password: ')
+            args.password = getpass.getpass("Please enter your Ge.tt password: ")
 
         try:
             user.login_auth(args.email, args.password)
         except APIError as ex:
-            logger.error('Unable to login: %s', ex)
+            logger.error("Unable to login: %s", ex)
             sys.exit(1)
 
-        reply = input('Do you wish to store the session token? (y/n): ')
+        reply = input("Do you wish to store the session token? (y/n): ")
 
         if reply.lower() == 'y':
             # Save the refreshtoken to the user's home directory (by default)
             with open(args.tokenfile, 'w') as file:
                 file.write(user.rtoken)
 
-
     # --list command
 
     if args.list is not None:
             match = url_re.match(name)
 
             if not match or match.group(2):
-                parser.error('argument --list: invalid format, please supply either share url or path')
+                parser.error("argument --list: invalid format, please supply either share url or path")
 
             share = Share(match.group(1))
             show_share(share)
         if not args.list:
             found = False
 
+            nshares = 0
+            nfiles = 0
+
             for share in user.list_shares():
                 found = True
+                nshares += 1
+                nfiles += len(share.files)
+
                 show_share(share)
 
+            print("Displayed %d shares and %d files." % (nshares, nfiles))
+            print()
+
             if not found:
-                print('You have no shares!')
+                print("You have no shares!")
                 print()
 
-
     # --delete command
 
     if args.delete:
             match = url_re.match(item)
 
             if not match:
-                parser.error('argument --delete: invalid format, please supply either file/share url or path')
+                parser.error("argument --delete: invalid format, please supply either file/share url or path")
 
             share = user.get_share(match.group(1))
 
                     file = share.files[id]
                     file.destroy()
 
-                    print('Deleted file: %s [%s]' % (file.name, file.url))
+                    print("Deleted file: %s [%s]" % (file.name, file.url))
                 except KeyError:
                     print("No such file in the share")
             else:
                 share.destroy()
-                print('Deleted share: %s [%s]' % (share.title or 'Untitled', share.url))
+                print("Deleted share: %s [%s]" % \
+                    (share.title or "Untitled", share.url))
         print()
 
     # --search command
         simplify = lambda s: ascii_only(s.lower())
         phrase = ' '.join(args.search)
         phrase_simple = simplify(phrase)
-        print('Searching for `%s`...\n' % phrase)
+        print("Searching for `%s`...\n" % phrase)
 
         ratio = args.similarity_ratio
         if not 0 <= ratio <= 1:
             ratio = DEFAULT_SIMILARITY_RATIO
-            logger.warning('Bad similarity ratio value. Using default: %2.f' % DEFAULT_SIMILARITY_RATIO)
+            logger.warning("Bad similarity ratio value. Using default: %2.f" % \
+                DEFAULT_SIMILARITY_RATIO)
 
         is_similar = lambda a, b: similar(a, b, ratio)
 
             max_url = 0
         try:
             max_url_shares = max(len(_.url) for _ in found_in_files.keys())
-            max_url_files = max(max(len(_.url) for _ in f) for f in found_in_files.values())
+            max_url_files = max(
+                max(len(_.url) for _ in f)
+                for f in found_in_files.values()
+            )
         except ValueError:
             max_url_shares = max_url_files = 0
 
         maximax = max(max_url, max_url_shares + 6, max_url_files + 3)
 
         if found_in_shares:
-            print('Found %d share(s):' % len(found_in_shares))
+            print("Found %d share(s):" % len(found_in_shares))
 
             for share in found_in_shares:
-                print(' - %s  %s%s' % (
+                print(" - %s  %s%s" % (
                     share.url.ljust(max_url),
                     ' ' * (maximax - max_url),
                     (share.title or '')[:75 - max_url]
                 ))
         else:
-            print('Nothing found in shares.')
+            print("Nothing found in share names.")
 
         print()
 
         if found_in_files:
 
-            print('Found %d file(s):' % sum(map(len, found_in_files.values())))
+            print("Found %d file(s):" % sum(map(len, found_in_files.values())))
 
             for share, files in found_in_files.items():
-                print(' - Share %s  %s%s' % (
+                print(" - Share %s  %s%s" % (
                     share.url.ljust(max_url_shares),
                     ' ' * (maximax - max_url_shares - 6),
                     (share.title or '')[:69 - max_url_shares]
                 ))
 
                 for file in files:
-                    print('    - %s  %s%s' % (
+                    print("    - %s  %s%s" % (
                         file.url.ljust(max_url_files),
                         ' ' * (maximax - max_url_files - 6),
                         shorten(file.name, 72 - max_url_files)
                     ))
         else:
-            print('Nothing found in files.')
+            print("Nothing found in file names.")
 
         print()
 
             if match:
                 share = user.get_share(match.group(1))
             else:
-                parser.error('argument --list: invalid share name, please supply either URL or name')
+                parser.error("argument --list: invalid share name, please supply either URL or name")
         else:
             # Upload to a new share
 
 
         # Create the file URLs
 
-        print('Creating file(s)...')
+        print("Creating file(s)...")
 
         for fp in chain.from_iterable(args.file):
             name = os.path.basename(fp.name)
                     print_status(upload, i + 1, len(uploads))
 
                     if upload.ex:
-                        sys.stderr.write(('\rError uploading %s: %s' % (upload.file.name, upload.ex)).ljust(80))
+                        sys.stderr.write(("\rError uploading %s: %s" % \
+                            (upload.file.name, upload.ex)).ljust(80))
 
                     sys.stderr.write('\n')
                     break
 
     user.refresh()
 
-    print('Storage used: %s out of %s (%d %%)' % (
-            humansize(user.storage_used),
-            humansize(user.storage_limit),
-            int(100 * user.storage_used / user.storage_limit)))
+    print("Storage used: %s out of %s (%.1f%%)" % (
+        humansize(user.storage_used),
+        humansize(user.storage_limit),
+        user.storage_used / user.storage_limit * 100,
+    ))
 
 
 if __name__ == '__main__':
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.