├── docs ├── _static │ └── .empty ├── changelog.rst ├── index.rst ├── security.rst ├── development │ ├── index.rst │ ├── reviewing-patches.rst │ ├── getting-started.rst │ └── submitting-patches.rst ├── conf.py └── Makefile ├── requirements.txt ├── setup.cfg ├── .coveragerc ├── .gitignore ├── LICENSE ├── examples ├── setup.py ├── Pipfile └── Pipfile.lock ├── tests ├── __init__.py └── test_parser.py ├── CHANGELOG.rst ├── MANIFEST.in ├── pipfile ├── __init__.py ├── __about__.py └── api.py ├── .travis.yml ├── LICENSE.BSD ├── tox.ini ├── setup.py ├── LICENSE.APACHE └── README.rst /docs/_static/.empty: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | toml==0.9.2 2 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [bdist_wheel] 2 | universal=1 3 | -------------------------------------------------------------------------------- /docs/changelog.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../CHANGELOG.rst 2 | -------------------------------------------------------------------------------- /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | branch = True 3 | 4 | [report] 5 | exclude_lines = 6 | @abc.abstractmethod 7 | @abc.abstractproperty 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.egg-info/ 2 | *.egg 3 | *.py[co] 4 | 5 | .tox/ 6 | .cache/ 7 | .coverage 8 | 9 | __pycache__/ 10 | _build/ 11 | build/ 12 | dist/ 13 | htmlcov/ 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This software is made available under the terms of *either* of the licenses 2 | found in LICENSE.APACHE or LICENSE.BSD. Contributions to this software is made 3 | under the terms of *both* these licenses. 4 | -------------------------------------------------------------------------------- /examples/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | 3 | setup( 4 | name='mypackage', 5 | version='0.0.1', 6 | packages=find_packages(), 7 | install_requires=[ 8 | 'lxml >= 3.3.5' 9 | ], 10 | zip_safe=False 11 | ) 12 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | # This file is dual licensed under the terms of the Apache License, Version 2 | # 2.0, and the BSD License. See the LICENSE file in the root of this repository 3 | # for complete details. 4 | from __future__ import absolute_import, division, print_function 5 | -------------------------------------------------------------------------------- /CHANGELOG.rst: -------------------------------------------------------------------------------- 1 | Changelog 2 | --------- 3 | 4 | 16.0 - `master`_ 5 | ~~~~~~~~~~~~~~~~~ 6 | 7 | .. note:: This version is not yet released and is under active development. 8 | 9 | 10 | * Initial release. 11 | 12 | 13 | .. _`master`: https://github.com/pypa/pipfile/ 14 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include CHANGELOG.rst CONTRIBUTING.rst README.rst 2 | include LICENSE LICENSE.APACHE LICENSE.BSD 3 | 4 | include .coveragerc 5 | include tox.ini 6 | 7 | recursive-include docs * 8 | recursive-include tests *.py 9 | 10 | exclude .travis.yml 11 | exclude dev-requirements.txt 12 | 13 | prune docs/_build 14 | prune tasks 15 | -------------------------------------------------------------------------------- /pipfile/__init__.py: -------------------------------------------------------------------------------- 1 | # This file is dual licensed under the terms of the Apache License, Version 2 | # 2.0, and the BSD License. See the LICENSE file in the root of this repository 3 | # for complete details. 4 | from __future__ import absolute_import, division, print_function 5 | 6 | from .__about__ import ( 7 | __author__, __copyright__, __email__, __license__, __summary__, __title__, 8 | __uri__, __version__ 9 | ) 10 | 11 | from .api import load, Pipfile 12 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | Welcome to pipfile 2 | ================== 3 | 4 | TODO: Description 5 | 6 | 7 | Installation 8 | ------------ 9 | 10 | You can install pipfile with ``pip``: 11 | 12 | .. code-block:: console 13 | 14 | $ pip install pipfile 15 | 16 | 17 | API 18 | --- 19 | 20 | .. toctree:: 21 | :maxdepth: 1 22 | 23 | 24 | 25 | Project 26 | ------- 27 | 28 | .. toctree:: 29 | :maxdepth: 2 30 | 31 | development/index 32 | security 33 | changelog 34 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3.4 3 | 4 | sudo: false 5 | 6 | env: 7 | - TOXENV=py26 8 | - TOXENV=py27 9 | - TOXENV=py33 10 | - TOXENV=py34 11 | - TOXENV=pypy 12 | - TOXENV=pep8 13 | - TOXENV=py2pep8 14 | - TOXENV=docs 15 | - TOXENV=packaging 16 | 17 | install: 18 | - pip install tox 19 | 20 | script: 21 | - tox 22 | 23 | notifications: 24 | irc: 25 | channels: 26 | - "irc.freenode.org#pypa-dev" 27 | use_notice: true 28 | skip_join: true 29 | -------------------------------------------------------------------------------- /docs/security.rst: -------------------------------------------------------------------------------- 1 | Security 2 | ======== 3 | 4 | We take the security of pipfile seriously. If you believe you've 5 | identified a security issue in it, please report it to 6 | ``donald@stufft.io``. Message may be encrypted with PGP using key 7 | fingerprint ``7C6B 7C5D 5E2B 6356 A926 F04F 6E3C BCE9 3372 DCFA`` (this public 8 | key is available from most commonly-used key servers). 9 | 10 | Once you've submitted an issue via email, you should receive an acknowledgment 11 | within 48 hours, and depending on the action to be taken, you may receive 12 | further follow-up emails. 13 | -------------------------------------------------------------------------------- /docs/development/index.rst: -------------------------------------------------------------------------------- 1 | Development 2 | =========== 3 | 4 | As an open source project, pipfile welcomes contributions of all 5 | forms. The sections below will help you get started. 6 | 7 | File bugs and feature requests on our issue tracker on `GitHub`_. If it is a 8 | bug check out `what to put in your bug report`_. 9 | 10 | .. toctree:: 11 | :maxdepth: 2 12 | 13 | getting-started 14 | submitting-patches 15 | reviewing-patches 16 | 17 | .. _`GitHub`: https://github.com/pypa/pipfile 18 | .. _`what to put in your bug report`: http://www.contribution-guide.org/#what-to-put-in-your-bug-report 19 | -------------------------------------------------------------------------------- /examples/Pipfile: -------------------------------------------------------------------------------- 1 | [[source]] 2 | url = 'https://pypi.python.org/simple' 3 | verify_ssl = true 4 | name = 'pypi' 5 | 6 | [requires] 7 | python_version = '3.6' 8 | 9 | [packages] 10 | requests = { extras = ['socks'] } 11 | records = '>0.5.0' 12 | django = { git = 'https://github.com/django/django.git', ref = '1.11.4', editable = true } 13 | "e682b37" = {file = "https://github.com/divio/django-cms/archive/release/3.4.x.zip"} 14 | "e1839a8" = {path = ".", editable = true} 15 | pywinusb = { version = "*", os_name = "=='nt'", index="pypi"} 16 | 17 | [dev-packages] 18 | nose = '*' 19 | unittest2 = {version = ">=1.0,<3.0", markers="python_version < '2.7.9' or (python_version >= '3.0' and python_version < '3.4')"} 20 | -------------------------------------------------------------------------------- /pipfile/__about__.py: -------------------------------------------------------------------------------- 1 | # This file is dual licensed under the terms of the Apache License, Version 2 | # 2.0, and the BSD License. See the LICENSE file in the root of this repository 3 | # for complete details. 4 | from __future__ import absolute_import, division, print_function 5 | 6 | __all__ = [ 7 | "__title__", "__summary__", "__uri__", "__version__", "__author__", 8 | "__email__", "__license__", "__copyright__", 9 | ] 10 | 11 | __title__ = "pipfile" 12 | __summary__ = "" 13 | __uri__ = "https://github.com/pypa/pipfile" 14 | 15 | __version__ = "0.0.1" 16 | 17 | __author__ = "Kenneth Reitz and individual contributors" 18 | __email__ = "me@kennethreitz.org" 19 | 20 | __license__ = "BSD or Apache License, Version 2.0" 21 | __copyright__ = "Copyright 2017 %s" % __author__ 22 | -------------------------------------------------------------------------------- /docs/development/reviewing-patches.rst: -------------------------------------------------------------------------------- 1 | Reviewing and merging patches 2 | ============================= 3 | 4 | Everyone is encouraged to review open pull requests. We only ask that you try 5 | and think carefully, ask questions and are `excellent to one another`_. Code 6 | review is our opportunity to share knowledge, design ideas and make friends. 7 | 8 | When reviewing a patch try to keep each of these concepts in mind: 9 | 10 | Architecture 11 | ------------ 12 | 13 | * Is the proposed change being made in the correct place? 14 | 15 | Intent 16 | ------ 17 | 18 | * What is the change being proposed? 19 | * Do we want this feature or is the bug they're fixing really a bug? 20 | 21 | Implementation 22 | -------------- 23 | 24 | * Does the change do what the author claims? 25 | * Are there sufficient tests? 26 | * Has it been documented? 27 | * Will this change introduce new bugs? 28 | 29 | Grammar and style 30 | ----------------- 31 | 32 | These are small things that are not caught by the automated style checkers. 33 | 34 | * Does a variable need a better name? 35 | * Should this be a keyword argument? 36 | 37 | .. _`excellent to one another`: https://speakerdeck.com/ohrite/better-code-review -------------------------------------------------------------------------------- /LICENSE.BSD: -------------------------------------------------------------------------------- 1 | Copyright (c) Kenneth Reitz and individual contributors. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = py26,py27,pypy,py33,py34,py35,py36,docs,pep8,py2pep8 3 | 4 | [testenv] 5 | deps = 6 | coverage 7 | pytest 8 | commands = 9 | python -m coverage run --source pipfile/ -m pytest --strict {posargs} 10 | python -m coverage report -m --fail-under 100 11 | 12 | # Python 2.6 doesn't support python -m on a package. 13 | [testenv:py26] 14 | commands = 15 | python -m coverage.__main__ run --source pipfile/ -m pytest --strict {posargs} 16 | python -m coverage.__main__ report -m --fail-under 100 17 | 18 | [testenv:pypy] 19 | commands = 20 | py.test --capture=no --strict {posargs} 21 | 22 | [testenv:docs] 23 | deps = 24 | sphinx 25 | sphinx_rtd_theme 26 | commands = 27 | sphinx-build -W -b html -d {envtmpdir}/doctrees docs docs/_build/html 28 | sphinx-build -W -b latex -d {envtmpdir}/doctrees docs docs/_build/latex 29 | sphinx-build -W -b doctest -d {envtmpdir}/doctrees docs docs/_build/html 30 | 31 | [testenv:pep8] 32 | basepython = python3.3 33 | deps = 34 | flake8 35 | pep8-naming 36 | commands = flake8 . 37 | 38 | [testenv:py2pep8] 39 | basepython = python2.6 40 | deps = 41 | flake8 42 | pep8-naming 43 | commands = flake8 . 44 | 45 | [testenv:packaging] 46 | deps = 47 | check-manifest 48 | readme_renderer 49 | commands = 50 | check-manifest 51 | python setup.py check --metadata --restructuredtext --strict 52 | 53 | [flake8] 54 | exclude = .tox,*.egg 55 | select = E,W,F,N 56 | -------------------------------------------------------------------------------- /tests/test_parser.py: -------------------------------------------------------------------------------- 1 | import json 2 | import os 3 | from unittest import TestCase, mock 4 | 5 | from pipfile.api import PipfileParser 6 | 7 | 8 | class TestEnvVarInsertion(TestCase): 9 | 10 | def setUp(self): 11 | self.p = PipfileParser() 12 | 13 | @staticmethod 14 | def example_dict(key): 15 | return { 16 | "a_string": "https://$%s@something.com" % key, 17 | "another_string": "https://${%s}@something.com" % key, 18 | "nested": { 19 | "a_string": "https://$%s@something.com" % key, 20 | "another_string": "${%s}" % key, 21 | }, 22 | "list": [ 23 | { 24 | "a_string": "https://$%s@something.com" % key, 25 | "another_string": "${%s}" % key, 26 | }, 27 | {}, 28 | ], 29 | "bool": True, 30 | "none": None, 31 | } 32 | 33 | @mock.patch.dict(os.environ, {'FOO': 'BAR'}) 34 | def test_correctly_inserts_env_vars(self): 35 | parsed_dict = self.p.inject_environment_variables(self.example_dict('FOO')) 36 | 37 | self.assertEqual(parsed_dict["a_string"], "https://BAR@something.com") 38 | self.assertEqual(parsed_dict["another_string"], "https://BAR@something.com") 39 | self.assertEqual(parsed_dict["nested"]["another_string"], "BAR") 40 | self.assertEqual(parsed_dict["list"][0]["a_string"], "https://BAR@something.com") 41 | self.assertEqual(parsed_dict["list"][1], {}) 42 | self.assertTrue(parsed_dict["bool"]) 43 | self.assertIsNone(parsed_dict["none"]) 44 | 45 | @mock.patch.dict(os.environ, {}) 46 | def test_leaves_values_intact_if_no_var_exists(self): 47 | d = self.example_dict('FOO') 48 | 49 | raw = json.dumps(d) 50 | parsed = json.dumps(self.p.inject_environment_variables(d)) 51 | 52 | self.assertEqual(raw, parsed) 53 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # This file is dual licensed under the terms of the Apache License, Version 3 | # 2.0, and the BSD License. See the LICENSE file in the root of this repository 4 | # for complete details. 5 | from __future__ import absolute_import, division, print_function 6 | 7 | import os 8 | import re 9 | 10 | from setuptools import setup 11 | 12 | 13 | base_dir = os.path.dirname(__file__) 14 | 15 | about = {} 16 | with open(os.path.join(base_dir, "pipfile", "__about__.py")) as f: 17 | exec(f.read(), about) 18 | 19 | with open(os.path.join(base_dir, "README.rst")) as f: 20 | long_description = f.read() 21 | 22 | with open(os.path.join(base_dir, "CHANGELOG.rst")) as f: 23 | # Remove :issue:`ddd` tags that breaks the description rendering 24 | changelog = re.sub( 25 | r":issue:`(\d+)`", 26 | r"`#\1 `__", 27 | f.read(), 28 | ) 29 | long_description = "\n".join([long_description, changelog]) 30 | 31 | 32 | setup( 33 | name=about["__title__"], 34 | version=about["__version__"], 35 | 36 | description=about["__summary__"], 37 | long_description=long_description, 38 | license=about["__license__"], 39 | url=about["__uri__"], 40 | 41 | author=about["__author__"], 42 | author_email=about["__email__"], 43 | 44 | install_requires=['toml'], 45 | 46 | classifiers=[ 47 | "Intended Audience :: Developers", 48 | 49 | "License :: OSI Approved :: Apache Software License", 50 | "License :: OSI Approved :: BSD License", 51 | 52 | "Programming Language :: Python", 53 | "Programming Language :: Python :: 2", 54 | "Programming Language :: Python :: 2.6", 55 | "Programming Language :: Python :: 2.7", 56 | "Programming Language :: Python :: 3", 57 | "Programming Language :: Python :: 3.3", 58 | "Programming Language :: Python :: 3.4", 59 | "Programming Language :: Python :: 3.5", 60 | "Programming Language :: Python :: 3.6", 61 | ], 62 | 63 | packages=[ 64 | "pipfile", 65 | ], 66 | ) 67 | -------------------------------------------------------------------------------- /docs/development/getting-started.rst: -------------------------------------------------------------------------------- 1 | Getting started 2 | =============== 3 | 4 | Working on pipfile requires the installation of a small number of 5 | development dependencies. These are listed in ``dev-requirements.txt`` and they 6 | can be installed in a `virtualenv`_ using `pip`_. Once you've installed the 7 | dependencies, install packaging in ``editable`` mode. For example: 8 | 9 | .. code-block:: console 10 | 11 | $ # Create a virtualenv and activate it 12 | $ pip install --requirement dev-requirements.txt 13 | $ pip install --editable . 14 | 15 | You are now ready to run the tests and build the documentation. 16 | 17 | Running tests 18 | ~~~~~~~~~~~~~ 19 | 20 | packaging unit tests are found in the ``tests/`` directory and are 21 | designed to be run using `pytest`_. `pytest`_ will discover the tests 22 | automatically, so all you have to do is: 23 | 24 | .. code-block:: console 25 | 26 | $ py.test 27 | ... 28 | 62746 passed in 220.43 seconds 29 | 30 | This runs the tests with the default Python interpreter. 31 | 32 | You can also verify that the tests pass on other supported Python interpreters. 33 | For this we use `tox`_, which will automatically create a `virtualenv`_ for 34 | each supported Python version and run the tests. For example: 35 | 36 | .. code-block:: console 37 | 38 | $ tox 39 | ... 40 | ERROR: py26: InterpreterNotFound: python2.6 41 | py27: commands succeeded 42 | ERROR: pypy: InterpreterNotFound: pypy 43 | ERROR: py33: InterpreterNotFound: python3.3 44 | py34: commands succeeded 45 | py35: commands succeeded 46 | py36: commands succeeded 47 | docs: commands succeeded 48 | pep8: commands succeeded 49 | 50 | You may not have all the required Python versions installed, in which case you 51 | will see one or more ``InterpreterNotFound`` errors. 52 | 53 | 54 | Building documentation 55 | ~~~~~~~~~~~~~~~~~~~~~~ 56 | 57 | packaging documentation is stored in the ``docs/`` directory. It is 58 | written in `reStructured Text`_ and rendered using `Sphinx`_. 59 | 60 | Use `tox`_ to build the documentation. For example: 61 | 62 | .. code-block:: console 63 | 64 | $ tox -e docs 65 | ... 66 | docs: commands succeeded 67 | congratulations :) 68 | 69 | The HTML documentation index can now be found at 70 | ``docs/_build/html/index.html``. 71 | 72 | .. _`pytest`: https://pypi.python.org/pypi/pytest 73 | .. _`tox`: https://pypi.python.org/pypi/tox 74 | .. _`virtualenv`: https://pypi.python.org/pypi/virtualenv 75 | .. _`pip`: https://pypi.python.org/pypi/pip 76 | .. _`sphinx`: https://pypi.python.org/pypi/Sphinx 77 | .. _`reStructured Text`: http://sphinx-doc.org/rest.html 78 | -------------------------------------------------------------------------------- /docs/development/submitting-patches.rst: -------------------------------------------------------------------------------- 1 | Submitting patches 2 | ================== 3 | 4 | * Always make a new branch for your work. 5 | * Patches should be small to facilitate easier review. `Studies have shown`_ 6 | that review quality falls off as patch size grows. Sometimes this will result 7 | in many small PRs to land a single large feature. 8 | * Larger changes should be discussed in a ticket before submission. 9 | * New features and significant bug fixes should be documented in the 10 | :doc:`/changelog`. 11 | * You must have legal permission to distribute any code you contribute and it 12 | must be available under both the BSD and Apache Software License Version 2.0 13 | licenses. 14 | 15 | If you believe you've identified a security issue in packaging, please 16 | follow the directions on the :doc:`security page `. 17 | 18 | Code 19 | ---- 20 | 21 | When in doubt, refer to :pep:`8` for Python code. You can check if your code 22 | meets our automated requirements by running ``flake8`` against it. If you've 23 | installed the development requirements this will automatically use our 24 | configuration. You can also run the ``tox`` job with ``tox -e pep8``. 25 | 26 | `Write comments as complete sentences.`_ 27 | 28 | Every code file must start with the boilerplate licensing notice: 29 | 30 | .. code-block:: python 31 | 32 | # This file is dual licensed under the terms of the Apache License, Version 33 | # 2.0, and the BSD License. See the LICENSE file in the root of this repository 34 | # for complete details. 35 | 36 | Additionally, every Python code file must contain 37 | 38 | .. code-block:: python 39 | 40 | from __future__ import absolute_import, division, print_function 41 | 42 | 43 | Tests 44 | ----- 45 | 46 | All code changes must be accompanied by unit tests with 100% code coverage (as 47 | measured by the combined metrics across our build matrix). 48 | 49 | 50 | Documentation 51 | ------------- 52 | 53 | All features should be documented with prose in the ``docs`` section. 54 | 55 | When referring to a hypothetical individual (such as "a person receiving an 56 | encrypted message") use gender neutral pronouns (they/them/their). 57 | 58 | Docstrings are typically only used when writing abstract classes, but should 59 | be written like this if required: 60 | 61 | .. code-block:: python 62 | 63 | def some_function(some_arg): 64 | """ 65 | Does some things. 66 | 67 | :param some_arg: Some argument. 68 | """ 69 | 70 | So, specifically: 71 | 72 | * Always use three double quotes. 73 | * Put the three double quotes on their own line. 74 | * No blank line at the end. 75 | * Use Sphinx parameter/attribute documentation `syntax`_. 76 | 77 | 78 | .. _`Write comments as complete sentences.`: http://nedbatchelder.com/blog/201401/comments_should_be_sentences.html 79 | .. _`syntax`: http://sphinx-doc.org/domains.html#info-field-lists 80 | .. _`Studies have shown`: http://www.ibm.com/developerworks/rational/library/11-proven-practices-for-peer-review/ 81 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # This file is dual licensed under the terms of the Apache License, Version 3 | # 2.0, and the BSD License. See the LICENSE file in the root of this repository 4 | # for complete details. 5 | from __future__ import absolute_import, division, print_function 6 | 7 | import os 8 | import sys 9 | 10 | try: 11 | import sphinx_rtd_theme 12 | except ImportError: 13 | sphinx_rtd_theme = None 14 | 15 | # If extensions (or modules to document with autodoc) are in another directory, 16 | # add these directories to sys.path here. If the directory is relative to the 17 | # documentation root, use os.path.abspath to make it absolute, like shown here. 18 | sys.path.insert(0, os.path.abspath(".")) 19 | 20 | # -- General configuration ---------------------------------------------------- 21 | 22 | # Add any Sphinx extension module names here, as strings. They can be 23 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. 24 | extensions = [ 25 | "sphinx.ext.autodoc", 26 | "sphinx.ext.doctest", 27 | "sphinx.ext.extlinks", 28 | "sphinx.ext.intersphinx", 29 | "sphinx.ext.viewcode", 30 | ] 31 | 32 | # Add any paths that contain templates here, relative to this directory. 33 | templates_path = ["_templates"] 34 | 35 | # The suffix of source filenames. 36 | source_suffix = ".rst" 37 | 38 | # The master toctree document. 39 | master_doc = "index" 40 | 41 | # General information about the project. 42 | project = "pipfile" 43 | copyright = "2016 Donald Stufft and individual contributors" 44 | 45 | # The version info for the project you're documenting, acts as replacement for 46 | # |version| and |release|, also used in various other places throughout the 47 | # built documents. 48 | # 49 | 50 | base_dir = os.path.join(os.path.dirname(__file__), os.pardir) 51 | about = {} 52 | with open(os.path.join(base_dir, "pipfile", "__about__.py")) as f: 53 | exec(f.read(), about) 54 | 55 | version = release = about["__version__"] 56 | 57 | # List of patterns, relative to source directory, that match files and 58 | # directories to ignore when looking for source files. 59 | exclude_patterns = ["_build"] 60 | 61 | # The name of the Pygments (syntax highlighting) style to use. 62 | pygments_style = "sphinx" 63 | 64 | extlinks = { 65 | 'issue': ('https://github.com/pypa/pipfile/issues/%s', '#'), 66 | 'pull': ('https://github.com/pypa/pipfile/pull/%s', 'PR #'), 67 | } 68 | # -- Options for HTML output -------------------------------------------------- 69 | 70 | # The theme to use for HTML and HTML Help pages. See the documentation for 71 | # a list of builtin themes. 72 | 73 | if sphinx_rtd_theme: 74 | html_theme = "sphinx_rtd_theme" 75 | html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] 76 | else: 77 | html_theme = "default" 78 | 79 | # Add any paths that contain custom static files (such as style sheets) here, 80 | # relative to this directory. They are copied after the builtin static files, 81 | # so a file named "default.css" will overwrite the builtin "default.css". 82 | html_static_path = ["_static"] 83 | 84 | # Output file base name for HTML help builder. 85 | htmlhelp_basename = "pipfiledoc" 86 | 87 | 88 | # -- Options for LaTeX output ------------------------------------------------- 89 | 90 | latex_elements = { 91 | } 92 | 93 | # Grouping the document tree into LaTeX files. List of tuples 94 | # (source start file, target name, title, author, documentclass [howto/manual]) 95 | latex_documents = [ 96 | ( 97 | "index", 98 | "Pipfile.tex", 99 | "Pipfile Documentation", 100 | "Donald Stufft", 101 | "manual", 102 | ), 103 | ] 104 | 105 | # -- Options for manual page output ------------------------------------------- 106 | 107 | # One entry per manual page. List of tuples 108 | # (source start file, name, description, authors, manual section). 109 | man_pages = [ 110 | ( 111 | "index", 112 | "pipfile", 113 | "Pipfile Documentation", 114 | ["Donald Stufft"], 115 | 1, 116 | ) 117 | ] 118 | 119 | # -- Options for Texinfo output ----------------------------------------------- 120 | 121 | # Grouping the document tree into Texinfo files. List of tuples 122 | # (source start file, target name, title, author, 123 | # dir menu entry, description, category) 124 | texinfo_documents = [ 125 | ( 126 | "index", 127 | "pipfile", 128 | "Pipfile Documentation", 129 | "Donald Stufft", 130 | "pipfile", 131 | "Core utilities for Python packages", 132 | "Miscellaneous", 133 | ), 134 | ] 135 | 136 | # Example configuration for intersphinx: refer to the Python standard library. 137 | intersphinx_mapping = { 138 | "http://docs.python.org/": None, 139 | } 140 | 141 | epub_theme = "epub" 142 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = _build 9 | 10 | # Internal variables. 11 | PAPEROPT_a4 = -D latex_paper_size=a4 12 | PAPEROPT_letter = -D latex_paper_size=letter 13 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 14 | # the i18n builder cannot share the environment and doctrees with the others 15 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 16 | 17 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext 18 | 19 | help: 20 | @echo "Please use \`make ' where is one of" 21 | @echo " html to make standalone HTML files" 22 | @echo " dirhtml to make HTML files named index.html in directories" 23 | @echo " singlehtml to make a single large HTML file" 24 | @echo " pickle to make pickle files" 25 | @echo " json to make JSON files" 26 | @echo " htmlhelp to make HTML files and a HTML help project" 27 | @echo " qthelp to make HTML files and a qthelp project" 28 | @echo " devhelp to make HTML files and a Devhelp project" 29 | @echo " epub to make an epub" 30 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 31 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 32 | @echo " text to make text files" 33 | @echo " man to make manual pages" 34 | @echo " texinfo to make Texinfo files" 35 | @echo " info to make Texinfo files and run them through makeinfo" 36 | @echo " gettext to make PO message catalogs" 37 | @echo " changes to make an overview of all changed/added/deprecated items" 38 | @echo " linkcheck to check all external links for integrity" 39 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 40 | 41 | clean: 42 | -rm -rf $(BUILDDIR)/* 43 | 44 | html: 45 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 46 | @echo 47 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 48 | 49 | dirhtml: 50 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 51 | @echo 52 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 53 | 54 | singlehtml: 55 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 56 | @echo 57 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 58 | 59 | pickle: 60 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 61 | @echo 62 | @echo "Build finished; now you can process the pickle files." 63 | 64 | json: 65 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 66 | @echo 67 | @echo "Build finished; now you can process the JSON files." 68 | 69 | htmlhelp: 70 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 71 | @echo 72 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 73 | ".hhp project file in $(BUILDDIR)/htmlhelp." 74 | 75 | qthelp: 76 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 77 | @echo 78 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 79 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 80 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/pipfile.qhcp" 81 | @echo "To view the help file:" 82 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/pipfile.qhc" 83 | 84 | devhelp: 85 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 86 | @echo 87 | @echo "Build finished." 88 | @echo "To view the help file:" 89 | @echo "# mkdir -p $$HOME/.local/share/devhelp/pipfile" 90 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/pipfile" 91 | @echo "# devhelp" 92 | 93 | epub: 94 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 95 | @echo 96 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 97 | 98 | latex: 99 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 100 | @echo 101 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 102 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 103 | "(use \`make latexpdf' here to do that automatically)." 104 | 105 | latexpdf: 106 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 107 | @echo "Running LaTeX files through pdflatex..." 108 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 109 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 110 | 111 | text: 112 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 113 | @echo 114 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 115 | 116 | man: 117 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 118 | @echo 119 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 120 | 121 | texinfo: 122 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 123 | @echo 124 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 125 | @echo "Run \`make' in that directory to run these through makeinfo" \ 126 | "(use \`make info' here to do that automatically)." 127 | 128 | info: 129 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 130 | @echo "Running Texinfo files through makeinfo..." 131 | make -C $(BUILDDIR)/texinfo info 132 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 133 | 134 | gettext: 135 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 136 | @echo 137 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 138 | 139 | changes: 140 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 141 | @echo 142 | @echo "The overview file is in $(BUILDDIR)/changes." 143 | 144 | linkcheck: 145 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 146 | @echo 147 | @echo "Link check complete; look for any errors in the above output " \ 148 | "or in $(BUILDDIR)/linkcheck/output.txt." 149 | 150 | doctest: 151 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 152 | @echo "Testing of doctests in the sources finished, look at the " \ 153 | "results in $(BUILDDIR)/doctest/output.txt." 154 | -------------------------------------------------------------------------------- /pipfile/api.py: -------------------------------------------------------------------------------- 1 | import toml 2 | 3 | import codecs 4 | import json 5 | import hashlib 6 | import platform 7 | import sys 8 | import os 9 | 10 | 11 | def format_full_version(info): 12 | version = '{0.major}.{0.minor}.{0.micro}'.format(info) 13 | kind = info.releaselevel 14 | if kind != 'final': 15 | version += kind[0] + str(info.serial) 16 | return version 17 | 18 | 19 | 20 | class PipfileParser(object): 21 | def __init__(self, filename='Pipfile'): 22 | self.filename = filename 23 | self.sources = [] 24 | self.groups = { 25 | 'default': [], 26 | 'develop': [] 27 | } 28 | self.group_stack = ['default'] 29 | self.requirements = [] 30 | 31 | def __repr__(self): 32 | return ''.format(self.filename) 33 | 34 | def inject_environment_variables(self, d): 35 | """ 36 | Recursively injects environment variables into TOML values 37 | """ 38 | 39 | if not d: 40 | return d 41 | 42 | for k, v in d.items(): 43 | if isinstance(v, str): 44 | d[k] = os.path.expandvars(v) 45 | elif isinstance(v, dict): 46 | d[k] = self.inject_environment_variables(v) 47 | elif isinstance(v, list): 48 | d[k] = [self.inject_environment_variables(e) for e in v] 49 | 50 | return d 51 | 52 | def parse(self): 53 | # Open the Pipfile. 54 | with open(self.filename) as f: 55 | content = f.read() 56 | 57 | # Load the default configuration. 58 | default_config = { 59 | u'source': [{u'url': u'https://pypi.python.org/simple', u'verify_ssl': True, 'name': "pypi"}], 60 | u'packages': {}, 61 | u'requires': {}, 62 | u'dev-packages': {} 63 | } 64 | 65 | config = {} 66 | config.update(default_config) 67 | 68 | # Deserialize the TOML, and parse for Environment Variables 69 | parsed_toml = self.inject_environment_variables(toml.loads(content)) 70 | 71 | # Load the Pipfile's configuration. 72 | config.update(parsed_toml) 73 | 74 | # Structure the data for output. 75 | data = { 76 | '_meta': { 77 | 'sources': config['source'], 78 | 'requires': config['requires'] 79 | }, 80 | } 81 | 82 | # TODO: Validate given data here. 83 | self.groups['default'] = config['packages'] 84 | self.groups['develop'] = config['dev-packages'] 85 | 86 | # Update the data structure with group information. 87 | data.update(self.groups) 88 | return data 89 | 90 | 91 | class Pipfile(object): 92 | def __init__(self, filename): 93 | super(Pipfile, self).__init__() 94 | self.filename = filename 95 | self.data = None 96 | 97 | @staticmethod 98 | def find(max_depth=3): 99 | """Returns the path of a Pipfile in parent directories.""" 100 | i = 0 101 | for c, d, f in os.walk(os.getcwd(), topdown=False): 102 | if i > max_depth: 103 | raise RuntimeError('No Pipfile found!') 104 | elif 'Pipfile' in f: 105 | return os.path.join(c, 'Pipfile') 106 | i += 1 107 | 108 | @classmethod 109 | def load(klass, filename): 110 | """Load a Pipfile from a given filename.""" 111 | p = PipfileParser(filename=filename) 112 | pipfile = klass(filename=filename) 113 | pipfile.data = p.parse() 114 | return pipfile 115 | 116 | @property 117 | def hash(self): 118 | """Returns the SHA256 of the pipfile's data.""" 119 | content = json.dumps(self.data, sort_keys=True, separators=(",", ":")) 120 | return hashlib.sha256(content.encode("utf8")).hexdigest() 121 | 122 | @property 123 | def contents(self): 124 | """Returns the contents of the pipfile.""" 125 | with codecs.open(self.filename, 'r', 'utf-8') as f: 126 | return f.read() 127 | 128 | def lock(self): 129 | """Returns a JSON representation of the Pipfile.""" 130 | data = self.data 131 | data['_meta']['hash'] = {"sha256": self.hash} 132 | data['_meta']['pipfile-spec'] = 6 133 | return json.dumps(data, indent=4, separators=(',', ': ')) 134 | 135 | def assert_requirements(self): 136 | """"Asserts PEP 508 specifiers.""" 137 | 138 | # Support for 508's implementation_version. 139 | if hasattr(sys, 'implementation'): 140 | implementation_version = format_full_version(sys.implementation.version) 141 | else: 142 | implementation_version = "0" 143 | 144 | # Default to cpython for 2.7. 145 | if hasattr(sys, 'implementation'): 146 | implementation_name = sys.implementation.name 147 | else: 148 | implementation_name = 'cpython' 149 | 150 | lookup = { 151 | 'os_name': os.name, 152 | 'sys_platform': sys.platform, 153 | 'platform_machine': platform.machine(), 154 | 'platform_python_implementation': platform.python_implementation(), 155 | 'platform_release': platform.release(), 156 | 'platform_system': platform.system(), 157 | 'platform_version': platform.version(), 158 | 'python_version': platform.python_version()[:3], 159 | 'python_full_version': platform.python_version(), 160 | 'implementation_name': implementation_name, 161 | 'implementation_version': implementation_version 162 | } 163 | 164 | # Assert each specified requirement. 165 | for marker, specifier in self.data['_meta']['requires'].items(): 166 | 167 | if marker in lookup: 168 | try: 169 | assert lookup[marker] == specifier 170 | except AssertionError: 171 | raise AssertionError('Specifier {!r} does not match {!r}.'.format(marker, specifier)) 172 | 173 | 174 | def load(pipfile_path=None): 175 | """Loads a pipfile from a given path. 176 | If none is provided, one will try to be found. 177 | """ 178 | 179 | if pipfile_path is None: 180 | pipfile_path = Pipfile.find() 181 | 182 | return Pipfile.load(filename=pipfile_path) 183 | -------------------------------------------------------------------------------- /LICENSE.APACHE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS -------------------------------------------------------------------------------- /examples/Pipfile.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_meta": { 3 | "hash": { 4 | "sha256": "e34c3a87a1be2067ce73dbe50cae2e971a0190f15e361c32c82371256b2045b2" 5 | }, 6 | "pipfile-spec": 6, 7 | "requires": { 8 | "python_version": "3.6" 9 | }, 10 | "sources": [ 11 | { 12 | "name": "pypi", 13 | "url": "https://pypi.python.org/simple", 14 | "verify_ssl": true 15 | } 16 | ] 17 | }, 18 | "default": { 19 | "certifi": { 20 | "hashes": [ 21 | "sha256:1d987a998c75633c40847cc966fcf5904906c920a7f17ef374f5aa4282abd304", 22 | "sha256:51fcb31174be6e6664c5f69e3e1691a2d72a1a12e90f872cbdb1567eb47b6519" 23 | ], 24 | "version": "==2020.4.5.1" 25 | }, 26 | "chardet": { 27 | "hashes": [ 28 | "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", 29 | "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" 30 | ], 31 | "version": "==3.0.4" 32 | }, 33 | "django": { 34 | "editable": true, 35 | "git": "https://github.com/django/django.git", 36 | "ref": "1a34dfcf797640d5d580d261694cb54e6f97c552" 37 | }, 38 | "docopt": { 39 | "hashes": [ 40 | "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491" 41 | ], 42 | "version": "==0.6.2" 43 | }, 44 | "e1839a8": { 45 | "editable": true, 46 | "path": "." 47 | }, 48 | "e682b37": { 49 | "file": "https://github.com/divio/django-cms/archive/release/3.4.x.zip" 50 | }, 51 | "et-xmlfile": { 52 | "hashes": [ 53 | "sha256:614d9722d572f6246302c4491846d2c393c199cfa4edc9af593437691683335b" 54 | ], 55 | "version": "==1.0.1" 56 | }, 57 | "idna": { 58 | "hashes": [ 59 | "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb", 60 | "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa" 61 | ], 62 | "version": "==2.9" 63 | }, 64 | "jdcal": { 65 | "hashes": [ 66 | "sha256:1abf1305fce18b4e8aa248cf8fe0c56ce2032392bc64bbd61b5dff2a19ec8bba", 67 | "sha256:472872e096eb8df219c23f2689fc336668bdb43d194094b5cc1707e1640acfc8" 68 | ], 69 | "version": "==1.4.1" 70 | }, 71 | "lxml": { 72 | "hashes": [ 73 | "sha256:06d4e0bbb1d62e38ae6118406d7cdb4693a3fa34ee3762238bcb96c9e36a93cd", 74 | "sha256:0701f7965903a1c3f6f09328c1278ac0eee8f56f244e66af79cb224b7ef3801c", 75 | "sha256:1f2c4ec372bf1c4a2c7e4bb20845e8bcf8050365189d86806bad1e3ae473d081", 76 | "sha256:4235bc124fdcf611d02047d7034164897ade13046bda967768836629bc62784f", 77 | "sha256:5828c7f3e615f3975d48f40d4fe66e8a7b25f16b5e5705ffe1d22e43fb1f6261", 78 | "sha256:585c0869f75577ac7a8ff38d08f7aac9033da2c41c11352ebf86a04652758b7a", 79 | "sha256:5d467ce9c5d35b3bcc7172c06320dddb275fea6ac2037f72f0a4d7472035cea9", 80 | "sha256:63dbc21efd7e822c11d5ddbedbbb08cd11a41e0032e382a0fd59b0b08e405a3a", 81 | "sha256:7bc1b221e7867f2e7ff1933165c0cec7153dce93d0cdba6554b42a8beb687bdb", 82 | "sha256:8620ce80f50d023d414183bf90cc2576c2837b88e00bea3f33ad2630133bbb60", 83 | "sha256:8a0ebda56ebca1a83eb2d1ac266649b80af8dd4b4a3502b2c1e09ac2f88fe128", 84 | "sha256:90ed0e36455a81b25b7034038e40880189169c308a3df360861ad74da7b68c1a", 85 | "sha256:95e67224815ef86924fbc2b71a9dbd1f7262384bca4bc4793645794ac4200717", 86 | "sha256:afdb34b715daf814d1abea0317b6d672476b498472f1e5aacbadc34ebbc26e89", 87 | "sha256:b4b2c63cc7963aedd08a5f5a454c9f67251b1ac9e22fd9d72836206c42dc2a72", 88 | "sha256:d068f55bda3c2c3fcaec24bd083d9e2eede32c583faf084d6e4b9daaea77dde8", 89 | "sha256:d5b3c4b7edd2e770375a01139be11307f04341ec709cf724e0f26ebb1eef12c3", 90 | "sha256:deadf4df349d1dcd7b2853a2c8796593cc346600726eff680ed8ed11812382a7", 91 | "sha256:df533af6f88080419c5a604d0d63b2c33b1c0c4409aba7d0cb6de305147ea8c8", 92 | "sha256:e4aa948eb15018a657702fee0b9db47e908491c64d36b4a90f59a64741516e77", 93 | "sha256:e5d842c73e4ef6ed8c1bd77806bf84a7cb535f9c0cf9b2c74d02ebda310070e1", 94 | "sha256:ebec08091a22c2be870890913bdadd86fcd8e9f0f22bcb398abd3af914690c15", 95 | "sha256:edc15fcfd77395e24543be48871c251f38132bb834d9fdfdad756adb6ea37679", 96 | "sha256:f2b74784ed7e0bc2d02bd53e48ad6ba523c9b36c194260b7a5045071abbb1012", 97 | "sha256:fa071559f14bd1e92077b1b5f6c22cf09756c6de7139370249eb372854ce51e6", 98 | "sha256:fd52e796fee7171c4361d441796b64df1acfceb51f29e545e812f16d023c4bbc", 99 | "sha256:fe976a0f1ef09b3638778024ab9fb8cde3118f203364212c198f71341c0715ca" 100 | ], 101 | "version": "==4.5.0" 102 | }, 103 | "openpyxl": { 104 | "hashes": [ 105 | "sha256:626d38647c063d55803ef4971c4d43226538d4e95cb6260c094e363ee33e10c7" 106 | ], 107 | "version": "==2.4.11" 108 | }, 109 | "pysocks": { 110 | "hashes": [ 111 | "sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299", 112 | "sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5", 113 | "sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0" 114 | ], 115 | "version": "==1.7.1" 116 | }, 117 | "pytz": { 118 | "hashes": [ 119 | "sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed", 120 | "sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048" 121 | ], 122 | "version": "==2020.1" 123 | }, 124 | "pywinusb": { 125 | "hashes": [ 126 | "sha256:e2f5e89f7b74239ca4843721a9bda0fc99014750630c189a176ec0e1b35e86df" 127 | ], 128 | "index": "pypi", 129 | "markers": "os_name == 'nt'", 130 | "version": "==0.4.2" 131 | }, 132 | "records": { 133 | "hashes": [ 134 | "sha256:47e4874096f4a8f4b5bcad8c7c7cf512be36186e6e263ff3dfd750b05ff0d3c4", 135 | "sha256:cdbacf52c61b4a3bc10fef1286a24a63ae95255a2e7b4e8ccb1e1f96737231ed" 136 | ], 137 | "index": "pypi", 138 | "version": "==0.5.3" 139 | }, 140 | "requests": { 141 | "extras": [ 142 | "socks" 143 | ], 144 | "hashes": [ 145 | "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee", 146 | "sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6" 147 | ], 148 | "index": "pypi", 149 | "version": "==2.23.0" 150 | }, 151 | "sqlalchemy": { 152 | "hashes": [ 153 | "sha256:128bc917ed20d78143a45024455ff0aed7d3b96772eba13d5dbaf9cc57e5c41b", 154 | "sha256:156a27548ba4e1fed944ff9fcdc150633e61d350d673ae7baaf6c25c04ac1f71", 155 | "sha256:27e2efc8f77661c9af2681755974205e7462f1ae126f498f4fe12a8b24761d15", 156 | "sha256:2a12f8be25b9ea3d1d5b165202181f2b7da4b3395289000284e5bb86154ce87c", 157 | "sha256:31c043d5211aa0e0773821fcc318eb5cbe2ec916dfbc4c6eea0c5188971988eb", 158 | "sha256:65eb3b03229f684af0cf0ad3bcc771970c1260a82a791a8d07bffb63d8c95bcc", 159 | "sha256:6cd157ce74a911325e164441ff2d9b4e244659a25b3146310518d83202f15f7a", 160 | "sha256:703c002277f0fbc3c04d0ae4989a174753a7554b2963c584ce2ec0cddcf2bc53", 161 | "sha256:869bbb637de58ab0a912b7f20e9192132f9fbc47fc6b5111cd1e0f6cdf5cf9b0", 162 | "sha256:8a0e0cd21da047ea10267c37caf12add400a92f0620c8bc09e4a6531a765d6d7", 163 | "sha256:8d01e949a5d22e5c4800d59b50617c56125fc187fbeb8fa423e99858546de616", 164 | "sha256:925b4fe5e7c03ed76912b75a9a41dfd682d59c0be43bce88d3b27f7f5ba028fb", 165 | "sha256:9cb1819008f0225a7c066cac8bb0cf90847b2c4a6eb9ebb7431dbd00c56c06c5", 166 | "sha256:a87d496884f40c94c85a647c385f4fd5887941d2609f71043e2b73f2436d9c65", 167 | "sha256:a9030cd30caf848a13a192c5e45367e3c6f363726569a56e75dc1151ee26d859", 168 | "sha256:a9e75e49a0f1583eee0ce93270232b8e7bb4b1edc89cc70b07600d525aef4f43", 169 | "sha256:b50f45d0e82b4562f59f0e0ca511f65e412f2a97d790eea5f60e34e5f1aabc9a", 170 | "sha256:b7878e59ec31f12d54b3797689402ee3b5cfcb5598f2ebf26491732758751908", 171 | "sha256:ce1ddaadee913543ff0154021d31b134551f63428065168e756d90bdc4c686f5", 172 | "sha256:ce2646e4c0807f3461be0653502bb48c6e91a5171d6e450367082c79e12868bf", 173 | "sha256:ce6c3d18b2a8ce364013d47b9cad71db815df31d55918403f8db7d890c9d07ae", 174 | "sha256:e4e2664232005bd306f878b0f167a31f944a07c4de0152c444f8c61bbe3cfb38", 175 | "sha256:e8aa395482728de8bdcca9cc0faf3765ab483e81e01923aaa736b42f0294f570", 176 | "sha256:eb4fcf7105bf071c71068c6eee47499ab8d4b8f5a11fc35147c934f0faa60f23", 177 | "sha256:ed375a79f06cad285166e5be74745df1ed6845c5624aafadec4b7a29c25866ef", 178 | "sha256:f35248f7e0d63b234a109dd72fbfb4b5cb6cb6840b221d0df0ecbf54ab087654", 179 | "sha256:f502ef245c492b391e0e23e94cba030ab91722dcc56963c85bfd7f3441ea2bbe", 180 | "sha256:fe01bac7226499aedf472c62fa3b85b2c619365f3f14dd222ffe4f3aa91e5f98" 181 | ], 182 | "markers": "python_version >= '3.0'", 183 | "version": "==1.3.17" 184 | }, 185 | "tablib": { 186 | "hashes": [ 187 | "sha256:4d1909aa3ff1c85ba97ad16176c0aeec33c8e894dc7ea6f10f2dd44701e99ba7", 188 | "sha256:80f6c3453431cedf1125f23d16b3d96b92b426495714ebf0b4dede1fa75b447d" 189 | ], 190 | "version": "==1.1.0" 191 | }, 192 | "urllib3": { 193 | "hashes": [ 194 | "sha256:3018294ebefce6572a474f0604c2021e33b3fd8006ecd11d62107a5d2a963527", 195 | "sha256:88206b0eb87e6d677d424843ac5209e3fb9d0190d0ee169599165ec25e9d9115" 196 | ], 197 | "version": "==1.25.9" 198 | } 199 | }, 200 | "develop": { 201 | "argparse": { 202 | "hashes": [ 203 | "sha256:62b089a55be1d8949cd2bc7e0df0bddb9e028faefc8c32038cc84862aefdd6e4", 204 | "sha256:c31647edb69fd3d465a847ea3157d37bed1f95f19760b11a47aa91c04b666314" 205 | ], 206 | "version": "==1.4.0" 207 | }, 208 | "linecache2": { 209 | "hashes": [ 210 | "sha256:4b26ff4e7110db76eeb6f5a7b64a82623839d595c2038eeda662f2a2db78e97c", 211 | "sha256:e78be9c0a0dfcbac712fe04fbf92b96cddae80b1b842f24248214c8496f006ef" 212 | ], 213 | "version": "==1.0.0" 214 | }, 215 | "nose": { 216 | "hashes": [ 217 | "sha256:9ff7c6cc443f8c51994b34a667bbcf45afd6d945be7477b52e97516fd17c53ac", 218 | "sha256:dadcddc0aefbf99eea214e0f1232b94f2fa9bd98fa8353711dacb112bfcbbb2a", 219 | "sha256:f1bffef9cbc82628f6e7d7b40d7e255aefaa1adb6a1b1d26c69a8b79e6208a98" 220 | ], 221 | "index": "pypi", 222 | "version": "==1.3.7" 223 | }, 224 | "six": { 225 | "hashes": [ 226 | "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a", 227 | "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c" 228 | ], 229 | "version": "==1.14.0" 230 | }, 231 | "traceback2": { 232 | "hashes": [ 233 | "sha256:05acc67a09980c2ecfedd3423f7ae0104839eccb55fc645773e1caa0951c3030", 234 | "sha256:8253cebec4b19094d67cc5ed5af99bf1dba1285292226e98a31929f87a5d6b23" 235 | ], 236 | "version": "==1.4.0" 237 | }, 238 | "unittest2": { 239 | "hashes": [ 240 | "sha256:13f77d0875db6d9b435e1d4f41e74ad4cc2eb6e1d5c824996092b3430f088bb8", 241 | "sha256:22882a0e418c284e1f718a822b3b022944d53d2d908e1690b319a9d3eb2c0579" 242 | ], 243 | "index": "pypi", 244 | "markers": "python_version < '2.7.9' or (python_version >= '3.0' and python_version < '3.4')", 245 | "version": "==1.1.0" 246 | } 247 | } 248 | } 249 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | Pipfile: the replacement for `requirements.txt` 2 | =============================================== 3 | 4 | ``Pipfile`` and its sister ``Pipfile.lock`` are designed as a proposed replacement for an existing format: `pip`_'s ``requirements.txt`` file. 5 | 6 | WARNING: This format is still under active design and development. Nothing is set in stone at this point in time. 7 | 8 | This repository contains the design specification of the ``Pipfile`` format, as well as a proposed implementation of a parser for the specification which can be used by `Pipenv`_ and, in the future, any other consumer (e.g. `pip`_), once the design (including the form of a ``Pipfile`` itself) has been built out and finalized. 9 | 10 | .. _`pip`: https://pip.pypa.io/en/stable/ 11 | .. _`pipenv`: https://pipenv.pypa.io/en/stable/ 12 | 13 | ------------------------- 14 | 15 | Today, `Pipenv `_ uses Pipfile and contains the current reference implementation. 16 | 17 | The Concept 18 | ----------- 19 | 20 | ``Pipfile`` will be superior to ``requirements.txt`` file in a number of ways: 21 | 22 | * `TOML `_ syntax for declaring all types of Python dependencies. 23 | * One ``Pipfile`` (as opposed to multiple ``requirements.txt`` files). 24 | 25 | * A ``Pipfile`` is inherently ordered. 26 | 27 | * Existing requirements files tend to proliferate into multiple files - e.g. ``dev-requirements.txt``, ``test-requirements.txt``, etc. - but a ``Pipfile`` will allow seamlessly specifying groups of dependencies in one place. 28 | * This will be surfaced as only two built-in groups (*default* & *development*). (see note below) 29 | 30 | * Fully specified (and *deterministic*) environments in the form of ``Pipfile.lock``. 31 | A deployed application can then be completely redeployed with the same exact versions of all recursive dependencies, by referencing the ``Pipfile.lock`` file. 32 | 33 | The concrete requirements for a Python Application would come from ``Pipfile``. This would include where the packages should be fetched from and their loose version constraints. 34 | 35 | The details of the environment (all installed packages with pinned versions and other details) would be stored in ``Pipfile.lock``, for reproducibility. This file will be automatically generated and should not be modified by the user. 36 | 37 | .. note:: Custom groups may be added in the future. Remember, it is easier to add features in the future than it is to remove them. The Composer community has been successful with only *default* and *development* as group options for many years. This model is being followed. 38 | 39 | 40 | Examples (spec v6) 41 | ------------------ 42 | 43 | Here is a complex, comprehensive example ``Pipfile`` and the resulting ``Pipfile.lock``, generated with `Pipenv `_, and this library: 44 | 45 | ``Pipfile`` 46 | +++++++++++ 47 | 48 | .. code-block:: toml 49 | 50 | [[source]] 51 | url = 'https://pypi.python.org/simple' 52 | verify_ssl = true 53 | name = 'pypi' 54 | 55 | [requires] 56 | python_version = '2.7' 57 | 58 | [packages] 59 | requests = { extras = ['socks'] } 60 | records = '>0.5.0' 61 | django = { git = 'https://github.com/django/django.git', ref = '1.11.4', editable = true } 62 | "e682b37" = {file = "https://github.com/divio/django-cms/archive/release/3.4.x.zip"} 63 | "e1839a8" = {path = ".", editable = true} 64 | pywinusb = { version = "*", os_name = "=='nt'", index="pypi"} 65 | 66 | [dev-packages] 67 | nose = '*' 68 | unittest2 = {version = ">=1.0,<3.0", markers="python_version < '2.7.9' or (python_version >= '3.0' and python_version < '3.4')"} 69 | 70 | Notes: 71 | 72 | - There will be a default ``source``. 73 | 74 | **PEP 508 Support** 75 | +++++++++++++++++++ 76 | 77 | .. code-block:: toml 78 | 79 | # Support for all PEP 508 markers 80 | [requires] 81 | 82 | python_full_version = '3.6.0b1' 83 | platform = 'windows' 84 | 85 | ``requires`` utilizes `PEP 508`_ ``marker = 'specifier'`` markers. This functionality may not be readily used, as it is only to assert (and therefore abort, if appropriate) installation on certain platforms (e.g. python version, platform version). 86 | 87 | This functionality can currently be tested with ``$ pipenv check``. 88 | 89 | .. _`PEP 508`: https://www.python.org/dev/peps/pep-0508/#environment-markers 90 | 91 | ``Pipfile.lock`` 92 | ++++++++++++++++ 93 | 94 | .. code-block:: json 95 | 96 | { 97 | "_meta": { 98 | "hash": { 99 | "sha256": "09da36fcc93fa9b94fbea5282d8206a9d2e13fcec27229ec62c16c134e3e760a" 100 | }, 101 | "host-environment-markers": { 102 | "implementation_name": "cpython", 103 | "implementation_version": "0", 104 | "os_name": "posix", 105 | "platform_machine": "x86_64", 106 | "platform_python_implementation": "CPython", 107 | "platform_release": "17.0.0", 108 | "platform_system": "Darwin", 109 | "platform_version": "Darwin Kernel Version 17.0.0: Thu Aug 24 21:48:19 PDT 2017; root:xnu-4570.1.46~2/RELEASE_X86_64", 110 | "python_full_version": "2.7.14", 111 | "python_version": "2.7", 112 | "sys_platform": "darwin" 113 | }, 114 | "pipfile-spec": 6, 115 | "requires": { 116 | "python_version": "2.7" 117 | }, 118 | "sources": [ 119 | { 120 | "name": "pypi", 121 | "url": "https://pypi.python.org/simple", 122 | "verify_ssl": true 123 | } 124 | ] 125 | }, 126 | "default": { 127 | "certifi": { 128 | "hashes": [ 129 | "sha256:54a07c09c586b0e4c619f02a5e94e36619da8e2b053e20f594348c0611803704", 130 | "sha256:40523d2efb60523e113b44602298f0960e900388cf3bb6043f645cf57ea9e3f5" 131 | ], 132 | "version": "==2017.7.27.1" 133 | }, 134 | "chardet": { 135 | "hashes": [ 136 | "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691", 137 | "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae" 138 | ], 139 | "version": "==3.0.4" 140 | }, 141 | "django": { 142 | "editable": true, 143 | "git": "https://github.com/django/django.git", 144 | "ref": "1.11.4" 145 | }, 146 | "docopt": { 147 | "hashes": [ 148 | "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491" 149 | ], 150 | "version": "==0.6.2" 151 | }, 152 | "e1839a8": { 153 | "editable": true, 154 | "path": "." 155 | }, 156 | "e682b37": { 157 | "file": "https://github.com/divio/django-cms/archive/release/3.4.x.zip" 158 | }, 159 | "et-xmlfile": { 160 | "hashes": [ 161 | "sha256:614d9722d572f6246302c4491846d2c393c199cfa4edc9af593437691683335b" 162 | ], 163 | "version": "==1.0.1" 164 | }, 165 | "idna": { 166 | "hashes": [ 167 | "sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4", 168 | "sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f" 169 | ], 170 | "version": "==2.6" 171 | }, 172 | "jdcal": { 173 | "hashes": [ 174 | "sha256:b760160f8dc8cc51d17875c6b663fafe64be699e10ce34b6a95184b5aa0fdc9e" 175 | ], 176 | "version": "==1.3" 177 | }, 178 | "lxml": { 179 | "hashes": [ 180 | "sha256:3593f49858fc6229cd93326be06b099ae477fd65d8f4a981320a6d0bb7fc7a5a", 181 | "sha256:8996df6b0f205b00b89bbd04d88f1fa1e04139a025fd291aa4ddd05dc86836f4", 182 | "sha256:9f399c37b8e61c3989ef12ecf0abd9c10a5075f0fc9ad1ecd67ce6f9c72a7211", 183 | "sha256:550a51dee73c14e5863bdbbbe5836b2b8092a3f92631b5a908b9c41e72f123a5", 184 | "sha256:e37eda3d05519918403084b43eb7324df21a0daf45c8ae8172a860710dd0fa78", 185 | "sha256:48ab0e79175fd16f9478edc679ee14c79524c64b26f665f92cbecff81312d04d", 186 | "sha256:52e18dd86f153c4383bb4c4ef62f81f9b7e44809d068848a5a183b2285496faf", 187 | "sha256:0b8f3d6e669ea26849a6184f04c7802dbef6fd418a8b90e6c026e237db07af31", 188 | "sha256:567b76f291a8d02aa8b4d3f8295ae749ac4d532570d8a8c7176f0556c7d95891", 189 | "sha256:61825daaf2d80dc3da7635ee108720b0739962db008343822753bbf343cbfd14", 190 | "sha256:b7f6ef610680709be11cb7662e46e254bc561dafe0de3b4848be2cf3924bd300", 191 | "sha256:824664493a012f5b70396e841a4b4049bdaf445a70307e60f82fe35619f72cc7", 192 | "sha256:e908d685800626f10cd6ae01a013fc42094be167fb2a683eb920dfddfaa0ee76", 193 | "sha256:10c86b2248043f4428be33ed10202764b02b281eaa4550f16f0fbbc6ccaae9ac", 194 | "sha256:d9ec728caddb161405e7c33ed9d176e96309893481370163bbf4b00e43008795", 195 | "sha256:b2ecb3fd5470b740dfc21b064bbc1337be4b7b805994a868488145d36f35f517", 196 | "sha256:a211288459c9115ddb255ff88e8ac12dc2063e70bddc15e3c65136477a358bb5", 197 | "sha256:1f81074e77c25f9b787fa3854f400ca924d3d798cb7ae910c0e7920be7138c90", 198 | "sha256:99b7eabfb46663ed5918eca4ed12420613ba24196964a741ccd962d09296c0b2", 199 | "sha256:a8ad0adeedbbb7b85916214fcd4f5d02829d0e7b3c32abc298789218b6c3d699", 200 | "sha256:88d137e440b5de35df2e0616da8e28a88d0119abdaa84520ad1ba815ee9da732", 201 | "sha256:c4e02657e629f02ab8712471d77d6896c2cf6f09f8ffa6a0f23b1b1ef0318474", 202 | "sha256:9581b438e5d0d0a6fa3937fac2abffd95380bd513bcd39f6952bfcf20cf0b9a7", 203 | "sha256:c446fde3284c363cd2085ad1ce5a07c18f15f6766d72684622bc14b0a9ddfd29", 204 | "sha256:d4507916c408feec2ea8cee3f0d1380e49ea431f6e07b0dd927388bd6e92d6eb", 205 | "sha256:7030f44b758e930fd09ade87d770f5a231a19a8c561a3acc54e5122b5ec09e29", 206 | "sha256:d78c0a114cf127a41a526aef99aef539c0b2537e57f04a2cc7a49e2c94a44ab8", 207 | "sha256:f7bc9f702500e205b1560d620f14015fec76dcd6f9e889a946a2ddcc3c344fd0" 208 | ], 209 | "version": "==4.0.0" 210 | }, 211 | "odfpy": { 212 | "hashes": [ 213 | "sha256:6db9bb1c9ea2d55d60e508a1318fd285442a8342b785704ea08598a260875a83", 214 | "sha256:6f8163f8464868cff9421a058f25566e41d73c8f7e849c021b86630941b44366" 215 | ], 216 | "version": "==1.3.5" 217 | }, 218 | "openpyxl": { 219 | "hashes": [ 220 | "sha256:ee7551efb70648fa8ee569c2b6a6dbbeff390cc94b321da5d508a573b90a4f17" 221 | ], 222 | "version": "==2.4.8" 223 | }, 224 | "pysocks": { 225 | "hashes": [ 226 | "sha256:18842328a4e6061f084cfba70f6950d9140ecf7418b3df7cef558ebb217bac8d", 227 | "sha256:d00329f27efa157db7efe3ca26fcd69033cd61f83822461ee3f8a353b48e33cf" 228 | ], 229 | "version": "==1.6.7" 230 | }, 231 | "pytz": { 232 | "hashes": [ 233 | "sha256:c883c2d6670042c7bc1688645cac73dd2b03193d1f7a6847b6154e96890be06d", 234 | "sha256:03c9962afe00e503e2d96abab4e8998a0f84d4230fa57afe1e0528473698cdd9", 235 | "sha256:487e7d50710661116325747a9cd1744d3323f8e49748e287bc9e659060ec6bf9", 236 | "sha256:43f52d4c6a0be301d53ebd867de05e2926c35728b3260157d274635a0a947f1c", 237 | "sha256:d1d6729c85acea5423671382868627129432fba9a89ecbb248d8d1c7a9f01c67", 238 | "sha256:54a935085f7bf101f86b2aff75bd9672b435f51c3339db2ff616e66845f2b8f9", 239 | "sha256:39504670abb5dae77f56f8eb63823937ce727d7cdd0088e6909e6dcac0f89043", 240 | "sha256:ddc93b6d41cfb81266a27d23a79e13805d4a5521032b512643af8729041a81b4", 241 | "sha256:f5c056e8f62d45ba8215e5cb8f50dfccb198b4b9fbea8500674f3443e4689589" 242 | ], 243 | "version": "==2017.2" 244 | }, 245 | "pywinusb": { 246 | "hashes": [ 247 | "sha256:e2f5e89f7b74239ca4843721a9bda0fc99014750630c189a176ec0e1b35e86df" 248 | ], 249 | "index": "pypi", 250 | "markers": "os_name == 'nt'", 251 | "version": "==0.4.2" 252 | }, 253 | "pyyaml": { 254 | "hashes": [ 255 | "sha256:3262c96a1ca437e7e4763e2843746588a965426550f3797a79fca9c6199c431f", 256 | "sha256:16b20e970597e051997d90dc2cddc713a2876c47e3d92d59ee198700c5427736", 257 | "sha256:e863072cdf4c72eebf179342c94e6989c67185842d9997960b3e69290b2fa269", 258 | "sha256:bc6bced57f826ca7cb5125a10b23fd0f2fff3b7c4701d64c439a300ce665fff8", 259 | "sha256:c01b880ec30b5a6e6aa67b09a2fe3fb30473008c85cd6a67359a1b15ed6d83a4", 260 | "sha256:827dc04b8fa7d07c44de11fabbc888e627fa8293b695e0f99cb544fdfa1bf0d1", 261 | "sha256:592766c6303207a20efc445587778322d7f73b161bd994f227adaa341ba212ab", 262 | "sha256:5f84523c076ad14ff5e6c037fe1c89a7f73a3e04cf0377cb4d017014976433f3", 263 | "sha256:0c507b7f74b3d2dd4d1322ec8a94794927305ab4cebbe89cc47fe5e81541e6e8", 264 | "sha256:b4c423ab23291d3945ac61346feeb9a0dc4184999ede5e7c43e1ffb975130ae6", 265 | "sha256:ca233c64c6e40eaa6c66ef97058cdc80e8d0157a443655baa1b2966e812807ca", 266 | "sha256:4474f8ea030b5127225b8894d626bb66c01cda098d47a2b0d3429b6700af9fd8", 267 | "sha256:326420cbb492172dec84b0f65c80942de6cedb5233c413dd824483989c000608", 268 | "sha256:5ac82e411044fb129bae5cfbeb3ba626acb2af31a8d17d175004b70862a741a7" 269 | ], 270 | "version": "==3.12" 271 | }, 272 | "records": { 273 | "hashes": [ 274 | "sha256:6d060a2b44ecc198d4e86efd5dab8558a2581b4019970bd8839e1604a243f57e", 275 | "sha256:238cba35e8efbb724493bbb195bd027d9e78db4a978597969a7af0f722ac3686" 276 | ], 277 | "version": "==0.5.2" 278 | }, 279 | "requests": { 280 | "hashes": [ 281 | "sha256:6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b", 282 | "sha256:9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e" 283 | ], 284 | "version": "==2.18.4" 285 | }, 286 | "sqlalchemy": { 287 | "hashes": [ 288 | "sha256:f1191e29e35b6fe1aef7175a09b1707ebb7bd08d0b17cb0feada76c49e5a2d1e" 289 | ], 290 | "version": "==1.1.14" 291 | }, 292 | "tablib": { 293 | "hashes": [ 294 | "sha256:b8cf50a61d66655229993f2ee29220553fb2c80403479f8e6de77c0c24649d87" 295 | ], 296 | "version": "==0.12.1" 297 | }, 298 | "unicodecsv": { 299 | "hashes": [ 300 | "sha256:018c08037d48649a0412063ff4eda26eaa81eff1546dbffa51fa5293276ff7fc" 301 | ], 302 | "version": "==0.14.1" 303 | }, 304 | "urllib3": { 305 | "hashes": [ 306 | "sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b", 307 | "sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f" 308 | ], 309 | "version": "==1.22" 310 | }, 311 | "xlrd": { 312 | "hashes": [ 313 | "sha256:83a1d2f1091078fb3f65876753b5302c5cfb6a41de64b9587b74cefa75157148", 314 | "sha256:8a21885513e6d915fe33a8ee5fdfa675433b61405ba13e2a69e62ee36828d7e2" 315 | ], 316 | "version": "==1.1.0" 317 | }, 318 | "xlwt": { 319 | "hashes": [ 320 | "sha256:a082260524678ba48a297d922cc385f58278b8aa68741596a87de01a9c628b2e", 321 | "sha256:c59912717a9b28f1a3c2a98fd60741014b06b043936dcecbc113eaaada156c88" 322 | ], 323 | "version": "==1.3.0" 324 | } 325 | }, 326 | "develop": { 327 | "argparse": { 328 | "hashes": [ 329 | "sha256:c31647edb69fd3d465a847ea3157d37bed1f95f19760b11a47aa91c04b666314", 330 | "sha256:62b089a55be1d8949cd2bc7e0df0bddb9e028faefc8c32038cc84862aefdd6e4" 331 | ], 332 | "version": "==1.4.0" 333 | }, 334 | "linecache2": { 335 | "hashes": [ 336 | "sha256:e78be9c0a0dfcbac712fe04fbf92b96cddae80b1b842f24248214c8496f006ef", 337 | "sha256:4b26ff4e7110db76eeb6f5a7b64a82623839d595c2038eeda662f2a2db78e97c" 338 | ], 339 | "version": "==1.0.0" 340 | }, 341 | "nose": { 342 | "hashes": [ 343 | "sha256:dadcddc0aefbf99eea214e0f1232b94f2fa9bd98fa8353711dacb112bfcbbb2a", 344 | "sha256:9ff7c6cc443f8c51994b34a667bbcf45afd6d945be7477b52e97516fd17c53ac", 345 | "sha256:f1bffef9cbc82628f6e7d7b40d7e255aefaa1adb6a1b1d26c69a8b79e6208a98" 346 | ], 347 | "version": "==1.3.7" 348 | }, 349 | "six": { 350 | "hashes": [ 351 | "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb", 352 | "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9" 353 | ], 354 | "version": "==1.11.0" 355 | }, 356 | "traceback2": { 357 | "hashes": [ 358 | "sha256:8253cebec4b19094d67cc5ed5af99bf1dba1285292226e98a31929f87a5d6b23", 359 | "sha256:05acc67a09980c2ecfedd3423f7ae0104839eccb55fc645773e1caa0951c3030" 360 | ], 361 | "version": "==1.4.0" 362 | }, 363 | "unittest2": { 364 | "hashes": [ 365 | "sha256:13f77d0875db6d9b435e1d4f41e74ad4cc2eb6e1d5c824996092b3430f088bb8", 366 | "sha256:22882a0e418c284e1f718a822b3b022944d53d2d908e1690b319a9d3eb2c0579" 367 | ], 368 | "markers": "python_version < '2.7.9' or (python_version >= '3.0' and python_version < '3.4')", 369 | "version": "==1.1.0" 370 | } 371 | } 372 | } 373 | 374 | 375 | 376 | This `example `_ was generated with ``$ pipenv lock``. 377 | 378 | ``Pipfile.lock`` is always to be generated and is not to be modified or constructed by a user. 379 | 380 | Do note how the versions of each dependency are recursively frozen and a hash gets computed so that you can take advantage of `new pip security features`_. 381 | 382 | Hashes are optional, because they can cause problems when using the same lockfile across different Python versions (e.g. a package will have different hashes according to different Pythons). 383 | 384 | .. _`new pip security features`: https://pip.pypa.io/en/stable/reference/pip_install/#hash-checking-mode 385 | 386 | Pip Integration (eventual) 387 | ++++++++++++++++++++++++++ 388 | 389 | `pip`_ will grow a new command line option, ``-p`` / ``--pipfile`` to install the versions as specified in a ``Pipfile``, similar to its existing ``-r`` / ``--requirement`` argument for installing ``requirements.txt`` files. 390 | 391 | Install packages from ``Pipfile``:: 392 | 393 | $ pip install -p 394 | ! Warning: Pipfile.lock (48d35f) is out of date. Updating to (73d81f). 395 | Installing packages from requirements.piplock... 396 | [installation output] 397 | 398 | To manually update the ``Pipfile.lock``:: 399 | 400 | $ pip freeze -p different_pipfile 401 | different_pipfile.lock (73d81f) written to disk. 402 | 403 | Notes:: 404 | 405 | # -p accepts a path argument, which defaults to 'Pipfile'. 406 | # Pipfile.lock will be written automatically during `install -p` if it does not exist. 407 | 408 | Ideas:: 409 | 410 | - Recursively look for `Pipfile` in parent directories (limit 3/4?) when ``-p`` is bare. 411 | 412 | 413 | Useful Links 414 | ------------ 415 | 416 | - `Pipenv`_: Current reference implementation 417 | - `pypa/pip#1795`_: Requirements 2.0 418 | - `Basic Concept Gist`_ (fork of @dstufft's) 419 | 420 | .. _`Pipenv`: http://pipenv.org 421 | .. _`Basic Concept Gist`: https://gist.github.com/kennethreitz/4745d35e57108f5b766b8f6ff396de85 422 | .. _`pypa/pip#1795`: https://github.com/pypa/pip/issues/1795 423 | 424 | Inspirations 425 | ++++++++++++ 426 | 427 | - `nvie/pip-tools`_: A set of tools to keep your pinned Python dependencies fresh. 428 | - `A Better Pip Workflow`_ by Kenneth Reitz 429 | - Lessons learned from Composer, Cargo, Yarn, NPM, Bundler and all Languages Owners at Heroku. 430 | 431 | 432 | .. _`nvie/pip-tools`: https://github.com/nvie/pip-tools 433 | .. _`A Better Pip Workflow`: https://www.kennethreitz.org/essays/a-better-pip-workflow 434 | 435 | 436 | Documentation 437 | ------------- 438 | 439 | The `documentation`_ for this project will, eventually, reside at pypi.org. 440 | 441 | .. _`documentation`: https://pipfile.pypa.io/ 442 | 443 | 444 | Discussion 445 | ---------- 446 | 447 | If you run into bugs, you can file them in our `issue tracker`_. You can also join ``#pypa`` on Freenode to ask questions or get involved. 448 | 449 | .. _`issue tracker`: https://github.com/pypa/pipfile/issues 450 | 451 | 452 | Code of Conduct 453 | --------------- 454 | 455 | Everyone interacting in the pipfile project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the `PSF Code of Conduct`_. 456 | 457 | .. _`PSF Code of Conduct`: https://github.com/pypa/.github/blob/main/CODE_OF_CONDUCT.md 458 | --------------------------------------------------------------------------------