{"action":"created","comment":{"url":"https://api.github.com/repos/pypa/interoperability-peps/pulls/comments/44206456","id":44206456,"diff_hunk":"@@ -0,0 +1,376 @@\n+:PEP: XX\n+:Title: Dependency specification for Python Software Packages\n+:Version: $Revision$\n+:Last-Modified: $Date$\n+:Author: Robert Collins <rbtcollins@hp.com>\n+:BDFL-Delegate: Donald Stufft <donald@stufft.io>\n+:Discussions-To: distutils-sig <distutils-sig@python.org>\n+:Status: Draft\n+:Type: Standards Track\n+:Content-Type: text/x-rst\n+:Created: 11-Nov-2015\n+:Post-History: XX\n+\n+\n+Abstract\n+========\n+\n+This PEP specifies the language used to describe dependencies for packages.\n+It draws a border at the edge of describing a single dependency - the\n+different sorts of dependencies and when they should be installed is a higher\n+level problem. The intent is provide a building block for higher layer\n+specifications.\n+\n+The job of a dependency is to enable tools like pip [#pip]_ to find the right\n+package to install. Sometimes this is very loose - just specifying a name, and\n+sometimes very specific - referring to a specific file to install. Sometimes\n+dependencies are only relevant in one platform, or only some versions are\n+acceptable, so the language permits describing all these cases.\n+\n+The language defined is a compact line based format which is already in\n+widespread use in pip requirements files, though we do not specify the command\n+line option handling that those files permit. There is one caveat - the\n+URL reference form, specified in PEP-440 [#pep440]_ is not actually\n+implemented in pip, but since PEP-440 is accepted, we use that format rather\n+than pip's current native format.\n+\n+Motivation\n+==========\n+\n+Any specification in the Python packaging ecosystem that needs to consume\n+lists of dependencies needs to build on an approved PEP for such, but \n+PEP-426 [#pep426]_ is mostly aspirational - and there are already existing\n+implementations of the dependency specification which we can instead adopt.\n+The existing implementations are battle proven and user friendly, so adopting\n+them is arguably much better than approving an aspirational, unconsumed, format.\n+\n+Specification\n+=============\n+\n+Examples\n+--------\n+\n+All features of the language shown with a name based lookup::\n+\n+    requests \\\n+        [security] >= 2.8.1, == 2.8.* \\\n+        ; python_version < \"2.7.10\" \\\n+        # Fix HTTPS on older Python versions.\n+\n+A minimal URL based lookup::\n+\n+    pip @ https://github.com/pypa/pip/archive/1.3.1.zip#sha1=da9234ee9982d4bbb3c72346a6de940a148ea686\n+\n+Concepts\n+--------\n+\n+A dependency specification always specifies a distribution name. It may\n+include extras, which expand the dependencies of the named distribution to\n+enable optional features. The version installed can be controlled using\n+version limits, or giving the URL to a specific artifact to install. Finally\n+the dependency can be made conditional using environment markers.\n+\n+Grammar\n+-------\n+\n+We first cover the grammar briefly and then drill into the semantics of each\n+section later.\n+\n+A distribution specification is written in ASCII text. We use ABNF [#abnf]_ to\n+provide a precise grammar. Specifications may have comments starting with a\n+'#' and running to the end of the line::\n+\n+    comment       = \"#\" *(WSP / VCHAR)\n+\n+Specifications may be spread across multiple lines if desired using\n+continuations - a single backslash followed by a new line ('\\\\\\\\n')::\n+\n+    CSP           = 1*(WSP / (\"\\\\\" LF))\n+\n+Versions may be specified according to the PEP-440 [#pep440]_ rules. (Note:\n+URI is defined in std-66 [#std66]_::\n+\n+    version-cmp   = \"<\" / \"<=\" / \"!=\" / \"==\" / \">=\" / \">\" / \"~=\" / \"===\"\n+    version       = 1*( DIGIT / ALPHA / \"-\" / \"_\" / \".\" / \"*\" )\n+    versionspec   = [\"(\"] version-cmp version *(',' version-cmp version) [\")\"]\n+    urlspec       = \"@\" URI\n+\n+Environment markers allow making a specification only take effect in some\n+environments::\n+\n+    marker-op     = version-cmp / \"in\" / \"not in\"\n+    python-str-c  = (WSP / ALPHA / DIGIT / \"(\" / \")\" / \".\" / \"{\" / \"}\" /\n+                    \"-\" / \"_\" / \"*\"\n+    python-str    = \"'\" *(python-str-c / DQUOTE) \"'\"\n+    python-str    =/ DQUOTE *(python-str-c / \"'\") DQUOTE\n+    marker-var    = python-str / \"python_version\" / \"python_full_version\" /\n+                    \"os_name\"\" / \"sys_platform\" / \"platform_release\" /\n+                    \"platform_version\" / \"platform_machine\" /\n+                    \"platform_python_implementation\" / \"implementation_name\" /\n+                    \"implementation_version\" / \"platform_dist_name\"\n+                    \"platform_dist_version\" / \"platform_dist_id\"","path":"dependency-specification.rst","position":111,"original_position":111,"commit_id":"f7b8d65d19cd91667855f79cd8362f751003f009","original_commit_id":"f7b8d65d19cd91667855f79cd8362f751003f009","user":{"login":"njsmith","id":609896,"avatar_url":"https://avatars.githubusercontent.com/u/609896?v=3","gravatar_id":"","url":"https://api.github.com/users/njsmith","html_url":"https://github.com/njsmith","followers_url":"https://api.github.com/users/njsmith/followers","following_url":"https://api.github.com/users/njsmith/following{/other_user}","gists_url":"https://api.github.com/users/njsmith/gists{/gist_id}","starred_url":"https://api.github.com/users/njsmith/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/njsmith/subscriptions","organizations_url":"https://api.github.com/users/njsmith/orgs","repos_url":"https://api.github.com/users/njsmith/repos","events_url":"https://api.github.com/users/njsmith/events{/privacy}","received_events_url":"https://api.github.com/users/njsmith/received_events","type":"User","site_admin":false},"body":"What happens if we encounter an unrecognized variable name? Do we want to gracefully degrade somehow, e.g. by treating any marker expression that contains an unrecognized variable as evaluating to False? If so, then the grammar should probably be rewritten to something like\r\n```\r\npython-str = ...\r\nmarker-var = (ALPHA / \"_\") *(ALPHA / DIGIT / \"_\")\r\nmarker-val = python-str / marker-var\r\n```\r\nso that arbitrary python variables can at least be parsed, and then the valid ones specified below.\r\n\r\nOTOH this may hide problems like @merwok's `os_name == posix` silently evaluating to False.\r\n\r\nProbably it would be a good idea to only allow marker expressions of the form `<variable> <op> <literal>` (in exactly that order), but I don't know if that would break existing usage...","created_at":"2015-11-07T02:36:20Z","updated_at":"2015-11-07T02:36:20Z","html_url":"https://github.com/pypa/interoperability-peps/pull/56#discussion_r44206456","pull_request_url":"https://api.github.com/repos/pypa/interoperability-peps/pulls/56","_links":{"self":{"href":"https://api.github.com/repos/pypa/interoperability-peps/pulls/comments/44206456"},"html":{"href":"https://github.com/pypa/interoperability-peps/pull/56#discussion_r44206456"},"pull_request":{"href":"https://api.github.com/repos/pypa/interoperability-peps/pulls/56"}}},"pull_request":{"url":"https://api.github.com/repos/pypa/interoperability-peps/pulls/56","id":49912435,"html_url":"https://github.com/pypa/interoperability-peps/pull/56","diff_url":"https://github.com/pypa/interoperability-peps/pull/56.diff","patch_url":"https://github.com/pypa/interoperability-peps/pull/56.patch","issue_url":"https://api.github.com/repos/pypa/interoperability-peps/issues/56","number":56,"state":"open","locked":false,"title":"Define dependency specifications formally.","user":{"login":"rbtcollins","id":499678,"avatar_url":"https://avatars.githubusercontent.com/u/499678?v=3","gravatar_id":"","url":"https://api.github.com/users/rbtcollins","html_url":"https://github.com/rbtcollins","followers_url":"https://api.github.com/users/rbtcollins/followers","following_url":"https://api.github.com/users/rbtcollins/following{/other_user}","gists_url":"https://api.github.com/users/rbtcollins/gists{/gist_id}","starred_url":"https://api.github.com/users/rbtcollins/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rbtcollins/subscriptions","organizations_url":"https://api.github.com/users/rbtcollins/orgs","repos_url":"https://api.github.com/users/rbtcollins/repos","events_url":"https://api.github.com/users/rbtcollins/events{/privacy}","received_events_url":"https://api.github.com/users/rbtcollins/received_events","type":"User","site_admin":false},"body":"","created_at":"2015-11-06T03:28:26Z","updated_at":"2015-11-07T02:36:20Z","closed_at":null,"merged_at":null,"merge_commit_sha":"25b9724072a7d1f10bb8292fc18d29fdf1817203","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/pypa/interoperability-peps/pulls/56/commits","review_comments_url":"https://api.github.com/repos/pypa/interoperability-peps/pulls/56/comments","review_comment_url":"https://api.github.com/repos/pypa/interoperability-peps/pulls/comments{/number}","comments_url":"https://api.github.com/repos/pypa/interoperability-peps/issues/56/comments","statuses_url":"https://api.github.com/repos/pypa/interoperability-peps/statuses/f7b8d65d19cd91667855f79cd8362f751003f009","head":{"label":"rbtcollins:dependency","ref":"dependency","sha":"f7b8d65d19cd91667855f79cd8362f751003f009","user":{"login":"rbtcollins","id":499678,"avatar_url":"https://avatars.githubusercontent.com/u/499678?v=3","gravatar_id":"","url":"https://api.github.com/users/rbtcollins","html_url":"https://github.com/rbtcollins","followers_url":"https://api.github.com/users/rbtcollins/followers","following_url":"https://api.github.com/users/rbtcollins/following{/other_user}","gists_url":"https://api.github.com/users/rbtcollins/gists{/gist_id}","starred_url":"https://api.github.com/users/rbtcollins/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rbtcollins/subscriptions","organizations_url":"https://api.github.com/users/rbtcollins/orgs","repos_url":"https://api.github.com/users/rbtcollins/repos","events_url":"https://api.github.com/users/rbtcollins/events{/privacy}","received_events_url":"https://api.github.com/users/rbtcollins/received_events","type":"User","site_admin":false},"repo":{"id":40106828,"name":"interoperability-peps","full_name":"rbtcollins/interoperability-peps","owner":{"login":"rbtcollins","id":499678,"avatar_url":"https://avatars.githubusercontent.com/u/499678?v=3","gravatar_id":"","url":"https://api.github.com/users/rbtcollins","html_url":"https://github.com/rbtcollins","followers_url":"https://api.github.com/users/rbtcollins/followers","following_url":"https://api.github.com/users/rbtcollins/following{/other_user}","gists_url":"https://api.github.com/users/rbtcollins/gists{/gist_id}","starred_url":"https://api.github.com/users/rbtcollins/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rbtcollins/subscriptions","organizations_url":"https://api.github.com/users/rbtcollins/orgs","repos_url":"https://api.github.com/users/rbtcollins/repos","events_url":"https://api.github.com/users/rbtcollins/events{/privacy}","received_events_url":"https://api.github.com/users/rbtcollins/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/rbtcollins/interoperability-peps","description":"Development repo for evolution of PyPA interoperability standards (released versions are published as PEPs on python.org)","fork":true,"url":"https://api.github.com/repos/rbtcollins/interoperability-peps","forks_url":"https://api.github.com/repos/rbtcollins/interoperability-peps/forks","keys_url":"https://api.github.com/repos/rbtcollins/interoperability-peps/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rbtcollins/interoperability-peps/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rbtcollins/interoperability-peps/teams","hooks_url":"https://api.github.com/repos/rbtcollins/interoperability-peps/hooks","issue_events_url":"https://api.github.com/repos/rbtcollins/interoperability-peps/issues/events{/number}","events_url":"https://api.github.com/repos/rbtcollins/interoperability-peps/events","assignees_url":"https://api.github.com/repos/rbtcollins/interoperability-peps/assignees{/user}","branches_url":"https://api.github.com/repos/rbtcollins/interoperability-peps/branches{/branch}","tags_url":"https://api.github.com/repos/rbtcollins/interoperability-peps/tags","blobs_url":"https://api.github.com/repos/rbtcollins/interoperability-peps/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rbtcollins/interoperability-peps/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rbtcollins/interoperability-peps/git/refs{/sha}","trees_url":"https://api.github.com/repos/rbtcollins/interoperability-peps/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rbtcollins/interoperability-peps/statuses/{sha}","languages_url":"https://api.github.com/repos/rbtcollins/interoperability-peps/languages","stargazers_url":"https://api.github.com/repos/rbtcollins/interoperability-peps/stargazers","contributors_url":"https://api.github.com/repos/rbtcollins/interoperability-peps/contributors","subscribers_url":"https://api.github.com/repos/rbtcollins/interoperability-peps/subscribers","subscription_url":"https://api.github.com/repos/rbtcollins/interoperability-peps/subscription","commits_url":"https://api.github.com/repos/rbtcollins/interoperability-peps/commits{/sha}","git_commits_url":"https://api.github.com/repos/rbtcollins/interoperability-peps/git/commits{/sha}","comments_url":"https://api.github.com/repos/rbtcollins/interoperability-peps/comments{/number}","issue_comment_url":"https://api.github.com/repos/rbtcollins/interoperability-peps/issues/comments{/number}","contents_url":"https://api.github.com/repos/rbtcollins/interoperability-peps/contents/{+path}","compare_url":"https://api.github.com/repos/rbtcollins/interoperability-peps/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rbtcollins/interoperability-peps/merges","archive_url":"https://api.github.com/repos/rbtcollins/interoperability-peps/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rbtcollins/interoperability-peps/downloads","issues_url":"https://api.github.com/repos/rbtcollins/interoperability-peps/issues{/number}","pulls_url":"https://api.github.com/repos/rbtcollins/interoperability-peps/pulls{/number}","milestones_url":"https://api.github.com/repos/rbtcollins/interoperability-peps/milestones{/number}","notifications_url":"https://api.github.com/repos/rbtcollins/interoperability-peps/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rbtcollins/interoperability-peps/labels{/name}","releases_url":"https://api.github.com/repos/rbtcollins/interoperability-peps/releases{/id}","created_at":"2015-08-03T05:36:56Z","updated_at":"2015-08-03T05:36:56Z","pushed_at":"2015-11-06T20:14:15Z","git_url":"git://github.com/rbtcollins/interoperability-peps.git","ssh_url":"git@github.com:rbtcollins/interoperability-peps.git","clone_url":"https://github.com/rbtcollins/interoperability-peps.git","svn_url":"https://github.com/rbtcollins/interoperability-peps","homepage":null,"size":24622,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"pypa:master","ref":"master","sha":"1dc2bd0c73df9546a0e3494343d4fd1eaccda8a8","user":{"login":"pypa","id":647025,"avatar_url":"https://avatars.githubusercontent.com/u/647025?v=3","gravatar_id":"","url":"https://api.github.com/users/pypa","html_url":"https://github.com/pypa","followers_url":"https://api.github.com/users/pypa/followers","following_url":"https://api.github.com/users/pypa/following{/other_user}","gists_url":"https://api.github.com/users/pypa/gists{/gist_id}","starred_url":"https://api.github.com/users/pypa/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pypa/subscriptions","organizations_url":"https://api.github.com/users/pypa/orgs","repos_url":"https://api.github.com/users/pypa/repos","events_url":"https://api.github.com/users/pypa/events{/privacy}","received_events_url":"https://api.github.com/users/pypa/received_events","type":"Organization","site_admin":false},"repo":{"id":28580365,"name":"interoperability-peps","full_name":"pypa/interoperability-peps","owner":{"login":"pypa","id":647025,"avatar_url":"https://avatars.githubusercontent.com/u/647025?v=3","gravatar_id":"","url":"https://api.github.com/users/pypa","html_url":"https://github.com/pypa","followers_url":"https://api.github.com/users/pypa/followers","following_url":"https://api.github.com/users/pypa/following{/other_user}","gists_url":"https://api.github.com/users/pypa/gists{/gist_id}","starred_url":"https://api.github.com/users/pypa/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pypa/subscriptions","organizations_url":"https://api.github.com/users/pypa/orgs","repos_url":"https://api.github.com/users/pypa/repos","events_url":"https://api.github.com/users/pypa/events{/privacy}","received_events_url":"https://api.github.com/users/pypa/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/pypa/interoperability-peps","description":"Development repo for evolution of PyPA interoperability standards (released versions are published as PEPs on python.org)","fork":false,"url":"https://api.github.com/repos/pypa/interoperability-peps","forks_url":"https://api.github.com/repos/pypa/interoperability-peps/forks","keys_url":"https://api.github.com/repos/pypa/interoperability-peps/keys{/key_id}","collaborators_url":"https://api.github.com/repos/pypa/interoperability-peps/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/pypa/interoperability-peps/teams","hooks_url":"https://api.github.com/repos/pypa/interoperability-peps/hooks","issue_events_url":"https://api.github.com/repos/pypa/interoperability-peps/issues/events{/number}","events_url":"https://api.github.com/repos/pypa/interoperability-peps/events","assignees_url":"https://api.github.com/repos/pypa/interoperability-peps/assignees{/user}","branches_url":"https://api.github.com/repos/pypa/interoperability-peps/branches{/branch}","tags_url":"https://api.github.com/repos/pypa/interoperability-peps/tags","blobs_url":"https://api.github.com/repos/pypa/interoperability-peps/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/pypa/interoperability-peps/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/pypa/interoperability-peps/git/refs{/sha}","trees_url":"https://api.github.com/repos/pypa/interoperability-peps/git/trees{/sha}","statuses_url":"https://api.github.com/repos/pypa/interoperability-peps/statuses/{sha}","languages_url":"https://api.github.com/repos/pypa/interoperability-peps/languages","stargazers_url":"https://api.github.com/repos/pypa/interoperability-peps/stargazers","contributors_url":"https://api.github.com/repos/pypa/interoperability-peps/contributors","subscribers_url":"https://api.github.com/repos/pypa/interoperability-peps/subscribers","subscription_url":"https://api.github.com/repos/pypa/interoperability-peps/subscription","commits_url":"https://api.github.com/repos/pypa/interoperability-peps/commits{/sha}","git_commits_url":"https://api.github.com/repos/pypa/interoperability-peps/git/commits{/sha}","comments_url":"https://api.github.com/repos/pypa/interoperability-peps/comments{/number}","issue_comment_url":"https://api.github.com/repos/pypa/interoperability-peps/issues/comments{/number}","contents_url":"https://api.github.com/repos/pypa/interoperability-peps/contents/{+path}","compare_url":"https://api.github.com/repos/pypa/interoperability-peps/compare/{base}...{head}","merges_url":"https://api.github.com/repos/pypa/interoperability-peps/merges","archive_url":"https://api.github.com/repos/pypa/interoperability-peps/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/pypa/interoperability-peps/downloads","issues_url":"https://api.github.com/repos/pypa/interoperability-peps/issues{/number}","pulls_url":"https://api.github.com/repos/pypa/interoperability-peps/pulls{/number}","milestones_url":"https://api.github.com/repos/pypa/interoperability-peps/milestones{/number}","notifications_url":"https://api.github.com/repos/pypa/interoperability-peps/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/pypa/interoperability-peps/labels{/name}","releases_url":"https://api.github.com/repos/pypa/interoperability-peps/releases{/id}","created_at":"2014-12-29T04:35:09Z","updated_at":"2015-10-28T19:04:51Z","pushed_at":"2015-11-06T20:14:15Z","git_url":"git://github.com/pypa/interoperability-peps.git","ssh_url":"git@github.com:pypa/interoperability-peps.git","clone_url":"https://github.com/pypa/interoperability-peps.git","svn_url":"https://github.com/pypa/interoperability-peps","homepage":null,"size":24905,"stargazers_count":6,"watchers_count":6,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":7,"mirror_url":null,"open_issues_count":32,"forks":7,"open_issues":32,"watchers":6,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/pypa/interoperability-peps/pulls/56"},"html":{"href":"https://github.com/pypa/interoperability-peps/pull/56"},"issue":{"href":"https://api.github.com/repos/pypa/interoperability-peps/issues/56"},"comments":{"href":"https://api.github.com/repos/pypa/interoperability-peps/issues/56/comments"},"review_comments":{"href":"https://api.github.com/repos/pypa/interoperability-peps/pulls/56/comments"},"review_comment":{"href":"https://api.github.com/repos/pypa/interoperability-peps/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/pypa/interoperability-peps/pulls/56/commits"},"statuses":{"href":"https://api.github.com/repos/pypa/interoperability-peps/statuses/f7b8d65d19cd91667855f79cd8362f751003f009"}}}}