Skip to content

Instantly share code, notes, and snippets.

@pudquick
Created November 20, 2012 07:23
Show Gist options
  • Save pudquick/4116558 to your computer and use it in GitHub Desktop.
Save pudquick/4116558 to your computer and use it in GitHub Desktop.
pipista - pip module (for installing other modules) for Pythonista
import os, os.path, sys, urllib2, requests
class PyPiError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
def _chunk_report(bytes_so_far, chunk_size, total_size):
if (total_size != None):
percent = float(bytes_so_far) / total_size
percent = round(percent*100, 2)
print 'Downloaded %d of %d bytes (%0.2f%%)' % (bytes_so_far, total_size, percent)
if bytes_so_far >= total_size:
print ''
else:
print 'Downloaded %d bytes' % (bytes_so_far)
def _chunk_read(response, chunk_size=32768, report_hook=None, filename=None):
file_data = []
if response.info().has_key('Content-Length'):
total_size = response.info().getheader('Content-Length').strip()
total_size = int(total_size)
else:
# No size
total_size = None
if report_hook:
print '* Warning: No total file size available.'
if (filename == None) and (response.info().has_key('Content-Disposition')):
# If the response has Content-Disposition, we take file name from it
try:
filename = response.info()['Content-Disposition'].split('filename=')[1]
if filename[0] == '"' or filename[0] == "'":
filename = filename[1:-1]
except Exception:
sys.exc_clear()
filename = 'output'
if (filename == None):
if report_hook:
print "* No detected filename, using 'output'"
filename = 'output'
bytes_so_far = 0
while True:
chunk = response.read(chunk_size)
bytes_so_far += len(chunk)
if not chunk:
break
else:
file_data.append(chunk)
report_hook(bytes_so_far, chunk_size, total_size)
return (file_data, filename)
def _download(src_dict, print_progress=True):
headers = {'User-Agent' : 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6;en-US; rv:1.9.2.9) Gecko/20100824 Firefox/3.6.9'}
if print_progress:
print '* Downloading:', src_dict['url']
req = urllib2.Request(src_dict['url'], headers=headers)
response = urllib2.urlopen(req)
output = src_dict['url'].split('/')[-1].split('#')[0].split('?')[0]
if print_progress:
data,filename = _chunk_read(response, report_hook=_chunk_report, filename=output)
else:
data,filename = _chunk_read(response, report_hook=None, filename=output)
if (len(data) > 0):
try:
f = open(filename, 'wb')
for x in data:
f.write(x)
f.close()
if print_progress:
print '* Saved to:', filename
except Exception:
if print_progress:
print '! Error:', sys.exc_info()[1]
raise
else:
if print_progress:
print '* Error: 0 bytes downloaded, not saved'
def pypi_download(pkg_name, pkg_ver='', print_progress=True):
pypi = xmlrpclib.ServerProxy('http://pypi.python.org/pypi')
hits = pypi.package_releases(pkg_name, True)
if not hits:
raise PyPiError('No package found with that name')
if not pkg_ver:
pkg_ver = hits[0]
elif not pkg_ver in hits:
raise PyPiError('That package version is not available')
hits = pypi.release_urls(pkg_name, pkg_ver)
if not hits:
raise PyPiError('No public download links for that version')
source = ([x for x in hits if x['packagetype'] == 'sdist'][:1] + [None])[0]
if not source:
raise PyPiError('No source-only download links for that version')
return _download(source, print_progress)
def pypi_versions(pkg_name, limit=10, show_hidden=True):
if not pkg_name:
return []
pypi = xmlrpclib.ServerProxy('http://pypi.python.org/pypi')
hits = pypi.package_releases(pkg_name, show_hidden)
if not hits:
return []
if len(hits) > limit:
hits = hits[:limit]
return hits
def pypi_search(search_str, limit=5):
if not search_str:
return []
pypi = xmlrpclib.ServerProxy('http://pypi.python.org/pypi')
hits = pypi.search({'name': search_str}, 'and')
if not hits:
return []
hits = sorted(hits, key=lambda pkg: pkg['_pypi_ordering'], reverse=True)
if len(hits) > limit:
hits = hits[:limit]
return hits
def install_xmlrpclib(path='.'):
# Grab the 2.7.3 version of xmlrpclib - even though Pythonista 1.2 is 2.7.0
r = requests.get('http://hg.python.org/cpython/raw-file/70274d53c1dd/Lib/xmlrpclib.py')
lib_file = os.path.join(path, 'xmlrpclib.py')
with open(lib_file, 'w') as f:
f.write(r.text)
# The following code is intentionally executed on import of the pipista module.
# It patches the standard import search paths to include the directory pipista
# installs downloaded modules in.
# If you really don't like this functionality, just edit this script to:
# _auto_path = False
_auto_path = True
# Begin library prep
if _auto_path:
# Get pipista location
mod_path = os.path.abspath(__file__)
mod_dir = os.path.dirname(mod_path)
lib_dir = os.path.join(mod_dir, 'pypi-modules')
if not os.path.exists(lib_dir):
try:
os.mkdir(lib_dir)
except Exception:
# Fail silently, if we can't make the directory
sys.exc_clear()
# Make sure lib_dir exists before adding it to the paths
if os.path.exists(lib_dir):
if lib_dir not in sys.path:
sys.path += [lib_dir]
# Attempt to load xmlrpclib - not present in Pythonista 1.2
try:
import xmlrpclib
except ImportError:
# Doesn't seem to be available - attempt to download it.
sys.exc_clear()
install_xmlrpclib(lib_dir)
import xmlrpclib
@boxed
Copy link

boxed commented Aug 27, 2016

It turns out my work was unnecessary. A working project is at: https://github.com/ywangd/stash

@eddo888
Copy link

eddo888 commented Jan 3, 2020

StaSh is only working on python2
anybody got pip install for Python3 for Pythonista

@CodyKochmann
Copy link

stash only works in python2 but installs python3 apps fine

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment