diff --git a/pipenv/cli.py b/pipenv/cli.py index 6b125868..de54a98d 100644 --- a/pipenv/cli.py +++ b/pipenv/cli.py @@ -10,6 +10,7 @@ import tempfile from glob import glob import json as simplejson + import background import click import click_completion @@ -24,6 +25,7 @@ import pipdeptree import requirements import semver +from pipreqs import pipreqs from blindspin import spinner from requests.packages.urllib3.exceptions import InsecureRequestWarning from pip.req.req_file import parse_requirements @@ -271,6 +273,10 @@ def ensure_environment(): ) +def import_from_code(path='.'): + return pipreqs.get_all_imports(path, encoding='utf-8') + + def ensure_pipfile(validate=True): """Creates a Pipfile for the project, if it doesn't exist.""" @@ -309,6 +315,11 @@ def ensure_pipfile(validate=True): python = which('python') if not USING_DEFAULT_PYTHON else False project.create_pipfile(python=python) + click.echo(crayons.white(u'Discovering imports from local codebase…', bold=True)) + for req in import_from_code('.'): + click.echo(' Found {0}!'.format(crayons.green(req))) + project.add_package_to_pipfile(req) + # Validate the Pipfile's contents. if validate and project.virtualenv_exists and not PIPENV_SKIP_VALIDATION: # Ensure that Pipfile is using proper casing. @@ -1571,6 +1582,7 @@ def do_py(system=False): @click.option('--python', default=False, nargs=1, help="Specify which version of Python virtualenv should use.") @click.option('--system', is_flag=True, default=False, help="System pip management.") @click.option('--requirements', '-r', nargs=1, default=False, help="Import a requirements.txt file.") +@click.option('--code', '-c', nargs=1, default=False, help="Import from codebase.") @click.option('--verbose', is_flag=True, default=False, help="Verbose mode.") @click.option('--ignore-pipfile', is_flag=True, default=False, help="Ignore Pipfile when installing, using the Pipfile.lock.") @click.option('--sequential', is_flag=True, default=False, help="Install dependencies one-at-a-time, isntead of concurrently.") @@ -1580,7 +1592,7 @@ def install( package_name=False, more_packages=False, dev=False, three=False, python=False, system=False, lock=True, ignore_pipfile=False, skip_lock=False, verbose=False, requirements=False, sequential=False, - pre=False + pre=False, code=False ): # Automatically use an activated virtualenv. @@ -1596,6 +1608,12 @@ def install( click.echo(crayons.white(u'Requirements file provided! Importing into Pipfile…', bold=True), err=True) import_requirements(r=requirements, dev=dev) + if code: + click.echo(crayons.white(u'Discovering imports from local codebase…', bold=True)) + for req in import_from_code(code): + click.echo(' Found {0}!'.format(crayons.green(req))) + project.add_package_to_pipfile(req) + # Capture -e argument and assign it to following package_name. more_packages = list(more_packages) if package_name == '-e': diff --git a/pipenv/vendor/docopt.py b/pipenv/vendor/docopt.py new file mode 100644 index 00000000..7c6a52df --- /dev/null +++ b/pipenv/vendor/docopt.py @@ -0,0 +1,581 @@ +"""Pythonic command-line interface parser that will make you smile. + + * http://docopt.org + * Repository and issue-tracker: https://github.com/docopt/docopt + * Licensed under terms of MIT license (see LICENSE-MIT) + * Copyright (c) 2013 Vladimir Keleshev, vladimir@keleshev.com + +""" +import sys +import re + + +__all__ = ['docopt'] +__version__ = '0.6.2' + + +class DocoptLanguageError(Exception): + + """Error in construction of usage-message by developer.""" + + +class DocoptExit(SystemExit): + + """Exit in case user invoked program with incorrect arguments.""" + + usage = '' + + def __init__(self, message=''): + SystemExit.__init__(self, (message + '\n' + self.usage).strip()) + + +class Pattern(object): + + def __eq__(self, other): + return repr(self) == repr(other) + + def __hash__(self): + return hash(repr(self)) + + def fix(self): + self.fix_identities() + self.fix_repeating_arguments() + return self + + def fix_identities(self, uniq=None): + """Make pattern-tree tips point to same object if they are equal.""" + if not hasattr(self, 'children'): + return self + uniq = list(set(self.flat())) if uniq is None else uniq + for i, child in enumerate(self.children): + if not hasattr(child, 'children'): + assert child in uniq + self.children[i] = uniq[uniq.index(child)] + else: + child.fix_identities(uniq) + + def fix_repeating_arguments(self): + """Fix elements that should accumulate/increment values.""" + either = [list(child.children) for child in transform(self).children] + for case in either: + for e in [child for child in case if case.count(child) > 1]: + if type(e) is Argument or type(e) is Option and e.argcount: + if e.value is None: + e.value = [] + elif type(e.value) is not list: + e.value = e.value.split() + if type(e) is Command or type(e) is Option and e.argcount == 0: + e.value = 0 + return self + + +def transform(pattern): + """Expand pattern into an (almost) equivalent one, but with single Either. + + Example: ((-a | -b) (-c | -d)) => (-a -c | -a -d | -b -c | -b -d) + Quirks: [-a] => (-a), (-a...) => (-a -a) + + """ + result = [] + groups = [[pattern]] + while groups: + children = groups.pop(0) + parents = [Required, Optional, OptionsShortcut, Either, OneOrMore] + if any(t in map(type, children) for t in parents): + child = [c for c in children if type(c) in parents][0] + children.remove(child) + if type(child) is Either: + for c in child.children: + groups.append([c] + children) + elif type(child) is OneOrMore: + groups.append(child.children * 2 + children) + else: + groups.append(child.children + children) + else: + result.append(children) + return Either(*[Required(*e) for e in result]) + + +class LeafPattern(Pattern): + + """Leaf/terminal node of a pattern tree.""" + + def __init__(self, name, value=None): + self.name, self.value = name, value + + def __repr__(self): + return '%s(%r, %r)' % (self.__class__.__name__, self.name, self.value) + + def flat(self, *types): + return [self] if not types or type(self) in types else [] + + def match(self, left, collected=None): + collected = [] if collected is None else collected + pos, match = self.single_match(left) + if match is None: + return False, left, collected + left_ = left[:pos] + left[pos + 1:] + same_name = [a for a in collected if a.name == self.name] + if type(self.value) in (int, list): + if type(self.value) is int: + increment = 1 + else: + increment = ([match.value] if type(match.value) is str + else match.value) + if not same_name: + match.value = increment + return True, left_, collected + [match] + same_name[0].value += increment + return True, left_, collected + return True, left_, collected + [match] + + +class BranchPattern(Pattern): + + """Branch/inner node of a pattern tree.""" + + def __init__(self, *children): + self.children = list(children) + + def __repr__(self): + return '%s(%s)' % (self.__class__.__name__, + ', '.join(repr(a) for a in self.children)) + + def flat(self, *types): + if type(self) in types: + return [self] + return sum([child.flat(*types) for child in self.children], []) + + +class Argument(LeafPattern): + + def single_match(self, left): + for n, pattern in enumerate(left): + if type(pattern) is Argument: + return n, Argument(self.name, pattern.value) + return None, None + + @classmethod + def parse(class_, source): + name = re.findall('(<\S*?>)', source)[0] + value = re.findall('\[default: (.*)\]', source, flags=re.I) + return class_(name, value[0] if value else None) + + +class Command(Argument): + + def __init__(self, name, value=False): + self.name, self.value = name, value + + def single_match(self, left): + for n, pattern in enumerate(left): + if type(pattern) is Argument: + if pattern.value == self.name: + return n, Command(self.name, True) + else: + break + return None, None + + +class Option(LeafPattern): + + def __init__(self, short=None, long=None, argcount=0, value=False): + assert argcount in (0, 1) + self.short, self.long, self.argcount = short, long, argcount + self.value = None if value is False and argcount else value + + @classmethod + def parse(class_, option_description): + short, long, argcount, value = None, None, 0, False + options, _, description = option_description.strip().partition(' ') + options = options.replace(',', ' ').replace('=', ' ') + for s in options.split(): + if s.startswith('--'): + long = s + elif s.startswith('-'): + short = s + else: + argcount = 1 + if argcount: + matched = re.findall('\[default: (.*)\]', description, flags=re.I) + value = matched[0] if matched else None + return class_(short, long, argcount, value) + + def single_match(self, left): + for n, pattern in enumerate(left): + if self.name == pattern.name: + return n, pattern + return None, None + + @property + def name(self): + return self.long or self.short + + def __repr__(self): + return 'Option(%r, %r, %r, %r)' % (self.short, self.long, + self.argcount, self.value) + + +class Required(BranchPattern): + + def match(self, left, collected=None): + collected = [] if collected is None else collected + l = left + c = collected + for pattern in self.children: + matched, l, c = pattern.match(l, c) + if not matched: + return False, left, collected + return True, l, c + + +class Optional(BranchPattern): + + def match(self, left, collected=None): + collected = [] if collected is None else collected + for pattern in self.children: + m, left, collected = pattern.match(left, collected) + return True, left, collected + + +class OptionsShortcut(Optional): + + """Marker/placeholder for [options] shortcut.""" + + +class OneOrMore(BranchPattern): + + def match(self, left, collected=None): + assert len(self.children) == 1 + collected = [] if collected is None else collected + l = left + c = collected + l_ = None + matched = True + times = 0 + while matched: + # could it be that something didn't match but changed l or c? + matched, l, c = self.children[0].match(l, c) + times += 1 if matched else 0 + if l_ == l: + break + l_ = l + if times >= 1: + return True, l, c + return False, left, collected + + +class Either(BranchPattern): + + def match(self, left, collected=None): + collected = [] if collected is None else collected + outcomes = [] + for pattern in self.children: + matched, _, _ = outcome = pattern.match(left, collected) + if matched: + outcomes.append(outcome) + if outcomes: + return min(outcomes, key=lambda outcome: len(outcome[1])) + return False, left, collected + + +class Tokens(list): + + def __init__(self, source, error=DocoptExit): + self += source.split() if hasattr(source, 'split') else source + self.error = error + + @staticmethod + def from_pattern(source): + source = re.sub(r'([\[\]\(\)\|]|\.\.\.)', r' \1 ', source) + source = [s for s in re.split('\s+|(\S*<.*?>)', source) if s] + return Tokens(source, error=DocoptLanguageError) + + def move(self): + return self.pop(0) if len(self) else None + + def current(self): + return self[0] if len(self) else None + + +def parse_long(tokens, options): + """long ::= '--' chars [ ( ' ' | '=' ) chars ] ;""" + long, eq, value = tokens.move().partition('=') + assert long.startswith('--') + value = None if eq == value == '' else value + similar = [o for o in options if o.long == long] + if tokens.error is DocoptExit and similar == []: # if no exact match + similar = [o for o in options if o.long and o.long.startswith(long)] + if len(similar) > 1: # might be simply specified ambiguously 2+ times? + raise tokens.error('%s is not a unique prefix: %s?' % + (long, ', '.join(o.long for o in similar))) + elif len(similar) < 1: + argcount = 1 if eq == '=' else 0 + o = Option(None, long, argcount) + options.append(o) + if tokens.error is DocoptExit: + o = Option(None, long, argcount, value if argcount else True) + else: + o = Option(similar[0].short, similar[0].long, + similar[0].argcount, similar[0].value) + if o.argcount == 0: + if value is not None: + raise tokens.error('%s must not have an argument' % o.long) + else: + if value is None: + if tokens.current() in [None, '--']: + raise tokens.error('%s requires argument' % o.long) + value = tokens.move() + if tokens.error is DocoptExit: + o.value = value if value is not None else True + return [o] + + +def parse_shorts(tokens, options): + """shorts ::= '-' ( chars )* [ [ ' ' ] chars ] ;""" + token = tokens.move() + assert token.startswith('-') and not token.startswith('--') + left = token.lstrip('-') + parsed = [] + while left != '': + short, left = '-' + left[0], left[1:] + similar = [o for o in options if o.short == short] + if len(similar) > 1: + raise tokens.error('%s is specified ambiguously %d times' % + (short, len(similar))) + elif len(similar) < 1: + o = Option(short, None, 0) + options.append(o) + if tokens.error is DocoptExit: + o = Option(short, None, 0, True) + else: # why copying is necessary here? + o = Option(short, similar[0].long, + similar[0].argcount, similar[0].value) + value = None + if o.argcount != 0: + if left == '': + if tokens.current() in [None, '--']: + raise tokens.error('%s requires argument' % short) + value = tokens.move() + else: + value = left + left = '' + if tokens.error is DocoptExit: + o.value = value if value is not None else True + parsed.append(o) + return parsed + + +def parse_pattern(source, options): + tokens = Tokens.from_pattern(source) + result = parse_expr(tokens, options) + if tokens.current() is not None: + raise tokens.error('unexpected ending: %r' % ' '.join(tokens)) + return Required(*result) + + +def parse_expr(tokens, options): + """expr ::= seq ( '|' seq )* ;""" + seq = parse_seq(tokens, options) + if tokens.current() != '|': + return seq + result = [Required(*seq)] if len(seq) > 1 else seq + while tokens.current() == '|': + tokens.move() + seq = parse_seq(tokens, options) + result += [Required(*seq)] if len(seq) > 1 else seq + return [Either(*result)] if len(result) > 1 else result + + +def parse_seq(tokens, options): + """seq ::= ( atom [ '...' ] )* ;""" + result = [] + while tokens.current() not in [None, ']', ')', '|']: + atom = parse_atom(tokens, options) + if tokens.current() == '...': + atom = [OneOrMore(*atom)] + tokens.move() + result += atom + return result + + +def parse_atom(tokens, options): + """atom ::= '(' expr ')' | '[' expr ']' | 'options' + | long | shorts | argument | command ; + """ + token = tokens.current() + result = [] + if token in '([': + tokens.move() + matching, pattern = {'(': [')', Required], '[': [']', Optional]}[token] + result = pattern(*parse_expr(tokens, options)) + if tokens.move() != matching: + raise tokens.error("unmatched '%s'" % token) + return [result] + elif token == 'options': + tokens.move() + return [OptionsShortcut()] + elif token.startswith('--') and token != '--': + return parse_long(tokens, options) + elif token.startswith('-') and token not in ('-', '--'): + return parse_shorts(tokens, options) + elif token.startswith('<') and token.endswith('>') or token.isupper(): + return [Argument(tokens.move())] + else: + return [Command(tokens.move())] + + +def parse_argv(tokens, options, options_first=False): + """Parse command-line argument vector. + + If options_first: + argv ::= [ long | shorts ]* [ argument ]* [ '--' [ argument ]* ] ; + else: + argv ::= [ long | shorts | argument ]* [ '--' [ argument ]* ] ; + + """ + parsed = [] + while tokens.current() is not None: + if tokens.current() == '--': + return parsed + [Argument(None, v) for v in tokens] + elif tokens.current().startswith('--'): + parsed += parse_long(tokens, options) + elif tokens.current().startswith('-') and tokens.current() != '-': + parsed += parse_shorts(tokens, options) + elif options_first: + return parsed + [Argument(None, v) for v in tokens] + else: + parsed.append(Argument(None, tokens.move())) + return parsed + + +def parse_defaults(doc): + defaults = [] + for s in parse_section('options:', doc): + # FIXME corner case "bla: options: --foo" + _, _, s = s.partition(':') # get rid of "options:" + split = re.split('\n[ \t]*(-\S+?)', '\n' + s)[1:] + split = [s1 + s2 for s1, s2 in zip(split[::2], split[1::2])] + options = [Option.parse(s) for s in split if s.startswith('-')] + defaults += options + return defaults + + +def parse_section(name, source): + pattern = re.compile('^([^\n]*' + name + '[^\n]*\n?(?:[ \t].*?(?:\n|$))*)', + re.IGNORECASE | re.MULTILINE) + return [s.strip() for s in pattern.findall(source)] + + +def formal_usage(section): + _, _, section = section.partition(':') # drop "usage:" + pu = section.split() + return '( ' + ' '.join(') | (' if s == pu[0] else s for s in pu[1:]) + ' )' + + +def extras(help, version, options, doc): + if help and any((o.name in ('-h', '--help')) and o.value for o in options): + print(doc.strip("\n")) + sys.exit() + if version and any(o.name == '--version' and o.value for o in options): + print(version) + sys.exit() + + +class Dict(dict): + def __repr__(self): + return '{%s}' % ',\n '.join('%r: %r' % i for i in sorted(self.items())) + + +def docopt(doc, argv=None, help=True, version=None, options_first=False): + """Parse `argv` based on command-line interface described in `doc`. + + `docopt` creates your command-line interface based on its + description that you pass as `doc`. Such description can contain + --options, , commands, which could be + [optional], (required), (mutually | exclusive) or repeated... + + Parameters + ---------- + doc : str + Description of your command-line interface. + argv : list of str, optional + Argument vector to be parsed. sys.argv[1:] is used if not + provided. + help : bool (default: True) + Set to False to disable automatic help on -h or --help + options. + version : any object + If passed, the object will be printed if --version is in + `argv`. + options_first : bool (default: False) + Set to True to require options precede positional arguments, + i.e. to forbid options and positional arguments intermix. + + Returns + ------- + args : dict + A dictionary, where keys are names of command-line elements + such as e.g. "--verbose" and "", and values are the + parsed values of those elements. + + Example + ------- + >>> from docopt import docopt + >>> doc = ''' + ... Usage: + ... my_program tcp [--timeout=] + ... my_program serial [--baud=] [--timeout=] + ... my_program (-h | --help | --version) + ... + ... Options: + ... -h, --help Show this screen and exit. + ... --baud= Baudrate [default: 9600] + ... ''' + >>> argv = ['tcp', '127.0.0.1', '80', '--timeout', '30'] + >>> docopt(doc, argv) + {'--baud': '9600', + '--help': False, + '--timeout': '30', + '--version': False, + '': '127.0.0.1', + '': '80', + 'serial': False, + 'tcp': True} + + See also + -------- + * For video introduction see http://docopt.org + * Full documentation is available in README.rst as well as online + at https://github.com/docopt/docopt#readme + + """ + argv = sys.argv[1:] if argv is None else argv + + usage_sections = parse_section('usage:', doc) + if len(usage_sections) == 0: + raise DocoptLanguageError('"usage:" (case-insensitive) not found.') + if len(usage_sections) > 1: + raise DocoptLanguageError('More than one "usage:" (case-insensitive).') + DocoptExit.usage = usage_sections[0] + + options = parse_defaults(doc) + pattern = parse_pattern(formal_usage(DocoptExit.usage), options) + # [default] syntax for argument is disabled + #for a in pattern.flat(Argument): + # same_name = [d for d in arguments if d.name == a.name] + # if same_name: + # a.value = same_name[0].value + argv = parse_argv(Tokens(argv), list(options), options_first) + pattern_options = set(pattern.flat(Option)) + for options_shortcut in pattern.flat(OptionsShortcut): + doc_options = parse_defaults(doc) + options_shortcut.children = list(set(doc_options) - pattern_options) + #if any_options: + # options_shortcut.children += [Option(o.short, o.long, o.argcount) + # for o in argv if type(o) is Option] + extras(help, version, argv, doc) + matched, left, collected = pattern.fix().match(argv) + if matched and left == []: # better error message if left? + return Dict((a.name, a.value) for a in (pattern.flat() + collected)) + raise DocoptExit() diff --git a/pipenv/vendor/pipreqs/__init__.py b/pipenv/vendor/pipreqs/__init__.py new file mode 100755 index 00000000..5b8d242d --- /dev/null +++ b/pipenv/vendor/pipreqs/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- + +__author__ = 'Vadim Kravcenko' +__email__ = 'vadim.kravcenko@gmail.com' +__version__ = '0.4.8' diff --git a/pipenv/vendor/pipreqs/mapping b/pipenv/vendor/pipreqs/mapping new file mode 100755 index 00000000..46cca297 --- /dev/null +++ b/pipenv/vendor/pipreqs/mapping @@ -0,0 +1,1123 @@ +AG_fft_tools:agpy +ANSI:pexpect +Adafruit:Adafruit_Libraries +App:Zope2 +Asterisk:py_Asterisk +BB_jekyll_hook:bitbucket_jekyll_hook +Banzai:Banzai_NGS +BeautifulSoupTests:BeautifulSoup +BioSQL:biopython +BuildbotStatusShields:BuildbotEightStatusShields +ComputedAttribute:ExtensionClass +Crypto:pycrypto +FSM:pexpect +FiftyOneDegrees:51degrees_mobile_detector_v3_wrapper +GeoBaseMain:GeoBasesDev +GeoBases:GeoBasesDev +Globals:Zope2 +HelpSys:Zope2 +IPython:ipython +Kittens:astro_kittens +Levenshtein:python_Levenshtein +Lifetime:Zope2 +MethodObject:ExtensionClass +OFS:Zope2 +OpenGL:PyOpenGL +OpenSSL:pyOpenSSL +PIL:Pillow +Products:Zope2 +PyWCSTools:astLib +Pyxides:astro_pyxis +QtCore:PySide +S3:s3cmd +SCons:pystick +Shared:Zope2 +Signals:Zope2 +Stemmer:PyStemmer +Testing:Zope2 +TopZooTools:topzootools +TreeDisplay:DocumentTemplate +WorkingWithDocumentConversion:aspose_pdf_java_for_python +ZPublisher:Zope2 +ZServer:Zope2 +ZTUtils:Zope2 +aadb:auto_adjust_display_brightness +abakaffe:abakaffe_cli +abiosgaming:abiosgaming.py +abiquo:abiquo_api +abl:abl.cssprocessor +abl:abl.robot +abl:abl.util +abl:abl.vpath +abo:abo_generator +abris_transform:abris +abstract:abstract.jwrotator +abu:abu.admin +ac_flask:AC_Flask_HipChat +acg:anikom15 +acme:acme.dchat +acme:acme.hello +acted:acted.projects +action:ActionServer +actionbar:actionbar.panel +activehomed:afn +activepapers:ActivePapers.Py +address_book:address_book_lansry +adi:adi.commons +adi:adi.devgen +adi:adi.fullscreen +adi:adi.init +adi:adi.playlist +adi:adi.samplecontent +adi:adi.slickstyle +adi:adi.suite +adi:adi.trash +adict:aDict2 +aditam:aditam.agent +aditam:aditam.core +adiumsh:adium_sh +adjector:AdjectorClient +adjector:AdjectorTracPlugin +adkit:Banner_Ad_Toolkit +admin_tools:django_admin_tools +adminishcategories:adminish_categories +adminsortable:django_admin_sortable +adspygoogle:adspygoogle.adwords +advancedcaching:agtl +adytum:Adytum_PyMonitor +affinitic:affinitic.docpyflakes +affinitic:affinitic.recipe.fakezope2eggs +affinitic:affinitic.simplecookiecuttr +affinitic:affinitic.verifyinterface +affinitic:affinitic.zamqp +afpy:afpy.xap +agatesql:agate_sql +ageliaco:ageliaco.recipe.csvconfig +agent_http:agent.http +agora:Agora_Client +agora:Agora_Fountain +agora:Agora_Fragment +agora:Agora_Planner +agora:Agora_Service_Provider +agoraplex:agoraplex.themes.sphinx +agsci:agsci.blognewsletter +agx:agx.core +agx:agx.dev +agx:agx.generator.buildout +agx:agx.generator.dexterity +agx:agx.generator.generator +agx:agx.generator.plone +agx:agx.generator.pyegg +agx:agx.generator.sql +agx:agx.generator.uml +agx:agx.generator.zca +agx:agx.transform.uml2fs +agx:agx.transform.xmi2uml +aimes:aimes.bundle +aimes:aimes.skeleton +aio:aio.app +aio:aio.config +aio:aio.core +aio:aio.signals +aiohs2:aio_hs2 +aioroutes:aio_routes +aios3:aio_s3 +airbrake:airbrake_flask +airship:airship_icloud +airship:airship_steamcloud +akamai:edgegrid_python +alation:alation_api +alba_client:alba_client_python +alburnum:alburnum_maas_client +alchemist:alchemist.audit +alchemist:alchemist.security +alchemist:alchemist.traversal +alchemist:alchemist.ui +alchemyapi:alchemyapi_python +alerta:alerta_server +alexandria_upload:Alexandria_Upload_Utils +alibaba:alibaba_python_sdk +aliyun:aliyun_python_sdk +aliyuncli:alicloudcli +aliyunsdkacs:aliyun_python_sdk_acs +aliyunsdkbatchcompute:aliyun_python_sdk_batchcompute +aliyunsdkbsn:aliyun_python_sdk_bsn +aliyunsdkbss:aliyun_python_sdk_bss +aliyunsdkcdn:aliyun_python_sdk_cdn +aliyunsdkcms:aliyun_python_sdk_cms +aliyunsdkcore:aliyun_python_sdk_core +aliyunsdkcrm:aliyun_python_sdk_crm +aliyunsdkcs:aliyun_python_sdk_cs +aliyunsdkdrds:aliyun_python_sdk_drds +aliyunsdkecs:aliyun_python_sdk_ecs +aliyunsdkess:aliyun_python_sdk_ess +aliyunsdkft:aliyun_python_sdk_ft +aliyunsdkmts:aliyun_python_sdk_mts +aliyunsdkocs:aliyun_python_sdk_ocs +aliyunsdkoms:aliyun_python_sdk_oms +aliyunsdkossadmin:aliyun_python_sdk_ossadmin +aliyunsdkr-kvstore:aliyun_python_sdk_r_kvstore +aliyunsdkram:aliyun_python_sdk_ram +aliyunsdkrds:aliyun_python_sdk_rds +aliyunsdkrisk:aliyun_python_sdk_risk +aliyunsdkros:aliyun_python_sdk_ros +aliyunsdkslb:aliyun_python_sdk_slb +aliyunsdksts:aliyun_python_sdk_sts +aliyunsdkubsms:aliyun_python_sdk_ubsms +aliyunsdkyundun:aliyun_python_sdk_yundun +allattachments:AllAttachmentsMacro +allocine:allocine_wrapper +allowedsites:django_allowedsites +alm:alm.solrindex +aloft:aloft.py +alpacalib:alpaca +alphabetic:alphabetic_simple +alphasms:alphasms_client +altered:altered.states +alterootheme:alterootheme.busycity +alterootheme:alterootheme.intensesimplicity +alterootheme:alterootheme.lazydays +alurinium:alurinium_image_processing +alxlib:alx +amara3:amara3_iri +amara3:amara3_xml +amazon:AmazonAPIWrapper +amazon:python_amazon_simple_product_api +ambikesh1349-1:ambikesh1349_1 +ambilight:AmbilightParty +amifs:amifs_core +amiorganizer:ami_organizer +amitu:amitu.lipy +amitu:amitu_putils +amitu:amitu_websocket_client +amitu:amitu_zutils +amltlearn:AMLT_learn +amocrm:amocrm_api +amqpdispatcher:amqp_dispatcher +amqpstorm:AMQP_Storm +analytics:analytics_python +analyzedir:AnalyzeDirectory +ancientsolutions:ancientsolutions_crypttools +anderson_paginator:anderson.paginator +android_clean_app:android_resource_remover +anel_power_control:AnelPowerControl +angus:angus_sdk_python +annalist_root:Annalist +annogesiclib:ANNOgesic +ansible-role-apply:ansible_role_apply +ansibledebugger:ansible_playbook_debugger +ansibledocgen:ansible_docgen +ansibleflow:ansible_flow +ansibleinventorygrapher:ansible_inventory_grapher +ansiblelint:ansible_lint +ansiblerolesgraph:ansible_roles_graph +ansibletools:ansible_tools +anthill:anthill.exampletheme +anthill:anthill.skinner +anthill:anthill.tal.macrorenderer +anthrax:AnthraxDojoFrontend +anthrax:AnthraxHTMLInput +anthrax:AnthraxImage +antisphinx:antiweb +antispoofing:antispoofing.evaluation +antlr4:antlr4_python2_runtime +antlr4:antlr4_python3_runtime +antlr4:antlr4_python_alt +anybox:anybox.buildbot.openerp +anybox:anybox.nose.odoo +anybox:anybox.paster.odoo +anybox:anybox.paster.openerp +anybox:anybox.recipe.sysdeps +anybox:anybox.scripts.odoo +apiclient:google_api_python_client +apitools:google_apitools +apm:arpm +app_data:django_appdata +appconf:django_appconf +appd:AppDynamicsDownloader +appd:AppDynamicsREST +appdynamics_bindeps:appdynamics_bindeps_linux_x64 +appdynamics_bindeps:appdynamics_bindeps_linux_x86 +appdynamics_bindeps:appdynamics_bindeps_osx_x64 +appdynamics_proxysupport:appdynamics_proxysupport_linux_x64 +appdynamics_proxysupport:appdynamics_proxysupport_linux_x86 +appdynamics_proxysupport:appdynamics_proxysupport_osx_x64 +appium:Appium_Python_Client +appliapps:applibase +appserver:broadwick +archetypes:archetypes.kss +archetypes:archetypes.multilingual +archetypes:archetypes.schemaextender +arm:ansible_role_manager +armor:armor_api +armstrong:armstrong.apps.related_content +armstrong:armstrong.apps.series +armstrong:armstrong.cli +armstrong:armstrong.core.arm_access +armstrong:armstrong.core.arm_layout +armstrong:armstrong.core.arm_sections +armstrong:armstrong.core.arm_wells +armstrong:armstrong.dev +armstrong:armstrong.esi +armstrong:armstrong.hatband +armstrong:armstrong.templates.standard +armstrong:armstrong.utils.backends +armstrong:armstrong.utils.celery +arrow:arrow_fatisar +arstecnica:arstecnica.raccoon.autobahn +arstecnica:arstecnica.sqlalchemy.async +article-downloader:article_downloader +artifactcli:artifact_cli +arvados:arvados_python_client +arvados_cwl:arvados_cwl_runner +arvnodeman:arvados_node_manager +asana_to_github:AsanaToGithub +asciibinary:AsciiBinaryConverter +asd:AdvancedSearchDiscovery +askbot:askbot_tuan +askbot:askbot_tuanpa +asnhistory:asnhistory_redis +aspen_jinja2_renderer:aspen_jinja2 +aspen_tornado_engine:aspen_tornado +asprise_ocr_api:asprise_ocr_sdk_python_api +aspy:aspy.refactor_imports +aspy:aspy.yaml +asterisk:asterisk_ami +asts:add_asts +asymmetricbase:asymmetricbase.enum +asymmetricbase:asymmetricbase.fields +asymmetricbase:asymmetricbase.logging +asymmetricbase:asymmetricbase.utils +asyncirc:asyncio_irc +asyncmongoorm:asyncmongoorm_je +asyncssh:asyncssh_unofficial +athletelist:athletelistyy +atm:automium +atmosphere:atmosphere_python_client +atom:gdata +atomic:AtomicWrite +atomisator:atomisator.db +atomisator:atomisator.enhancers +atomisator:atomisator.feed +atomisator:atomisator.indexer +atomisator:atomisator.outputs +atomisator:atomisator.parser +atomisator:atomisator.readers +atreal:atreal.cmfeditions.unlocker +atreal:atreal.filestorage.common +atreal:atreal.layouts +atreal:atreal.mailservices +atreal:atreal.massloader +atreal:atreal.monkeyplone +atreal:atreal.override.albumview +atreal:atreal.richfile.preview +atreal:atreal.richfile.qualifier +atreal:atreal.usersinout +atsim:atsim.potentials +attractsdk:attract_sdk +audio:audio.bitstream +audio:audio.coders +audio:audio.filters +audio:audio.fourier +audio:audio.frames +audio:audio.lp +audio:audio.psychoacoustics +audio:audio.quantizers +audio:audio.shrink +audio:audio.wave +aufrefer:auf_refer +auslfe:auslfe.formonline.content +auspost:auspost_apis +auth0:auth0_python +auth_server_client:AuthServerClient +authorize:AuthorizeSauce +authzpolicy:AuthzPolicyPlugin +autobahn:autobahn_rce +avatar:geonode_avatar +awebview:android_webview +azure:azure_common +azure:azure_mgmt_common +azure:azure_mgmt_compute +azure:azure_mgmt_network +azure:azure_mgmt_nspkg +azure:azure_mgmt_resource +azure:azure_mgmt_storage +azure:azure_nspkg +azure:azure_servicebus +azure:azure_servicemanagement_legacy +azure:azure_storage +b2gcommands:b2g_commands +b2gperf:b2gperf_v1.3 +b2gperf:b2gperf_v1.4 +b2gperf:b2gperf_v2.0 +b2gperf:b2gperf_v2.1 +b2gperf:b2gperf_v2.2 +b2gpopulate:b2gpopulate_v1.3 +b2gpopulate:b2gpopulate_v1.4 +b2gpopulate:b2gpopulate_v2.0 +b2gpopulate:b2gpopulate_v2.1 +b2gpopulate:b2gpopulate_v2.2 +b3j0f:b3j0f.annotation +b3j0f:b3j0f.aop +b3j0f:b3j0f.conf +b3j0f:b3j0f.sync +b3j0f:b3j0f.utils +babel:Babel +babelglade:BabelGladeExtractor +backplane:backplane2_pyclient +backport_abcoll:backport_collections +backports:backports.functools_lru_cache +backports:backports.inspect +backports:backports.pbkdf2 +backports:backports.shutil_get_terminal_size +backports:backports.socketpair +backports:backports.ssl +backports:backports.ssl_match_hostname +backports:backports.statistics +badgekit:badgekit_api_client +badlinks:BadLinksPlugin +bael:bael.project +baidu:baidupy +balrog:buildtools +baluhn:baluhn_redux +bamboo:bamboo.pantrybell +bamboo:bamboo.scaffold +bamboo:bamboo.setuptools_version +bamboo:bamboo_data +bamboo:bamboo_server +bambu:bambu_codemirror +bambu:bambu_dataportability +bambu:bambu_enqueue +bambu:bambu_faq +bambu:bambu_ffmpeg +bambu:bambu_grids +bambu:bambu_international +bambu:bambu_jwplayer +bambu:bambu_minidetect +bambu:bambu_navigation +bambu:bambu_notifications +bambu:bambu_payments +bambu:bambu_pusher +bambu:bambu_saas +bambu:bambu_sites +banana:Bananas +banana:banana.maya +bang:bangtext +barcode:barcode_generator +bark:bark_ssg +barking_owl:BarkingOwl +bart:bart_py +basalt:basalt_tasks +base62:base_62 +basemap:basemap_Jim +bash:bash_toolbelt +bashutils:Python_Bash_Utils +basic_http:BasicHttp +basil:basil_daq +batchapps:azure_batch_apps +bcrypt:python_bcrypt +beaker:Beaker +beetsplug:beets +begin:begins +benchit:bench_it +beproud:beproud.utils +bfillings:burrito_fillings +bigjob:BigJob +billboard:billboard.py +binstar_build_client:anaconda_build +binstar_client:anaconda_client +biocommons:biocommons.dev +birdhousebuilder:birdhousebuilder.recipe.conda +birdhousebuilder:birdhousebuilder.recipe.docker +birdhousebuilder:birdhousebuilder.recipe.redis +birdhousebuilder:birdhousebuilder.recipe.supervisor +blender26-meshio:pymeshio +bootstrap:BigJob +borg:borg.localrole +bow:bagofwords +bpdb:bpython +bqapi:bisque_api +braces:django_braces +briefscaster:briefs_caster +brisa_media_server/plugins:brisa_media_server_plugins +brkt_requests:brkt_sdk +broadcastlogging:broadcast_logging +brocadetool:brocade_tool +bronto:bronto_python +brownie:Brownie +browsermobproxy:browsermob_proxy +brubeckmysql:brubeck_mysql +brubeckoauth:brubeck_oauth +brubeckservice:brubeck_service +brubeckuploader:brubeck_uploader +bs4:beautifulsoup4 +bson:pymongo +bst:bst.pygasus.core +bst:bst.pygasus.datamanager +bst:bst.pygasus.demo +bst:bst.pygasus.i18n +bst:bst.pygasus.resources +bst:bst.pygasus.scaffolding +bst:bst.pygasus.security +bst:bst.pygasus.session +bst:bst.pygasus.wsgi +btable:btable_py +btapi:bananatag_api +btceapi:btce_api +btcebot:btce_bot +btsync:btsync.py +buck:buck.pprint +bud:bud.nospam +budy:budy_api +buffer:buffer_alpaca +buggd:bug.gd +bugle:bugle_sites +bugspots:bug_spots +bugzilla:python_bugzilla +bugzscout:bugzscout_py +buildTools:ajk_ios_buildTools +buildnotifylib:BuildNotify +buildout:buildout.bootstrap +buildout:buildout.disablessl +buildout:buildout.dumppickedversions +buildout:buildout.dumppickedversions2 +buildout:buildout.dumprequirements +buildout:buildout.eggnest +buildout:buildout.eggscleaner +buildout:buildout.eggsdirectories +buildout:buildout.eggtractor +buildout:buildout.extensionscripts +buildout:buildout.locallib +buildout:buildout.packagename +buildout:buildout.recipe.isolation +buildout:buildout.removeaddledeggs +buildout:buildout.requirements +buildout:buildout.sanitycheck +buildout:buildout.sendpickedversions +buildout:buildout.threatlevel +buildout:buildout.umask +buildout:buildout.variables +buildslave:buildbot_slave +builtins:pies2overrides +bumper:bumper_lib +bumple:bumple_downloader +bundesliga:bundesliga_cli +bundlemaker:bundlemanager +burpui:burp_ui +busyflow:busyflow.pivotal +buttercms-django:buttercms_django +buzz:buzz_python_client +bvc:buildout_versions_checker +bvggrabber:bvg_grabber +byond:BYONDTools +bzETL:Bugzilla_ETL +bzlib:bugzillatools +bzrlib:bzr +bzrlib:bzr_automirror +bzrlib:bzr_bash_completion +bzrlib:bzr_colo +bzrlib:bzr_killtrailing +bzrlib:bzr_pqm +c2c:c2c.cssmin +c2c:c2c.recipe.closurecompile +c2c:c2c.recipe.cssmin +c2c:c2c.recipe.jarfile +c2c:c2c.recipe.msgfmt +c2c:c2c.recipe.pkgversions +c2c:c2c.sqlalchemy.rest +c2c:c2c.versions +c2c_recipe_facts:c2c.recipe.facts +cabalgata:cabalgata_silla_de_montar +cabalgata:cabalgata_zookeeper +cache_utils:django_cache_utils +captcha:django_recaptcha +cartridge:Cartridge +cassandra:cassandra_driver +cassandralauncher:CassandraLauncher +cc42:42qucc +cerberus:Cerberus +chameleon:Chameleon +charmtools:charm_tools +chef:PyChef +chip8:c8d +cjson:python_cjson +classytags:django_classy_tags +cloghandler:ConcurrentLogHandler +clonevirtualenv:virtualenv_clone +cloud-insight:al_cloudinsight +cloud_admin:adminapi +cloudservers:python_cloudservers +clusterconsole:cerebrod +clustersitter:cerebrod +cms:django_cms +colander:ba_colander +colors:ansicolors +compile:bf_lc3 +compose:docker_compose +compressor:django_compressor +concurrent:futures +configargparse:ConfigArgParse +configparser:pies2overrides +contracts:PyContracts +coordination:BigJob +copyreg:pies2overrides +corebio:weblogo +couchapp:Couchapp +couchdb:CouchDB +couchdbcurl:couchdb_python_curl +courseradownloader:coursera_dl +cow:cow_framework +creole:python_creole +creoleparser:Creoleparser +crispy_forms:django_crispy_forms +cronlog:python_crontab +crontab:python_crontab +ctff:tff +cups:pycups +curator:elasticsearch_curator +curl:pycurl +daemon:python_daemon +dare:DARE +dateutil:python_dateutil +dawg:DAWG +deb822:python_debian +debian:python_debian +demo:webunit +deployer:juju_deployer +depot:filedepot +devtools:tg.devtools +dgis:2gis +dhtmlparser:pyDHTMLParser +digitalocean:python_digitalocean +distribute_setup:ez_setup +distutils2:Distutils2 +django:Django +django_hstore:amitu_hstore +djangobower:django_bower +djcelery:django_celery +djkombu:django_kombu +djorm_pgarray:djorm_ext_pgarray +dns:dnspython +docgen:ansible_docgenerator +docker:docker_py +dogpile:dogpile.cache +dogpile:dogpile.core +dogshell:dogapi +dot_parser:pydot +dot_parser:pydot2 +dot_parser:pydot3k +dotenv:python-dotenv +dpkt:dpkt_fix +dsml:python_ldap +durationfield:django_durationfield +dzclient:datazilla +easybuild:easybuild_framework +editor:python_editor +elasticluster:azure_elasticluster +elasticluster:azure_elasticluster_current +elftools:pyelftools +elixir:Elixir +em:empy +emlib:empy +enchant:pyenchant +encutils:cssutils +engineio:python_engineio +enum:enum34 +ephem:pyephem +errorreporter:abl.errorreporter +esplot:beaker_es_plot +example:adrest +examples:tweepy +ez_setup:pycassa +fabfile:Fabric +fabric:Fabric +faker:Faker +fdpexpect:pexpect +fedora:python_fedora +fias:ailove_django_fias +fiftyone_degrees:51degrees_mobile_detector +five:five.customerize +five:five.globalrequest +five:five.intid +five:five.localsitemanager +five:five.pt +flasher:android_flasher +flask:Flask +flask_frozen:Frozen_Flask +flask_redis:Flask_And_Redis +flaskext:Flask_Bcrypt +flvscreen:vnc2flv +followit:django_followit +forge:pyforge +formencode:FormEncode +formtools:django_formtools +fourch:4ch +franz:allegrordf +freetype:freetype_py +frontmatter:python_frontmatter +ftpcloudfs:ftp_cloudfs +funtests:librabbitmq +fuse:fusepy +fuzzy:Fuzzy +gabbi:tiddlyweb +gen_3dwallet:3d_wallet_generator +gendimen:android_gendimen +genshi:Genshi +geohash:python_geohash +geonode:GeoNode +geoserver:gsconfig +geraldo:Geraldo +getenv:django_getenv +geventwebsocket:gevent_websocket +gflags:python_gflags +git:GitPython +github:PyGithub +gitpy:git_py +globusonline:globusonline_transfer_api_client +google:protobuf +googleapiclient:google_api_python_client +grace-dizmo:grace_dizmo +grammar:anovelmous_grammar +grapheneapi:graphenelib +greplin:scales +gridfs:pymongo +grokcore:grokcore.component +gslib:gsutil +hamcrest:PyHamcrest +harpy:HARPy +hawk:PyHawk_with_a_single_extra_commit +haystack:django_haystack +hgext:mercurial +hggit:hg_git +hglib:python_hglib +ho:pisa +hola:amarokHola +hoover:Hoover +hostlist:python_hostlist +html:pies2overrides +htmloutput:nosehtmloutput +http:pies2overrides +hvad:django_hvad +i99fix:199Fix +igraph:python_igraph +imdb:IMDbPY +impala:impyla +inmemorystorage:ambition_inmemorystorage +ipaddress:backport_ipaddress +jaraco:jaraco.timing +jaraco:jaraco.util +jinja2:Jinja2 +jiracli:jira_cli +johnny:johnny_cache +jpgrid:python_geohash +jpiarea:python_geohash +jpype:JPype1 +jpypex:JPype1 +jsonfield:django_jsonfield +jstools:aino_jstools +jupyterpip:jupyter_pip +jwt:PyJWT +kazoo:asana_kazoo +kernprof:line_profiler +keyczar:python_keyczar +keyedcache:django_keyedcache +keystoneclient:python_keystoneclient +kickstarter:kickstart +kss:kss.core +kuyruk:Kuyruk +langconv:AdvancedLangConv +lava:lava_utils_interface +lazr:lazr.authentication +lazr:lazr.restfulclient +lazr:lazr.uri +ldap:python_ldap +ldaplib:adpasswd +ldapurl:python_ldap +ldif:python_ldap +lib2or3:2or3 +lib3to2:3to2 +libaito:Aito +libbe:bugs_everywhere +libbucket:bucket +libcloud:apache_libcloud +libfuturize:future +libgenerateDS:generateDS +libmproxy:mitmproxy +libpasteurize:future +libsvm:7lk_ocr_deploy +lisa:lisa_server +loadingandsaving:aspose_words_java_for_python +locust:locustio +logbook:Logbook +logentries:buildbot_status_logentries +logilab:logilab_mtconverter +machineconsole:cerebrod +machinesitter:cerebrod +magic:python_magic +mako:Mako +manifestparser:ManifestDestiny +marionette:marionette_client +markdown:Markdown +marks:pytest_marks +markupsafe:MarkupSafe +mavnative:pymavlink +memcache:python_memcached +metacomm:AllPairs +metaphone:Metafone +metlog:metlog_py +mezzanine:Mezzanine +migrate:sqlalchemy_migrate +mimeparse:python_mimeparse +minitage:minitage.paste +minitage:minitage.recipe.common +missingdrawables:android_missingdrawables +mkrst_themes:2lazy2rest +mockredis:mockredispy +modargs:python_modargs +model_utils:django_model_utils +models:asposebarcode +models:asposestorage +moksha:moksha.common +moksha:moksha.hub +moksha:moksha.wsgi +moneyed:py_moneyed +mongoalchemy:MongoAlchemy +monthdelta:MonthDelta +mopidy:Mopidy +mopytools:MoPyTools +mptt:django_mptt +mrbob:mr.bob +msgpack:msgpack_python +mutations:aino_mutations +mws:amazon_mws +mysql:mysql_connector_repackaged +native_tags:django_native_tags +ndg:ndg_httpsclient +nereid:trytond_nereid +nested:baojinhuan +nester:Amauri +nester:abofly +nester:bssm_pythonSig +novaclient:python_novaclient +oauth2_provider:alauda_django_oauth +oauth2client:google_api_python_client +odf:odfpy +ometa:Parsley +openid:python_openid +opensearchsdk:ali_opensearch +oslo_i18n:oslo.i18n +oslo_serialization:oslo.serialization +oslo_utils:oslo.utils +oss:alioss +oss:aliyun_python_sdk_oss +oss:aliyunoss +output:cashew +owslib:OWSLib +packetdiag:nwdiag +paho:paho_mqtt +paintstore:django_paintstore +parler:django_parler +past:future +paste:PasteScript +path:forked_path +path:path.py +paver:Paver +peak:ProxyTypes +picasso:anderson.picasso +picklefield:django-picklefield +pilot:BigJob +pivotal:pivotal_py +playhouse:peewee +plivoxml:plivo +plone:plone.alterego +plone:plone.api +plone:plone.app.blob +plone:plone.app.collection +plone:plone.app.content +plone:plone.app.contentlisting +plone:plone.app.contentmenu +plone:plone.app.contentrules +plone:plone.app.contenttypes +plone:plone.app.controlpanel +plone:plone.app.customerize +plone:plone.app.dexterity +plone:plone.app.discussion +plone:plone.app.event +plone:plone.app.folder +plone:plone.app.i18n +plone:plone.app.imaging +plone:plone.app.intid +plone:plone.app.layout +plone:plone.app.linkintegrity +plone:plone.app.locales +plone:plone.app.lockingbehavior +plone:plone.app.multilingual +plone:plone.app.portlets +plone:plone.app.querystring +plone:plone.app.redirector +plone:plone.app.registry +plone:plone.app.relationfield +plone:plone.app.textfield +plone:plone.app.theming +plone:plone.app.users +plone:plone.app.uuid +plone:plone.app.versioningbehavior +plone:plone.app.viewletmanager +plone:plone.app.vocabularies +plone:plone.app.widgets +plone:plone.app.workflow +plone:plone.app.z3cform +plone:plone.autoform +plone:plone.batching +plone:plone.behavior +plone:plone.browserlayer +plone:plone.caching +plone:plone.contentrules +plone:plone.dexterity +plone:plone.event +plone:plone.folder +plone:plone.formwidget.namedfile +plone:plone.formwidget.recurrence +plone:plone.i18n +plone:plone.indexer +plone:plone.intelligenttext +plone:plone.keyring +plone:plone.locking +plone:plone.memoize +plone:plone.namedfile +plone:plone.outputfilters +plone:plone.portlet.collection +plone:plone.portlet.static +plone:plone.portlets +plone:plone.protect +plone:plone.recipe.zope2install +plone:plone.registry +plone:plone.resource +plone:plone.resourceeditor +plone:plone.rfc822 +plone:plone.scale +plone:plone.schema +plone:plone.schemaeditor +plone:plone.session +plone:plone.stringinterp +plone:plone.subrequest +plone:plone.supermodel +plone:plone.synchronize +plone:plone.theme +plone:plone.transformchain +plone:plone.uuid +plone:plone.z3cform +plonetheme:plonetheme.barceloneta +png:pypng +polymorphic:django_polymorphic +portalocker:ConcurrentLogHandler +postmark:python_postmark +powerprompt:bash_powerprompt +printList:AndrewList +progressbar:progressbar2 +progressbar:progressbar33 +provider:django_oauth2_provider +puresasl:pure_sasl +pwiz:peewee +pxssh:pexpect +py7zlib:pylzma +pyAMI:pyAMI_core +pyarsespyder:arsespyder +pyasdf:asdf +pyaspell:aspell_python_ctypes +pybb:pybbm +pybloomfilter:pybloomfiltermmap +pyccuracy:Pyccuracy +pyck:PyCK +pycrfsuite:python_crfsuite +pydispatch:PyDispatcher +pygeolib:pygeocoder +pygments:Pygments +pygraph:python_graph_core +pyjon:pyjon.utils +pyjsonrpc:python_jsonrpc +pykka:Pykka +pylogo:PyLogo +pylons:adhocracy_Pylons +pymagic:libmagic +pymycraawler:Amalwebcrawler +pynma:AbakaffeNotifier +pyphen:Pyphen +pyrimaa:AEI +pysideuic:PySide +pysqlite2:adhocracy_pysqlite +pysqlite2:pysqlite +pythongettext:python_gettext +pythonjsonlogger:python_json_logger +pyutilib:PyUtilib +pyximport:Cython +qs:qserve +quadtree:python_geohash +queue:future +quickapi:django_quickapi +quickunit:nose_quickunit +rackdiag:nwdiag +radical:radical.pilot +radical:radical.utils +reStructuredText:Zope2 +readability:readability_lxml +readline:gnureadline +recaptcha_works:django_recaptcha_works +relstorage:RelStorage +reportapi:django_reportapi +reprlib:pies2overrides +requests:Requests +requirements:requirements_parser +rest_framework:djangorestframework +restclient:py_restclient +retrial:async_retrial +reversion:django_reversion +rhaptos2:rhaptos2.common +robot:robotframework +robots:django_robots +rosdep2:rosdep +rsbackends:RSFile +ruamel:ruamel.base +s2repoze:pysaml2 +saga:saga_python +saml2:pysaml2 +sass:libsass +sassc:libsass +sasstests:libsass +sassutils:libsass +sayhi:alex_sayhi +scalrtools:scalr +scikits:scikits.talkbox +scratch:scratchpy +screen:pexpect +scss:pyScss +sdict:dict.sorted +sdk_updater:android_sdk_updater +sekizai:django_sekizai +sendfile:pysendfile +serial:pyserial +setuputils:astor +shapefile:pyshp +shapely:Shapely +sika:ahonya_sika +singleton:pysingleton +sittercommon:cerebrod +skbio:scikit_bio +sklearn:scikit_learn +slugify:unicode_slugify +smarkets:smk_python_sdk +snappy:ctypes_snappy +socketio:gevent_socketio +socketserver:pies2overrides +sockjs:sockjs_tornado +socks:SocksiPy_branch +solr:solrpy +solution:Solution +sorl:sorl_thumbnail +south:South +sphinx:Sphinx +sphinx_pypi_upload:ATD_document +sphinxcontrib:sphinxcontrib_programoutput +sqlalchemy:SQLAlchemy +src:atlas +src:auto_mix_prep +stats_toolkit:bw_stats_toolkit +statsd:dogstatsd_python +stdnum:python_stdnum +stoneagehtml:StoneageHTML +storages:django_storages +stubout:mox +suds:suds_jurko +swiftclient:python_swiftclient +sx:pisa +tabix:pytabix +taggit:django_taggit +tasksitter:cerebrod +tastypie:django_tastypie +teamcity:teamcity_messages +telebot:pyTelegramBotAPI +tempita:Tempita +tenjin:Tenjin +termstyle:python_termstyle +test:pytabix +thclient:treeherder_client +threaded_multihost:django_threaded_multihost +threecolor:3color_Press +tidylib:pytidylib +tkinter:future +tlw:3lwg +toredis:toredis_fork +tornadoredis:tornado_redis +tower_cli:ansible_tower_cli +trac:Trac +tracopt:Trac +translation_helper:android_localization_helper +treebeard:django_treebeard +trytond:trytond_stock +tsuru:tsuru_circus +tvrage:python_tvrage +tw2:tw2.core +tw2:tw2.d3 +tw2:tw2.dynforms +tw2:tw2.excanvas +tw2:tw2.forms +tw2:tw2.jit +tw2:tw2.jqplugins.flot +tw2:tw2.jqplugins.gritter +tw2:tw2.jqplugins.ui +tw2:tw2.jquery +tw2:tw2.sqla +twisted:Twisted +twitter:python_twitter +txclib:transifex_client +u115:115wangpan +unidecode:Unidecode +universe:ansible_universe +usb:pyusb +useless:useless.pipes +userpass:auth_userpass +utilities:automakesetup.py +utkik:aino_utkik +uwsgidecorators:uWSGI +valentine:ab +validate:configobj +version:chartio +virtualenvapi:ar_virtualenv_api +vyatta:brocade_plugins +webdav:Zope2 +weblogolib:weblogo +webob:WebOb +websocket:websocket_client +webtest:WebTest +werkzeug:Werkzeug +wheezy:wheezy.caching +wheezy:wheezy.core +wheezy:wheezy.http +wikklytext:tiddlywebwiki +winreg:future +winrm:pywinrm +workflow:Alfred_Workflow +wsmeext:WSME +wtforms:WTForms +wtfpeewee:wtf_peewee +xdg:pyxdg +xdist:pytest_xdist +xmldsig:pysaml2 +xmlenc:pysaml2 +xmlrpc:pies2overrides +xmpp:xmpppy +xstatic:XStatic_Font_Awesome +xstatic:XStatic_jQuery +xstatic:XStatic_jquery_ui +yaml:PyYAML +z3c:z3c.autoinclude +z3c:z3c.caching +z3c:z3c.form +z3c:z3c.formwidget.query +z3c:z3c.objpath +z3c:z3c.pt +z3c:z3c.relationfield +z3c:z3c.traverser +z3c:z3c.zcmlhook +zmq:pyzmq +zopyx:zopyx.textindexng3 diff --git a/pipenv/vendor/pipreqs/pipreqs.py b/pipenv/vendor/pipreqs/pipreqs.py new file mode 100755 index 00000000..791168a9 --- /dev/null +++ b/pipenv/vendor/pipreqs/pipreqs.py @@ -0,0 +1,402 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +"""pipreqs - Generate pip requirements.txt file based on imports + +Usage: + pipreqs [options] + +Options: + --use-local Use ONLY local package info instead of querying PyPI + --pypi-server Use custom PyPi server + --proxy Use Proxy, parameter will be passed to requests library. You can also just set the + environments parameter in your terminal: + $ export HTTP_PROXY="http://10.10.1.10:3128" + $ export HTTPS_PROXY="https://10.10.1.10:1080" + --debug Print debug information + --ignore ... Ignore extra directories, each separated by a comma + --encoding Use encoding parameter for file open + --savepath Save the list of requirements in the given file + --print Output the list of requirements in the standard output + --force Overwrite existing requirements.txt + --diff Compare modules in requirements.txt to project imports. + --clean Clean up requirements.txt by removing modules that are not imported in project. +""" +from __future__ import print_function, absolute_import +import os +import sys +import re +import logging +import codecs +import ast +import traceback +from docopt import docopt +import requests +from yarg import json2package +from yarg.exceptions import HTTPError + +from pipreqs import __version__ + +REGEXP = [ + re.compile(r'^import (.+)$'), + re.compile(r'^from ((?!\.+).*?) import (?:.*)$') +] + +if sys.version_info[0] > 2: + open_func = open + py2 = False +else: + open_func = codecs.open + py2 = True + py2_exclude = ["concurrent", "concurrent.futures"] + + +def get_all_imports(path, encoding=None, extra_ignore_dirs=None): + imports = set() + raw_imports = set() + candidates = [] + ignore_errors = False + ignore_dirs = [".hg", ".svn", ".git", ".tox", "__pycache__", "env", "venv"] + + if extra_ignore_dirs: + ignore_dirs_parsed = [] + for e in extra_ignore_dirs: + ignore_dirs_parsed.append(os.path.basename(os.path.realpath(e))) + ignore_dirs.extend(ignore_dirs_parsed) + + for root, dirs, files in os.walk(path): + dirs[:] = [d for d in dirs if d not in ignore_dirs] + + candidates.append(os.path.basename(root)) + files = [fn for fn in files if os.path.splitext(fn)[1] == ".py"] + + candidates += [os.path.splitext(fn)[0] for fn in files] + for file_name in files: + with open_func(os.path.join(root, file_name), "r", encoding=encoding) as f: + contents = f.read() + try: + tree = ast.parse(contents) + for node in ast.walk(tree): + if isinstance(node, ast.Import): + for subnode in node.names: + raw_imports.add(subnode.name) + elif isinstance(node, ast.ImportFrom): + raw_imports.add(node.module) + except Exception as exc: + if ignore_errors: + traceback.print_exc(exc) + logging.warn("Failed on file: %s" % os.path.join(root, file_name)) + continue + else: + logging.error("Failed on file: %s" % os.path.join(root, file_name)) + raise exc + + + + # Clean up imports + for name in [n for n in raw_imports if n]: + # Sanity check: Name could have been None if the import statement was as from . import X + # Cleanup: We only want to first part of the import. + # Ex: from django.conf --> django.conf. But we only want django as an import + cleaned_name, _, _ = name.partition('.') + imports.add(cleaned_name) + + packages = set(imports) - set(set(candidates) & set(imports)) + logging.debug('Found packages: {0}'.format(packages)) + + with open(join("stdlib"), "r") as f: + data = [x.strip() for x in f.readlines()] + data = [x for x in data if x not in py2_exclude] if py2 else data + return sorted(list(set(packages) - set(data))) + + +def filter_line(l): + return len(l) > 0 and l[0] != "#" + + +def generate_requirements_file(path, imports): + with open(path, "w") as out_file: + logging.debug('Writing {num} requirements: {imports} to {file}'.format( + num=len(imports), + file=path, + imports=", ".join([x['name'] for x in imports]) + )) + fmt = '{name}=={version}' + out_file.write('\n'.join(fmt.format(**item) if item['version'] else '{name}'.format(**item) + for item in imports) + '\n') + +def output_requirements(imports): + logging.debug('Writing {num} requirements: {imports} to stdout'.format( + num=len(imports), + imports=", ".join([x['name'] for x in imports]) + )) + fmt = '{name}=={version}' + print('\n'.join(fmt.format(**item) if item['version'] else '{name}'.format(**item) + for item in imports)) + + +def get_imports_info(imports, pypi_server="https://pypi.python.org/pypi/", proxy=None): + result = [] + + for item in imports: + try: + response = requests.get("{0}{1}/json".format(pypi_server, item), proxies=proxy) + if response.status_code == 200: + if hasattr(response.content, 'decode'): + data = json2package(response.content.decode()) + else: + data = json2package(response.content) + elif response.status_code >= 300: + raise HTTPError(status_code=response.status_code, + reason=response.reason) + except HTTPError: + logging.debug( + 'Package %s does not exist or network problems', item) + continue + result.append({'name': item, 'version': data.latest_release_id}) + return result + + +def get_locally_installed_packages(encoding=None): + packages = {} + ignore = ["tests", "_tests", "egg", "EGG", "info"] + for path in sys.path: + for root, dirs, files in os.walk(path): + for item in files: + if "top_level" in item: + with open_func(os.path.join(root, item), "r", encoding=encoding) as f: + package = root.split(os.sep)[-1].split("-") + try: + package_import = f.read().strip().split("\n") + except: + continue + for i_item in package_import: + if ((i_item not in ignore) and + (package[0] not in ignore)): + version = None + if len(package) > 1: + version = package[1].replace( + ".dist", "").replace(".egg", "") + + packages[i_item] = { + 'version': version, + 'name': package[0] + } + return packages + + +def get_import_local(imports, encoding=None): + local = get_locally_installed_packages() + result = [] + for item in imports: + if item.lower() in local: + result.append(local[item.lower()]) + + # removing duplicates of package/version + result_unique = [ + dict(t) + for t in set([ + tuple(d.items()) for d in result + ]) + ] + + return result_unique + + +def get_pkg_names(pkgs): + result = [] + with open(join("mapping"), "r") as f: + data = [x.strip().split(":") for x in f.readlines()] + for pkg in pkgs: + toappend = pkg + for item in data: + if item[0] == pkg: + toappend = item[1] + break + if toappend not in result: + result.append(toappend) + return result + + +def get_name_without_alias(name): + if "import " in name: + match = REGEXP[0].match(name.strip()) + if match: + name = match.groups(0)[0] + return name.partition(' as ')[0].partition('.')[0].strip() + + +def join(f): + return os.path.join(os.path.dirname(__file__), f) + +def parse_requirements(file_): + """Parse a requirements formatted file. + + Traverse a string until a delimiter is detected, then split at said + delimiter, get module name by element index, create a dict consisting of + module:version, and add dict to list of parsed modules. + + Args: + file_: File to parse. + + Raises: + OSerror: If there's any issues accessing the file. + + Returns: + tuple: The contents of the file, excluding comments. + """ + modules = [] + delim = ["<", ">", "=", "!", "~"] # https://www.python.org/dev/peps/pep-0508/#complete-grammar + + try: + f = open_func(file_, "r") + except OSError: + logging.error("Failed on file: {}".format(file_)) + raise + else: + data = [x.strip() for x in f.readlines() if x != "\n"] + finally: + f.close() + + data = [x for x in data if x[0].isalpha()] + + for x in data: + if not any([y in x for y in delim]): # Check for modules w/o a specifier. + modules.append({"name": x, "version": None}) + for y in x: + if y in delim: + module = x.split(y) + module_name = module[0] + module_version = module[-1].replace("=", "") + module = {"name": module_name, "version": module_version} + + if module not in modules: + modules.append(module) + + break + + return modules + + +def compare_modules(file_, imports): + """Compare modules in a file to imported modules in a project. + + Args: + file_ (str): File to parse for modules to be compared. + imports (tuple): Modules being imported in the project. + + Returns: + tuple: The modules not imported in the project, but do exist in the + specified file. + """ + modules = parse_requirements(file_) + + imports = [imports[i]["name"] for i in range(len(imports))] + modules = [modules[i]["name"] for i in range(len(modules))] + modules_not_imported = set(modules) - set(imports) + + return modules_not_imported + + +def diff(file_, imports): + """Display the difference between modules in a file and imported modules.""" + modules_not_imported = compare_modules(file_, imports) + + logging.info("The following modules are in {} but do not seem to be imported: " + "{}".format(file_, ", ".join(x for x in modules_not_imported))) + +def clean(file_, imports): + """Remove modules that aren't imported in project from file.""" + modules_not_imported = compare_modules(file_, imports) + re_remove = re.compile("|".join(modules_not_imported)) + to_write = [] + + try: + f = open_func(file_, "r+") + except OSError: + logging.error("Failed on file: {}".format(file_)) + raise + else: + for i in f.readlines(): + if re_remove.match(i) is None: + to_write.append(i) + f.seek(0) + f.truncate() + + for i in to_write: + f.write(i) + finally: + f.close() + + logging.info("Successfully cleaned up requirements in " + file_) + +def init(args): + encoding = args.get('--encoding') + extra_ignore_dirs = args.get('--ignore') + + if extra_ignore_dirs: + extra_ignore_dirs = extra_ignore_dirs.split(',') + + candidates = get_all_imports(args[''], + encoding=encoding, + extra_ignore_dirs=extra_ignore_dirs) + candidates = get_pkg_names(candidates) + logging.debug("Found imports: " + ", ".join(candidates)) + pypi_server = "https://pypi.python.org/pypi/" + proxy = None + if args["--pypi-server"]: + pypi_server = args["--pypi-server"] + + if args["--proxy"]: + proxy = {'http': args["--proxy"], 'https': args["--proxy"]} + + if args["--use-local"]: + logging.debug( + "Getting package information ONLY from local installation.") + imports = get_import_local(candidates, encoding=encoding) + else: + logging.debug("Getting packages information from Local/PyPI") + local = get_import_local(candidates, encoding=encoding) + # Get packages that were not found locally + difference = [x for x in candidates + if x.lower() not in [z['name'].lower() for z in local]] + imports = local + get_imports_info(difference, + proxy=proxy, + pypi_server=pypi_server) + + path = (args["--savepath"] if args["--savepath"] else + os.path.join(args[''], "requirements.txt")) + + if args["--diff"]: + diff(args["--diff"], imports) + return + + if args["--clean"]: + clean(args["--clean"], imports) + return + + if not args["--print"] and not args["--savepath"] and not args["--force"] and os.path.exists(path): + logging.warning("Requirements.txt already exists, " + "use --force to overwrite it") + return + + if args["--print"]: + output_requirements(imports) + logging.info("Successfully output requirements") + else: + generate_requirements_file(path, imports) + logging.info("Successfully saved requirements file in " + path) + + +def main(): # pragma: no cover + args = docopt(__doc__, version=__version__) + log_level = logging.DEBUG if args['--debug'] else logging.INFO + logging.basicConfig(level=log_level, format='%(levelname)s: %(message)s') + + try: + init(args) + except KeyboardInterrupt: + sys.exit(0) + + +if __name__ == '__main__': + main() # pragma: no cover diff --git a/pipenv/vendor/pipreqs/stdlib b/pipenv/vendor/pipreqs/stdlib new file mode 100755 index 00000000..71edcc87 --- /dev/null +++ b/pipenv/vendor/pipreqs/stdlib @@ -0,0 +1,1076 @@ +__builtin__ +__future__ +__main__ +_winreg +abc +aepack +aetools +aetypes +aifc +AL +al +anydbm +applesingle +argparse +array +ast +asynchat +asyncore +atexit +audioop +autoGIL +base64 +BaseHTTPServer +Bastion +bdb +binascii +binhex +bisect +bsddb +buildtools +bz2 +calendar +Carbon +Carbon.AE +Carbon.AH +Carbon.App +Carbon.Appearance +Carbon.CarbonEvents +Carbon.CarbonEvt +Carbon.CF +Carbon.CG +Carbon.Cm +Carbon.Components +Carbon.ControlAccessor +Carbon.Controls +Carbon.CoreFounation +Carbon.CoreGraphics +Carbon.Ctl +Carbon.Dialogs +Carbon.Dlg +Carbon.Drag +Carbon.Dragconst +Carbon.Events +Carbon.Evt +Carbon.File +Carbon.Files +Carbon.Fm +Carbon.Folder +Carbon.Folders +Carbon.Fonts +Carbon.Help +Carbon.IBCarbon +Carbon.IBCarbonRuntime +Carbon.Icns +Carbon.Icons +Carbon.Launch +Carbon.LaunchServices +Carbon.List +Carbon.Lists +Carbon.MacHelp +Carbon.MediaDescr +Carbon.Menu +Carbon.Menus +Carbon.Mlte +Carbon.OSA +Carbon.OSAconst +Carbon.Qd +Carbon.Qdoffs +Carbon.QDOffscreen +Carbon.Qt +Carbon.QuickDraw +Carbon.QuickTime +Carbon.Res +Carbon.Resources +Carbon.Scrap +Carbon.Snd +Carbon.Sound +Carbon.TE +Carbon.TextEdit +Carbon.Win +Carbon.Windows +cd +cfmfile +cgi +CGIHTTPServer +cgitb +chunk +cmath +cmd +code +codecs +codeop +collections +ColorPicker +colorsys +commands +compileall +compiler +compiler.ast +compiler.visitor +ConfigParser +contextlib +Cookie +cookielib +copy +copy_reg +cPickle +cProfile +crypt +cStringIO +csv +ctypes +curses +curses.ascii +curses.panel +curses.textpad +datetime +dbhash +dbm +decimal +DEVICE +difflib +dircache +dis +distutils +distutils.archive_util +distutils.bcppcompiler +distutils.ccompiler +distutils.cmd +distutils.command +distutils.command.bdist +distutils.command.bdist_dumb +distutils.command.bdist_msi +distutils.command.bdist_packager +distutils.command.bdist_rpm +distutils.command.bdist_wininst +distutils.command.build +distutils.command.build_clib +distutils.command.build_ext +distutils.command.build_py +distutils.command.build_scripts +distutils.command.check +distutils.command.clean +distutils.command.config +distutils.command.install +distutils.command.install_data +distutils.command.install_headers +distutils.command.install_lib +distutils.command.install_scripts +distutils.command.register +distutils.command.sdist +distutils.core +distutils.cygwinccompiler +distutils.debug +distutils.dep_util +distutils.dir_util +distutils.dist +distutils.emxccompiler +distutils.errors +distutils.extension +distutils.fancy_getopt +distutils.file_util +distutils.filelist +distutils.log +distutils.msvccompiler +distutils.spawn +distutils.sysconfig +distutils.text_file +distutils.unixccompiler +distutils.util +distutils.version +dl +doctest +DocXMLRPCServer +dumbdbm +dummy_thread +dummy_threading +EasyDialogs +email +email.charset +email.encoders +email.errors +email.generator +email.header +email.iterators +email.message +email.mime +email.parser +email.utils +encodings +encodings.idna +encodings.utf_8_sig +ensurepip +errno +exceptions +fcntl +filecmp +fileinput +findertools +FL +fl +flp +fm +fnmatch +formatter +fpectl +fpformat +fractions +FrameWork +ftplib +functools +future_builtins +gc +gdbm +gensuitemodule +getopt +getpass +gettext +gl +GL +glob +grp +gzip +hashlib +heapq +hmac +hotshot +hotshot.stats +htmlentitydefs +htmllib +HTMLParser +httplib +ic +icopen +imageop +imaplib +imgfile +imghdr +imp +importlib +imputil +inspect +io +itertools +jpeg +json +keyword +lib2to3 +linecache +locale +logging +logging.config +logging.handlers +macerrors +MacOS +macostools +macpath +macresource +mailbox +mailcap +marshal +math +md5 +mhlib +mimetools +mimetypes +MimeWriter +mimify +MiniAEFrame +mmap +modulefinder +msilib +msvcrt +multifile +multiprocessing +multiprocessing.connection +multiprocessing.dummy +multiprocessing.managers +multiprocessing.pool +multiprocessing.sharedctypes +mutex +Nav +netrc +new +nis +nntplib +numbers +operator +optparse +os +os.path +ossaudiodev +parser +pdb +pickle +pickletools +pipes +PixMapWrapper +pkgutil +platform +plistlib +popen2 +poplib +posix +posixfile +pprint +profile +pstats +pty +pwd +py_compile +pyclbr +pydoc +Queue +quopri +random +re +readline +resource +rexec +rfc822 +rlcompleter +robotparser +runpy +sched +ScrolledText +select +sets +sgmllib +sha +shelve +shlex +shutil +signal +SimpleHTTPServer +SimpleXMLRPCServer +site +smtpd +smtplib +sndhdr +socket +SocketServer +spwd +sqlite3 +ssl +stat +statvfs +string +StringIO +stringprep +struct +subprocess +sunau +sunaudiodev +SUNAUDIODEV +symbol +symtable +sys +sysconfig +syslog +tabnanny +tarfile +telnetlib +tempfile +termios +test +test.test_support +textwrap +thread +threading +time +timeit +Tix +Tkinter +token +tokenize +trace +traceback +ttk +tty +turtle +types +unicodedata +unittest +urllib +urllib2 +urlparse +user +UserDict +UserList +UserString +uu +uuid +videoreader +W +warnings +wave +weakref +webbrowser +whichdb +winsound +wsgiref +wsgiref.handlers +wsgiref.headers +wsgiref.simple_server +wsgiref.util +wsgiref.validate +xdrlib +xml +xml.dom +xml.dom.minidom +xml.dom.pulldom +xml.etree.ElementTree +xml.parsers.expat +xml.sax +xml.sax.handler +xml.sax.saxutils +xml.sax.xmlreader +xmlrpclib +zipfile +zipimport +zlib +__future__ +__main__ +_dummy_thread +_thread +abc +aifc +argparse +array +ast +asynchat +asyncio +asyncore +atexit +audioop +base64 +bdb +binascii +binhex +bisect +builtins +bz2 +calendar +cgi +cgitb +chunk +cmath +cmd +code +codecs +codeop +collections +collections.abc +colorsys +compileall +concurrent +concurrent.futures +configparser +contextlib +copy +copyreg +cProfile +crypt +csv +ctypes +curses +curses.ascii +curses.panel +curses.textpad +datetime +dbm +dbm.dumb +dbm.gnu +dbm.ndbm +decimal +difflib +dis +distutils +distutils.archive_util +distutils.bcppcompiler +distutils.ccompiler +distutils.cmd +distutils.command +distutils.command.bdist +distutils.command.bdist_dumb +distutils.command.bdist_msi +distutils.command.bdist_packager +distutils.command.bdist_rpm +distutils.command.bdist_wininst +distutils.command.build +distutils.command.build_clib +distutils.command.build_ext +distutils.command.build_py +distutils.command.build_scripts +distutils.command.check +distutils.command.clean +distutils.command.config +distutils.command.install +distutils.command.install_data +distutils.command.install_headers +distutils.command.install_lib +distutils.command.install_scripts +distutils.command.register +distutils.command.sdist +distutils.core +distutils.cygwinccompiler +distutils.debug +distutils.dep_util +distutils.dir_util +distutils.dist +distutils.errors +distutils.extension +distutils.fancy_getopt +distutils.file_util +distutils.filelist +distutils.log +distutils.msvccompiler +distutils.spawn +distutils.sysconfig +distutils.text_file +distutils.unixccompiler +distutils.util +distutils.version +doctest +dummy_threading +email +email.charset +email.contentmanager +email.encoders +email.errors +email.generator +email.header +email.headerregistry +email.iterators +email.message +email.mime +email.parser +email.policy +email.utils +encodings +encodings.idna +encodings.mbcs +encodings.utf_8_sig +ensurepip +enum +errno +faulthandler +fcntl +filecmp +fileinput +fnmatch +formatter +fpectl +fractions +ftplib +functools +gc +getopt +getpass +gettext +glob +grp +gzip +hashlib +heapq +hmac +html +html.entities +html.parser +http +http.client +http.cookiejar +http.cookies +http.server +imaplib +imghdr +imp +importlib +importlib.abc +importlib.machinery +importlib.util +inspect +io +ipaddress +itertools +json +keyword +lib2to3 +linecache +locale +logging +logging.config +logging.handlers +lzma +macpath +mailbox +mailcap +marshal +math +mimetypes +mmap +modulefinder +msilib +msvcrt +multiprocessing +multiprocessing.connection +multiprocessing.dummy +multiprocessing.managers +multiprocessing.pool +multiprocessing.sharedctypes +netrc +nis +nntplib +numbers +operator +optparse +os +os.path +ossaudiodev +parser +pathlib +pdb +pickle +pickletools +pipes +pkgutil +platform +plistlib +poplib +posix +pprint +profile +pstats +pty +pwd +py_compile +pyclbr +pydoc +queue +quopri +random +re +readline +reprlib +resource +rlcompleter +runpy +sched +select +selectors +shelve +shlex +shutil +signal +site +smtpd +smtplib +sndhdr +socket +socketserver +spwd +sqlite3 +ssl +stat +statistics +string +stringprep +struct +subprocess +sunau +symbol +symtable +sys +sysconfig +syslog +tabnanny +tarfile +telnetlib +tempfile +termios +test +test.support +textwrap +threading +time +timeit +tkinter +tkinter.scrolledtext +tkinter.tix +tkinter.ttk +token +tokenize +trace +traceback +tracemalloc +tty +turtle +turtledemo +types +unicodedata +unittest +unittest.mock +urllib +urllib.error +urllib.parse +urllib.request +urllib.response +urllib.robotparser +uu +uuid +venv +warnings +wave +weakref +webbrowser +winreg +winsound +wsgiref +wsgiref.handlers +wsgiref.headers +wsgiref.simple_server +wsgiref.util +wsgiref.validate +xdrlib +xml +xml.dom +xml.dom.minidom +xml.dom.pulldom +xml.etree.ElementTree +xml.parsers.expat +xml.parsers.expat.errors +xml.parsers.expat.model +xml.sax +xml.sax.handler +xml.sax.saxutils +xml.sax.xmlreader +xmlrpc +xmlrpc.client +xmlrpc.server +zipfile +zipimport +zlib +__future__ +__main__ +_dummy_thread +_thread +abc +aifc +argparse +array +ast +asynchat +asyncio +asyncore +atexit +audioop +base64 +bdb +binascii +binhex +bisect +builtins +bz2 +calendar +cgi +cgitb +chunk +cmath +cmd +code +codecs +codeop +collections +collections.abc +colorsys +compileall +concurrent +concurrent.futures +configparser +contextlib +copy +copyreg +cProfile +crypt +csv +ctypes +curses +curses.ascii +curses.panel +curses.textpad +datetime +dbm +dbm.dumb +dbm.gnu +dbm.ndbm +decimal +difflib +dis +distutils +distutils.archive_util +distutils.bcppcompiler +distutils.ccompiler +distutils.cmd +distutils.command +distutils.command.bdist +distutils.command.bdist_dumb +distutils.command.bdist_msi +distutils.command.bdist_packager +distutils.command.bdist_rpm +distutils.command.bdist_wininst +distutils.command.build +distutils.command.build_clib +distutils.command.build_ext +distutils.command.build_py +distutils.command.build_scripts +distutils.command.check +distutils.command.clean +distutils.command.config +distutils.command.install +distutils.command.install_data +distutils.command.install_headers +distutils.command.install_lib +distutils.command.install_scripts +distutils.command.register +distutils.command.sdist +distutils.core +distutils.cygwinccompiler +distutils.debug +distutils.dep_util +distutils.dir_util +distutils.dist +distutils.errors +distutils.extension +distutils.fancy_getopt +distutils.file_util +distutils.filelist +distutils.log +distutils.msvccompiler +distutils.spawn +distutils.sysconfig +distutils.text_file +distutils.unixccompiler +distutils.util +distutils.version +doctest +dummy_threading +email +email.charset +email.contentmanager +email.encoders +email.errors +email.generator +email.header +email.headerregistry +email.iterators +email.message +email.mime +email.parser +email.policy +email.utils +encodings +encodings.idna +encodings.mbcs +encodings.utf_8_sig +ensurepip +enum +errno +faulthandler +fcntl +filecmp +fileinput +fnmatch +formatter +fpectl +fractions +ftplib +functools +gc +getopt +getpass +gettext +glob +grp +gzip +hashlib +heapq +hmac +html +html.entities +html.parser +http +http.client +http.cookiejar +http.cookies +http.server +imaplib +imghdr +imp +importlib +importlib.abc +importlib.machinery +importlib.util +inspect +io +ipaddress +itertools +json +json.tool +keyword +lib2to3 +linecache +locale +logging +logging.config +logging.handlers +lzma +macpath +mailbox +mailcap +marshal +math +mimetypes +mmap +modulefinder +msilib +msvcrt +multiprocessing +multiprocessing.connection +multiprocessing.dummy +multiprocessing.managers +multiprocessing.pool +multiprocessing.sharedctypes +netrc +nis +nntplib +numbers +operator +optparse +os +os.path +ossaudiodev +parser +pathlib +pdb +pickle +pickletools +pipes +pkgutil +platform +plistlib +poplib +posix +pprint +profile +pstats +pty +pwd +py_compile +pyclbr +pydoc +queue +quopri +random +re +readline +reprlib +resource +rlcompleter +runpy +sched +select +selectors +shelve +shlex +shutil +signal +site +smtpd +smtplib +sndhdr +socket +socketserver +spwd +sqlite3 +ssl +stat +statistics +string +stringprep +struct +subprocess +sunau +symbol +symtable +sys +sysconfig +syslog +tabnanny +tarfile +telnetlib +tempfile +termios +test +test.support +textwrap +threading +time +timeit +tkinter +tkinter.scrolledtext +tkinter.tix +tkinter.ttk +token +tokenize +trace +traceback +tracemalloc +tty +turtle +turtledemo +types +unicodedata +unittest +unittest.mock +urllib +urllib.error +urllib.parse +urllib.request +urllib.response +urllib.robotparser +uu +uuid +venv +warnings +wave +weakref +webbrowser +winreg +winsound +wsgiref +wsgiref.handlers +wsgiref.headers +wsgiref.simple_server +wsgiref.util +wsgiref.validate +xdrlib +xml +xml.dom +xml.dom.minidom +xml.dom.pulldom +xml.etree.ElementTree +xml.parsers.expat +xml.parsers.expat.errors +xml.parsers.expat.model +xml.sax +xml.sax.handler +xml.sax.saxutils +xml.sax.xmlreader +xmlrpc +xmlrpc.client +xmlrpc.server +zipapp +zipfile +zipimport +zlib diff --git a/pipenv/vendor/yarg/__about__.py b/pipenv/vendor/yarg/__about__.py new file mode 100644 index 00000000..ff6cadc8 --- /dev/null +++ b/pipenv/vendor/yarg/__about__.py @@ -0,0 +1,7 @@ +__title__ = 'yarg' +__version__ = '0.1.9' +__author__ = 'Kura' +__email__ = 'kura@kura.io' +__url__ = 'https://yarg.readthedocs.org/' +__license__ = 'MIT' +__copyright__ = 'Copyright 2014 Kura' diff --git a/pipenv/vendor/yarg/__init__.py b/pipenv/vendor/yarg/__init__.py new file mode 100644 index 00000000..d5594ebd --- /dev/null +++ b/pipenv/vendor/yarg/__init__.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- + +# (The MIT License) +# +# Copyright (c) 2014 Kura +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the 'Software'), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +""" +yarg(1) -- A semi hard Cornish cheese, also queries PyPI +======================================================== + +Yarg is a PyPI client. + + >>> import yarg + >>> + >>> package = yarg.get("yarg") + >>> package.name + u'yarg' + >>> package.author + Author(name=u'Kura', email=u'kura@kura.io') + >>> + >>> yarg.newest_packages() + [, , ] + >>> + >>> yarg.latest_updated_packages() + [, , ] + +Full documentation is at . +""" + + +from .client import get +from .exceptions import HTTPError +from .package import json2package +from .parse import (newest_packages, latest_updated_packages) + + +__all__ = ['get', 'HTTPError', 'json2package', 'newest_packages', + 'latest_updated_packages', ] diff --git a/pipenv/vendor/yarg/client.py b/pipenv/vendor/yarg/client.py new file mode 100644 index 00000000..829b40b7 --- /dev/null +++ b/pipenv/vendor/yarg/client.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- + +# (The MIT License) +# +# Copyright (c) 2014 Kura +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the 'Software'), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +import requests + +from .exceptions import HTTPError +from .package import json2package + + +def get(package_name, pypi_server="https://pypi.python.org/pypi/"): + """ + Constructs a request to the PyPI server and returns a + :class:`yarg.package.Package`. + + :param package_name: case sensitive name of the package on the PyPI server. + :param pypi_server: (option) URL to the PyPI server. + + >>> import yarg + >>> package = yarg.get('yarg') + + """ + if not pypi_server.endswith("/"): + pypi_server = pypi_server + "/" + response = requests.get("{0}{1}/json".format(pypi_server, + package_name)) + if response.status_code >= 300: + raise HTTPError(status_code=response.status_code, + reason=response.reason) + if hasattr(response.content, 'decode'): + return json2package(response.content.decode()) + else: + return json2package(response.content) diff --git a/pipenv/vendor/yarg/exceptions.py b/pipenv/vendor/yarg/exceptions.py new file mode 100644 index 00000000..adfdb838 --- /dev/null +++ b/pipenv/vendor/yarg/exceptions.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- + +# (The MIT License) +# +# Copyright (c) 2014 Kura +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the 'Software'), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +from requests.exceptions import HTTPError as RHTTPError + + +class YargException(Exception): + pass + + +class HTTPError(YargException, RHTTPError): + """ + A catchall HTTPError exception to handle HTTP errors + when using :meth:`yarg.get`. + + This exception is also loaded at :class:`yarg.HTTPError` + for ease of access. + + :member: status_code + """ + + def __init__(self, *args, **kwargs): + for key, val in kwargs.items(): + setattr(self, key, val) + if hasattr(self, 'status_code'): + setattr(self, 'errno', self.status_code) + if hasattr(self, 'reason'): + setattr(self, 'message', self.reason) + + def __str__(self): + return self.__repr__() + + def __repr__(self): + if hasattr(self, 'status_code') and hasattr(self, 'reason'): + return "".format(self.status_code, self.reason) + return "" diff --git a/pipenv/vendor/yarg/package.py b/pipenv/vendor/yarg/package.py new file mode 100644 index 00000000..761df39e --- /dev/null +++ b/pipenv/vendor/yarg/package.py @@ -0,0 +1,324 @@ +# -*- coding: utf-8 -*- + +# (The MIT License) +# +# Copyright (c) 2014 Kura +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the 'Software'), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +try: + import simplejson as json +except ImportError: + import json +from collections import namedtuple +import re + +from .release import Release + + +class Package(object): + """ + A PyPI package. + + :param pypi_dict: A dictionary retrieved from the PyPI server. + """ + + def __init__(self, pypi_dict): + self._package = pypi_dict['info'] + self._releases = pypi_dict['releases'] + + def __repr__(self): + return "".format(self.name) + + @property + def name(self): + """ + >>> package = yarg.get('yarg') + >>> package.name + u'yarg' + """ + return self._package['name'] + + @property + def pypi_url(self): + """ + >>> package = yarg.get('yarg') + >>> package.url + u'https://pypi.python.org/pypi/yarg' + """ + return self._package['package_url'] + + @property + def summary(self): + """ + >>> package = yarg.get('yarg') + >>> package.summary + u'Some random summary stuff' + """ + return self._package['summary'] + + @property + def description(self): + """ + >>> package = yarg.get('yarg') + >>> package.description + u'A super long description, usually uploaded from the README' + """ + return self._package['description'] + + @property + def homepage(self): + """ + >>> package = yarg.get('yarg') + >>> package.homepage + u'https://kura.io/yarg/' + """ + if ('home_page' not in self._package or + self._package['home_page'] == ""): + return None + return self._package['home_page'] + + @property + def bugtracker(self): + """ + >>> package = yarg.get('yarg') + >>> package.bugtracker + u'https://github.com/kura/yarg/issues' + """ + if ('bugtrack_url' not in self._package or + self._package['bugtrack_url'] == ""): + return None + return self._package['bugtrack_url'] + + @property + def docs(self): + """ + >>> package = yarg.get('yarg') + >>> package.docs + u'https://yarg.readthedocs.org/en/latest' + """ + if ('docs_url' not in self._package or + self._package['docs_url'] == ""): + return None + return self._package['docs_url'] + + @property + def author(self): + """ + >>> package = yarg.get('yarg') + >>> package.author + Author(name=u'Kura', email=u'kura@kura.io') + """ + author = namedtuple('Author', 'name email') + return author(name=self._package['author'], + email=self._package['author_email']) + + @property + def maintainer(self): + """ + >>> package = yarg.get('yarg') + >>> package.maintainer + Maintainer(name=u'Kura', email=u'kura@kura.io') + """ + maintainer = namedtuple('Maintainer', 'name email') + return maintainer(name=self._package['maintainer'], + email=self._package['maintainer_email']) + + @property + def license(self): + """ + >>> package = yarg.get('yarg') + >>> package.license + u'MIT' + """ + return self._package['license'] + + @property + def license_from_classifiers(self): + """ + >>> package = yarg.get('yarg') + >>> package.license_from_classifiers + u'MIT License' + """ + if len(self.classifiers) > 0: + for c in self.classifiers: + if c.startswith("License"): + return c.split(" :: ")[-1] + + @property + def downloads(self): + """ + >>> package = yarg.get('yarg') + >>> package.downloads + Downloads(day=50100, week=367941, month=1601938) # I wish + """ + _downloads = self._package['downloads'] + downloads = namedtuple('Downloads', 'day week month') + return downloads(day=_downloads['last_day'], + week=_downloads['last_week'], + month=_downloads['last_month']) + + @property + def classifiers(self): + """ + >>> package = yarg.get('yarg') + >>> package.classifiers + [u'License :: OSI Approved :: MIT License', + u'Programming Language :: Python :: 2.7', + u'Programming Language :: Python :: 3.4'] + """ + return self._package['classifiers'] + + @property + def python_versions(self): + """ + Returns a list of Python version strings that + the package has listed in :attr:`yarg.Release.classifiers`. + + >>> package = yarg.get('yarg') + >>> package.python_versions + [u'2.6', u'2.7', u'3.3', u'3.4'] + """ + version_re = re.compile(r"""Programming Language \:\: """ + """Python \:\: \d\.\d""") + return [c.split(' :: ')[-1] for c in self.classifiers + if version_re.match(c)] + + @property + def python_implementations(self): + """ + Returns a list of Python implementation strings that + the package has listed in :attr:`yarg.Release.classifiers`. + + >>> package = yarg.get('yarg') + >>> package.python_implementations + [u'CPython', u'PyPy'] + """ + return [c.split(' :: ')[-1] for c in self.classifiers + if c.startswith("""Programming Language :: """ + """Python :: Implementation""")] + + @property + def latest_release_id(self): + """ + >>> package = yarg.get('yarg') + >>> package.latest_release_id + u'0.1.0' + """ + return self._package['version'] + + @property + def latest_release(self): + """ + A list of :class:`yarg.release.Release` objects for each file in the + latest release. + + >>> package = yarg.get('yarg') + >>> package.latest_release + [, ] + """ + release_id = self.latest_release_id + return self.release(release_id) + + @property + def has_wheel(self): + """ + Returns `True` if one of the :class:`yarg.release.Release` objects + in the latest set of release files is `wheel` format. Returns + `False` if not. + + >>> package = yarg.get('yarg') + >>> package.has_wheel + True + """ + for release in self.latest_release: + if release.package_type in ('wheel', 'bdist_wheel'): + return True + return False + + @property + def has_egg(self): + """ + Returns `True` if one of the :class:`yarg.release.Release` objects + in the latest set of release files is `egg` format. Returns + `False` if not. + + >>> package = yarg.get('yarg') + >>> package.has_egg + False + """ + for release in self.latest_release: + if release.package_type in ('egg', 'bdist_egg'): + return True + return False + + @property + def has_source(self): + """ + Returns `True` if one of the :class:`yarg.release.Release` objects + in the latest set of release files is `source` format. Returns + `False` if not. + + >>> package = yarg.get('yarg') + >>> package.has_source + True + """ + for release in self.latest_release: + if release.package_type in ('source', 'sdist'): + return True + return False + + @property + def release_ids(self): + """ + >>> package = yarg.get('yarg') + >>> package.release_ids + [u'0.0.1', u'0.0.5', u'0.1.0'] + """ + r = [(k, self._releases[k][0]['upload_time']) + for k in self._releases.keys() + if len(self._releases[k]) > 0] + return [k[0] for k in sorted(r, key=lambda k: k[1])] + + def release(self, release_id): + """ + A list of :class:`yarg.release.Release` objects for each file in a + release. + + :param release_id: A pypi release id. + + >>> package = yarg.get('yarg') + >>> last_release = yarg.releases[-1] + >>> package.release(last_release) + [, ] + """ + if release_id not in self.release_ids: + return None + return [Release(release_id, r) for r in self._releases[release_id]] + + +def json2package(json_content): + """ + Returns a :class:`yarg.release.Release` object from JSON content from the + PyPI server. + + :param json_content: JSON encoded content from the PyPI server. + """ + return Package(json.loads(json_content)) diff --git a/pipenv/vendor/yarg/parse.py b/pipenv/vendor/yarg/parse.py new file mode 100644 index 00000000..60cd90a8 --- /dev/null +++ b/pipenv/vendor/yarg/parse.py @@ -0,0 +1,172 @@ +# -*- coding: utf-8 -*- + +# (The MIT License) +# +# Copyright (c) 2014 Kura +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the 'Software'), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +from datetime import datetime +import xml.etree.ElementTree + +import requests + +from .exceptions import HTTPError + + +def _get(pypi_server): + """ + Query the PyPI RSS feed and return a list + of XML items. + """ + response = requests.get(pypi_server) + if response.status_code >= 300: + raise HTTPError(status_code=response.status_code, + reason=response.reason) + if hasattr(response.content, 'decode'): + tree = xml.etree.ElementTree.fromstring(response.content.decode()) + else: + tree = xml.etree.ElementTree.fromstring(response.content) + channel = tree.find('channel') + return channel.findall('item') + + +def newest_packages( + pypi_server="https://pypi.python.org/pypi?%3Aaction=packages_rss"): + """ + Constructs a request to the PyPI server and returns a list of + :class:`yarg.parse.Package`. + + :param pypi_server: (option) URL to the PyPI server. + + >>> import yarg + >>> yarg.newest_packages() + [, , ] + """ + items = _get(pypi_server) + i = [] + for item in items: + i_dict = {'name': item[0].text.split()[0], + 'url': item[1].text, + 'description': item[3].text, + 'date': item[4].text} + i.append(Package(i_dict)) + return i + + +def latest_updated_packages( + pypi_server="https://pypi.python.org/pypi?%3Aaction=rss"): + """ + Constructs a request to the PyPI server and returns a list of + :class:`yarg.parse.Package`. + + :param pypi_server: (option) URL to the PyPI server. + + >>> import yarg + >>> yarg.latest_updated_packages() + [, , ] + """ + items = _get(pypi_server) + i = [] + for item in items: + name, version = item[0].text.split() + i_dict = {'name': name, + 'version': version, + 'url': item[1].text, + 'description': item[2].text, + 'date': item[3].text} + i.append(Package(i_dict)) + return i + + +class Package(object): + """ + A PyPI package generated from the RSS feed information. + + :param pypi_dict: A dictionary retrieved from the PyPI server. + """ + + def __init__(self, pypi_dict): + self._content = pypi_dict + + def __repr__(self): + return "".format(self.name) + + @property + def name(self): + """ + >>> package = yarg.newest_packages()[0] + >>> package.name + u'yarg' + >>> package = yarg.latest_updated_packages()[0] + >>> package.name + u'yarg' + """ + return self._content['name'] + + @property + def version(self): + """ + >>> package = yarg.newest_packages()[0] + >>> package.name + u'yarg' + >>> package = yarg.latest_updated_packages()[0] + >>> package.name + u'yarg' + """ + if 'version' not in self._content: + return None + return self._content['version'] + + @property + def url(self): + """ + This is only available for :meth:`yarg.latest_updated_packages`, for + :meth:`yarg.newest_packages` will return `None` + + >>> package = yarg.latest_updated_packages()[0] + >>> package.url + u'http://pypi.python.org/pypi/yarg' + """ + return self._content['url'] + + @property + def date(self): + """ + >>> package = yarg.newest_packages()[0] + >>> package.date + datetime.datetime(2014, 8, 9, 8, 40, 20) + >>> package = yarg.latest_updated_packages()[0] + >>> package.date + datetime.datetime(2014, 8, 9, 8, 40, 20) + """ + return datetime.strptime(self._content['date'], + "%d %b %Y %H:%M:%S %Z") + + @property + def description(self): + """ + >>> package = yarg.newest_packages()[0] + >>> package.description + u'Some random summary stuff' + >>> package = yarg.latest_updated_packages()[0] + >>> package.description + u'Some random summary stuff' + """ + return self._content['description'] diff --git a/pipenv/vendor/yarg/release.py b/pipenv/vendor/yarg/release.py new file mode 100644 index 00000000..6f05750d --- /dev/null +++ b/pipenv/vendor/yarg/release.py @@ -0,0 +1,147 @@ +# -*- coding: utf-8 -*- + +# (The MIT License) +# +# Copyright (c) 2014 Kura +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the 'Software'), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +from datetime import datetime + + +class Release(object): + """ + A release file from PyPI. + + :param release_id: A release id. + :param pypi_dict: A dictionary of a release file. + """ + + def __init__(self, release_id, pypi_dict): + self._release = pypi_dict + self._release['release_id'] = release_id + + def __repr__(self): + return "".format(self.release_id) + + @property + def release_id(self): + """ + >>> package = yarg.get('yarg') + >>> v = "0.1.0" + >>> r = package.release(v) + >>> r[0].release_id + u'0.1.0' + """ + return self._release['release_id'] + + @property + def uploaded(self): + """ + >>> package = yarg.get('yarg') + >>> v = "0.1.0" + >>> r = package.release(v) + >>> r.uploaded + datetime.datime(2014, 8, 7, 21, 26, 19) + """ + return datetime.strptime(self._release['upload_time'], + '%Y-%m-%dT%H:%M:%S') + + @property + def python_version(self): + """ + >>> package = yarg.get('yarg') + >>> v = "0.1.0" + >>> r = package.release(v) + >>> r.python_version + u'2.7' + """ + return self._release['python_version'] + + @property + def url(self): + """ + >>> package = yarg.get('yarg') + >>> v = "0.1.0" + >>> r = package.release(v) + >>> r.url + u'https://pypi.python.org/packages/2.7/y/yarg/yarg...' + """ + return self._release['url'] + + @property + def md5_digest(self): + """ + >>> package = yarg.get('yarg') + >>> v = "0.1.0" + >>> r = package.release(v) + >>> r.md5_digest + u'bec88e1c1765ca6177360e8f37b44c5c' + """ + return self._release['md5_digest'] + + @property + def filename(self): + """ + >>> package = yarg.get('yarg') + >>> v = "0.1.0" + >>> r = package.release(v) + >>> r.filename + u'yarg-0.1.0-py27-none-any.whl' + """ + return self._release['filename'] + + @property + def size(self): + """ + >>> package = yarg.get('yarg') + >>> v = "0.1.0" + >>> r = package.release(v) + >>> r.size + 52941 + """ + return self._release['size'] + + @property + def package_type(self): + """ + >>> package = yarg.get('yarg') + >>> v = "0.1.0" + >>> r = package.release(v) + >>> r.package_type + u'wheel' + """ + mapping = {'bdist_egg': u'egg', 'bdist_wheel': u'wheel', + 'sdist': u'source'} + ptype = self._release['packagetype'] + if ptype in mapping.keys(): + return mapping[ptype] + return ptype + + @property + def has_sig(self): + """ + >>> package = yarg.get('yarg') + >>> v = "0.1.0" + >>> r = package.release(v) + >>> r.has_sig + True + """ + return self._release['has_sig']