com.googler.python 1.0.7 → 1.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (354) hide show
  1. package/package.json +4 -2
  2. package/python3.4.2/lib/python3.4/site-packages/pip/__init__.py +1 -277
  3. package/python3.4.2/lib/python3.4/site-packages/pip/__main__.py +19 -7
  4. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/__init__.py +246 -0
  5. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/basecommand.py +373 -0
  6. package/python3.4.2/lib/python3.4/site-packages/pip/{baseparser.py → _internal/baseparser.py} +240 -224
  7. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/build_env.py +92 -0
  8. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/cache.py +202 -0
  9. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/cmdoptions.py +609 -0
  10. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/commands/__init__.py +79 -0
  11. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/commands/check.py +42 -0
  12. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/commands/completion.py +94 -0
  13. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/commands/configuration.py +227 -0
  14. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/commands/download.py +233 -0
  15. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/commands/freeze.py +96 -0
  16. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/commands/hash.py +57 -0
  17. package/python3.4.2/lib/python3.4/site-packages/pip/{commands → _internal/commands}/help.py +36 -33
  18. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/commands/install.py +477 -0
  19. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/commands/list.py +343 -0
  20. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/commands/search.py +135 -0
  21. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/commands/show.py +164 -0
  22. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/commands/uninstall.py +71 -0
  23. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/commands/wheel.py +179 -0
  24. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/compat.py +235 -0
  25. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/configuration.py +378 -0
  26. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/download.py +922 -0
  27. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/exceptions.py +249 -0
  28. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/index.py +1117 -0
  29. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/locations.py +194 -0
  30. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/models/__init__.py +4 -0
  31. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/models/index.py +15 -0
  32. package/python3.4.2/lib/python3.4/site-packages/pip/{_vendor/requests/packages/urllib3/contrib → _internal/operations}/__init__.py +0 -0
  33. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/operations/check.py +106 -0
  34. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/operations/freeze.py +252 -0
  35. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/operations/prepare.py +378 -0
  36. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/pep425tags.py +317 -0
  37. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/req/__init__.py +69 -0
  38. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/req/req_file.py +338 -0
  39. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/req/req_install.py +1115 -0
  40. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/req/req_set.py +164 -0
  41. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/req/req_uninstall.py +455 -0
  42. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/resolve.py +354 -0
  43. package/python3.4.2/lib/python3.4/site-packages/pip/{status_codes.py → _internal/status_codes.py} +8 -6
  44. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/utils/__init__.py +0 -0
  45. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/utils/appdirs.py +258 -0
  46. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/utils/deprecation.py +77 -0
  47. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/utils/encoding.py +33 -0
  48. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/utils/filesystem.py +28 -0
  49. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/utils/glibc.py +84 -0
  50. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/utils/hashes.py +94 -0
  51. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/utils/logging.py +132 -0
  52. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/utils/misc.py +851 -0
  53. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/utils/outdated.py +163 -0
  54. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/utils/packaging.py +70 -0
  55. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/utils/setuptools_build.py +8 -0
  56. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/utils/temp_dir.py +82 -0
  57. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/utils/typing.py +29 -0
  58. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/utils/ui.py +421 -0
  59. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/vcs/__init__.py +471 -0
  60. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/vcs/bazaar.py +113 -0
  61. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/vcs/git.py +311 -0
  62. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/vcs/mercurial.py +105 -0
  63. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/vcs/subversion.py +271 -0
  64. package/python3.4.2/lib/python3.4/site-packages/pip/_internal/wheel.py +817 -0
  65. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/__init__.py +109 -8
  66. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/appdirs.py +604 -0
  67. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/cachecontrol/__init__.py +11 -0
  68. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/cachecontrol/_cmd.py +60 -0
  69. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/cachecontrol/adapter.py +134 -0
  70. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/cachecontrol/cache.py +39 -0
  71. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/cachecontrol/caches/__init__.py +2 -0
  72. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py +133 -0
  73. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py +43 -0
  74. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/cachecontrol/compat.py +29 -0
  75. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/cachecontrol/controller.py +373 -0
  76. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/cachecontrol/filewrapper.py +78 -0
  77. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/cachecontrol/heuristics.py +138 -0
  78. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/cachecontrol/serialize.py +194 -0
  79. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/cachecontrol/wrapper.py +27 -0
  80. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/certifi/__init__.py +3 -0
  81. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/certifi/__main__.py +2 -0
  82. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/{requests → certifi}/cacert.pem +1765 -2358
  83. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/certifi/core.py +37 -0
  84. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/{requests/packages/chardet → chardet}/__init__.py +39 -32
  85. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/chardet/big5freq.py +386 -0
  86. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/{requests/packages/chardet → chardet}/big5prober.py +47 -42
  87. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/{requests/packages/chardet → chardet}/chardistribution.py +233 -231
  88. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/chardet/charsetgroupprober.py +106 -0
  89. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/chardet/charsetprober.py +145 -0
  90. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/chardet/cli/__init__.py +1 -0
  91. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/chardet/cli/chardetect.py +85 -0
  92. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/chardet/codingstatemachine.py +88 -0
  93. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/{requests/packages/chardet → chardet}/compat.py +34 -34
  94. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/{requests/packages/chardet → chardet}/cp949prober.py +49 -44
  95. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/chardet/enums.py +76 -0
  96. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/chardet/escprober.py +101 -0
  97. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/chardet/escsm.py +246 -0
  98. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/chardet/eucjpprober.py +92 -0
  99. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/chardet/euckrfreq.py +195 -0
  100. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/{requests/packages/chardet → chardet}/euckrprober.py +47 -42
  101. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/{requests/packages/chardet → chardet}/euctwfreq.py +387 -428
  102. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/{requests/packages/chardet → chardet}/euctwprober.py +46 -41
  103. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/{requests/packages/chardet → chardet}/gb2312freq.py +283 -472
  104. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/{requests/packages/chardet → chardet}/gb2312prober.py +46 -41
  105. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/{requests/packages/chardet → chardet}/hebrewprober.py +292 -283
  106. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/{requests/packages/chardet → chardet}/jisfreq.py +325 -569
  107. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/{requests/packages/chardet → chardet}/jpcntx.py +233 -219
  108. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/{requests/packages/chardet → chardet}/langbulgarianmodel.py +228 -229
  109. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/{requests/packages/chardet → chardet}/langcyrillicmodel.py +333 -329
  110. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/{requests/packages/chardet → chardet}/langgreekmodel.py +225 -225
  111. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/{requests/packages/chardet → chardet}/langhebrewmodel.py +200 -201
  112. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/{requests/packages/chardet → chardet}/langhungarianmodel.py +225 -225
  113. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/{requests/packages/chardet → chardet}/langthaimodel.py +199 -200
  114. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/chardet/langturkishmodel.py +193 -0
  115. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/{requests/packages/chardet → chardet}/latin1prober.py +145 -139
  116. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/chardet/mbcharsetprober.py +91 -0
  117. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/{requests/packages/chardet → chardet}/mbcsgroupprober.py +54 -54
  118. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/chardet/mbcssm.py +572 -0
  119. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/chardet/sbcharsetprober.py +132 -0
  120. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/{requests/packages/chardet → chardet}/sbcsgroupprober.py +73 -69
  121. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/chardet/sjisprober.py +92 -0
  122. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/chardet/universaldetector.py +286 -0
  123. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/{requests/packages/chardet → chardet}/utf8prober.py +82 -76
  124. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/chardet/version.py +9 -0
  125. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/colorama/__init__.py +7 -7
  126. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/colorama/ansi.py +102 -50
  127. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/colorama/ansitowin32.py +236 -190
  128. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/colorama/initialise.py +82 -56
  129. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/colorama/win32.py +156 -137
  130. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/colorama/winterm.py +162 -120
  131. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/distlib/__init__.py +23 -23
  132. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/distlib/_backport/__init__.py +6 -6
  133. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/distlib/_backport/misc.py +41 -41
  134. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/distlib/_backport/shutil.py +761 -761
  135. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/distlib/_backport/sysconfig.cfg +84 -84
  136. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/distlib/_backport/sysconfig.py +788 -788
  137. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/distlib/_backport/tarfile.py +2607 -2607
  138. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/distlib/compat.py +1117 -1064
  139. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/distlib/database.py +1318 -1301
  140. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/distlib/index.py +516 -488
  141. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/distlib/locators.py +1292 -1194
  142. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/distlib/manifest.py +393 -364
  143. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/distlib/markers.py +131 -190
  144. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/distlib/metadata.py +1068 -1026
  145. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/distlib/resources.py +355 -317
  146. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/distlib/scripts.py +415 -323
  147. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/distlib/t32.exe +0 -0
  148. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/distlib/t64.exe +0 -0
  149. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/distlib/util.py +1755 -1575
  150. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/distlib/version.py +736 -721
  151. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/distlib/w32.exe +0 -0
  152. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/distlib/w64.exe +0 -0
  153. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/distlib/wheel.py +984 -958
  154. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/distro.py +1104 -0
  155. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/__init__.py +35 -23
  156. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/{ihatexml.py → _ihatexml.py} +288 -285
  157. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/{inputstream.py → _inputstream.py} +923 -881
  158. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/{tokenizer.py → _tokenizer.py} +1721 -1731
  159. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/{trie → _trie}/__init__.py +14 -12
  160. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/{trie → _trie}/_base.py +37 -37
  161. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/{trie → _trie}/datrie.py +44 -44
  162. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/{trie → _trie}/py.py +67 -67
  163. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/{utils.py → _utils.py} +124 -82
  164. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/constants.py +2947 -3104
  165. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/filters/alphabeticalattributes.py +29 -20
  166. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/filters/{_base.py → base.py} +12 -12
  167. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/filters/inject_meta_charset.py +73 -65
  168. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/filters/lint.py +93 -93
  169. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/filters/optionaltags.py +207 -205
  170. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/filters/sanitizer.py +896 -12
  171. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/filters/whitespace.py +38 -38
  172. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/html5parser.py +2791 -2713
  173. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/serializer.py +409 -0
  174. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/treeadapters/__init__.py +30 -0
  175. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/treeadapters/genshi.py +54 -0
  176. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/treeadapters/sax.py +50 -44
  177. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/treebuilders/__init__.py +88 -76
  178. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/treebuilders/{_base.py → base.py} +417 -377
  179. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/treebuilders/dom.py +236 -227
  180. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/treebuilders/etree.py +340 -337
  181. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/treebuilders/etree_lxml.py +366 -369
  182. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/treewalkers/__init__.py +154 -57
  183. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/treewalkers/{_base.py → base.py} +252 -200
  184. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/treewalkers/dom.py +43 -46
  185. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/treewalkers/etree.py +130 -138
  186. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/treewalkers/{lxmletree.py → etree_lxml.py} +213 -208
  187. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/treewalkers/{genshistream.py → genshi.py} +69 -69
  188. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/idna/__init__.py +2 -0
  189. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/idna/codec.py +118 -0
  190. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/idna/compat.py +12 -0
  191. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/idna/core.py +387 -0
  192. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/idna/idnadata.py +1585 -0
  193. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/idna/intranges.py +53 -0
  194. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/idna/package_data.py +2 -0
  195. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/idna/uts46data.py +7634 -0
  196. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/ipaddress.py +2419 -0
  197. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/lockfile/__init__.py +347 -0
  198. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/lockfile/linklockfile.py +73 -0
  199. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/lockfile/mkdirlockfile.py +84 -0
  200. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/lockfile/pidlockfile.py +190 -0
  201. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/lockfile/sqlitelockfile.py +156 -0
  202. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/lockfile/symlinklockfile.py +70 -0
  203. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/msgpack/__init__.py +66 -0
  204. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/msgpack/_version.py +1 -0
  205. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/msgpack/exceptions.py +41 -0
  206. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/msgpack/fallback.py +971 -0
  207. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/packaging/__about__.py +21 -0
  208. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/packaging/__init__.py +14 -0
  209. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/packaging/_compat.py +30 -0
  210. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/packaging/_structures.py +70 -0
  211. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/packaging/markers.py +301 -0
  212. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/packaging/requirements.py +130 -0
  213. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/packaging/specifiers.py +774 -0
  214. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/packaging/utils.py +63 -0
  215. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/packaging/version.py +441 -0
  216. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/{pkg_resources.py → pkg_resources/__init__.py} +3125 -2762
  217. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/pkg_resources/py31compat.py +22 -0
  218. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/progress/__init__.py +127 -0
  219. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/progress/bar.py +88 -0
  220. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/progress/counter.py +48 -0
  221. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/progress/helpers.py +91 -0
  222. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/progress/spinner.py +44 -0
  223. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/pyparsing.py +5720 -0
  224. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/pytoml/__init__.py +3 -0
  225. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/pytoml/core.py +13 -0
  226. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/pytoml/parser.py +374 -0
  227. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/pytoml/writer.py +127 -0
  228. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/__init__.py +123 -77
  229. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/__version__.py +14 -0
  230. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/_internal_utils.py +42 -0
  231. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/adapters.py +525 -388
  232. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/api.py +152 -120
  233. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/auth.py +293 -193
  234. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/certs.py +18 -24
  235. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/compat.py +73 -115
  236. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/cookies.py +542 -454
  237. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/exceptions.py +122 -75
  238. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/help.py +120 -0
  239. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/hooks.py +34 -45
  240. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/models.py +948 -803
  241. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/packages.py +16 -0
  242. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/sessions.py +737 -637
  243. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/status_codes.py +91 -88
  244. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/structures.py +105 -127
  245. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/utils.py +904 -673
  246. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/retrying.py +267 -0
  247. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/six.py +891 -646
  248. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/urllib3/__init__.py +97 -0
  249. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/urllib3/_collections.py +319 -0
  250. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/urllib3/connection.py +373 -0
  251. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/{requests/packages/urllib3 → urllib3}/connectionpool.py +905 -710
  252. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/urllib3/contrib/__init__.py +0 -0
  253. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__init__.py +0 -0
  254. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/urllib3/contrib/_securetransport/bindings.py +593 -0
  255. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/urllib3/contrib/_securetransport/low_level.py +343 -0
  256. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/urllib3/contrib/appengine.py +296 -0
  257. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/{requests/packages/urllib3 → urllib3}/contrib/ntlmpool.py +112 -120
  258. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py +455 -0
  259. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/urllib3/contrib/securetransport.py +810 -0
  260. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/urllib3/contrib/socks.py +188 -0
  261. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/urllib3/exceptions.py +246 -0
  262. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/{requests/packages/urllib3 → urllib3}/fields.py +178 -177
  263. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/{requests/packages/urllib3 → urllib3}/filepost.py +94 -100
  264. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/{requests/packages/urllib3 → urllib3}/packages/__init__.py +5 -4
  265. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py +0 -0
  266. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py +53 -0
  267. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/{requests/packages/urllib3 → urllib3}/packages/ordered_dict.py +259 -260
  268. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/urllib3/packages/six.py +868 -0
  269. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/{requests/packages/urllib3 → urllib3}/packages/ssl_match_hostname/__init__.py +19 -13
  270. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/{requests/packages/urllib3 → urllib3}/packages/ssl_match_hostname/_implementation.py +157 -105
  271. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/urllib3/poolmanager.py +440 -0
  272. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/{requests/packages/urllib3 → urllib3}/request.py +148 -141
  273. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/urllib3/response.py +626 -0
  274. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/urllib3/util/__init__.py +54 -0
  275. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/urllib3/util/connection.py +130 -0
  276. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/urllib3/util/request.py +118 -0
  277. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/urllib3/util/response.py +81 -0
  278. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/urllib3/util/retry.py +401 -0
  279. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/urllib3/util/selectors.py +581 -0
  280. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/urllib3/util/ssl_.py +341 -0
  281. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/{requests/packages/urllib3 → urllib3}/util/timeout.py +242 -234
  282. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/{requests/packages/urllib3 → urllib3}/util/url.py +230 -162
  283. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/urllib3/util/wait.py +40 -0
  284. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/webencodings/__init__.py +342 -0
  285. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/webencodings/labels.py +231 -0
  286. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/webencodings/mklabels.py +59 -0
  287. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/webencodings/tests.py +153 -0
  288. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/webencodings/x_user_defined.py +325 -0
  289. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/_markerlib/__init__.py +0 -16
  290. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/_markerlib/markers.py +0 -119
  291. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/sanitizer.py +0 -271
  292. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/serializer/__init__.py +0 -16
  293. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/serializer/htmlserializer.py +0 -320
  294. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/html5lib/treewalkers/pulldom.py +0 -63
  295. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/re-vendor.py +0 -34
  296. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/packages/__init__.py +0 -3
  297. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/packages/chardet/big5freq.py +0 -925
  298. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/packages/chardet/chardetect.py +0 -46
  299. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/packages/chardet/charsetgroupprober.py +0 -106
  300. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/packages/chardet/charsetprober.py +0 -62
  301. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/packages/chardet/codingstatemachine.py +0 -61
  302. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/packages/chardet/constants.py +0 -39
  303. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/packages/chardet/escprober.py +0 -86
  304. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/packages/chardet/escsm.py +0 -242
  305. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/packages/chardet/eucjpprober.py +0 -90
  306. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/packages/chardet/euckrfreq.py +0 -596
  307. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/packages/chardet/mbcharsetprober.py +0 -86
  308. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/packages/chardet/mbcssm.py +0 -575
  309. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/packages/chardet/sbcharsetprober.py +0 -120
  310. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/packages/chardet/sjisprober.py +0 -91
  311. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/packages/chardet/universaldetector.py +0 -170
  312. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/packages/urllib3/__init__.py +0 -58
  313. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/packages/urllib3/_collections.py +0 -205
  314. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/packages/urllib3/connection.py +0 -204
  315. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/packages/urllib3/contrib/pyopenssl.py +0 -422
  316. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/packages/urllib3/exceptions.py +0 -126
  317. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/packages/urllib3/packages/six.py +0 -385
  318. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/packages/urllib3/poolmanager.py +0 -258
  319. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/packages/urllib3/response.py +0 -308
  320. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/packages/urllib3/util/__init__.py +0 -27
  321. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/packages/urllib3/util/connection.py +0 -45
  322. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/packages/urllib3/util/request.py +0 -68
  323. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/packages/urllib3/util/response.py +0 -13
  324. package/python3.4.2/lib/python3.4/site-packages/pip/_vendor/requests/packages/urllib3/util/ssl_.py +0 -133
  325. package/python3.4.2/lib/python3.4/site-packages/pip/backwardcompat/__init__.py +0 -138
  326. package/python3.4.2/lib/python3.4/site-packages/pip/basecommand.py +0 -201
  327. package/python3.4.2/lib/python3.4/site-packages/pip/cmdoptions.py +0 -371
  328. package/python3.4.2/lib/python3.4/site-packages/pip/commands/__init__.py +0 -88
  329. package/python3.4.2/lib/python3.4/site-packages/pip/commands/bundle.py +0 -42
  330. package/python3.4.2/lib/python3.4/site-packages/pip/commands/completion.py +0 -59
  331. package/python3.4.2/lib/python3.4/site-packages/pip/commands/freeze.py +0 -114
  332. package/python3.4.2/lib/python3.4/site-packages/pip/commands/install.py +0 -314
  333. package/python3.4.2/lib/python3.4/site-packages/pip/commands/list.py +0 -162
  334. package/python3.4.2/lib/python3.4/site-packages/pip/commands/search.py +0 -132
  335. package/python3.4.2/lib/python3.4/site-packages/pip/commands/show.py +0 -80
  336. package/python3.4.2/lib/python3.4/site-packages/pip/commands/uninstall.py +0 -59
  337. package/python3.4.2/lib/python3.4/site-packages/pip/commands/unzip.py +0 -7
  338. package/python3.4.2/lib/python3.4/site-packages/pip/commands/wheel.py +0 -195
  339. package/python3.4.2/lib/python3.4/site-packages/pip/commands/zip.py +0 -351
  340. package/python3.4.2/lib/python3.4/site-packages/pip/download.py +0 -644
  341. package/python3.4.2/lib/python3.4/site-packages/pip/exceptions.py +0 -46
  342. package/python3.4.2/lib/python3.4/site-packages/pip/index.py +0 -990
  343. package/python3.4.2/lib/python3.4/site-packages/pip/locations.py +0 -171
  344. package/python3.4.2/lib/python3.4/site-packages/pip/log.py +0 -276
  345. package/python3.4.2/lib/python3.4/site-packages/pip/pep425tags.py +0 -102
  346. package/python3.4.2/lib/python3.4/site-packages/pip/req.py +0 -1931
  347. package/python3.4.2/lib/python3.4/site-packages/pip/runner.py +0 -18
  348. package/python3.4.2/lib/python3.4/site-packages/pip/util.py +0 -720
  349. package/python3.4.2/lib/python3.4/site-packages/pip/vcs/__init__.py +0 -251
  350. package/python3.4.2/lib/python3.4/site-packages/pip/vcs/bazaar.py +0 -131
  351. package/python3.4.2/lib/python3.4/site-packages/pip/vcs/git.py +0 -194
  352. package/python3.4.2/lib/python3.4/site-packages/pip/vcs/mercurial.py +0 -151
  353. package/python3.4.2/lib/python3.4/site-packages/pip/vcs/subversion.py +0 -273
  354. package/python3.4.2/lib/python3.4/site-packages/pip/wheel.py +0 -560
@@ -1,1026 +1,1068 @@
1
- # -*- coding: utf-8 -*-
2
- #
3
- # Copyright (C) 2012 The Python Software Foundation.
4
- # See LICENSE.txt and CONTRIBUTORS.txt.
5
- #
6
- """Implementation of the Metadata for Python packages PEPs.
7
-
8
- Supports all metadata formats (1.0, 1.1, 1.2, and 2.0 experimental).
9
- """
10
- from __future__ import unicode_literals
11
-
12
- import codecs
13
- from email import message_from_file
14
- import json
15
- import logging
16
- import re
17
-
18
-
19
- from . import DistlibException, __version__
20
- from .compat import StringIO, string_types, text_type
21
- from .markers import interpret
22
- from .util import extract_by_key, get_extras
23
- from .version import get_scheme, PEP426_VERSION_RE
24
-
25
- logger = logging.getLogger(__name__)
26
-
27
-
28
- class MetadataMissingError(DistlibException):
29
- """A required metadata is missing"""
30
-
31
-
32
- class MetadataConflictError(DistlibException):
33
- """Attempt to read or write metadata fields that are conflictual."""
34
-
35
-
36
- class MetadataUnrecognizedVersionError(DistlibException):
37
- """Unknown metadata version number."""
38
-
39
-
40
- class MetadataInvalidError(DistlibException):
41
- """A metadata value is invalid"""
42
-
43
- # public API of this module
44
- __all__ = ['Metadata', 'PKG_INFO_ENCODING', 'PKG_INFO_PREFERRED_VERSION']
45
-
46
- # Encoding used for the PKG-INFO files
47
- PKG_INFO_ENCODING = 'utf-8'
48
-
49
- # preferred version. Hopefully will be changed
50
- # to 1.2 once PEP 345 is supported everywhere
51
- PKG_INFO_PREFERRED_VERSION = '1.1'
52
-
53
- _LINE_PREFIX = re.compile('\n \|')
54
- _241_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform',
55
- 'Summary', 'Description',
56
- 'Keywords', 'Home-page', 'Author', 'Author-email',
57
- 'License')
58
-
59
- _314_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform',
60
- 'Supported-Platform', 'Summary', 'Description',
61
- 'Keywords', 'Home-page', 'Author', 'Author-email',
62
- 'License', 'Classifier', 'Download-URL', 'Obsoletes',
63
- 'Provides', 'Requires')
64
-
65
- _314_MARKERS = ('Obsoletes', 'Provides', 'Requires', 'Classifier',
66
- 'Download-URL')
67
-
68
- _345_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform',
69
- 'Supported-Platform', 'Summary', 'Description',
70
- 'Keywords', 'Home-page', 'Author', 'Author-email',
71
- 'Maintainer', 'Maintainer-email', 'License',
72
- 'Classifier', 'Download-URL', 'Obsoletes-Dist',
73
- 'Project-URL', 'Provides-Dist', 'Requires-Dist',
74
- 'Requires-Python', 'Requires-External')
75
-
76
- _345_MARKERS = ('Provides-Dist', 'Requires-Dist', 'Requires-Python',
77
- 'Obsoletes-Dist', 'Requires-External', 'Maintainer',
78
- 'Maintainer-email', 'Project-URL')
79
-
80
- _426_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform',
81
- 'Supported-Platform', 'Summary', 'Description',
82
- 'Keywords', 'Home-page', 'Author', 'Author-email',
83
- 'Maintainer', 'Maintainer-email', 'License',
84
- 'Classifier', 'Download-URL', 'Obsoletes-Dist',
85
- 'Project-URL', 'Provides-Dist', 'Requires-Dist',
86
- 'Requires-Python', 'Requires-External', 'Private-Version',
87
- 'Obsoleted-By', 'Setup-Requires-Dist', 'Extension',
88
- 'Provides-Extra')
89
-
90
- _426_MARKERS = ('Private-Version', 'Provides-Extra', 'Obsoleted-By',
91
- 'Setup-Requires-Dist', 'Extension')
92
-
93
- _ALL_FIELDS = set()
94
- _ALL_FIELDS.update(_241_FIELDS)
95
- _ALL_FIELDS.update(_314_FIELDS)
96
- _ALL_FIELDS.update(_345_FIELDS)
97
- _ALL_FIELDS.update(_426_FIELDS)
98
-
99
- EXTRA_RE = re.compile(r'''extra\s*==\s*("([^"]+)"|'([^']+)')''')
100
-
101
-
102
- def _version2fieldlist(version):
103
- if version == '1.0':
104
- return _241_FIELDS
105
- elif version == '1.1':
106
- return _314_FIELDS
107
- elif version == '1.2':
108
- return _345_FIELDS
109
- elif version == '2.0':
110
- return _426_FIELDS
111
- raise MetadataUnrecognizedVersionError(version)
112
-
113
-
114
- def _best_version(fields):
115
- """Detect the best version depending on the fields used."""
116
- def _has_marker(keys, markers):
117
- for marker in markers:
118
- if marker in keys:
119
- return True
120
- return False
121
-
122
- keys = []
123
- for key, value in fields.items():
124
- if value in ([], 'UNKNOWN', None):
125
- continue
126
- keys.append(key)
127
-
128
- possible_versions = ['1.0', '1.1', '1.2', '2.0']
129
-
130
- # first let's try to see if a field is not part of one of the version
131
- for key in keys:
132
- if key not in _241_FIELDS and '1.0' in possible_versions:
133
- possible_versions.remove('1.0')
134
- if key not in _314_FIELDS and '1.1' in possible_versions:
135
- possible_versions.remove('1.1')
136
- if key not in _345_FIELDS and '1.2' in possible_versions:
137
- possible_versions.remove('1.2')
138
- if key not in _426_FIELDS and '2.0' in possible_versions:
139
- possible_versions.remove('2.0')
140
-
141
- # possible_version contains qualified versions
142
- if len(possible_versions) == 1:
143
- return possible_versions[0] # found !
144
- elif len(possible_versions) == 0:
145
- raise MetadataConflictError('Unknown metadata set')
146
-
147
- # let's see if one unique marker is found
148
- is_1_1 = '1.1' in possible_versions and _has_marker(keys, _314_MARKERS)
149
- is_1_2 = '1.2' in possible_versions and _has_marker(keys, _345_MARKERS)
150
- is_2_0 = '2.0' in possible_versions and _has_marker(keys, _426_MARKERS)
151
- if int(is_1_1) + int(is_1_2) + int(is_2_0) > 1:
152
- raise MetadataConflictError('You used incompatible 1.1/1.2/2.0 fields')
153
-
154
- # we have the choice, 1.0, or 1.2, or 2.0
155
- # - 1.0 has a broken Summary field but works with all tools
156
- # - 1.1 is to avoid
157
- # - 1.2 fixes Summary but has little adoption
158
- # - 2.0 adds more features and is very new
159
- if not is_1_1 and not is_1_2 and not is_2_0:
160
- # we couldn't find any specific marker
161
- if PKG_INFO_PREFERRED_VERSION in possible_versions:
162
- return PKG_INFO_PREFERRED_VERSION
163
- if is_1_1:
164
- return '1.1'
165
- if is_1_2:
166
- return '1.2'
167
-
168
- return '2.0'
169
-
170
- _ATTR2FIELD = {
171
- 'metadata_version': 'Metadata-Version',
172
- 'name': 'Name',
173
- 'version': 'Version',
174
- 'platform': 'Platform',
175
- 'supported_platform': 'Supported-Platform',
176
- 'summary': 'Summary',
177
- 'description': 'Description',
178
- 'keywords': 'Keywords',
179
- 'home_page': 'Home-page',
180
- 'author': 'Author',
181
- 'author_email': 'Author-email',
182
- 'maintainer': 'Maintainer',
183
- 'maintainer_email': 'Maintainer-email',
184
- 'license': 'License',
185
- 'classifier': 'Classifier',
186
- 'download_url': 'Download-URL',
187
- 'obsoletes_dist': 'Obsoletes-Dist',
188
- 'provides_dist': 'Provides-Dist',
189
- 'requires_dist': 'Requires-Dist',
190
- 'setup_requires_dist': 'Setup-Requires-Dist',
191
- 'requires_python': 'Requires-Python',
192
- 'requires_external': 'Requires-External',
193
- 'requires': 'Requires',
194
- 'provides': 'Provides',
195
- 'obsoletes': 'Obsoletes',
196
- 'project_url': 'Project-URL',
197
- 'private_version': 'Private-Version',
198
- 'obsoleted_by': 'Obsoleted-By',
199
- 'extension': 'Extension',
200
- 'provides_extra': 'Provides-Extra',
201
- }
202
-
203
- _PREDICATE_FIELDS = ('Requires-Dist', 'Obsoletes-Dist', 'Provides-Dist')
204
- _VERSIONS_FIELDS = ('Requires-Python',)
205
- _VERSION_FIELDS = ('Version',)
206
- _LISTFIELDS = ('Platform', 'Classifier', 'Obsoletes',
207
- 'Requires', 'Provides', 'Obsoletes-Dist',
208
- 'Provides-Dist', 'Requires-Dist', 'Requires-External',
209
- 'Project-URL', 'Supported-Platform', 'Setup-Requires-Dist',
210
- 'Provides-Extra', 'Extension')
211
- _LISTTUPLEFIELDS = ('Project-URL',)
212
-
213
- _ELEMENTSFIELD = ('Keywords',)
214
-
215
- _UNICODEFIELDS = ('Author', 'Maintainer', 'Summary', 'Description')
216
-
217
- _MISSING = object()
218
-
219
- _FILESAFE = re.compile('[^A-Za-z0-9.]+')
220
-
221
-
222
- def _get_name_and_version(name, version, for_filename=False):
223
- """Return the distribution name with version.
224
-
225
- If for_filename is true, return a filename-escaped form."""
226
- if for_filename:
227
- # For both name and version any runs of non-alphanumeric or '.'
228
- # characters are replaced with a single '-'. Additionally any
229
- # spaces in the version string become '.'
230
- name = _FILESAFE.sub('-', name)
231
- version = _FILESAFE.sub('-', version.replace(' ', '.'))
232
- return '%s-%s' % (name, version)
233
-
234
-
235
- class LegacyMetadata(object):
236
- """The legacy metadata of a release.
237
-
238
- Supports versions 1.0, 1.1 and 1.2 (auto-detected). You can
239
- instantiate the class with one of these arguments (or none):
240
- - *path*, the path to a metadata file
241
- - *fileobj* give a file-like object with metadata as content
242
- - *mapping* is a dict-like object
243
- - *scheme* is a version scheme name
244
- """
245
- # TODO document the mapping API and UNKNOWN default key
246
-
247
- def __init__(self, path=None, fileobj=None, mapping=None,
248
- scheme='default'):
249
- if [path, fileobj, mapping].count(None) < 2:
250
- raise TypeError('path, fileobj and mapping are exclusive')
251
- self._fields = {}
252
- self.requires_files = []
253
- self._dependencies = None
254
- self.scheme = scheme
255
- if path is not None:
256
- self.read(path)
257
- elif fileobj is not None:
258
- self.read_file(fileobj)
259
- elif mapping is not None:
260
- self.update(mapping)
261
- self.set_metadata_version()
262
-
263
- def set_metadata_version(self):
264
- self._fields['Metadata-Version'] = _best_version(self._fields)
265
-
266
- def _write_field(self, fileobj, name, value):
267
- fileobj.write('%s: %s\n' % (name, value))
268
-
269
- def __getitem__(self, name):
270
- return self.get(name)
271
-
272
- def __setitem__(self, name, value):
273
- return self.set(name, value)
274
-
275
- def __delitem__(self, name):
276
- field_name = self._convert_name(name)
277
- try:
278
- del self._fields[field_name]
279
- except KeyError:
280
- raise KeyError(name)
281
-
282
- def __contains__(self, name):
283
- return (name in self._fields or
284
- self._convert_name(name) in self._fields)
285
-
286
- def _convert_name(self, name):
287
- if name in _ALL_FIELDS:
288
- return name
289
- name = name.replace('-', '_').lower()
290
- return _ATTR2FIELD.get(name, name)
291
-
292
- def _default_value(self, name):
293
- if name in _LISTFIELDS or name in _ELEMENTSFIELD:
294
- return []
295
- return 'UNKNOWN'
296
-
297
- def _remove_line_prefix(self, value):
298
- return _LINE_PREFIX.sub('\n', value)
299
-
300
- def __getattr__(self, name):
301
- if name in _ATTR2FIELD:
302
- return self[name]
303
- raise AttributeError(name)
304
-
305
- #
306
- # Public API
307
- #
308
-
309
- # dependencies = property(_get_dependencies, _set_dependencies)
310
-
311
- def get_fullname(self, filesafe=False):
312
- """Return the distribution name with version.
313
-
314
- If filesafe is true, return a filename-escaped form."""
315
- return _get_name_and_version(self['Name'], self['Version'], filesafe)
316
-
317
- def is_field(self, name):
318
- """return True if name is a valid metadata key"""
319
- name = self._convert_name(name)
320
- return name in _ALL_FIELDS
321
-
322
- def is_multi_field(self, name):
323
- name = self._convert_name(name)
324
- return name in _LISTFIELDS
325
-
326
- def read(self, filepath):
327
- """Read the metadata values from a file path."""
328
- fp = codecs.open(filepath, 'r', encoding='utf-8')
329
- try:
330
- self.read_file(fp)
331
- finally:
332
- fp.close()
333
-
334
- def read_file(self, fileob):
335
- """Read the metadata values from a file object."""
336
- msg = message_from_file(fileob)
337
- self._fields['Metadata-Version'] = msg['metadata-version']
338
-
339
- # When reading, get all the fields we can
340
- for field in _ALL_FIELDS:
341
- if field not in msg:
342
- continue
343
- if field in _LISTFIELDS:
344
- # we can have multiple lines
345
- values = msg.get_all(field)
346
- if field in _LISTTUPLEFIELDS and values is not None:
347
- values = [tuple(value.split(',')) for value in values]
348
- self.set(field, values)
349
- else:
350
- # single line
351
- value = msg[field]
352
- if value is not None and value != 'UNKNOWN':
353
- self.set(field, value)
354
- self.set_metadata_version()
355
-
356
- def write(self, filepath, skip_unknown=False):
357
- """Write the metadata fields to filepath."""
358
- fp = codecs.open(filepath, 'w', encoding='utf-8')
359
- try:
360
- self.write_file(fp, skip_unknown)
361
- finally:
362
- fp.close()
363
-
364
- def write_file(self, fileobject, skip_unknown=False):
365
- """Write the PKG-INFO format data to a file object."""
366
- self.set_metadata_version()
367
-
368
- for field in _version2fieldlist(self['Metadata-Version']):
369
- values = self.get(field)
370
- if skip_unknown and values in ('UNKNOWN', [], ['UNKNOWN']):
371
- continue
372
- if field in _ELEMENTSFIELD:
373
- self._write_field(fileobject, field, ','.join(values))
374
- continue
375
- if field not in _LISTFIELDS:
376
- if field == 'Description':
377
- values = values.replace('\n', '\n |')
378
- values = [values]
379
-
380
- if field in _LISTTUPLEFIELDS:
381
- values = [','.join(value) for value in values]
382
-
383
- for value in values:
384
- self._write_field(fileobject, field, value)
385
-
386
- def update(self, other=None, **kwargs):
387
- """Set metadata values from the given iterable `other` and kwargs.
388
-
389
- Behavior is like `dict.update`: If `other` has a ``keys`` method,
390
- they are looped over and ``self[key]`` is assigned ``other[key]``.
391
- Else, ``other`` is an iterable of ``(key, value)`` iterables.
392
-
393
- Keys that don't match a metadata field or that have an empty value are
394
- dropped.
395
- """
396
- def _set(key, value):
397
- if key in _ATTR2FIELD and value:
398
- self.set(self._convert_name(key), value)
399
-
400
- if not other:
401
- # other is None or empty container
402
- pass
403
- elif hasattr(other, 'keys'):
404
- for k in other.keys():
405
- _set(k, other[k])
406
- else:
407
- for k, v in other:
408
- _set(k, v)
409
-
410
- if kwargs:
411
- for k, v in kwargs.items():
412
- _set(k, v)
413
-
414
- def set(self, name, value):
415
- """Control then set a metadata field."""
416
- name = self._convert_name(name)
417
-
418
- if ((name in _ELEMENTSFIELD or name == 'Platform') and
419
- not isinstance(value, (list, tuple))):
420
- if isinstance(value, string_types):
421
- value = [v.strip() for v in value.split(',')]
422
- else:
423
- value = []
424
- elif (name in _LISTFIELDS and
425
- not isinstance(value, (list, tuple))):
426
- if isinstance(value, string_types):
427
- value = [value]
428
- else:
429
- value = []
430
-
431
- if logger.isEnabledFor(logging.WARNING):
432
- project_name = self['Name']
433
-
434
- scheme = get_scheme(self.scheme)
435
- if name in _PREDICATE_FIELDS and value is not None:
436
- for v in value:
437
- # check that the values are valid
438
- if not scheme.is_valid_matcher(v.split(';')[0]):
439
- logger.warning(
440
- '%r: %r is not valid (field %r)',
441
- project_name, v, name)
442
- # FIXME this rejects UNKNOWN, is that right?
443
- elif name in _VERSIONS_FIELDS and value is not None:
444
- if not scheme.is_valid_constraint_list(value):
445
- logger.warning('%r: %r is not a valid version (field %r)',
446
- project_name, value, name)
447
- elif name in _VERSION_FIELDS and value is not None:
448
- if not scheme.is_valid_version(value):
449
- logger.warning('%r: %r is not a valid version (field %r)',
450
- project_name, value, name)
451
-
452
- if name in _UNICODEFIELDS:
453
- if name == 'Description':
454
- value = self._remove_line_prefix(value)
455
-
456
- self._fields[name] = value
457
-
458
- def get(self, name, default=_MISSING):
459
- """Get a metadata field."""
460
- name = self._convert_name(name)
461
- if name not in self._fields:
462
- if default is _MISSING:
463
- default = self._default_value(name)
464
- return default
465
- if name in _UNICODEFIELDS:
466
- value = self._fields[name]
467
- return value
468
- elif name in _LISTFIELDS:
469
- value = self._fields[name]
470
- if value is None:
471
- return []
472
- res = []
473
- for val in value:
474
- if name not in _LISTTUPLEFIELDS:
475
- res.append(val)
476
- else:
477
- # That's for Project-URL
478
- res.append((val[0], val[1]))
479
- return res
480
-
481
- elif name in _ELEMENTSFIELD:
482
- value = self._fields[name]
483
- if isinstance(value, string_types):
484
- return value.split(',')
485
- return self._fields[name]
486
-
487
- def check(self, strict=False):
488
- """Check if the metadata is compliant. If strict is True then raise if
489
- no Name or Version are provided"""
490
- self.set_metadata_version()
491
-
492
- # XXX should check the versions (if the file was loaded)
493
- missing, warnings = [], []
494
-
495
- for attr in ('Name', 'Version'): # required by PEP 345
496
- if attr not in self:
497
- missing.append(attr)
498
-
499
- if strict and missing != []:
500
- msg = 'missing required metadata: %s' % ', '.join(missing)
501
- raise MetadataMissingError(msg)
502
-
503
- for attr in ('Home-page', 'Author'):
504
- if attr not in self:
505
- missing.append(attr)
506
-
507
- # checking metadata 1.2 (XXX needs to check 1.1, 1.0)
508
- if self['Metadata-Version'] != '1.2':
509
- return missing, warnings
510
-
511
- scheme = get_scheme(self.scheme)
512
-
513
- def are_valid_constraints(value):
514
- for v in value:
515
- if not scheme.is_valid_matcher(v.split(';')[0]):
516
- return False
517
- return True
518
-
519
- for fields, controller in ((_PREDICATE_FIELDS, are_valid_constraints),
520
- (_VERSIONS_FIELDS,
521
- scheme.is_valid_constraint_list),
522
- (_VERSION_FIELDS,
523
- scheme.is_valid_version)):
524
- for field in fields:
525
- value = self.get(field, None)
526
- if value is not None and not controller(value):
527
- warnings.append('Wrong value for %r: %s' % (field, value))
528
-
529
- return missing, warnings
530
-
531
- def todict(self, skip_missing=False):
532
- """Return fields as a dict.
533
-
534
- Field names will be converted to use the underscore-lowercase style
535
- instead of hyphen-mixed case (i.e. home_page instead of Home-page).
536
- """
537
- self.set_metadata_version()
538
-
539
- mapping_1_0 = (
540
- ('metadata_version', 'Metadata-Version'),
541
- ('name', 'Name'),
542
- ('version', 'Version'),
543
- ('summary', 'Summary'),
544
- ('home_page', 'Home-page'),
545
- ('author', 'Author'),
546
- ('author_email', 'Author-email'),
547
- ('license', 'License'),
548
- ('description', 'Description'),
549
- ('keywords', 'Keywords'),
550
- ('platform', 'Platform'),
551
- ('classifier', 'Classifier'),
552
- ('download_url', 'Download-URL'),
553
- )
554
-
555
- data = {}
556
- for key, field_name in mapping_1_0:
557
- if not skip_missing or field_name in self._fields:
558
- data[key] = self[field_name]
559
-
560
- if self['Metadata-Version'] == '1.2':
561
- mapping_1_2 = (
562
- ('requires_dist', 'Requires-Dist'),
563
- ('requires_python', 'Requires-Python'),
564
- ('requires_external', 'Requires-External'),
565
- ('provides_dist', 'Provides-Dist'),
566
- ('obsoletes_dist', 'Obsoletes-Dist'),
567
- ('project_url', 'Project-URL'),
568
- ('maintainer', 'Maintainer'),
569
- ('maintainer_email', 'Maintainer-email'),
570
- )
571
- for key, field_name in mapping_1_2:
572
- if not skip_missing or field_name in self._fields:
573
- if key != 'project_url':
574
- data[key] = self[field_name]
575
- else:
576
- data[key] = [','.join(u) for u in self[field_name]]
577
-
578
- elif self['Metadata-Version'] == '1.1':
579
- mapping_1_1 = (
580
- ('provides', 'Provides'),
581
- ('requires', 'Requires'),
582
- ('obsoletes', 'Obsoletes'),
583
- )
584
- for key, field_name in mapping_1_1:
585
- if not skip_missing or field_name in self._fields:
586
- data[key] = self[field_name]
587
-
588
- return data
589
-
590
- def add_requirements(self, requirements):
591
- if self['Metadata-Version'] == '1.1':
592
- # we can't have 1.1 metadata *and* Setuptools requires
593
- for field in ('Obsoletes', 'Requires', 'Provides'):
594
- if field in self:
595
- del self[field]
596
- self['Requires-Dist'] += requirements
597
-
598
- # Mapping API
599
- # TODO could add iter* variants
600
-
601
- def keys(self):
602
- return list(_version2fieldlist(self['Metadata-Version']))
603
-
604
- def __iter__(self):
605
- for key in self.keys():
606
- yield key
607
-
608
- def values(self):
609
- return [self[key] for key in self.keys()]
610
-
611
- def items(self):
612
- return [(key, self[key]) for key in self.keys()]
613
-
614
- def __repr__(self):
615
- return '<%s %s %s>' % (self.__class__.__name__, self.name,
616
- self.version)
617
-
618
-
619
- METADATA_FILENAME = 'pydist.json'
620
-
621
-
622
- class Metadata(object):
623
- """
624
- The metadata of a release. This implementation uses 2.0 (JSON)
625
- metadata where possible. If not possible, it wraps a LegacyMetadata
626
- instance which handles the key-value metadata format.
627
- """
628
-
629
- METADATA_VERSION_MATCHER = re.compile('^\d+(\.\d+)*$')
630
-
631
- NAME_MATCHER = re.compile('^[0-9A-Z]([0-9A-Z_.-]*[0-9A-Z])?$', re.I)
632
-
633
- VERSION_MATCHER = PEP426_VERSION_RE
634
-
635
- SUMMARY_MATCHER = re.compile('.{1,2047}')
636
-
637
- METADATA_VERSION = '2.0'
638
-
639
- GENERATOR = 'distlib (%s)' % __version__
640
-
641
- MANDATORY_KEYS = {
642
- 'name': (),
643
- 'version': (),
644
- 'summary': ('legacy',),
645
- }
646
-
647
- INDEX_KEYS = ('name version license summary description author '
648
- 'author_email keywords platform home_page classifiers '
649
- 'download_url')
650
-
651
- DEPENDENCY_KEYS = ('extras run_requires test_requires build_requires '
652
- 'dev_requires provides meta_requires obsoleted_by '
653
- 'supports_environments')
654
-
655
- SYNTAX_VALIDATORS = {
656
- 'metadata_version': (METADATA_VERSION_MATCHER, ()),
657
- 'name': (NAME_MATCHER, ('legacy',)),
658
- 'version': (VERSION_MATCHER, ('legacy',)),
659
- 'summary': (SUMMARY_MATCHER, ('legacy',)),
660
- }
661
-
662
- __slots__ = ('_legacy', '_data', 'scheme')
663
-
664
- def __init__(self, path=None, fileobj=None, mapping=None,
665
- scheme='default'):
666
- if [path, fileobj, mapping].count(None) < 2:
667
- raise TypeError('path, fileobj and mapping are exclusive')
668
- self._legacy = None
669
- self._data = None
670
- self.scheme = scheme
671
- #import pdb; pdb.set_trace()
672
- if mapping is not None:
673
- try:
674
- self._validate_mapping(mapping, scheme)
675
- self._data = mapping
676
- except MetadataUnrecognizedVersionError:
677
- self._legacy = LegacyMetadata(mapping=mapping, scheme=scheme)
678
- self.validate()
679
- else:
680
- data = None
681
- if path:
682
- with open(path, 'rb') as f:
683
- data = f.read()
684
- elif fileobj:
685
- data = fileobj.read()
686
- if data is None:
687
- # Initialised with no args - to be added
688
- self._data = {
689
- 'metadata_version': self.METADATA_VERSION,
690
- 'generator': self.GENERATOR,
691
- }
692
- else:
693
- if not isinstance(data, text_type):
694
- data = data.decode('utf-8')
695
- try:
696
- self._data = json.loads(data)
697
- self._validate_mapping(self._data, scheme)
698
- except ValueError:
699
- # Note: MetadataUnrecognizedVersionError does not
700
- # inherit from ValueError (it's a DistlibException,
701
- # which should not inherit from ValueError).
702
- # The ValueError comes from the json.load - if that
703
- # succeeds and we get a validation error, we want
704
- # that to propagate
705
- self._legacy = LegacyMetadata(fileobj=StringIO(data),
706
- scheme=scheme)
707
- self.validate()
708
-
709
- common_keys = set(('name', 'version', 'license', 'keywords', 'summary'))
710
-
711
- none_list = (None, list)
712
- none_dict = (None, dict)
713
-
714
- mapped_keys = {
715
- 'run_requires': ('Requires-Dist', list),
716
- 'build_requires': ('Setup-Requires-Dist', list),
717
- 'dev_requires': none_list,
718
- 'test_requires': none_list,
719
- 'meta_requires': none_list,
720
- 'extras': ('Provides-Extra', list),
721
- 'modules': none_list,
722
- 'namespaces': none_list,
723
- 'exports': none_dict,
724
- 'commands': none_dict,
725
- 'classifiers': ('Classifier', list),
726
- 'source_url': ('Download-URL', None),
727
- 'metadata_version': ('Metadata-Version', None),
728
- }
729
-
730
- del none_list, none_dict
731
-
732
- def __getattribute__(self, key):
733
- common = object.__getattribute__(self, 'common_keys')
734
- mapped = object.__getattribute__(self, 'mapped_keys')
735
- if key in mapped:
736
- lk, maker = mapped[key]
737
- if self._legacy:
738
- if lk is None:
739
- result = None if maker is None else maker()
740
- else:
741
- result = self._legacy.get(lk)
742
- else:
743
- value = None if maker is None else maker()
744
- result = self._data.get(key, value)
745
- elif key not in common:
746
- result = object.__getattribute__(self, key)
747
- elif self._legacy:
748
- result = self._legacy.get(key)
749
- else:
750
- result = self._data.get(key)
751
- return result
752
-
753
- def _validate_value(self, key, value, scheme=None):
754
- if key in self.SYNTAX_VALIDATORS:
755
- pattern, exclusions = self.SYNTAX_VALIDATORS[key]
756
- if (scheme or self.scheme) not in exclusions:
757
- m = pattern.match(value)
758
- if not m:
759
- raise MetadataInvalidError('%r is an invalid value for '
760
- 'the %r property' % (value,
761
- key))
762
-
763
- def __setattr__(self, key, value):
764
- self._validate_value(key, value)
765
- common = object.__getattribute__(self, 'common_keys')
766
- mapped = object.__getattribute__(self, 'mapped_keys')
767
- if key in mapped:
768
- lk, _ = mapped[key]
769
- if self._legacy:
770
- if lk is None:
771
- raise NotImplementedError
772
- self._legacy[lk] = value
773
- else:
774
- self._data[key] = value
775
- elif key not in common:
776
- object.__setattr__(self, key, value)
777
- else:
778
- if key == 'keywords':
779
- if isinstance(value, string_types):
780
- value = value.strip()
781
- if value:
782
- value = value.split()
783
- else:
784
- value = []
785
- if self._legacy:
786
- self._legacy[key] = value
787
- else:
788
- self._data[key] = value
789
-
790
- @property
791
- def name_and_version(self):
792
- return _get_name_and_version(self.name, self.version, True)
793
-
794
- @property
795
- def provides(self):
796
- if self._legacy:
797
- result = self._legacy['Provides-Dist']
798
- else:
799
- result = self._data.setdefault('provides', [])
800
- s = '%s (%s)' % (self.name, self.version)
801
- if s not in result:
802
- result.append(s)
803
- return result
804
-
805
- @provides.setter
806
- def provides(self, value):
807
- if self._legacy:
808
- self._legacy['Provides-Dist'] = value
809
- else:
810
- self._data['provides'] = value
811
-
812
- def get_requirements(self, reqts, extras=None, env=None):
813
- """
814
- Base method to get dependencies, given a set of extras
815
- to satisfy and an optional environment context.
816
- :param reqts: A list of sometimes-wanted dependencies,
817
- perhaps dependent on extras and environment.
818
- :param extras: A list of optional components being requested.
819
- :param env: An optional environment for marker evaluation.
820
- """
821
- if self._legacy:
822
- result = reqts
823
- else:
824
- result = []
825
- extras = get_extras(extras or [], self.extras)
826
- for d in reqts:
827
- if 'extra' not in d and 'environment' not in d:
828
- # unconditional
829
- include = True
830
- else:
831
- if 'extra' not in d:
832
- # Not extra-dependent - only environment-dependent
833
- include = True
834
- else:
835
- include = d.get('extra') in extras
836
- if include:
837
- # Not excluded because of extras, check environment
838
- marker = d.get('environment')
839
- if marker:
840
- include = interpret(marker, env)
841
- if include:
842
- result.extend(d['requires'])
843
- for key in ('build', 'dev', 'test'):
844
- e = ':%s:' % key
845
- if e in extras:
846
- extras.remove(e)
847
- # A recursive call, but it should terminate since 'test'
848
- # has been removed from the extras
849
- reqts = self._data.get('%s_requires' % key, [])
850
- result.extend(self.get_requirements(reqts, extras=extras,
851
- env=env))
852
- return result
853
-
854
- @property
855
- def dictionary(self):
856
- if self._legacy:
857
- return self._from_legacy()
858
- return self._data
859
-
860
- @property
861
- def dependencies(self):
862
- if self._legacy:
863
- raise NotImplementedError
864
- else:
865
- return extract_by_key(self._data, self.DEPENDENCY_KEYS)
866
-
867
- @dependencies.setter
868
- def dependencies(self, value):
869
- if self._legacy:
870
- raise NotImplementedError
871
- else:
872
- self._data.update(value)
873
-
874
- def _validate_mapping(self, mapping, scheme):
875
- if mapping.get('metadata_version') != self.METADATA_VERSION:
876
- raise MetadataUnrecognizedVersionError()
877
- missing = []
878
- for key, exclusions in self.MANDATORY_KEYS.items():
879
- if key not in mapping:
880
- if scheme not in exclusions:
881
- missing.append(key)
882
- if missing:
883
- msg = 'Missing metadata items: %s' % ', '.join(missing)
884
- raise MetadataMissingError(msg)
885
- for k, v in mapping.items():
886
- self._validate_value(k, v, scheme)
887
-
888
- def validate(self):
889
- if self._legacy:
890
- missing, warnings = self._legacy.check(True)
891
- if missing or warnings:
892
- logger.warning('Metadata: missing: %s, warnings: %s',
893
- missing, warnings)
894
- else:
895
- self._validate_mapping(self._data, self.scheme)
896
-
897
- def todict(self):
898
- if self._legacy:
899
- return self._legacy.todict(True)
900
- else:
901
- result = extract_by_key(self._data, self.INDEX_KEYS)
902
- return result
903
-
904
- def _from_legacy(self):
905
- assert self._legacy and not self._data
906
- result = {
907
- 'metadata_version': self.METADATA_VERSION,
908
- 'generator': self.GENERATOR,
909
- }
910
- lmd = self._legacy.todict(True) # skip missing ones
911
- for k in ('name', 'version', 'license', 'summary', 'description',
912
- 'classifier'):
913
- if k in lmd:
914
- if k == 'classifier':
915
- nk = 'classifiers'
916
- else:
917
- nk = k
918
- result[nk] = lmd[k]
919
- kw = lmd.get('Keywords', [])
920
- if kw == ['']:
921
- kw = []
922
- result['keywords'] = kw
923
- keys = (('requires_dist', 'run_requires'),
924
- ('setup_requires_dist', 'build_requires'))
925
- for ok, nk in keys:
926
- if ok in lmd and lmd[ok]:
927
- result[nk] = [{'requires': lmd[ok]}]
928
- result['provides'] = self.provides
929
- author = {}
930
- maintainer = {}
931
- return result
932
-
933
- LEGACY_MAPPING = {
934
- 'name': 'Name',
935
- 'version': 'Version',
936
- 'license': 'License',
937
- 'summary': 'Summary',
938
- 'description': 'Description',
939
- 'classifiers': 'Classifier',
940
- }
941
-
942
- def _to_legacy(self):
943
- def process_entries(entries):
944
- reqts = set()
945
- for e in entries:
946
- extra = e.get('extra')
947
- env = e.get('environment')
948
- rlist = e['requires']
949
- for r in rlist:
950
- if not env and not extra:
951
- reqts.add(r)
952
- else:
953
- marker = ''
954
- if extra:
955
- marker = 'extra == "%s"' % extra
956
- if env:
957
- if marker:
958
- marker = '(%s) and %s' % (env, marker)
959
- else:
960
- marker = env
961
- reqts.add(';'.join((r, marker)))
962
- return reqts
963
-
964
- assert self._data and not self._legacy
965
- result = LegacyMetadata()
966
- nmd = self._data
967
- for nk, ok in self.LEGACY_MAPPING.items():
968
- if nk in nmd:
969
- result[ok] = nmd[nk]
970
- r1 = process_entries(self.run_requires + self.meta_requires)
971
- r2 = process_entries(self.build_requires + self.dev_requires)
972
- if self.extras:
973
- result['Provides-Extra'] = sorted(self.extras)
974
- result['Requires-Dist'] = sorted(r1)
975
- result['Setup-Requires-Dist'] = sorted(r2)
976
- # TODO: other fields such as contacts
977
- return result
978
-
979
- def write(self, path=None, fileobj=None, legacy=False, skip_unknown=True):
980
- if [path, fileobj].count(None) != 1:
981
- raise ValueError('Exactly one of path and fileobj is needed')
982
- self.validate()
983
- if legacy:
984
- if self._legacy:
985
- legacy_md = self._legacy
986
- else:
987
- legacy_md = self._to_legacy()
988
- if path:
989
- legacy_md.write(path, skip_unknown=skip_unknown)
990
- else:
991
- legacy_md.write_file(fileobj, skip_unknown=skip_unknown)
992
- else:
993
- if self._legacy:
994
- d = self._from_legacy()
995
- else:
996
- d = self._data
997
- if fileobj:
998
- json.dump(d, fileobj, ensure_ascii=True, indent=2,
999
- sort_keys=True)
1000
- else:
1001
- with codecs.open(path, 'w', 'utf-8') as f:
1002
- json.dump(d, f, ensure_ascii=True, indent=2,
1003
- sort_keys=True)
1004
-
1005
- def add_requirements(self, requirements):
1006
- if self._legacy:
1007
- self._legacy.add_requirements(requirements)
1008
- else:
1009
- run_requires = self._data.setdefault('run_requires', [])
1010
- always = None
1011
- for entry in run_requires:
1012
- if 'environment' not in entry and 'extra' not in entry:
1013
- always = entry
1014
- break
1015
- if always is None:
1016
- always = { 'requires': requirements }
1017
- run_requires.insert(0, always)
1018
- else:
1019
- rset = set(always['requires']) | set(requirements)
1020
- always['requires'] = sorted(rset)
1021
-
1022
- def __repr__(self):
1023
- name = self.name or '(no name)'
1024
- version = self.version or 'no version'
1025
- return '<%s %s %s (%s)>' % (self.__class__.__name__,
1026
- self.metadata_version, name, version)
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2012 The Python Software Foundation.
4
+ # See LICENSE.txt and CONTRIBUTORS.txt.
5
+ #
6
+ """Implementation of the Metadata for Python packages PEPs.
7
+
8
+ Supports all metadata formats (1.0, 1.1, 1.2, and 2.0 experimental).
9
+ """
10
+ from __future__ import unicode_literals
11
+
12
+ import codecs
13
+ from email import message_from_file
14
+ import json
15
+ import logging
16
+ import re
17
+
18
+
19
+ from . import DistlibException, __version__
20
+ from .compat import StringIO, string_types, text_type
21
+ from .markers import interpret
22
+ from .util import extract_by_key, get_extras
23
+ from .version import get_scheme, PEP440_VERSION_RE
24
+
25
+ logger = logging.getLogger(__name__)
26
+
27
+
28
+ class MetadataMissingError(DistlibException):
29
+ """A required metadata is missing"""
30
+
31
+
32
+ class MetadataConflictError(DistlibException):
33
+ """Attempt to read or write metadata fields that are conflictual."""
34
+
35
+
36
+ class MetadataUnrecognizedVersionError(DistlibException):
37
+ """Unknown metadata version number."""
38
+
39
+
40
+ class MetadataInvalidError(DistlibException):
41
+ """A metadata value is invalid"""
42
+
43
+ # public API of this module
44
+ __all__ = ['Metadata', 'PKG_INFO_ENCODING', 'PKG_INFO_PREFERRED_VERSION']
45
+
46
+ # Encoding used for the PKG-INFO files
47
+ PKG_INFO_ENCODING = 'utf-8'
48
+
49
+ # preferred version. Hopefully will be changed
50
+ # to 1.2 once PEP 345 is supported everywhere
51
+ PKG_INFO_PREFERRED_VERSION = '1.1'
52
+
53
+ _LINE_PREFIX_1_2 = re.compile('\n \\|')
54
+ _LINE_PREFIX_PRE_1_2 = re.compile('\n ')
55
+ _241_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform',
56
+ 'Summary', 'Description',
57
+ 'Keywords', 'Home-page', 'Author', 'Author-email',
58
+ 'License')
59
+
60
+ _314_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform',
61
+ 'Supported-Platform', 'Summary', 'Description',
62
+ 'Keywords', 'Home-page', 'Author', 'Author-email',
63
+ 'License', 'Classifier', 'Download-URL', 'Obsoletes',
64
+ 'Provides', 'Requires')
65
+
66
+ _314_MARKERS = ('Obsoletes', 'Provides', 'Requires', 'Classifier',
67
+ 'Download-URL')
68
+
69
+ _345_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform',
70
+ 'Supported-Platform', 'Summary', 'Description',
71
+ 'Keywords', 'Home-page', 'Author', 'Author-email',
72
+ 'Maintainer', 'Maintainer-email', 'License',
73
+ 'Classifier', 'Download-URL', 'Obsoletes-Dist',
74
+ 'Project-URL', 'Provides-Dist', 'Requires-Dist',
75
+ 'Requires-Python', 'Requires-External')
76
+
77
+ _345_MARKERS = ('Provides-Dist', 'Requires-Dist', 'Requires-Python',
78
+ 'Obsoletes-Dist', 'Requires-External', 'Maintainer',
79
+ 'Maintainer-email', 'Project-URL')
80
+
81
+ _426_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform',
82
+ 'Supported-Platform', 'Summary', 'Description',
83
+ 'Keywords', 'Home-page', 'Author', 'Author-email',
84
+ 'Maintainer', 'Maintainer-email', 'License',
85
+ 'Classifier', 'Download-URL', 'Obsoletes-Dist',
86
+ 'Project-URL', 'Provides-Dist', 'Requires-Dist',
87
+ 'Requires-Python', 'Requires-External', 'Private-Version',
88
+ 'Obsoleted-By', 'Setup-Requires-Dist', 'Extension',
89
+ 'Provides-Extra')
90
+
91
+ _426_MARKERS = ('Private-Version', 'Provides-Extra', 'Obsoleted-By',
92
+ 'Setup-Requires-Dist', 'Extension')
93
+
94
+ _ALL_FIELDS = set()
95
+ _ALL_FIELDS.update(_241_FIELDS)
96
+ _ALL_FIELDS.update(_314_FIELDS)
97
+ _ALL_FIELDS.update(_345_FIELDS)
98
+ _ALL_FIELDS.update(_426_FIELDS)
99
+
100
+ EXTRA_RE = re.compile(r'''extra\s*==\s*("([^"]+)"|'([^']+)')''')
101
+
102
+
103
+ def _version2fieldlist(version):
104
+ if version == '1.0':
105
+ return _241_FIELDS
106
+ elif version == '1.1':
107
+ return _314_FIELDS
108
+ elif version == '1.2':
109
+ return _345_FIELDS
110
+ elif version == '2.0':
111
+ return _426_FIELDS
112
+ raise MetadataUnrecognizedVersionError(version)
113
+
114
+
115
+ def _best_version(fields):
116
+ """Detect the best version depending on the fields used."""
117
+ def _has_marker(keys, markers):
118
+ for marker in markers:
119
+ if marker in keys:
120
+ return True
121
+ return False
122
+
123
+ keys = []
124
+ for key, value in fields.items():
125
+ if value in ([], 'UNKNOWN', None):
126
+ continue
127
+ keys.append(key)
128
+
129
+ possible_versions = ['1.0', '1.1', '1.2', '2.0']
130
+
131
+ # first let's try to see if a field is not part of one of the version
132
+ for key in keys:
133
+ if key not in _241_FIELDS and '1.0' in possible_versions:
134
+ possible_versions.remove('1.0')
135
+ if key not in _314_FIELDS and '1.1' in possible_versions:
136
+ possible_versions.remove('1.1')
137
+ if key not in _345_FIELDS and '1.2' in possible_versions:
138
+ possible_versions.remove('1.2')
139
+ if key not in _426_FIELDS and '2.0' in possible_versions:
140
+ possible_versions.remove('2.0')
141
+
142
+ # possible_version contains qualified versions
143
+ if len(possible_versions) == 1:
144
+ return possible_versions[0] # found !
145
+ elif len(possible_versions) == 0:
146
+ raise MetadataConflictError('Unknown metadata set')
147
+
148
+ # let's see if one unique marker is found
149
+ is_1_1 = '1.1' in possible_versions and _has_marker(keys, _314_MARKERS)
150
+ is_1_2 = '1.2' in possible_versions and _has_marker(keys, _345_MARKERS)
151
+ is_2_0 = '2.0' in possible_versions and _has_marker(keys, _426_MARKERS)
152
+ if int(is_1_1) + int(is_1_2) + int(is_2_0) > 1:
153
+ raise MetadataConflictError('You used incompatible 1.1/1.2/2.0 fields')
154
+
155
+ # we have the choice, 1.0, or 1.2, or 2.0
156
+ # - 1.0 has a broken Summary field but works with all tools
157
+ # - 1.1 is to avoid
158
+ # - 1.2 fixes Summary but has little adoption
159
+ # - 2.0 adds more features and is very new
160
+ if not is_1_1 and not is_1_2 and not is_2_0:
161
+ # we couldn't find any specific marker
162
+ if PKG_INFO_PREFERRED_VERSION in possible_versions:
163
+ return PKG_INFO_PREFERRED_VERSION
164
+ if is_1_1:
165
+ return '1.1'
166
+ if is_1_2:
167
+ return '1.2'
168
+
169
+ return '2.0'
170
+
171
+ _ATTR2FIELD = {
172
+ 'metadata_version': 'Metadata-Version',
173
+ 'name': 'Name',
174
+ 'version': 'Version',
175
+ 'platform': 'Platform',
176
+ 'supported_platform': 'Supported-Platform',
177
+ 'summary': 'Summary',
178
+ 'description': 'Description',
179
+ 'keywords': 'Keywords',
180
+ 'home_page': 'Home-page',
181
+ 'author': 'Author',
182
+ 'author_email': 'Author-email',
183
+ 'maintainer': 'Maintainer',
184
+ 'maintainer_email': 'Maintainer-email',
185
+ 'license': 'License',
186
+ 'classifier': 'Classifier',
187
+ 'download_url': 'Download-URL',
188
+ 'obsoletes_dist': 'Obsoletes-Dist',
189
+ 'provides_dist': 'Provides-Dist',
190
+ 'requires_dist': 'Requires-Dist',
191
+ 'setup_requires_dist': 'Setup-Requires-Dist',
192
+ 'requires_python': 'Requires-Python',
193
+ 'requires_external': 'Requires-External',
194
+ 'requires': 'Requires',
195
+ 'provides': 'Provides',
196
+ 'obsoletes': 'Obsoletes',
197
+ 'project_url': 'Project-URL',
198
+ 'private_version': 'Private-Version',
199
+ 'obsoleted_by': 'Obsoleted-By',
200
+ 'extension': 'Extension',
201
+ 'provides_extra': 'Provides-Extra',
202
+ }
203
+
204
+ _PREDICATE_FIELDS = ('Requires-Dist', 'Obsoletes-Dist', 'Provides-Dist')
205
+ _VERSIONS_FIELDS = ('Requires-Python',)
206
+ _VERSION_FIELDS = ('Version',)
207
+ _LISTFIELDS = ('Platform', 'Classifier', 'Obsoletes',
208
+ 'Requires', 'Provides', 'Obsoletes-Dist',
209
+ 'Provides-Dist', 'Requires-Dist', 'Requires-External',
210
+ 'Project-URL', 'Supported-Platform', 'Setup-Requires-Dist',
211
+ 'Provides-Extra', 'Extension')
212
+ _LISTTUPLEFIELDS = ('Project-URL',)
213
+
214
+ _ELEMENTSFIELD = ('Keywords',)
215
+
216
+ _UNICODEFIELDS = ('Author', 'Maintainer', 'Summary', 'Description')
217
+
218
+ _MISSING = object()
219
+
220
+ _FILESAFE = re.compile('[^A-Za-z0-9.]+')
221
+
222
+
223
+ def _get_name_and_version(name, version, for_filename=False):
224
+ """Return the distribution name with version.
225
+
226
+ If for_filename is true, return a filename-escaped form."""
227
+ if for_filename:
228
+ # For both name and version any runs of non-alphanumeric or '.'
229
+ # characters are replaced with a single '-'. Additionally any
230
+ # spaces in the version string become '.'
231
+ name = _FILESAFE.sub('-', name)
232
+ version = _FILESAFE.sub('-', version.replace(' ', '.'))
233
+ return '%s-%s' % (name, version)
234
+
235
+
236
+ class LegacyMetadata(object):
237
+ """The legacy metadata of a release.
238
+
239
+ Supports versions 1.0, 1.1 and 1.2 (auto-detected). You can
240
+ instantiate the class with one of these arguments (or none):
241
+ - *path*, the path to a metadata file
242
+ - *fileobj* give a file-like object with metadata as content
243
+ - *mapping* is a dict-like object
244
+ - *scheme* is a version scheme name
245
+ """
246
+ # TODO document the mapping API and UNKNOWN default key
247
+
248
+ def __init__(self, path=None, fileobj=None, mapping=None,
249
+ scheme='default'):
250
+ if [path, fileobj, mapping].count(None) < 2:
251
+ raise TypeError('path, fileobj and mapping are exclusive')
252
+ self._fields = {}
253
+ self.requires_files = []
254
+ self._dependencies = None
255
+ self.scheme = scheme
256
+ if path is not None:
257
+ self.read(path)
258
+ elif fileobj is not None:
259
+ self.read_file(fileobj)
260
+ elif mapping is not None:
261
+ self.update(mapping)
262
+ self.set_metadata_version()
263
+
264
+ def set_metadata_version(self):
265
+ self._fields['Metadata-Version'] = _best_version(self._fields)
266
+
267
+ def _write_field(self, fileobj, name, value):
268
+ fileobj.write('%s: %s\n' % (name, value))
269
+
270
+ def __getitem__(self, name):
271
+ return self.get(name)
272
+
273
+ def __setitem__(self, name, value):
274
+ return self.set(name, value)
275
+
276
+ def __delitem__(self, name):
277
+ field_name = self._convert_name(name)
278
+ try:
279
+ del self._fields[field_name]
280
+ except KeyError:
281
+ raise KeyError(name)
282
+
283
+ def __contains__(self, name):
284
+ return (name in self._fields or
285
+ self._convert_name(name) in self._fields)
286
+
287
+ def _convert_name(self, name):
288
+ if name in _ALL_FIELDS:
289
+ return name
290
+ name = name.replace('-', '_').lower()
291
+ return _ATTR2FIELD.get(name, name)
292
+
293
+ def _default_value(self, name):
294
+ if name in _LISTFIELDS or name in _ELEMENTSFIELD:
295
+ return []
296
+ return 'UNKNOWN'
297
+
298
+ def _remove_line_prefix(self, value):
299
+ if self.metadata_version in ('1.0', '1.1'):
300
+ return _LINE_PREFIX_PRE_1_2.sub('\n', value)
301
+ else:
302
+ return _LINE_PREFIX_1_2.sub('\n', value)
303
+
304
+ def __getattr__(self, name):
305
+ if name in _ATTR2FIELD:
306
+ return self[name]
307
+ raise AttributeError(name)
308
+
309
+ #
310
+ # Public API
311
+ #
312
+
313
+ # dependencies = property(_get_dependencies, _set_dependencies)
314
+
315
+ def get_fullname(self, filesafe=False):
316
+ """Return the distribution name with version.
317
+
318
+ If filesafe is true, return a filename-escaped form."""
319
+ return _get_name_and_version(self['Name'], self['Version'], filesafe)
320
+
321
+ def is_field(self, name):
322
+ """return True if name is a valid metadata key"""
323
+ name = self._convert_name(name)
324
+ return name in _ALL_FIELDS
325
+
326
+ def is_multi_field(self, name):
327
+ name = self._convert_name(name)
328
+ return name in _LISTFIELDS
329
+
330
+ def read(self, filepath):
331
+ """Read the metadata values from a file path."""
332
+ fp = codecs.open(filepath, 'r', encoding='utf-8')
333
+ try:
334
+ self.read_file(fp)
335
+ finally:
336
+ fp.close()
337
+
338
+ def read_file(self, fileob):
339
+ """Read the metadata values from a file object."""
340
+ msg = message_from_file(fileob)
341
+ self._fields['Metadata-Version'] = msg['metadata-version']
342
+
343
+ # When reading, get all the fields we can
344
+ for field in _ALL_FIELDS:
345
+ if field not in msg:
346
+ continue
347
+ if field in _LISTFIELDS:
348
+ # we can have multiple lines
349
+ values = msg.get_all(field)
350
+ if field in _LISTTUPLEFIELDS and values is not None:
351
+ values = [tuple(value.split(',')) for value in values]
352
+ self.set(field, values)
353
+ else:
354
+ # single line
355
+ value = msg[field]
356
+ if value is not None and value != 'UNKNOWN':
357
+ self.set(field, value)
358
+ self.set_metadata_version()
359
+
360
+ def write(self, filepath, skip_unknown=False):
361
+ """Write the metadata fields to filepath."""
362
+ fp = codecs.open(filepath, 'w', encoding='utf-8')
363
+ try:
364
+ self.write_file(fp, skip_unknown)
365
+ finally:
366
+ fp.close()
367
+
368
+ def write_file(self, fileobject, skip_unknown=False):
369
+ """Write the PKG-INFO format data to a file object."""
370
+ self.set_metadata_version()
371
+
372
+ for field in _version2fieldlist(self['Metadata-Version']):
373
+ values = self.get(field)
374
+ if skip_unknown and values in ('UNKNOWN', [], ['UNKNOWN']):
375
+ continue
376
+ if field in _ELEMENTSFIELD:
377
+ self._write_field(fileobject, field, ','.join(values))
378
+ continue
379
+ if field not in _LISTFIELDS:
380
+ if field == 'Description':
381
+ if self.metadata_version in ('1.0', '1.1'):
382
+ values = values.replace('\n', '\n ')
383
+ else:
384
+ values = values.replace('\n', '\n |')
385
+ values = [values]
386
+
387
+ if field in _LISTTUPLEFIELDS:
388
+ values = [','.join(value) for value in values]
389
+
390
+ for value in values:
391
+ self._write_field(fileobject, field, value)
392
+
393
+ def update(self, other=None, **kwargs):
394
+ """Set metadata values from the given iterable `other` and kwargs.
395
+
396
+ Behavior is like `dict.update`: If `other` has a ``keys`` method,
397
+ they are looped over and ``self[key]`` is assigned ``other[key]``.
398
+ Else, ``other`` is an iterable of ``(key, value)`` iterables.
399
+
400
+ Keys that don't match a metadata field or that have an empty value are
401
+ dropped.
402
+ """
403
+ def _set(key, value):
404
+ if key in _ATTR2FIELD and value:
405
+ self.set(self._convert_name(key), value)
406
+
407
+ if not other:
408
+ # other is None or empty container
409
+ pass
410
+ elif hasattr(other, 'keys'):
411
+ for k in other.keys():
412
+ _set(k, other[k])
413
+ else:
414
+ for k, v in other:
415
+ _set(k, v)
416
+
417
+ if kwargs:
418
+ for k, v in kwargs.items():
419
+ _set(k, v)
420
+
421
+ def set(self, name, value):
422
+ """Control then set a metadata field."""
423
+ name = self._convert_name(name)
424
+
425
+ if ((name in _ELEMENTSFIELD or name == 'Platform') and
426
+ not isinstance(value, (list, tuple))):
427
+ if isinstance(value, string_types):
428
+ value = [v.strip() for v in value.split(',')]
429
+ else:
430
+ value = []
431
+ elif (name in _LISTFIELDS and
432
+ not isinstance(value, (list, tuple))):
433
+ if isinstance(value, string_types):
434
+ value = [value]
435
+ else:
436
+ value = []
437
+
438
+ if logger.isEnabledFor(logging.WARNING):
439
+ project_name = self['Name']
440
+
441
+ scheme = get_scheme(self.scheme)
442
+ if name in _PREDICATE_FIELDS and value is not None:
443
+ for v in value:
444
+ # check that the values are valid
445
+ if not scheme.is_valid_matcher(v.split(';')[0]):
446
+ logger.warning(
447
+ "'%s': '%s' is not valid (field '%s')",
448
+ project_name, v, name)
449
+ # FIXME this rejects UNKNOWN, is that right?
450
+ elif name in _VERSIONS_FIELDS and value is not None:
451
+ if not scheme.is_valid_constraint_list(value):
452
+ logger.warning("'%s': '%s' is not a valid version (field '%s')",
453
+ project_name, value, name)
454
+ elif name in _VERSION_FIELDS and value is not None:
455
+ if not scheme.is_valid_version(value):
456
+ logger.warning("'%s': '%s' is not a valid version (field '%s')",
457
+ project_name, value, name)
458
+
459
+ if name in _UNICODEFIELDS:
460
+ if name == 'Description':
461
+ value = self._remove_line_prefix(value)
462
+
463
+ self._fields[name] = value
464
+
465
+ def get(self, name, default=_MISSING):
466
+ """Get a metadata field."""
467
+ name = self._convert_name(name)
468
+ if name not in self._fields:
469
+ if default is _MISSING:
470
+ default = self._default_value(name)
471
+ return default
472
+ if name in _UNICODEFIELDS:
473
+ value = self._fields[name]
474
+ return value
475
+ elif name in _LISTFIELDS:
476
+ value = self._fields[name]
477
+ if value is None:
478
+ return []
479
+ res = []
480
+ for val in value:
481
+ if name not in _LISTTUPLEFIELDS:
482
+ res.append(val)
483
+ else:
484
+ # That's for Project-URL
485
+ res.append((val[0], val[1]))
486
+ return res
487
+
488
+ elif name in _ELEMENTSFIELD:
489
+ value = self._fields[name]
490
+ if isinstance(value, string_types):
491
+ return value.split(',')
492
+ return self._fields[name]
493
+
494
+ def check(self, strict=False):
495
+ """Check if the metadata is compliant. If strict is True then raise if
496
+ no Name or Version are provided"""
497
+ self.set_metadata_version()
498
+
499
+ # XXX should check the versions (if the file was loaded)
500
+ missing, warnings = [], []
501
+
502
+ for attr in ('Name', 'Version'): # required by PEP 345
503
+ if attr not in self:
504
+ missing.append(attr)
505
+
506
+ if strict and missing != []:
507
+ msg = 'missing required metadata: %s' % ', '.join(missing)
508
+ raise MetadataMissingError(msg)
509
+
510
+ for attr in ('Home-page', 'Author'):
511
+ if attr not in self:
512
+ missing.append(attr)
513
+
514
+ # checking metadata 1.2 (XXX needs to check 1.1, 1.0)
515
+ if self['Metadata-Version'] != '1.2':
516
+ return missing, warnings
517
+
518
+ scheme = get_scheme(self.scheme)
519
+
520
+ def are_valid_constraints(value):
521
+ for v in value:
522
+ if not scheme.is_valid_matcher(v.split(';')[0]):
523
+ return False
524
+ return True
525
+
526
+ for fields, controller in ((_PREDICATE_FIELDS, are_valid_constraints),
527
+ (_VERSIONS_FIELDS,
528
+ scheme.is_valid_constraint_list),
529
+ (_VERSION_FIELDS,
530
+ scheme.is_valid_version)):
531
+ for field in fields:
532
+ value = self.get(field, None)
533
+ if value is not None and not controller(value):
534
+ warnings.append("Wrong value for '%s': %s" % (field, value))
535
+
536
+ return missing, warnings
537
+
538
+ def todict(self, skip_missing=False):
539
+ """Return fields as a dict.
540
+
541
+ Field names will be converted to use the underscore-lowercase style
542
+ instead of hyphen-mixed case (i.e. home_page instead of Home-page).
543
+ """
544
+ self.set_metadata_version()
545
+
546
+ mapping_1_0 = (
547
+ ('metadata_version', 'Metadata-Version'),
548
+ ('name', 'Name'),
549
+ ('version', 'Version'),
550
+ ('summary', 'Summary'),
551
+ ('home_page', 'Home-page'),
552
+ ('author', 'Author'),
553
+ ('author_email', 'Author-email'),
554
+ ('license', 'License'),
555
+ ('description', 'Description'),
556
+ ('keywords', 'Keywords'),
557
+ ('platform', 'Platform'),
558
+ ('classifiers', 'Classifier'),
559
+ ('download_url', 'Download-URL'),
560
+ )
561
+
562
+ data = {}
563
+ for key, field_name in mapping_1_0:
564
+ if not skip_missing or field_name in self._fields:
565
+ data[key] = self[field_name]
566
+
567
+ if self['Metadata-Version'] == '1.2':
568
+ mapping_1_2 = (
569
+ ('requires_dist', 'Requires-Dist'),
570
+ ('requires_python', 'Requires-Python'),
571
+ ('requires_external', 'Requires-External'),
572
+ ('provides_dist', 'Provides-Dist'),
573
+ ('obsoletes_dist', 'Obsoletes-Dist'),
574
+ ('project_url', 'Project-URL'),
575
+ ('maintainer', 'Maintainer'),
576
+ ('maintainer_email', 'Maintainer-email'),
577
+ )
578
+ for key, field_name in mapping_1_2:
579
+ if not skip_missing or field_name in self._fields:
580
+ if key != 'project_url':
581
+ data[key] = self[field_name]
582
+ else:
583
+ data[key] = [','.join(u) for u in self[field_name]]
584
+
585
+ elif self['Metadata-Version'] == '1.1':
586
+ mapping_1_1 = (
587
+ ('provides', 'Provides'),
588
+ ('requires', 'Requires'),
589
+ ('obsoletes', 'Obsoletes'),
590
+ )
591
+ for key, field_name in mapping_1_1:
592
+ if not skip_missing or field_name in self._fields:
593
+ data[key] = self[field_name]
594
+
595
+ return data
596
+
597
+ def add_requirements(self, requirements):
598
+ if self['Metadata-Version'] == '1.1':
599
+ # we can't have 1.1 metadata *and* Setuptools requires
600
+ for field in ('Obsoletes', 'Requires', 'Provides'):
601
+ if field in self:
602
+ del self[field]
603
+ self['Requires-Dist'] += requirements
604
+
605
+ # Mapping API
606
+ # TODO could add iter* variants
607
+
608
+ def keys(self):
609
+ return list(_version2fieldlist(self['Metadata-Version']))
610
+
611
+ def __iter__(self):
612
+ for key in self.keys():
613
+ yield key
614
+
615
+ def values(self):
616
+ return [self[key] for key in self.keys()]
617
+
618
+ def items(self):
619
+ return [(key, self[key]) for key in self.keys()]
620
+
621
+ def __repr__(self):
622
+ return '<%s %s %s>' % (self.__class__.__name__, self.name,
623
+ self.version)
624
+
625
+
626
+ METADATA_FILENAME = 'pydist.json'
627
+ WHEEL_METADATA_FILENAME = 'metadata.json'
628
+
629
+
630
+ class Metadata(object):
631
+ """
632
+ The metadata of a release. This implementation uses 2.0 (JSON)
633
+ metadata where possible. If not possible, it wraps a LegacyMetadata
634
+ instance which handles the key-value metadata format.
635
+ """
636
+
637
+ METADATA_VERSION_MATCHER = re.compile(r'^\d+(\.\d+)*$')
638
+
639
+ NAME_MATCHER = re.compile('^[0-9A-Z]([0-9A-Z_.-]*[0-9A-Z])?$', re.I)
640
+
641
+ VERSION_MATCHER = PEP440_VERSION_RE
642
+
643
+ SUMMARY_MATCHER = re.compile('.{1,2047}')
644
+
645
+ METADATA_VERSION = '2.0'
646
+
647
+ GENERATOR = 'distlib (%s)' % __version__
648
+
649
+ MANDATORY_KEYS = {
650
+ 'name': (),
651
+ 'version': (),
652
+ 'summary': ('legacy',),
653
+ }
654
+
655
+ INDEX_KEYS = ('name version license summary description author '
656
+ 'author_email keywords platform home_page classifiers '
657
+ 'download_url')
658
+
659
+ DEPENDENCY_KEYS = ('extras run_requires test_requires build_requires '
660
+ 'dev_requires provides meta_requires obsoleted_by '
661
+ 'supports_environments')
662
+
663
+ SYNTAX_VALIDATORS = {
664
+ 'metadata_version': (METADATA_VERSION_MATCHER, ()),
665
+ 'name': (NAME_MATCHER, ('legacy',)),
666
+ 'version': (VERSION_MATCHER, ('legacy',)),
667
+ 'summary': (SUMMARY_MATCHER, ('legacy',)),
668
+ }
669
+
670
+ __slots__ = ('_legacy', '_data', 'scheme')
671
+
672
+ def __init__(self, path=None, fileobj=None, mapping=None,
673
+ scheme='default'):
674
+ if [path, fileobj, mapping].count(None) < 2:
675
+ raise TypeError('path, fileobj and mapping are exclusive')
676
+ self._legacy = None
677
+ self._data = None
678
+ self.scheme = scheme
679
+ #import pdb; pdb.set_trace()
680
+ if mapping is not None:
681
+ try:
682
+ self._validate_mapping(mapping, scheme)
683
+ self._data = mapping
684
+ except MetadataUnrecognizedVersionError:
685
+ self._legacy = LegacyMetadata(mapping=mapping, scheme=scheme)
686
+ self.validate()
687
+ else:
688
+ data = None
689
+ if path:
690
+ with open(path, 'rb') as f:
691
+ data = f.read()
692
+ elif fileobj:
693
+ data = fileobj.read()
694
+ if data is None:
695
+ # Initialised with no args - to be added
696
+ self._data = {
697
+ 'metadata_version': self.METADATA_VERSION,
698
+ 'generator': self.GENERATOR,
699
+ }
700
+ else:
701
+ if not isinstance(data, text_type):
702
+ data = data.decode('utf-8')
703
+ try:
704
+ self._data = json.loads(data)
705
+ self._validate_mapping(self._data, scheme)
706
+ except ValueError:
707
+ # Note: MetadataUnrecognizedVersionError does not
708
+ # inherit from ValueError (it's a DistlibException,
709
+ # which should not inherit from ValueError).
710
+ # The ValueError comes from the json.load - if that
711
+ # succeeds and we get a validation error, we want
712
+ # that to propagate
713
+ self._legacy = LegacyMetadata(fileobj=StringIO(data),
714
+ scheme=scheme)
715
+ self.validate()
716
+
717
+ common_keys = set(('name', 'version', 'license', 'keywords', 'summary'))
718
+
719
+ none_list = (None, list)
720
+ none_dict = (None, dict)
721
+
722
+ mapped_keys = {
723
+ 'run_requires': ('Requires-Dist', list),
724
+ 'build_requires': ('Setup-Requires-Dist', list),
725
+ 'dev_requires': none_list,
726
+ 'test_requires': none_list,
727
+ 'meta_requires': none_list,
728
+ 'extras': ('Provides-Extra', list),
729
+ 'modules': none_list,
730
+ 'namespaces': none_list,
731
+ 'exports': none_dict,
732
+ 'commands': none_dict,
733
+ 'classifiers': ('Classifier', list),
734
+ 'source_url': ('Download-URL', None),
735
+ 'metadata_version': ('Metadata-Version', None),
736
+ }
737
+
738
+ del none_list, none_dict
739
+
740
+ def __getattribute__(self, key):
741
+ common = object.__getattribute__(self, 'common_keys')
742
+ mapped = object.__getattribute__(self, 'mapped_keys')
743
+ if key in mapped:
744
+ lk, maker = mapped[key]
745
+ if self._legacy:
746
+ if lk is None:
747
+ result = None if maker is None else maker()
748
+ else:
749
+ result = self._legacy.get(lk)
750
+ else:
751
+ value = None if maker is None else maker()
752
+ if key not in ('commands', 'exports', 'modules', 'namespaces',
753
+ 'classifiers'):
754
+ result = self._data.get(key, value)
755
+ else:
756
+ # special cases for PEP 459
757
+ sentinel = object()
758
+ result = sentinel
759
+ d = self._data.get('extensions')
760
+ if d:
761
+ if key == 'commands':
762
+ result = d.get('python.commands', value)
763
+ elif key == 'classifiers':
764
+ d = d.get('python.details')
765
+ if d:
766
+ result = d.get(key, value)
767
+ else:
768
+ d = d.get('python.exports')
769
+ if not d:
770
+ d = self._data.get('python.exports')
771
+ if d:
772
+ result = d.get(key, value)
773
+ if result is sentinel:
774
+ result = value
775
+ elif key not in common:
776
+ result = object.__getattribute__(self, key)
777
+ elif self._legacy:
778
+ result = self._legacy.get(key)
779
+ else:
780
+ result = self._data.get(key)
781
+ return result
782
+
783
+ def _validate_value(self, key, value, scheme=None):
784
+ if key in self.SYNTAX_VALIDATORS:
785
+ pattern, exclusions = self.SYNTAX_VALIDATORS[key]
786
+ if (scheme or self.scheme) not in exclusions:
787
+ m = pattern.match(value)
788
+ if not m:
789
+ raise MetadataInvalidError("'%s' is an invalid value for "
790
+ "the '%s' property" % (value,
791
+ key))
792
+
793
+ def __setattr__(self, key, value):
794
+ self._validate_value(key, value)
795
+ common = object.__getattribute__(self, 'common_keys')
796
+ mapped = object.__getattribute__(self, 'mapped_keys')
797
+ if key in mapped:
798
+ lk, _ = mapped[key]
799
+ if self._legacy:
800
+ if lk is None:
801
+ raise NotImplementedError
802
+ self._legacy[lk] = value
803
+ elif key not in ('commands', 'exports', 'modules', 'namespaces',
804
+ 'classifiers'):
805
+ self._data[key] = value
806
+ else:
807
+ # special cases for PEP 459
808
+ d = self._data.setdefault('extensions', {})
809
+ if key == 'commands':
810
+ d['python.commands'] = value
811
+ elif key == 'classifiers':
812
+ d = d.setdefault('python.details', {})
813
+ d[key] = value
814
+ else:
815
+ d = d.setdefault('python.exports', {})
816
+ d[key] = value
817
+ elif key not in common:
818
+ object.__setattr__(self, key, value)
819
+ else:
820
+ if key == 'keywords':
821
+ if isinstance(value, string_types):
822
+ value = value.strip()
823
+ if value:
824
+ value = value.split()
825
+ else:
826
+ value = []
827
+ if self._legacy:
828
+ self._legacy[key] = value
829
+ else:
830
+ self._data[key] = value
831
+
832
+ @property
833
+ def name_and_version(self):
834
+ return _get_name_and_version(self.name, self.version, True)
835
+
836
+ @property
837
+ def provides(self):
838
+ if self._legacy:
839
+ result = self._legacy['Provides-Dist']
840
+ else:
841
+ result = self._data.setdefault('provides', [])
842
+ s = '%s (%s)' % (self.name, self.version)
843
+ if s not in result:
844
+ result.append(s)
845
+ return result
846
+
847
+ @provides.setter
848
+ def provides(self, value):
849
+ if self._legacy:
850
+ self._legacy['Provides-Dist'] = value
851
+ else:
852
+ self._data['provides'] = value
853
+
854
+ def get_requirements(self, reqts, extras=None, env=None):
855
+ """
856
+ Base method to get dependencies, given a set of extras
857
+ to satisfy and an optional environment context.
858
+ :param reqts: A list of sometimes-wanted dependencies,
859
+ perhaps dependent on extras and environment.
860
+ :param extras: A list of optional components being requested.
861
+ :param env: An optional environment for marker evaluation.
862
+ """
863
+ if self._legacy:
864
+ result = reqts
865
+ else:
866
+ result = []
867
+ extras = get_extras(extras or [], self.extras)
868
+ for d in reqts:
869
+ if 'extra' not in d and 'environment' not in d:
870
+ # unconditional
871
+ include = True
872
+ else:
873
+ if 'extra' not in d:
874
+ # Not extra-dependent - only environment-dependent
875
+ include = True
876
+ else:
877
+ include = d.get('extra') in extras
878
+ if include:
879
+ # Not excluded because of extras, check environment
880
+ marker = d.get('environment')
881
+ if marker:
882
+ include = interpret(marker, env)
883
+ if include:
884
+ result.extend(d['requires'])
885
+ for key in ('build', 'dev', 'test'):
886
+ e = ':%s:' % key
887
+ if e in extras:
888
+ extras.remove(e)
889
+ # A recursive call, but it should terminate since 'test'
890
+ # has been removed from the extras
891
+ reqts = self._data.get('%s_requires' % key, [])
892
+ result.extend(self.get_requirements(reqts, extras=extras,
893
+ env=env))
894
+ return result
895
+
896
+ @property
897
+ def dictionary(self):
898
+ if self._legacy:
899
+ return self._from_legacy()
900
+ return self._data
901
+
902
+ @property
903
+ def dependencies(self):
904
+ if self._legacy:
905
+ raise NotImplementedError
906
+ else:
907
+ return extract_by_key(self._data, self.DEPENDENCY_KEYS)
908
+
909
+ @dependencies.setter
910
+ def dependencies(self, value):
911
+ if self._legacy:
912
+ raise NotImplementedError
913
+ else:
914
+ self._data.update(value)
915
+
916
+ def _validate_mapping(self, mapping, scheme):
917
+ if mapping.get('metadata_version') != self.METADATA_VERSION:
918
+ raise MetadataUnrecognizedVersionError()
919
+ missing = []
920
+ for key, exclusions in self.MANDATORY_KEYS.items():
921
+ if key not in mapping:
922
+ if scheme not in exclusions:
923
+ missing.append(key)
924
+ if missing:
925
+ msg = 'Missing metadata items: %s' % ', '.join(missing)
926
+ raise MetadataMissingError(msg)
927
+ for k, v in mapping.items():
928
+ self._validate_value(k, v, scheme)
929
+
930
+ def validate(self):
931
+ if self._legacy:
932
+ missing, warnings = self._legacy.check(True)
933
+ if missing or warnings:
934
+ logger.warning('Metadata: missing: %s, warnings: %s',
935
+ missing, warnings)
936
+ else:
937
+ self._validate_mapping(self._data, self.scheme)
938
+
939
+ def todict(self):
940
+ if self._legacy:
941
+ return self._legacy.todict(True)
942
+ else:
943
+ result = extract_by_key(self._data, self.INDEX_KEYS)
944
+ return result
945
+
946
+ def _from_legacy(self):
947
+ assert self._legacy and not self._data
948
+ result = {
949
+ 'metadata_version': self.METADATA_VERSION,
950
+ 'generator': self.GENERATOR,
951
+ }
952
+ lmd = self._legacy.todict(True) # skip missing ones
953
+ for k in ('name', 'version', 'license', 'summary', 'description',
954
+ 'classifier'):
955
+ if k in lmd:
956
+ if k == 'classifier':
957
+ nk = 'classifiers'
958
+ else:
959
+ nk = k
960
+ result[nk] = lmd[k]
961
+ kw = lmd.get('Keywords', [])
962
+ if kw == ['']:
963
+ kw = []
964
+ result['keywords'] = kw
965
+ keys = (('requires_dist', 'run_requires'),
966
+ ('setup_requires_dist', 'build_requires'))
967
+ for ok, nk in keys:
968
+ if ok in lmd and lmd[ok]:
969
+ result[nk] = [{'requires': lmd[ok]}]
970
+ result['provides'] = self.provides
971
+ author = {}
972
+ maintainer = {}
973
+ return result
974
+
975
+ LEGACY_MAPPING = {
976
+ 'name': 'Name',
977
+ 'version': 'Version',
978
+ 'license': 'License',
979
+ 'summary': 'Summary',
980
+ 'description': 'Description',
981
+ 'classifiers': 'Classifier',
982
+ }
983
+
984
+ def _to_legacy(self):
985
+ def process_entries(entries):
986
+ reqts = set()
987
+ for e in entries:
988
+ extra = e.get('extra')
989
+ env = e.get('environment')
990
+ rlist = e['requires']
991
+ for r in rlist:
992
+ if not env and not extra:
993
+ reqts.add(r)
994
+ else:
995
+ marker = ''
996
+ if extra:
997
+ marker = 'extra == "%s"' % extra
998
+ if env:
999
+ if marker:
1000
+ marker = '(%s) and %s' % (env, marker)
1001
+ else:
1002
+ marker = env
1003
+ reqts.add(';'.join((r, marker)))
1004
+ return reqts
1005
+
1006
+ assert self._data and not self._legacy
1007
+ result = LegacyMetadata()
1008
+ nmd = self._data
1009
+ for nk, ok in self.LEGACY_MAPPING.items():
1010
+ if nk in nmd:
1011
+ result[ok] = nmd[nk]
1012
+ r1 = process_entries(self.run_requires + self.meta_requires)
1013
+ r2 = process_entries(self.build_requires + self.dev_requires)
1014
+ if self.extras:
1015
+ result['Provides-Extra'] = sorted(self.extras)
1016
+ result['Requires-Dist'] = sorted(r1)
1017
+ result['Setup-Requires-Dist'] = sorted(r2)
1018
+ # TODO: other fields such as contacts
1019
+ return result
1020
+
1021
+ def write(self, path=None, fileobj=None, legacy=False, skip_unknown=True):
1022
+ if [path, fileobj].count(None) != 1:
1023
+ raise ValueError('Exactly one of path and fileobj is needed')
1024
+ self.validate()
1025
+ if legacy:
1026
+ if self._legacy:
1027
+ legacy_md = self._legacy
1028
+ else:
1029
+ legacy_md = self._to_legacy()
1030
+ if path:
1031
+ legacy_md.write(path, skip_unknown=skip_unknown)
1032
+ else:
1033
+ legacy_md.write_file(fileobj, skip_unknown=skip_unknown)
1034
+ else:
1035
+ if self._legacy:
1036
+ d = self._from_legacy()
1037
+ else:
1038
+ d = self._data
1039
+ if fileobj:
1040
+ json.dump(d, fileobj, ensure_ascii=True, indent=2,
1041
+ sort_keys=True)
1042
+ else:
1043
+ with codecs.open(path, 'w', 'utf-8') as f:
1044
+ json.dump(d, f, ensure_ascii=True, indent=2,
1045
+ sort_keys=True)
1046
+
1047
+ def add_requirements(self, requirements):
1048
+ if self._legacy:
1049
+ self._legacy.add_requirements(requirements)
1050
+ else:
1051
+ run_requires = self._data.setdefault('run_requires', [])
1052
+ always = None
1053
+ for entry in run_requires:
1054
+ if 'environment' not in entry and 'extra' not in entry:
1055
+ always = entry
1056
+ break
1057
+ if always is None:
1058
+ always = { 'requires': requirements }
1059
+ run_requires.insert(0, always)
1060
+ else:
1061
+ rset = set(always['requires']) | set(requirements)
1062
+ always['requires'] = sorted(rset)
1063
+
1064
+ def __repr__(self):
1065
+ name = self.name or '(no name)'
1066
+ version = self.version or 'no version'
1067
+ return '<%s %s %s (%s)>' % (self.__class__.__name__,
1068
+ self.metadata_version, name, version)