mirror of
https://github.com/kennethreitz/pipenv.git
synced 2026-06-05 22:50:18 +00:00
Merge pull request #1540 from pypa/builds
Massive improvements to build infrastructure (Travis-CI)
This commit is contained in:
+11
-7
@@ -1,21 +1,25 @@
|
||||
sudo: false
|
||||
cache: pip
|
||||
language: python
|
||||
python:
|
||||
- "2.7"
|
||||
- "3.4"
|
||||
- "3.5"
|
||||
- "3.6"
|
||||
# - "pypy" # too many cache issues
|
||||
# - "3.7-dev" # no need, slows down builds
|
||||
# - "pypy3" # TODO: pkg_config issues
|
||||
env:
|
||||
- TEST_SUITE='install'
|
||||
- TEST_SUITE='dotvenv or check or unused'
|
||||
- TEST_SUITE='cli or requirements'
|
||||
- TEST_SUITE='complex'
|
||||
- TEST_SUITE='run or project or utils'
|
||||
|
||||
# command to install dependencies
|
||||
install:
|
||||
- "pip install -e . --upgrade"
|
||||
- "pip install --upgrade pip"
|
||||
- "pip install -e . --upgrade --upgrade-strategy=only-if-needed"
|
||||
- "pipenv install --dev"
|
||||
|
||||
# command to run the dependencies
|
||||
script:
|
||||
- "pipenv run pytest -n 8 tests"
|
||||
- "pipenv run bash ./run-tests.sh"
|
||||
|
||||
# command to run tests
|
||||
# jobs:
|
||||
|
||||
@@ -8,6 +8,7 @@ twine = "*"
|
||||
sphinx-click = "*"
|
||||
pytest-xdist = "*"
|
||||
click = "*"
|
||||
"bf8d106" = {path = "./tests/pytest-pypi", editable = true}
|
||||
|
||||
|
||||
[packages]
|
||||
|
||||
Generated
+25
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "30cda285af4ec2464aed0a9c99ec997e3423ec9d69068910f77ec100db2ec653"
|
||||
"sha256": "f901280e04e0d3e853369cf63eb52086c265e54b10c036e4d0d1f2e06c82aca1"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {},
|
||||
@@ -124,6 +124,10 @@
|
||||
],
|
||||
"version": "==2.5.3"
|
||||
},
|
||||
"bf8d106": {
|
||||
"editable": true,
|
||||
"path": "./tests/pytest-pypi"
|
||||
},
|
||||
"certifi": {
|
||||
"hashes": [
|
||||
"sha256:14131608ad2fd56836d33a71ee60fa1c82bc9d2c8d98b7bdbc631fe1b3cd1296",
|
||||
@@ -192,6 +196,13 @@
|
||||
],
|
||||
"version": "==3.5.0"
|
||||
},
|
||||
"flask": {
|
||||
"hashes": [
|
||||
"sha256:0749df235e3ff61ac108f69ac178c9770caeaccad2509cb762ce1f65570a8856",
|
||||
"sha256:49f44461237b69ecd901cc7ce66feea0319b9158743dd27a2899962ab214dac1"
|
||||
],
|
||||
"version": "==0.12.2"
|
||||
},
|
||||
"funcsigs": {
|
||||
"hashes": [
|
||||
"sha256:330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca",
|
||||
@@ -214,6 +225,12 @@
|
||||
],
|
||||
"version": "==1.0.0"
|
||||
},
|
||||
"itsdangerous": {
|
||||
"hashes": [
|
||||
"sha256:cbb3fcf8d3e33df861709ecaf89d9e6629cff0a217bc2848f1b41cd30d360519"
|
||||
],
|
||||
"version": "==0.24"
|
||||
},
|
||||
"jinja2": {
|
||||
"hashes": [
|
||||
"sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd",
|
||||
@@ -386,6 +403,13 @@
|
||||
"sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f"
|
||||
],
|
||||
"version": "==1.22"
|
||||
},
|
||||
"werkzeug": {
|
||||
"hashes": [
|
||||
"sha256:c3fd7a7d41976d9f44db327260e263132466836cef6f91512889ed60ad26557c",
|
||||
"sha256:d5da73735293558eb1651ee2fddc4d0dedcfa06538b8813a2e20011583c9e49b"
|
||||
],
|
||||
"version": "==0.14.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,9 @@ PIPENV_SHELL_FANCY = bool(os.environ.get('PIPENV_SHELL_FANCY'))
|
||||
# Create the virtualenv in the project, instead of with pew.
|
||||
PIPENV_VENV_IN_PROJECT = bool(os.environ.get('PIPENV_VENV_IN_PROJECT')) or os.path.isdir('.venv')
|
||||
|
||||
# Overwrite all index funcitonality.
|
||||
PIPENV_TEST_INDEX = os.environ.get('PIPENV_TEST_INDEX')
|
||||
|
||||
# No color mode, for unfun people.
|
||||
PIPENV_COLORBLIND = bool(os.environ.get('PIPENV_COLORBLIND'))
|
||||
|
||||
|
||||
+14
-10
@@ -23,7 +23,8 @@ from .environments import (
|
||||
PIPENV_PIPFILE,
|
||||
PIPENV_VENV_IN_PROJECT,
|
||||
PIPENV_VIRTUALENV,
|
||||
PIPENV_NO_INHERIT
|
||||
PIPENV_NO_INHERIT,
|
||||
PIPENV_TEST_INDEX
|
||||
)
|
||||
|
||||
if PIPENV_PIPFILE:
|
||||
@@ -410,17 +411,20 @@ class Project(object):
|
||||
install = dict(config_parser.get_config_section('install'))
|
||||
indexes = install.get('extra-index-url', '').lstrip('\n').split('\n')
|
||||
|
||||
# Default source.
|
||||
pypi_source = {u'url': u'https://pypi.python.org/simple', u'verify_ssl': True, u'name': 'pypi'}
|
||||
sources = [pypi_source]
|
||||
if PIPENV_TEST_INDEX:
|
||||
sources = [{u'url': PIPENV_TEST_INDEX, u'verify_ssl': True, u'name': u'custom'}]
|
||||
else:
|
||||
# Default source.
|
||||
pypi_source = {u'url': u'https://pypi.python.org/simple', u'verify_ssl': True, u'name': 'pypi'}
|
||||
sources = [pypi_source]
|
||||
|
||||
for i, index in enumerate(indexes):
|
||||
if not index:
|
||||
continue
|
||||
source_name = 'pip_index_{}'.format(i)
|
||||
verify_ssl = index.startswith('https')
|
||||
for i, index in enumerate(indexes):
|
||||
if not index:
|
||||
continue
|
||||
source_name = 'pip_index_{}'.format(i)
|
||||
verify_ssl = index.startswith('https')
|
||||
|
||||
sources.append({u'url': index, u'verify_ssl': verify_ssl, u'name': source_name})
|
||||
sources.append({u'url': index, u'verify_ssl': verify_ssl, u'name': source_name})
|
||||
|
||||
data = {
|
||||
u'source': sources,
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
PYPI_VENDOR_DIR="$(pwd)/tests/pypi/"
|
||||
export PYPI_VENDOR_DIR
|
||||
|
||||
pytest -n 8 tests -m "$TEST_SUITE"
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,30 @@
|
||||
pytest-httpbin
|
||||
==============
|
||||
|
||||
httpbin is an amazing web service for testing HTTP libraries. It has several
|
||||
great endpoints that can test pretty much everything you need in a HTTP
|
||||
library. The only problem is: maybe you don't want to wait for your tests to
|
||||
travel across the Internet and back to make assertions against a remote web
|
||||
service.
|
||||
|
||||
Enter pytest-httpbin. Pytest-httpbin creates a pytest "fixture" that is
|
||||
dependency-injected into your tests. It automatically starts up a HTTP server
|
||||
in a separate thread running httpbin and provides your test with the URL in the
|
||||
fixture. Check out this example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def test_that_my_library_works_kinda_ok(httpbin):
|
||||
assert requests.get(httpbin.url + '/get/').status_code == 200
|
||||
|
||||
This replaces a test that might have looked like this before:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def test_that_my_library_works_kinda_ok():
|
||||
assert requests.get('http://httpbin.org/get').status_code == 200
|
||||
|
||||
pytest-httpbin also supports https and includes its own CA cert you can use.
|
||||
Check out `the full documentation`_ on the github page.
|
||||
|
||||
.. _the full documentation: https://github.com/kevin1024/pytest-httpbin
|
||||
@@ -0,0 +1,4 @@
|
||||
# If using Python 2.6 or less, then have to include package data, even though
|
||||
# it's already declared in setup.py
|
||||
include pytest_httpbin/certs/*
|
||||
include DESCRIPTION.rst
|
||||
@@ -0,0 +1,23 @@
|
||||
[[source]]
|
||||
|
||||
url = "https://pypi.python.org/simple"
|
||||
verify_ssl = true
|
||||
name = "pypi"
|
||||
|
||||
|
||||
[packages]
|
||||
|
||||
|
||||
|
||||
[dev-packages]
|
||||
|
||||
pytest = "*"
|
||||
"e1839a8" = {path = ".", editable = true}
|
||||
httpbin = "*"
|
||||
requests = "*"
|
||||
twine = "*"
|
||||
|
||||
|
||||
[requires]
|
||||
|
||||
python_version = "3.6"
|
||||
Generated
+480
@@ -0,0 +1,480 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "b871e70f9f0b7bd3852672c371c754d8db50e5015c8dbdad1d217a3e58a26c33"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
"python_version": "3.6"
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"name": "pypi",
|
||||
"url": "https://pypi.python.org/simple",
|
||||
"verify_ssl": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"default": {},
|
||||
"develop": {
|
||||
"argparse": {
|
||||
"hashes": [
|
||||
"sha256:62b089a55be1d8949cd2bc7e0df0bddb9e028faefc8c32038cc84862aefdd6e4",
|
||||
"sha256:c31647edb69fd3d465a847ea3157d37bed1f95f19760b11a47aa91c04b666314"
|
||||
],
|
||||
"markers": "python_version == '2.6'",
|
||||
"version": "==1.4.0"
|
||||
},
|
||||
"attrs": {
|
||||
"hashes": [
|
||||
"sha256:1c7960ccfd6a005cd9f7ba884e6316b5e430a3f1a6c37c5f87d8b43f83b54ec9",
|
||||
"sha256:a17a9573a6f475c99b551c0e0a812707ddda1ec9653bed04c13841404ed6f450"
|
||||
],
|
||||
"version": "==17.4.0"
|
||||
},
|
||||
"blinker": {
|
||||
"hashes": [
|
||||
"sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"
|
||||
],
|
||||
"version": "==1.4"
|
||||
},
|
||||
"brotlipy": {
|
||||
"hashes": [
|
||||
"sha256:07194f4768eb62a4f4ea76b6d0df6ade185e24ebd85877c351daa0a069f1111a",
|
||||
"sha256:091b299bf36dd6ef7a06570dbc98c0f80a504a56c5b797f31934d2ad01ae7d17",
|
||||
"sha256:09ec3e125d16749b31c74f021aba809541b3564e5359f8c265cbae442810b41a",
|
||||
"sha256:0be698678a114addcf87a4b9496c552c68a2c99bf93cf8e08f5738b392e82057",
|
||||
"sha256:0fa6088a9a87645d43d7e21e32b4a6bf8f7c3939015a50158c10972aa7f425b7",
|
||||
"sha256:1ea4e578241504b58f2456a6c69952c88866c794648bdc74baee74839da61d44",
|
||||
"sha256:2699945a0a992c04fc7dc7fa2f1d0575a2c8b4b769f2874a08e8eae46bef36ae",
|
||||
"sha256:2a80319ae13ea8dd60ecdc4f5ccf6da3ae64787765923256b62c598c5bba4121",
|
||||
"sha256:2e5c64522364a9ebcdf47c5744a5ddeb3f934742d31e61ebfbbc095460b47162",
|
||||
"sha256:36def0b859beaf21910157b4c33eb3b06d8ce459c942102f16988cca6ea164df",
|
||||
"sha256:3a3e56ced8b15fbbd363380344f70f3b438e0fd1fcf27b7526b6172ea950e867",
|
||||
"sha256:3c1d5e2cf945a46975bdb11a19257fa057b67591eb232f393d260e7246d9e571",
|
||||
"sha256:50ca336374131cfad20612f26cc43c637ac0bfd2be3361495e99270883b52962",
|
||||
"sha256:5de6f7d010b7558f72f4b061a07395c5c3fd57f0285c5af7f126a677b976a868",
|
||||
"sha256:637847560d671657f993313ecc6c6c6666a936b7a925779fd044065c7bc035b9",
|
||||
"sha256:653faef61241bf8bf99d73ca7ec4baa63401ba7b2a2aa88958394869379d67c7",
|
||||
"sha256:786afc8c9bd67de8d31f46e408a3386331e126829114e4db034f91eacb05396d",
|
||||
"sha256:79aaf217072840f3e9a3b641cccc51f7fc23037496bd71e26211856b93f4b4cb",
|
||||
"sha256:7e31f7adcc5851ca06134705fcf3478210da45d35ad75ec181e1ce9ce345bb38",
|
||||
"sha256:8b39abc3256c978f575df5cd7893153277216474f303e26f0e43ba3d3969ef96",
|
||||
"sha256:9448227b0df082e574c45c983fa5cd4bda7bfb11ea6b59def0940c1647be0c3c",
|
||||
"sha256:96bc59ff9b5b5552843dc67999486a220e07a0522dddd3935da05dc194fa485c",
|
||||
"sha256:a07647886e24e2fb2d68ca8bf3ada398eb56fd8eac46c733d4d95c64d17f743b",
|
||||
"sha256:af65d2699cb9f13b26ec3ba09e75e80d31ff422c03675fcb36ee4dabe588fdc2",
|
||||
"sha256:b4c98b0d2c9c7020a524ca5bbff42027db1004c6571f8bc7b747f2b843128e7a",
|
||||
"sha256:c6cc0036b1304dd0073eec416cb2f6b9e37ac8296afd9e481cac3b1f07f9db25",
|
||||
"sha256:d2c1c724c4ac375feb2110f1af98ecdc0e5a8ea79d068efb5891f621a5b235cb",
|
||||
"sha256:dc6c5ee0df9732a44d08edab32f8a616b769cc5a4155a12d2d010d248eb3fb07",
|
||||
"sha256:fd1d1c64214af5d90014d82cee5d8141b13d44c92ada7a0c0ec0679c6f15a471"
|
||||
],
|
||||
"version": "==0.7.0"
|
||||
},
|
||||
"certifi": {
|
||||
"hashes": [
|
||||
"sha256:14131608ad2fd56836d33a71ee60fa1c82bc9d2c8d98b7bdbc631fe1b3cd1296",
|
||||
"sha256:edbc3f203427eef571f79a7692bb160a2b0f7ccaa31953e99bd17e307cf63f7d"
|
||||
],
|
||||
"version": "==2018.1.18"
|
||||
},
|
||||
"cffi": {
|
||||
"hashes": [
|
||||
"sha256:151b7eefd035c56b2b2e1eb9963c90c6302dc15fbd8c1c0a83a163ff2c7d7743",
|
||||
"sha256:1553d1e99f035ace1c0544050622b7bc963374a00c467edafac50ad7bd276aef",
|
||||
"sha256:1b0493c091a1898f1136e3f4f991a784437fac3673780ff9de3bcf46c80b6b50",
|
||||
"sha256:2ba8a45822b7aee805ab49abfe7eec16b90587f7f26df20c71dd89e45a97076f",
|
||||
"sha256:3c85641778460581c42924384f5e68076d724ceac0f267d66c757f7535069c93",
|
||||
"sha256:3eb6434197633b7748cea30bf0ba9f66727cdce45117a712b29a443943733257",
|
||||
"sha256:4c91af6e967c2015729d3e69c2e51d92f9898c330d6a851bf8f121236f3defd3",
|
||||
"sha256:770f3782b31f50b68627e22f91cb182c48c47c02eb405fd689472aa7b7aa16dc",
|
||||
"sha256:79f9b6f7c46ae1f8ded75f68cf8ad50e5729ed4d590c74840471fc2823457d04",
|
||||
"sha256:7a33145e04d44ce95bcd71e522b478d282ad0eafaf34fe1ec5bbd73e662f22b6",
|
||||
"sha256:857959354ae3a6fa3da6651b966d13b0a8bed6bbc87a0de7b38a549db1d2a359",
|
||||
"sha256:87f37fe5130574ff76c17cab61e7d2538a16f843bb7bca8ebbc4b12de3078596",
|
||||
"sha256:95d5251e4b5ca00061f9d9f3d6fe537247e145a8524ae9fd30a2f8fbce993b5b",
|
||||
"sha256:9d1d3e63a4afdc29bd76ce6aa9d58c771cd1599fbba8cf5057e7860b203710dd",
|
||||
"sha256:a36c5c154f9d42ec176e6e620cb0dd275744aa1d804786a71ac37dc3661a5e95",
|
||||
"sha256:ae5e35a2c189d397b91034642cb0eab0e346f776ec2eb44a49a459e6615d6e2e",
|
||||
"sha256:b0f7d4a3df8f06cf49f9f121bead236e328074de6449866515cea4907bbc63d6",
|
||||
"sha256:b75110fb114fa366b29a027d0c9be3709579602ae111ff61674d28c93606acca",
|
||||
"sha256:ba5e697569f84b13640c9e193170e89c13c6244c24400fc57e88724ef610cd31",
|
||||
"sha256:be2a9b390f77fd7676d80bc3cdc4f8edb940d8c198ed2d8c0be1319018c778e1",
|
||||
"sha256:d5d8555d9bfc3f02385c1c37e9f998e2011f0db4f90e250e5bc0c0a85a813085",
|
||||
"sha256:e55e22ac0a30023426564b1059b035973ec82186ddddbac867078435801c7801",
|
||||
"sha256:e90f17980e6ab0f3c2f3730e56d1fe9bcba1891eeea58966e89d352492cc74f4",
|
||||
"sha256:ecbb7b01409e9b782df5ded849c178a0aa7c906cf8c5a67368047daab282b184",
|
||||
"sha256:ed01918d545a38998bfa5902c7c00e0fee90e957ce036a4000a88e3fe2264917",
|
||||
"sha256:edabd457cd23a02965166026fd9bfd196f4324fe6032e866d0f3bd0301cd486f",
|
||||
"sha256:fdf1c1dc5bafc32bc5d08b054f94d659422b05aba244d6be4ddc1c72d9aa70fb"
|
||||
],
|
||||
"version": "==1.11.5"
|
||||
},
|
||||
"chardet": {
|
||||
"hashes": [
|
||||
"sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
|
||||
"sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
|
||||
],
|
||||
"version": "==3.0.4"
|
||||
},
|
||||
"click": {
|
||||
"hashes": [
|
||||
"sha256:29f99fc6125fbc931b758dc053b3114e55c77a6e4c6c3a2674a2dc986016381d",
|
||||
"sha256:f15516df478d5a56180fbf80e68f206010e6d160fc39fa508b65e035fd75130b"
|
||||
],
|
||||
"version": "==6.7"
|
||||
},
|
||||
"colorama": {
|
||||
"hashes": [
|
||||
"sha256:463f8483208e921368c9f306094eb6f725c6ca42b0f97e313cb5d5512459feda",
|
||||
"sha256:48eb22f4f8461b1df5734a074b57042430fb06e1d61bd1e11b078c0fe6d7a1f1"
|
||||
],
|
||||
"markers": "sys_platform == 'win32'",
|
||||
"version": "==0.3.9"
|
||||
},
|
||||
"contextlib2": {
|
||||
"hashes": [
|
||||
"sha256:509f9419ee91cdd00ba34443217d5ca51f5a364a404e1dce9e8979cea969ca48",
|
||||
"sha256:f5260a6e679d2ff42ec91ec5252f4eeffdcf21053db9113bd0a8e4d953769c00"
|
||||
],
|
||||
"markers": "python_version < '3.2'",
|
||||
"version": "==0.5.5"
|
||||
},
|
||||
"crayons": {
|
||||
"hashes": [
|
||||
"sha256:5e17691605e564d63482067eb6327d01a584bbaf870beffd4456a3391bd8809d",
|
||||
"sha256:6f51241d0c4faec1c04c1c0ac6a68f1d66a4655476ce1570b3f37e5166a599cc"
|
||||
],
|
||||
"version": "==0.1.2"
|
||||
},
|
||||
"dateparser": {
|
||||
"hashes": [
|
||||
"sha256:940828183c937bcec530753211b70f673c0a9aab831e43273489b310538dff86",
|
||||
"sha256:b452ef8b36cd78ae86a50721794bc674aa3994e19b570f7ba92810f4e0a2ae03"
|
||||
],
|
||||
"version": "==0.7.0"
|
||||
},
|
||||
"decorator": {
|
||||
"hashes": [
|
||||
"sha256:7d46dd9f3ea1cf5f06ee0e4e1277ae618cf48dfb10ada7c8427cd46c42702a0e",
|
||||
"sha256:94d1d8905f5010d74bbbd86c30471255661a14187c45f8d7f3e5aa8540fdb2e5"
|
||||
],
|
||||
"version": "==4.2.1"
|
||||
},
|
||||
"e1839a8": {
|
||||
"editable": true,
|
||||
"path": "."
|
||||
},
|
||||
"flask": {
|
||||
"hashes": [
|
||||
"sha256:0749df235e3ff61ac108f69ac178c9770caeaccad2509cb762ce1f65570a8856",
|
||||
"sha256:49f44461237b69ecd901cc7ce66feea0319b9158743dd27a2899962ab214dac1"
|
||||
],
|
||||
"version": "==0.12.2"
|
||||
},
|
||||
"flask-cache": {
|
||||
"hashes": [
|
||||
"sha256:33187b3ddceeee233fe3db68ffcc118b5498e8ad28edde711bcbdcbf4924ce35",
|
||||
"sha256:90126ca9bc063854ef8ee276e95d38b2b4ec8e45fd77d5751d37971ee27c7ef4",
|
||||
"sha256:ae9d1ac4549517dfbc1f178ccc5429f61f836be3cc109a0b2481c98b3711c329"
|
||||
],
|
||||
"version": "==0.13.1"
|
||||
},
|
||||
"flask-common": {
|
||||
"hashes": [
|
||||
"sha256:44fbb57a12bc7478d56c223eb5de7b2fb98ce42a70314c74ffecf5dbe75ed1b8"
|
||||
],
|
||||
"version": "==0.2.0"
|
||||
},
|
||||
"flask-limiter": {
|
||||
"hashes": [
|
||||
"sha256:473aa5bc97310406aa8c12ab3dc080697bcfa8cd21a6d0aba30916911bbc673c",
|
||||
"sha256:8cce98dcf25bf2ddbb824c2b503b4fc8e1a139154240fd2c60d9306bad8a0db8"
|
||||
],
|
||||
"version": "==1.0.1"
|
||||
},
|
||||
"funcsigs": {
|
||||
"hashes": [
|
||||
"sha256:330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca",
|
||||
"sha256:a7bb0f2cf3a3fd1ab2732cb49eba4252c2af4240442415b4abce3b87022a8f50"
|
||||
],
|
||||
"markers": "python_version < '3.0'",
|
||||
"version": "==1.0.2"
|
||||
},
|
||||
"greenlet": {
|
||||
"hashes": [
|
||||
"sha256:09ef2636ea35782364c830f07127d6c7a70542b178268714a9a9ba16318e7e8b",
|
||||
"sha256:0fef83d43bf87a5196c91e73cb9772f945a4caaff91242766c5916d1dd1381e4",
|
||||
"sha256:1b7df09c6598f5cfb40f843ade14ed1eb40596e75cd79b6fa2efc750ba01bb01",
|
||||
"sha256:1fff21a2da5f9e03ddc5bd99131a6b8edf3d7f9d6bc29ba21784323d17806ed7",
|
||||
"sha256:42118bf608e0288e35304b449a2d87e2ba77d1e373e8aa221ccdea073de026fa",
|
||||
"sha256:50643fd6d54fd919f9a0a577c5f7b71f5d21f0959ab48767bd4bb73ae0839500",
|
||||
"sha256:58798b5d30054bb4f6cf0f712f08e6092df23a718b69000786634a265e8911a9",
|
||||
"sha256:5b49b3049697aeae17ef7bf21267e69972d9e04917658b4e788986ea5cc518e8",
|
||||
"sha256:75c413551a436b462d5929255b6dc9c0c3c2b25cbeaee5271a56c7fda8ca49c0",
|
||||
"sha256:769b740aeebd584cd59232be84fdcaf6270b8adc356596cdea5b2152c82caaac",
|
||||
"sha256:ad2383d39f13534f3ca5c48fe1fc0975676846dc39c2cece78c0f1f9891418e0",
|
||||
"sha256:b417bb7ff680d43e7bd7a13e2e08956fa6acb11fd432f74c97b7664f8bdb6ec1",
|
||||
"sha256:b6ef0cabaf5a6ecb5ac122e689d25ba12433a90c7b067b12e5f28bdb7fb78254",
|
||||
"sha256:c2de19c88bdb0366c976cc125dca1002ec1b346989d59524178adfd395e62421",
|
||||
"sha256:c7b04a6dc74087b1598de8d713198de4718fa30ec6cbb84959b26426c198e041",
|
||||
"sha256:f8f2a0ae8de0b49c7b5b2daca4f150fdd9c1173e854df2cce3b04123244f9f45",
|
||||
"sha256:fcfadaf4bf68a27e5dc2f42cbb2f4b4ceea9f05d1d0b8f7787e640bed2801634"
|
||||
],
|
||||
"version": "==0.4.13"
|
||||
},
|
||||
"gunicorn": {
|
||||
"hashes": [
|
||||
"sha256:75af03c99389535f218cc596c7de74df4763803f7b63eb09d77e92b3956b36c6",
|
||||
"sha256:eee1169f0ca667be05db3351a0960765620dad53f53434262ff8901b68a1b622"
|
||||
],
|
||||
"version": "==19.7.1"
|
||||
},
|
||||
"httpbin": {
|
||||
"hashes": [
|
||||
"sha256:0afa0486a76305cac441b5cc80d5d4ccd82b20875da7c5119ecfe616cefef45f",
|
||||
"sha256:7c3a4d69f9d495e6df1d51a50ba7b1e4f33a1cb61e0db95ee7f8953e27a2243f"
|
||||
],
|
||||
"version": "==0.6.2"
|
||||
},
|
||||
"humanize": {
|
||||
"hashes": [
|
||||
"sha256:a43f57115831ac7c70de098e6ac46ac13be00d69abbf60bdcac251344785bb19"
|
||||
],
|
||||
"version": "==0.5.1"
|
||||
},
|
||||
"idna": {
|
||||
"hashes": [
|
||||
"sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f",
|
||||
"sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4"
|
||||
],
|
||||
"version": "==2.6"
|
||||
},
|
||||
"itsdangerous": {
|
||||
"hashes": [
|
||||
"sha256:cbb3fcf8d3e33df861709ecaf89d9e6629cff0a217bc2848f1b41cd30d360519"
|
||||
],
|
||||
"version": "==0.24"
|
||||
},
|
||||
"jinja2": {
|
||||
"hashes": [
|
||||
"sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd",
|
||||
"sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4"
|
||||
],
|
||||
"version": "==2.10"
|
||||
},
|
||||
"limits": {
|
||||
"hashes": [
|
||||
"sha256:9df578f4161017d79f5188609f1d65f6b639f8aad2914c3960c9252e56a0ff95",
|
||||
"sha256:a017b8d9e9da6761f4574642149c337f8f540d4edfe573fb91ad2c4001a2bc76"
|
||||
],
|
||||
"version": "==1.3"
|
||||
},
|
||||
"markupsafe": {
|
||||
"hashes": [
|
||||
"sha256:a6be69091dac236ea9c6bc7d012beab42010fa914c459791d627dad4910eb665"
|
||||
],
|
||||
"version": "==1.0"
|
||||
},
|
||||
"maya": {
|
||||
"hashes": [
|
||||
"sha256:ad1969bae78afb148c45a2f63591a7575ec05b4a0ab7ec04987ab7d73649f9d6",
|
||||
"sha256:d8a7ed8513b2990036fe456c9f595b54d19ec49cb4461cd95a2ef6c487fb55eb"
|
||||
],
|
||||
"version": "==0.3.4"
|
||||
},
|
||||
"meinheld": {
|
||||
"hashes": [
|
||||
"sha256:293eff4983b7fcbd9134b47706b22189883fe354993bd10163c65869d141e565",
|
||||
"sha256:40d9dbce0165b2d9142f364d26fd6d59d3682f89d0dfe2117717a8ddad1f4133"
|
||||
],
|
||||
"version": "==0.6.1"
|
||||
},
|
||||
"pendulum": {
|
||||
"hashes": [
|
||||
"sha256:0c14388546db6605a860b8b7112cb69d0b11c9ce5e072210504544e0d4575799",
|
||||
"sha256:39a255776528afe11ea0d57814f9bf3729c1e0b99063af2e5c6cfd750c3e1f7f",
|
||||
"sha256:3c85e8cbc91f45e1cc916cc9180b34153cd6aaaaacfb51a48b3156318314fa82",
|
||||
"sha256:8199206c479b13947dcac63c025575d035331bb3819d1783dc1d568a11962906",
|
||||
"sha256:8798aeca58b3dd7ffdc5a4993c9eaafedc4048165429e8f499ddd62c73bf3964",
|
||||
"sha256:881efe37328de0785c0731d462e1485a45712f2cd5cb55907d6c15458460ebeb",
|
||||
"sha256:bcca072f82e84b419efec1320cd3ee5c230d263f3a601b146651ed4db77d89f0",
|
||||
"sha256:ff0c5fa3af4a471a218408c448b804ac6bccb105127727474f4e83c0e4072e97"
|
||||
],
|
||||
"version": "==1.4.2"
|
||||
},
|
||||
"pkginfo": {
|
||||
"hashes": [
|
||||
"sha256:31a49103180ae1518b65d3f4ce09c784e2bc54e338197668b4fb7dc539521024",
|
||||
"sha256:bb1a6aeabfc898f5df124e7e00303a5b3ec9a489535f346bfbddb081af93f89e"
|
||||
],
|
||||
"version": "==1.4.1"
|
||||
},
|
||||
"pluggy": {
|
||||
"hashes": [
|
||||
"sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff"
|
||||
],
|
||||
"version": "==0.6.0"
|
||||
},
|
||||
"py": {
|
||||
"hashes": [
|
||||
"sha256:8cca5c229d225f8c1e3085be4fcf306090b00850fefad892f9d96c7b6e2f310f",
|
||||
"sha256:ca18943e28235417756316bfada6cd96b23ce60dd532642690dcfdaba988a76d"
|
||||
],
|
||||
"version": "==1.5.2"
|
||||
},
|
||||
"pycparser": {
|
||||
"hashes": [
|
||||
"sha256:99a8ca03e29851d96616ad0404b4aad7d9ee16f25c9f9708a11faf2810f7b226"
|
||||
],
|
||||
"version": "==2.18"
|
||||
},
|
||||
"pytest": {
|
||||
"hashes": [
|
||||
"sha256:8970e25181e15ab14ae895599a0a0e0ade7d1f1c4c8ca1072ce16f25526a184d",
|
||||
"sha256:9ddcb879c8cc859d2540204b5399011f842e5e8823674bf429f70ada281b3cc6"
|
||||
],
|
||||
"version": "==3.4.1"
|
||||
},
|
||||
"python-dateutil": {
|
||||
"hashes": [
|
||||
"sha256:891c38b2a02f5bb1be3e4793866c8df49c7d19baabf9c1bad62547e0b4866aca",
|
||||
"sha256:95511bae634d69bc7329ba55e646499a842bc4ec342ad54a8cdb65645a0aad3c"
|
||||
],
|
||||
"version": "==2.6.1"
|
||||
},
|
||||
"pytz": {
|
||||
"hashes": [
|
||||
"sha256:07edfc3d4d2705a20a6e99d97f0c4b61c800b8232dc1c04d87e8554f130148dd",
|
||||
"sha256:3a47ff71597f821cd84a162e71593004286e5be07a340fd462f0d33a760782b5",
|
||||
"sha256:410bcd1d6409026fbaa65d9ed33bf6dd8b1e94a499e32168acfc7b332e4095c0",
|
||||
"sha256:5bd55c744e6feaa4d599a6cbd8228b4f8f9ba96de2c38d56f08e534b3c9edf0d",
|
||||
"sha256:61242a9abc626379574a166dc0e96a66cd7c3b27fc10868003fa210be4bff1c9",
|
||||
"sha256:887ab5e5b32e4d0c86efddd3d055c1f363cbaa583beb8da5e22d2fa2f64d51ef",
|
||||
"sha256:ba18e6a243b3625513d85239b3e49055a2f0318466e0b8a92b8fb8ca7ccdf55f",
|
||||
"sha256:ed6509d9af298b7995d69a440e2822288f2eca1681b8cce37673dbb10091e5fe",
|
||||
"sha256:f93ddcdd6342f94cea379c73cddb5724e0d6d0a1c91c9bdef364dc0368ba4fda"
|
||||
],
|
||||
"version": "==2018.3"
|
||||
},
|
||||
"pytzdata": {
|
||||
"hashes": [
|
||||
"sha256:4e2cceb54335cd6c28caea46b15cd592e2aec5e8b05b0241cbccfb1b23c02ae7",
|
||||
"sha256:7cd949123e2c2060fd12793de3a4a449e36b5dea5e169b810a3ac3f0b9877cfa"
|
||||
],
|
||||
"version": "==2018.3"
|
||||
},
|
||||
"raven": {
|
||||
"hashes": [
|
||||
"sha256:738a52019d01955d5b44b49d67c9f2f4cedb1b4f70d4fb0b493931174d00e044",
|
||||
"sha256:92bf4c4819472ed20f1b9905eeeafe1bc6fe5f273d7c14506fdb8fb3a6ab2074"
|
||||
],
|
||||
"version": "==6.6.0"
|
||||
},
|
||||
"regex": {
|
||||
"hashes": [
|
||||
"sha256:1b428a296531ea1642a7da48562746309c5c06471a97bd0c02dd6a82e9cecee8",
|
||||
"sha256:27d72bb42dffb32516c28d218bb054ce128afd3e18464f30837166346758af67",
|
||||
"sha256:32cf4743debee9ea12d3626ee21eae83052763740e04086304e7a74778bf58c9",
|
||||
"sha256:32f6408dbca35040bc65f9f4ae1444d5546411fde989cb71443a182dd643305e",
|
||||
"sha256:333687d9a44738c486735955993f83bd22061a416c48f5a5f9e765e90cf1b0c9",
|
||||
"sha256:35eeccf17af3b017a54d754e160af597036435c58eceae60f1dd1364ae1250c7",
|
||||
"sha256:361a1fd703a35580a4714ec28d85e29780081a4c399a99bbfb2aee695d72aedb",
|
||||
"sha256:494bed6396a20d3aa6376bdf2d3fbb1005b8f4339558d8ac7b53256755f80303",
|
||||
"sha256:5b9c0ddd5b4afa08c9074170a2ea9b34ea296e32aeea522faaaaeeeb2fe0af2e",
|
||||
"sha256:a50532f61b23d4ab9d216a6214f359dd05c911c1a1ad20986b6738a782926c1a",
|
||||
"sha256:a9243d7b359b72c681a2c32eaa7ace8d346b7e8ce09d172a683acf6853161d9c",
|
||||
"sha256:b44624a38d07d3c954c84ad302c29f7930f4bf01443beef5589e9157b14e2a29",
|
||||
"sha256:be42a601aaaeb7a317f818490a39d153952a97c40c6e9beeb2a1103616405348",
|
||||
"sha256:eee4d94b1a626490fc8170ffd788883f8c641b576e11ba9b4a29c9f6623371e0",
|
||||
"sha256:f69d1201a4750f763971ea8364ed95ee888fc128968b39d38883a72a4d005895"
|
||||
],
|
||||
"version": "==2018.2.21"
|
||||
},
|
||||
"requests": {
|
||||
"hashes": [
|
||||
"sha256:6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b",
|
||||
"sha256:9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e"
|
||||
],
|
||||
"version": "==2.18.4"
|
||||
},
|
||||
"requests-toolbelt": {
|
||||
"hashes": [
|
||||
"sha256:42c9c170abc2cacb78b8ab23ac957945c7716249206f90874651971a4acff237",
|
||||
"sha256:f6a531936c6fa4c6cfce1b9c10d5c4f498d16528d2a54a22ca00011205a187b5"
|
||||
],
|
||||
"version": "==0.8.0"
|
||||
},
|
||||
"ruamel.yaml": {
|
||||
"hashes": [
|
||||
"sha256:01e30ecb1b1c0ebf9fce814dc20dace402571517277799291202b61b22096c24",
|
||||
"sha256:02babffd019911841ba01b76e23dfec7c9e9b2725503fb2698c4982fa1a6e835",
|
||||
"sha256:072f6364a89972e8dc0afdce3335a709d5464dfeaa4f736d092a54574338b874",
|
||||
"sha256:14d161558e3bf89e87d77c218098be22fa9a0d6d0bea40250fce525b1d0cbee2",
|
||||
"sha256:5504398fc755a2b14c9983b2101161a8591a4b30812590cc1c365e7fcc117dfa",
|
||||
"sha256:68c8f2986bcb91b6db1aea8698941769840c7257e951a9377048f7eff35be773",
|
||||
"sha256:6d05c5a5baf829c70916c226ef3200650846a7227de226bca8a59efaf88bb973",
|
||||
"sha256:6d7929b24e329d662fa43b657fddfee5260e2d35d0a543065cd755d4e17a9b2f",
|
||||
"sha256:8dc74821e4bb6b21fb1ab35964e159391d99ee44981d07d57bf96e2395f3ef75",
|
||||
"sha256:9225c83952d28f302cfc23c3d9a6f8231bfd581476d7aff1e3c7de49eecb4ee9",
|
||||
"sha256:b6c5d5f03ba78e3f27c7188a00c4e09b6a4507fe3154ba40a294e09cb30ee016",
|
||||
"sha256:c0908896e34b617ead40552cab03c1769bdc43d1da02419160dc900c5dfddde2",
|
||||
"sha256:c41e04b526d0153c9246cfab87d7ddefdc9f165cb8886a8ec48ba7a2b73069f6",
|
||||
"sha256:e2d2715bf92156bec5fb42e92e95dac1c4d9904f8a3d4e2d0c438758fe9092d7",
|
||||
"sha256:e3bbfe0d294e08fdbb0cb05485435a2ceb4e168e98b5dc611f051c1864986b4b",
|
||||
"sha256:f2d02a4af5a13b09d0b823cdd0317b54f3e0115e50b5ac4d9840c3a1b566817f",
|
||||
"sha256:fcfc24a21594c071cc4588e84b7657a1f47ebcf6037c6c43fa15c4bbd3989ec2"
|
||||
],
|
||||
"version": "==0.15.35"
|
||||
},
|
||||
"six": {
|
||||
"hashes": [
|
||||
"sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9",
|
||||
"sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb"
|
||||
],
|
||||
"version": "==1.11.0"
|
||||
},
|
||||
"tqdm": {
|
||||
"hashes": [
|
||||
"sha256:5ec0d4442358e55cdb4a0471d04c6c831518fd8837f259db5537d90feab380df",
|
||||
"sha256:f66468c14ccd011a627734c9b3fd72f20ce16f8faecc47384eb2507af5924fb9"
|
||||
],
|
||||
"version": "==4.19.6"
|
||||
},
|
||||
"twine": {
|
||||
"hashes": [
|
||||
"sha256:caa45b7987fc96321258cd7668e3be2ff34064f5c66d2d975b641adca659c1ab",
|
||||
"sha256:d3ce5c480c22ccfb761cd358526e862b32546d2fe4bc93d46b5cf04ea3cc46ca"
|
||||
],
|
||||
"version": "==1.9.1"
|
||||
},
|
||||
"tzlocal": {
|
||||
"hashes": [
|
||||
"sha256:4ebeb848845ac898da6519b9b31879cf13b6626f7184c496037b818e238f2c4e"
|
||||
],
|
||||
"version": "==1.5.1"
|
||||
},
|
||||
"urllib3": {
|
||||
"hashes": [
|
||||
"sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b",
|
||||
"sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f"
|
||||
],
|
||||
"version": "==1.22"
|
||||
},
|
||||
"werkzeug": {
|
||||
"hashes": [
|
||||
"sha256:c3fd7a7d41976d9f44db327260e263132466836cef6f91512889ed60ad26557c",
|
||||
"sha256:d5da73735293558eb1651ee2fddc4d0dedcfa06538b8813a2e20011583c9e49b"
|
||||
],
|
||||
"version": "==0.14.1"
|
||||
},
|
||||
"whitenoise": {
|
||||
"hashes": [
|
||||
"sha256:15f43b2e701821b95c9016cf469d29e2a546cb1c7dead584ba82c36f843995cf",
|
||||
"sha256:9d81515f2b5b27051910996e1e860b1332e354d9e7bcf30c98f21dcb6713e0dd"
|
||||
],
|
||||
"version": "==3.3.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
# pytest-httpbin
|
||||
|
||||
[](https://travis-ci.org/kevin1024/pytest-httpbin)
|
||||
|
||||
[httpbin](https://httpbin.org/) is an amazing web service for testing HTTP libraries. It has several great endpoints that can test pretty much everything you need in a HTTP library. The only problem is: maybe you don't want to wait for your tests to travel across the Internet and back to make assertions against a remote web service (speed), and maybe you want to work offline (convenience).
|
||||
|
||||
Enter **pytest-httpbin**. Pytest-httpbin creates a [pytest fixture](http://pytest.org/latest/fixture.html) that is dependency-injected into your tests. It automatically starts up a HTTP server in a separate thread running httpbin and provides your test with the URL in the fixture. Check out this example:
|
||||
|
||||
```python
|
||||
def test_that_my_library_works_kinda_ok(httpbin):
|
||||
assert requests.get(httpbin.url + '/get').status_code == 200
|
||||
```
|
||||
|
||||
This replaces a test that might have looked like this before:
|
||||
|
||||
```python
|
||||
def test_that_my_library_works_kinda_ok():
|
||||
assert requests.get('http://httpbin.org/get').status_code == 200
|
||||
```
|
||||
|
||||
If you're making a lot of requests to httpbin, it can radically speed up your tests.
|
||||
|
||||

|
||||
|
||||
|
||||
# HTTPS support
|
||||
|
||||
pytest-httpbin also supports HTTPS:
|
||||
|
||||
```python
|
||||
def test_that_my_library_works_kinda_ok(httpbin_secure):
|
||||
assert requests.get(httpbin_secure.url + '/get/').status_code == 200
|
||||
```
|
||||
|
||||
It's actually starting 2 web servers in separate threads in the background: one HTTP and one HTTPS. The servers are started on a random port (see below for fixed port support), on the loopback interface on your machine. Pytest-httpbin includes a self-signed certificate. If your library verifies certificates against a CA (and it should), you'll have to add the CA from pytest-httpbin. The path to the pytest-httpbin CA bundle can by found like this `python -m pytest_httpbin.certs`.
|
||||
|
||||
For example in requests, you can set the `REQUESTS_CA_BUNDLE` python path. You can run your tests like this:
|
||||
|
||||
```bash
|
||||
REQUESTS_CA_BUNDLE=`python -m pytest_httpbin.certs` py.test tests/
|
||||
```
|
||||
|
||||
# API of the injected object
|
||||
|
||||
The injected object has the following attributes:
|
||||
|
||||
* url
|
||||
* port
|
||||
* host
|
||||
|
||||
and the following methods:
|
||||
|
||||
* join(string): Returns the results of calling `urlparse.urljoin` with the url from the injected server automatically applied as the first argument. You supply the second argument
|
||||
|
||||
Also, I defined `__add__` on the object to append to `httpbin.url`. This means you can do stuff like `httpbin + '/get'` instead of `httpbin.url + '/get'`.
|
||||
|
||||
## Testing both HTTP and HTTPS endpoints with one test
|
||||
|
||||
If you ever find yourself needing to test both the http and https version of and endpoint, you can use the `httpbin_both` funcarg like this:
|
||||
|
||||
|
||||
```python
|
||||
def test_that_my_library_works_kinda_ok(httpbin_both):
|
||||
assert requests.get(httpbin_both.url + '/get/').status_code == 200
|
||||
```
|
||||
|
||||
Through the magic of pytest parametrization, this function will actually execute twice: once with an http url and once with an https url.
|
||||
|
||||
## Using pytest-httpbin with unittest-style test cases
|
||||
|
||||
I have provided 2 additional fixtures to make testing with class-based tests easier. I have also provided a couple decorators that provide some syntactic sugar around the pytest method of adding the fixtures to class-based tests. Just add the `use_class_based_httpbin` and/or `use_class_based_httpbin_secure` class decorators to your class, and then you can access httpbin using self.httpbin and self.httpbin_secure.
|
||||
|
||||
```python
|
||||
import pytest_httpbin
|
||||
|
||||
@pytest_httpbin.use_class_based_httpbin
|
||||
@pytest_httpbin.use_class_based_httpbin_secure
|
||||
class TestClassBassedTests(unittest.TestCase):
|
||||
def test_http(self):
|
||||
assert requests.get(self.httpbin.url + '/get').response
|
||||
|
||||
def test_http_secure(self):
|
||||
assert requests.get(self.httpbin_secure.url + '/get').response
|
||||
```
|
||||
|
||||
## Running the server on fixed port
|
||||
|
||||
Sometimes a randomized port can be a problem. Worry not, you can fix the port number to a desired value with the `HTTPBIN_HTTP_PORT` and `HTTPBIN_HTTPS_PORT` environment variables. If those are defined during pytest plugins are loaded, `httbin` and `httpbin_secure` fixtures will run on given ports. You can run your tests like this:
|
||||
|
||||
```bash
|
||||
HTTPBIN_HTTP_PORT=8080 HTTPBIN_HTTPS_PORT=8443 py.test tests/
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
All you need to do is this:
|
||||
|
||||
```bash
|
||||
pip install pytest-httpbin
|
||||
```
|
||||
|
||||
and your tests executed by pytest all will have access to the `httpbin` and `httpbin_secure` funcargs. Cool right?
|
||||
|
||||
## Support and dependencies
|
||||
|
||||
pytest-httpbin suports Python 2.6, 2.7, 3.4, and pypy. It will automatically install httpbin and flask when you install it from pypi.
|
||||
|
||||
[httpbin](https://github.com/kennethreitz/httpbin) itself does not support python 2.6 as of version 0.6.0, when the Flask-common dependency was added. If you need python 2.6 support pin the httpbin version to 0.5.0
|
||||
|
||||
## Running the pytest-httpbin test suite
|
||||
|
||||
If you want to run pytest-httpbin's test suite, you'll need to install requests and pytest, and then use the ./runtests.sh script.
|
||||
|
||||
```bash
|
||||
pip install pytest
|
||||
/.runtests.sh
|
||||
```
|
||||
|
||||
Also, you can use tox to run the tests on all supported python versions:
|
||||
|
||||
```bash
|
||||
pip install tox
|
||||
tox
|
||||
```
|
||||
|
||||
## Changelog
|
||||
|
||||
* 0.3.0
|
||||
* Allow to run httpbin on fixed port using environment variables (thanks @hroncok)
|
||||
* Allow server to be thread.join()ed (thanks @graingert)
|
||||
* Add support for Python 3.6 (thanks @graingert)
|
||||
* 0.2.3:
|
||||
* Another attempt to fix #32 (Rare bug, only happens on Travis)
|
||||
* 0.2.2:
|
||||
* Fix bug with python3
|
||||
* 0.2.1:
|
||||
* Attempt to fix strange, impossible-to-reproduce bug with broken SSL certs
|
||||
that only happens on Travis (#32) [Bad release, breaks py3]
|
||||
* 0.2.0:
|
||||
* Remove threaded HTTP server. I built it for Requests, but they deleted
|
||||
their threaded test since it didn't really work very well. The threaded
|
||||
server seems to cause some strange problems with HTTP chunking, so I'll
|
||||
just remove it since nobody is using it (I hope)
|
||||
* 0.1.1:
|
||||
* Fix weird hang with SSL on pypy (again)
|
||||
* 0.1.0:
|
||||
* Update server to use multithreaded werkzeug server
|
||||
* 0.0.7:
|
||||
* Update the certificates (they expired)
|
||||
* 0.0.6:
|
||||
* Fix an issue where pypy was hanging when a request was made with an invalid
|
||||
certificate
|
||||
* 0.0.5:
|
||||
* Fix broken version parsing in 0.0.4
|
||||
* 0.0.4:
|
||||
* **Bad release: Broken version parsing**
|
||||
* Fix `BadStatusLine` error that occurs when sending multiple requests
|
||||
in a single session (PR #16). Thanks @msabramo!
|
||||
* Fix #9 ("Can't be installed at the same time than pytest?") (PR
|
||||
#14). Thanks @msabramo!
|
||||
* Add `httpbin_ca_bundle` pytest fixture. With this fixture there is
|
||||
no need to specify the bundle on every request, as it will
|
||||
automatically set `REQUESTS_CA_BUNDLE` if using
|
||||
[requests](http://docs.python-requests.org/). And you don't have to
|
||||
care about where it is located (PR #8). Thanks @t-8ch!
|
||||
* 0.0.3: Add a couple test fixtures to make testing old class-based test suites
|
||||
easier
|
||||
* 0.0.2: Fixed a couple bugs with the wsgiref server to bring behavior in line
|
||||
with httpbin.org, thanks @jakubroztocil for the bug reports
|
||||
* 0.0.1: Initial release
|
||||
|
||||
## License
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014-2015 Kevin McCarthy
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,54 @@
|
||||
Metadata-Version: 1.1
|
||||
Name: pytest-pypi
|
||||
Version: 0.1.1
|
||||
Summary: Easily test your HTTP library against a local copy of pypi
|
||||
Home-page: https://github.com/kennethreitz/pytest-pypi
|
||||
Author: Kenneth Reitz
|
||||
Author-email: me@kennethreitz.org
|
||||
License: MIT
|
||||
Description-Content-Type: UNKNOWN
|
||||
Description: pytest-httpbin
|
||||
==============
|
||||
|
||||
httpbin is an amazing web service for testing HTTP libraries. It has several
|
||||
great endpoints that can test pretty much everything you need in a HTTP
|
||||
library. The only problem is: maybe you don't want to wait for your tests to
|
||||
travel across the Internet and back to make assertions against a remote web
|
||||
service.
|
||||
|
||||
Enter pytest-httpbin. Pytest-httpbin creates a pytest "fixture" that is
|
||||
dependency-injected into your tests. It automatically starts up a HTTP server
|
||||
in a separate thread running httpbin and provides your test with the URL in the
|
||||
fixture. Check out this example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def test_that_my_library_works_kinda_ok(httpbin):
|
||||
assert requests.get(httpbin.url + '/get/').status_code == 200
|
||||
|
||||
This replaces a test that might have looked like this before:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def test_that_my_library_works_kinda_ok():
|
||||
assert requests.get('http://httpbin.org/get').status_code == 200
|
||||
|
||||
pytest-httpbin also supports https and includes its own CA cert you can use.
|
||||
Check out `the full documentation`_ on the github page.
|
||||
|
||||
.. _the full documentation: https://github.com/kevin1024/pytest-httpbin
|
||||
|
||||
Keywords: pytest-pypi testing pytest pypi
|
||||
Platform: UNKNOWN
|
||||
Classifier: Development Status :: 3 - Alpha
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: Topic :: Software Development :: Testing
|
||||
Classifier: Topic :: Software Development :: Libraries
|
||||
Classifier: License :: OSI Approved :: MIT License
|
||||
Classifier: Programming Language :: Python :: 2
|
||||
Classifier: Programming Language :: Python :: 2.6
|
||||
Classifier: Programming Language :: Python :: 2.7
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.4
|
||||
Classifier: Programming Language :: Python :: 3.5
|
||||
Classifier: Programming Language :: Python :: 3.6
|
||||
@@ -0,0 +1,17 @@
|
||||
DESCRIPTION.rst
|
||||
MANIFEST.in
|
||||
README.md
|
||||
setup.cfg
|
||||
setup.py
|
||||
pytest_pypi/__init__.py
|
||||
pytest_pypi/app.py
|
||||
pytest_pypi/certs.py
|
||||
pytest_pypi/plugin.py
|
||||
pytest_pypi/serve.py
|
||||
pytest_pypi/version.py
|
||||
pytest_pypi.egg-info/PKG-INFO
|
||||
pytest_pypi.egg-info/SOURCES.txt
|
||||
pytest_pypi.egg-info/dependency_links.txt
|
||||
pytest_pypi.egg-info/entry_points.txt
|
||||
pytest_pypi.egg-info/requires.txt
|
||||
pytest_pypi.egg-info/top_level.txt
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[pytest11]
|
||||
pypi = pytest_pypi.plugin
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
Flask
|
||||
six
|
||||
@@ -0,0 +1 @@
|
||||
pytest_pypi
|
||||
@@ -0,0 +1,14 @@
|
||||
import os
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
here = os.path.dirname(__file__)
|
||||
version_file = os.path.join(here, "version.py")
|
||||
|
||||
with open(version_file) as f:
|
||||
code = compile(f.read(), version_file, 'exec')
|
||||
exec(code)
|
||||
|
||||
use_class_based_httpbin = pytest.mark.usefixtures("class_based_pypi")
|
||||
use_class_based_httpbin_secure = pytest.mark.usefixtures("class_based_pypi_secure")
|
||||
@@ -0,0 +1,76 @@
|
||||
import os
|
||||
from flask import Flask, redirect, abort, render_template, send_file
|
||||
|
||||
PYPI_VENDOR_DIR = os.environ.get('PYPI_VENDOR_DIR', './pypi')
|
||||
PYPI_VENDOR_DIR = os.path.abspath(PYPI_VENDOR_DIR)
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
packages = {}
|
||||
|
||||
|
||||
class Package(object):
|
||||
"""docstring for Package"""
|
||||
|
||||
def __init__(self, name):
|
||||
super(Package, self).__init__()
|
||||
self.name = name
|
||||
self._releases = []
|
||||
|
||||
@property
|
||||
def releases(self):
|
||||
r = []
|
||||
for release in self._releases:
|
||||
release = release[len(PYPI_VENDOR_DIR):]
|
||||
r.append(release)
|
||||
return r
|
||||
|
||||
def __repr__(self):
|
||||
return "<Package name={0!r} releases={1!r}".format(self.name, len(self.releases))
|
||||
|
||||
def add_release(self, path_to_binary):
|
||||
self._releases.append(path_to_binary)
|
||||
|
||||
|
||||
def prepare_packages(path=PYPI_VENDOR_DIR):
|
||||
print(os.path.abspath(PYPI_VENDOR_DIR))
|
||||
for root, dirs, files in os.walk(os.path.abspath(PYPI_VENDOR_DIR)):
|
||||
for file in files:
|
||||
if not file.startswith('.'):
|
||||
package_name = root.split(os.path.sep)[-1]
|
||||
|
||||
if package_name not in packages:
|
||||
packages[package_name] = Package(package_name)
|
||||
|
||||
packages[package_name].add_release(os.path.sep.join([root, file]))
|
||||
|
||||
prepare_packages()
|
||||
|
||||
@app.route('/')
|
||||
def hello_world():
|
||||
return redirect('/simple', code=302)
|
||||
|
||||
@app.route('/simple')
|
||||
def simple():
|
||||
return render_template('simple.html', packages=packages.values())
|
||||
|
||||
@app.route('/simple/<package>/')
|
||||
def simple_package(package):
|
||||
if package in packages:
|
||||
return render_template('package.html', package=packages[package])
|
||||
else:
|
||||
abort(404)
|
||||
|
||||
@app.route('/<package>/<release>')
|
||||
def serve_package(package, release):
|
||||
if package in packages:
|
||||
package = packages[package]
|
||||
|
||||
for _release in package.releases:
|
||||
if _release.endswith(release):
|
||||
return send_file(os.path.sep.join([PYPI_VENDOR_DIR, _release]))
|
||||
|
||||
abort(404)
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run()
|
||||
@@ -0,0 +1,21 @@
|
||||
"""
|
||||
certs.py
|
||||
~~~~~~~~
|
||||
|
||||
This module returns the preferred default CA certificate bundle.
|
||||
|
||||
If you are packaging pytest-httpbin, e.g., for a Linux distribution or a
|
||||
managed environment, you can change the definition of where() to return a
|
||||
separately packaged CA bundle.
|
||||
"""
|
||||
|
||||
import os.path
|
||||
|
||||
|
||||
def where():
|
||||
"""Return the preferred certificate bundle."""
|
||||
# vendored bundle inside Requests
|
||||
return os.path.join(os.path.dirname(__file__), 'certs', 'cacert.pem')
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(where())
|
||||
@@ -0,0 +1,63 @@
|
||||
Certificate:
|
||||
Data:
|
||||
Version: 3 (0x2)
|
||||
Serial Number:
|
||||
dd:39:30:16:60:55:90:7c
|
||||
Signature Algorithm: sha1WithRSAEncryption
|
||||
Issuer: C=US, ST=Hawaii, O=kevin1024, CN=pytest-httpbin Certificate Authority
|
||||
Validity
|
||||
Not Before: Jun 26 18:16:59 2015 GMT
|
||||
Not After : Jun 18 18:16:59 2045 GMT
|
||||
Subject: C=US, ST=Hawaii, O=kevin1024, CN=pytest-httpbin Certificate Authority
|
||||
Subject Public Key Info:
|
||||
Public Key Algorithm: rsaEncryption
|
||||
RSA Public Key: (1024 bit)
|
||||
Modulus (1024 bit):
|
||||
00:bd:80:fd:e4:96:0e:3b:5e:35:9b:83:00:34:88:
|
||||
64:5a:50:53:0e:1d:94:76:c9:dc:e7:b5:59:1e:d4:
|
||||
82:55:36:a6:b4:41:2c:60:ad:76:f0:cd:42:a0:0f:
|
||||
4a:1c:0d:d7:29:da:c3:d9:c0:ea:f1:48:e0:66:4d:
|
||||
4b:7c:ff:d6:5e:e0:73:89:53:8b:6e:6c:57:7d:bd:
|
||||
e9:d0:46:39:5d:85:a5:f1:3a:d4:3d:83:19:03:44:
|
||||
93:71:2c:5e:d7:61:8e:db:cc:80:d0:f1:c0:47:bf:
|
||||
98:8f:06:40:e1:f7:41:ee:ed:a7:57:0d:a6:4c:26:
|
||||
75:8e:f1:78:d3:80:ad:9c:e9
|
||||
Exponent: 65537 (0x10001)
|
||||
X509v3 extensions:
|
||||
X509v3 Subject Key Identifier:
|
||||
AE:05:EF:BD:A9:CE:BB:A6:D8:0E:EB:C4:8C:72:2F:13:E5:CD:AA:CA
|
||||
X509v3 Authority Key Identifier:
|
||||
keyid:AE:05:EF:BD:A9:CE:BB:A6:D8:0E:EB:C4:8C:72:2F:13:E5:CD:AA:CA
|
||||
DirName:/C=US/ST=Hawaii/O=kevin1024/CN=pytest-httpbin Certificate Authority
|
||||
serial:DD:39:30:16:60:55:90:7C
|
||||
|
||||
X509v3 Basic Constraints:
|
||||
CA:TRUE
|
||||
Signature Algorithm: sha1WithRSAEncryption
|
||||
bc:0c:b4:21:03:bf:35:bf:88:9f:de:06:23:f4:e3:8f:bc:34:
|
||||
b5:8b:af:bf:31:5d:17:44:2c:72:c9:88:25:d1:c7:d0:1c:70:
|
||||
06:82:a5:fa:fa:d7:b9:16:64:c2:08:54:1e:4c:93:9f:22:4e:
|
||||
e5:4f:a7:71:e5:6e:14:31:e9:41:e2:33:23:8b:c8:01:c3:2a:
|
||||
66:a8:d8:df:ef:ee:7b:bb:84:f4:78:a6:ca:8f:29:aa:d5:fa:
|
||||
8a:73:94:0c:32:53:c8:93:bd:fc:c4:60:4d:9a:80:4f:c6:d4:
|
||||
27:44:a2:37:63:6c:97:04:ce:e3:6a:6f:d3:84:0d:b4:74:1f:
|
||||
49:eb
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDBzCCAnCgAwIBAgIJAN05MBZgVZB8MA0GCSqGSIb3DQEBBQUAMGExCzAJBgNV
|
||||
BAYTAlVTMQ8wDQYDVQQIEwZIYXdhaWkxEjAQBgNVBAoTCWtldmluMTAyNDEtMCsG
|
||||
A1UEAxMkcHl0ZXN0LWh0dHBiaW4gQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTE1
|
||||
MDYyNjE4MTY1OVoXDTQ1MDYxODE4MTY1OVowYTELMAkGA1UEBhMCVVMxDzANBgNV
|
||||
BAgTBkhhd2FpaTESMBAGA1UEChMJa2V2aW4xMDI0MS0wKwYDVQQDEyRweXRlc3Qt
|
||||
aHR0cGJpbiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwgZ8wDQYJKoZIhvcNAQEBBQAD
|
||||
gY0AMIGJAoGBAL2A/eSWDjteNZuDADSIZFpQUw4dlHbJ3Oe1WR7UglU2prRBLGCt
|
||||
dvDNQqAPShwN1ynaw9nA6vFI4GZNS3z/1l7gc4lTi25sV3296dBGOV2FpfE61D2D
|
||||
GQNEk3EsXtdhjtvMgNDxwEe/mI8GQOH3Qe7tp1cNpkwmdY7xeNOArZzpAgMBAAGj
|
||||
gcYwgcMwHQYDVR0OBBYEFK4F772pzrum2A7rxIxyLxPlzarKMIGTBgNVHSMEgYsw
|
||||
gYiAFK4F772pzrum2A7rxIxyLxPlzarKoWWkYzBhMQswCQYDVQQGEwJVUzEPMA0G
|
||||
A1UECBMGSGF3YWlpMRIwEAYDVQQKEwlrZXZpbjEwMjQxLTArBgNVBAMTJHB5dGVz
|
||||
dC1odHRwYmluIENlcnRpZmljYXRlIEF1dGhvcml0eYIJAN05MBZgVZB8MAwGA1Ud
|
||||
EwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAvAy0IQO/Nb+In94GI/Tjj7w0tYuv
|
||||
vzFdF0QscsmIJdHH0BxwBoKl+vrXuRZkwghUHkyTnyJO5U+nceVuFDHpQeIzI4vI
|
||||
AcMqZqjY3+/ue7uE9Himyo8pqtX6inOUDDJTyJO9/MRgTZqAT8bUJ0SiN2NslwTO
|
||||
42pv04QNtHQfSes=
|
||||
-----END CERTIFICATE-----
|
||||
@@ -0,0 +1,73 @@
|
||||
Certificate:
|
||||
Data:
|
||||
Version: 3 (0x2)
|
||||
Serial Number:
|
||||
dd:39:30:16:60:55:90:7e
|
||||
Signature Algorithm: sha1WithRSAEncryption
|
||||
Issuer: C=US, ST=Hawaii, O=kevin1024, CN=pytest-httpbin Certificate Authority
|
||||
Validity
|
||||
Not Before: Jun 26 18:20:35 2015 GMT
|
||||
Not After : Jun 23 18:20:35 2025 GMT
|
||||
Subject: C=US, ST=Hawaii, O=kevin1024, OU=kevin1024, CN=127.0.0.1
|
||||
Subject Public Key Info:
|
||||
Public Key Algorithm: rsaEncryption
|
||||
RSA Public Key: (2048 bit)
|
||||
Modulus (2048 bit):
|
||||
00:ce:b4:0f:0b:86:17:68:24:6f:7c:25:32:73:81:
|
||||
bd:55:38:05:ae:09:29:00:c0:f1:99:30:5a:7f:05:
|
||||
9f:e7:e9:d3:ce:d0:dd:4f:73:c8:bf:65:04:94:e5:
|
||||
11:8e:1d:91:f0:88:85:3e:48:d3:09:5b:3f:8f:97:
|
||||
95:34:bf:8d:00:cb:70:d2:c1:2b:34:dd:99:1d:86:
|
||||
9b:90:54:a5:de:18:c4:03:3d:53:f0:dd:cc:6d:ec:
|
||||
fb:b9:93:ab:19:85:05:63:2d:34:a6:47:42:71:3b:
|
||||
e4:1e:4a:4c:d9:60:d4:6b:d6:51:a8:4a:30:70:2e:
|
||||
6c:62:a2:34:da:cf:30:34:97:a4:9d:17:72:0b:b2:
|
||||
37:69:e2:ca:b6:d5:9f:46:c5:eb:cf:dc:46:b0:fe:
|
||||
ef:37:5e:4f:eb:f3:50:4d:2c:4e:c2:0c:e4:0c:63:
|
||||
c2:d8:ab:a3:d6:a0:12:bf:d6:fc:3f:b6:4c:dc:2b:
|
||||
9b:c5:ae:83:4d:3b:3c:19:85:50:88:82:a2:5f:ff:
|
||||
de:98:60:fc:12:3a:55:c3:4f:0a:e9:1f:aa:12:cb:
|
||||
f8:ce:14:d6:ed:89:ff:c7:ea:3b:fe:97:87:54:eb:
|
||||
62:de:cd:ef:6b:e2:9e:47:82:77:55:59:4f:b8:ad:
|
||||
1b:e0:9d:1a:28:16:9f:6a:cb:b2:44:f9:65:c3:c4:
|
||||
03:09
|
||||
Exponent: 65537 (0x10001)
|
||||
X509v3 extensions:
|
||||
X509v3 Basic Constraints:
|
||||
CA:FALSE
|
||||
Netscape Comment:
|
||||
OpenSSL Generated Certificate
|
||||
X509v3 Subject Key Identifier:
|
||||
1E:28:41:6B:12:03:41:29:64:0D:E5:C3:E3:F7:9E:82:0C:66:1E:B9
|
||||
X509v3 Authority Key Identifier:
|
||||
keyid:AE:05:EF:BD:A9:CE:BB:A6:D8:0E:EB:C4:8C:72:2F:13:E5:CD:AA:CA
|
||||
|
||||
Signature Algorithm: sha1WithRSAEncryption
|
||||
67:8c:6d:a1:2f:b3:35:87:a3:c0:04:92:5d:8a:8b:f8:51:6e:
|
||||
94:88:59:ed:66:b2:54:b0:a2:3d:7a:05:ee:19:17:a6:0b:3b:
|
||||
20:f7:d2:73:2c:f0:b9:ad:2e:5d:45:11:5d:8d:33:5c:69:7f:
|
||||
4a:c5:8c:10:3e:35:b4:39:d7:52:66:bc:02:d8:4d:d0:ba:a1:
|
||||
ae:55:f5:36:01:17:97:40:1a:9d:6a:e0:b8:33:be:2d:98:b7:
|
||||
5b:92:6a:77:a7:d9:f5:5b:a4:5f:fa:aa:5b:c1:6b:4d:0c:b7:
|
||||
5a:4c:47:b2:f7:90:a3:ff:6f:8c:fd:f2:60:38:53:29:71:48:
|
||||
d7:69
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDODCCAqGgAwIBAgIJAN05MBZgVZB+MA0GCSqGSIb3DQEBBQUAMGExCzAJBgNV
|
||||
BAYTAlVTMQ8wDQYDVQQIEwZIYXdhaWkxEjAQBgNVBAoTCWtldmluMTAyNDEtMCsG
|
||||
A1UEAxMkcHl0ZXN0LWh0dHBiaW4gQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTE1
|
||||
MDYyNjE4MjAzNVoXDTI1MDYyMzE4MjAzNVowWjELMAkGA1UEBhMCVVMxDzANBgNV
|
||||
BAgTBkhhd2FpaTESMBAGA1UEChMJa2V2aW4xMDI0MRIwEAYDVQQLEwlrZXZpbjEw
|
||||
MjQxEjAQBgNVBAMTCTEyNy4wLjAuMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
|
||||
AQoCggEBAM60DwuGF2gkb3wlMnOBvVU4Ba4JKQDA8ZkwWn8Fn+fp087Q3U9zyL9l
|
||||
BJTlEY4dkfCIhT5I0wlbP4+XlTS/jQDLcNLBKzTdmR2Gm5BUpd4YxAM9U/DdzG3s
|
||||
+7mTqxmFBWMtNKZHQnE75B5KTNlg1GvWUahKMHAubGKiNNrPMDSXpJ0XcguyN2ni
|
||||
yrbVn0bF68/cRrD+7zdeT+vzUE0sTsIM5Axjwtiro9agEr/W/D+2TNwrm8Wug007
|
||||
PBmFUIiCol//3phg/BI6VcNPCukfqhLL+M4U1u2J/8fqO/6Xh1TrYt7N72vinkeC
|
||||
d1VZT7itG+CdGigWn2rLskT5ZcPEAwkCAwEAAaN7MHkwCQYDVR0TBAIwADAsBglg
|
||||
hkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0O
|
||||
BBYEFB4oQWsSA0EpZA3lw+P3noIMZh65MB8GA1UdIwQYMBaAFK4F772pzrum2A7r
|
||||
xIxyLxPlzarKMA0GCSqGSIb3DQEBBQUAA4GBAGeMbaEvszWHo8AEkl2Ki/hRbpSI
|
||||
We1mslSwoj16Be4ZF6YLOyD30nMs8LmtLl1FEV2NM1xpf0rFjBA+NbQ511JmvALY
|
||||
TdC6oa5V9TYBF5dAGp1q4Lgzvi2Yt1uSanen2fVbpF/6qlvBa00Mt1pMR7L3kKP/
|
||||
b4z98mA4UylxSNdp
|
||||
-----END CERTIFICATE-----
|
||||
@@ -0,0 +1,28 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpQIBAAKCAQEAzrQPC4YXaCRvfCUyc4G9VTgFrgkpAMDxmTBafwWf5+nTztDd
|
||||
T3PIv2UElOURjh2R8IiFPkjTCVs/j5eVNL+NAMtw0sErNN2ZHYabkFSl3hjEAz1T
|
||||
8N3Mbez7uZOrGYUFYy00pkdCcTvkHkpM2WDUa9ZRqEowcC5sYqI02s8wNJeknRdy
|
||||
C7I3aeLKttWfRsXrz9xGsP7vN15P6/NQTSxOwgzkDGPC2Kuj1qASv9b8P7ZM3Cub
|
||||
xa6DTTs8GYVQiIKiX//emGD8EjpVw08K6R+qEsv4zhTW7Yn/x+o7/peHVOti3s3v
|
||||
a+KeR4J3VVlPuK0b4J0aKBafasuyRPllw8QDCQIDAQABAoIBAQCJ//iTbwCtjLXJ
|
||||
omPebd3jyTUxjfgMAsTJy1h/uVea06ePSi6W3uxFq8G1ToG76c4HUn3yqVgLxRnY
|
||||
WhFJWCFhSHGYo1KfRtr0tWuinoDmmI40w3sJMmtLcI5WxVnT/dUs839VC/o18xBH
|
||||
kL9h2Z24KSv3OSDBpJzD9Rtogi7izK8DSQoANBMDEmPPJ5UJBLPjdZn04i6BYZCM
|
||||
U/+ZADHKXbq6I+7RAcbPJbkvrbBEP234KZvIdw1eIAIZufQBQuDhnwS0Fi9iY/EP
|
||||
awoYa9HLgFjh+iprhwh+2SDyIp8DA+4HrY1tXAyzCqjgLn/X8wifOUrZECYj1i65
|
||||
EOiryxMBAoGBAPjmvIwBRxnr1OsKX3gCFoZr+Zu5RjACD9IOSV17cv7glZQVfXBR
|
||||
REDBoL7CmZrhsW4zBK0YWz30Dx7TGBniTFJ3e8IZJ7Th8PSOhIRYWqqFQ78YBHFi
|
||||
VcpPOBswy1i8BM9FE0GyF1zusmz8Ak2hFr/IHVkIqHwWvkTI6gGhbJ2RAoGBANSZ
|
||||
OqEWJKbRX9nuRqSdROqLOtUgWXZ78yvcQaaifyZHEFSKZZjc5MXT96lVd1PyGGAY
|
||||
uyjAqdd5LiwsS9Rw1cuC5fix2ihH5KFq7EnEJA/zdy91YdO6xmAyBOtjuTHsNj93
|
||||
if4ilib290/mRKXeI1zpzzWHsvL9Az5spqlkljH5AoGAfln7ewMnCfSbCJoibrR4
|
||||
pNJpSvEZvUM+rr6L5cXGUbbGl/70x7CpekoRBOWavnI19SA3Dnvfzap4hohYosMr
|
||||
RW3cSGMmsf9Ep5E1mk2T8R5njrltf/WQYXwnmj4B7FC+DE4fgWkbzRRrRUIFFU1i
|
||||
VAcNRuZLSXruKdLoX92HWtECgYEAhpTlf3n0A8JBKkVjZOvF56/xs19CIvY+LsLE
|
||||
sIbndMTBurLNs+IJ1I3llsVqv7Je6d5eBGNKYQPuTbpQ2o//V1Bq4m88CgnQ2rpE
|
||||
EEJhDdPy3BEzt4Ph9p1Tbet4HflJMg4rRbyBTvNCBctgI5wmyLeeG2Xmy1mNhyPi
|
||||
sRLi3YkCgYEAiHMsniJc1gZBevjtnqGTPdUo0syAnkZ7RUk/Piur/c0Altkgu5vK
|
||||
I7p3DbkHBAMDjpAZs1kpfmR4sTYKke+IQDxj2pOZEyYnmQxlGdy8xxoE9dWQeDeg
|
||||
Le+R83OAKjU4LHpH7hhJMR8X60MJaWC1BDACFO35kqIzvtCYxgEoOiI=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
from __future__ import absolute_import
|
||||
import pytest
|
||||
from .app import app as pypi_app
|
||||
from . import serve, certs
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def pypi(request):
|
||||
server = serve.Server(application=pypi_app)
|
||||
server.start()
|
||||
request.addfinalizer(server.stop)
|
||||
return server
|
||||
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def pypi_secure(request):
|
||||
server = serve.SecureServer(application=pypi_app)
|
||||
server.start()
|
||||
request.addfinalizer(server.stop)
|
||||
return server
|
||||
|
||||
|
||||
@pytest.fixture(scope='session', params=['http', 'https'])
|
||||
def pypi_both(request, pypi, pypi_secure):
|
||||
if request.param == 'http':
|
||||
return pypi
|
||||
elif request.param == 'https':
|
||||
return pypi_secure
|
||||
|
||||
|
||||
@pytest.fixture(scope='class')
|
||||
def class_based_pypi(request, pypi):
|
||||
request.cls.pypi = pypi
|
||||
|
||||
@pytest.fixture(scope='class')
|
||||
def class_based_pypi_secure(request, pypi_secure):
|
||||
request.cls.pypi_secure = pypi_secure
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
def pypi_ca_bundle(monkeypatch):
|
||||
monkeypatch.setenv('REQUESTS_CA_BUNDLE', certs.where())
|
||||
@@ -0,0 +1,134 @@
|
||||
import os
|
||||
import threading
|
||||
import ssl
|
||||
from wsgiref.simple_server import WSGIServer, make_server, WSGIRequestHandler
|
||||
from wsgiref.handlers import SimpleHandler
|
||||
from six.moves.urllib.parse import urljoin
|
||||
|
||||
|
||||
CERT_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'certs')
|
||||
|
||||
|
||||
class ServerHandler(SimpleHandler):
|
||||
|
||||
server_software = 'Pytest-HTTPBIN/0.1.0'
|
||||
http_version = '1.1'
|
||||
|
||||
def cleanup_headers(self):
|
||||
SimpleHandler.cleanup_headers(self)
|
||||
self.headers['Connection'] = 'Close'
|
||||
|
||||
def close(self):
|
||||
try:
|
||||
self.request_handler.log_request(
|
||||
self.status.split(' ', 1)[0], self.bytes_sent
|
||||
)
|
||||
finally:
|
||||
SimpleHandler.close(self)
|
||||
|
||||
|
||||
class Handler(WSGIRequestHandler):
|
||||
|
||||
def handle(self):
|
||||
"""Handle a single HTTP request"""
|
||||
|
||||
self.raw_requestline = self.rfile.readline()
|
||||
if not self.parse_request(): # An error code has been sent, just exit
|
||||
return
|
||||
|
||||
handler = ServerHandler(
|
||||
self.rfile, self.wfile, self.get_stderr(), self.get_environ()
|
||||
)
|
||||
handler.request_handler = self # backpointer for logging
|
||||
handler.run(self.server.get_app())
|
||||
|
||||
def get_environ(self):
|
||||
"""
|
||||
wsgiref simple server adds content-type text/plain to everything, this
|
||||
removes it if it's not actually in the headers.
|
||||
"""
|
||||
# Note: Can't use super since this is an oldstyle class in python 2.x
|
||||
environ = WSGIRequestHandler.get_environ(self).copy()
|
||||
if self.headers.get('content-type') is None:
|
||||
del environ['CONTENT_TYPE']
|
||||
return environ
|
||||
|
||||
|
||||
class SecureWSGIServer(WSGIServer):
|
||||
|
||||
def finish_request(self, request, client_address):
|
||||
"""
|
||||
Negotiates SSL and then mimics BaseServer behavior.
|
||||
"""
|
||||
request.settimeout(1.0)
|
||||
try:
|
||||
ssock = ssl.wrap_socket(
|
||||
request,
|
||||
keyfile=os.path.join(CERT_DIR, 'key.pem'),
|
||||
certfile=os.path.join(CERT_DIR, 'cert.pem'),
|
||||
server_side=True,
|
||||
suppress_ragged_eofs=False,
|
||||
)
|
||||
self.RequestHandlerClass(ssock, client_address, self)
|
||||
except Exception as e:
|
||||
print("pytest-httpbin server hit an exception serving request: %s" % e)
|
||||
print("attempting to ignore so the rest of the tests can run")
|
||||
# WSGIRequestHandler seems to close the socket for us.
|
||||
# Thanks, WSGIRequestHandler!!
|
||||
|
||||
|
||||
class Server(object):
|
||||
"""
|
||||
HTTP server running a WSGI application in its own thread.
|
||||
"""
|
||||
|
||||
port_envvar = 'HTTPBIN_HTTP_PORT'
|
||||
|
||||
def __init__(self, host='127.0.0.1', port=0, application=None, **kwargs):
|
||||
self.app = application
|
||||
if self.port_envvar in os.environ:
|
||||
port = int(os.environ[self.port_envvar])
|
||||
self._server = make_server(
|
||||
host,
|
||||
port,
|
||||
self.app,
|
||||
handler_class=Handler,
|
||||
**kwargs
|
||||
)
|
||||
self.host = self._server.server_address[0]
|
||||
self.port = self._server.server_address[1]
|
||||
self.protocol = 'http'
|
||||
|
||||
self._thread = threading.Thread(
|
||||
name=self.__class__,
|
||||
target=self._server.serve_forever,
|
||||
)
|
||||
|
||||
def __del__(self):
|
||||
if hasattr(self, '_server'):
|
||||
self.stop()
|
||||
|
||||
def start(self):
|
||||
self._thread.start()
|
||||
|
||||
def __add__(self, other):
|
||||
return self.url + other
|
||||
|
||||
def stop(self):
|
||||
self._server.shutdown()
|
||||
|
||||
@property
|
||||
def url(self):
|
||||
return '{0}://{1}:{2}'.format(self.protocol, self.host, self.port)
|
||||
|
||||
def join(self, url, allow_fragments=True):
|
||||
return urljoin(self.url, url, allow_fragments=allow_fragments)
|
||||
|
||||
|
||||
class SecureServer(Server):
|
||||
port_envvar = 'HTTPBIN_HTTPS_PORT'
|
||||
|
||||
def __init__(self, host='127.0.0.1', port=0, application=None, **kwargs):
|
||||
kwargs['server_class'] = SecureWSGIServer
|
||||
super(SecureServer, self).__init__(host, port, application, **kwargs)
|
||||
self.protocol = 'https'
|
||||
@@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Links for {{ package.name }}</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Links for {{ package.name }}</h1>
|
||||
{% for release in package.releases %}
|
||||
<a href="{{ release }}">{{ release }}</a>
|
||||
<br>
|
||||
{% endfor %}
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Simple Index</title>
|
||||
</head>
|
||||
<body>
|
||||
{% for package in packages %}
|
||||
<a href="/simple/{{ package.name }}/" rel="internal">{{ package.name }}</a>
|
||||
<br>
|
||||
{% endfor %}
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
__version__ = '0.1.1'
|
||||
Executable
+3
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
|
||||
py.test $1 -v -s
|
||||
@@ -0,0 +1,5 @@
|
||||
[bdist_wheel]
|
||||
# This flag says that the code is written to work on both Python 2 and Python
|
||||
# 3. If at all possible, it is good practice to do this. If you cannot, you
|
||||
# will need to generate wheels for each Python version that you support.
|
||||
universal=1
|
||||
@@ -0,0 +1,104 @@
|
||||
from setuptools import setup, find_packages, Command
|
||||
import codecs
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from shutil import rmtree
|
||||
|
||||
with open("pytest_pypi/version.py") as f:
|
||||
code = compile(f.read(), "pytest_pypi/version.py", 'exec')
|
||||
exec(code)
|
||||
|
||||
here = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
# Get the long description from the relevant file
|
||||
with codecs.open(os.path.join(here, 'DESCRIPTION.rst'), encoding='utf-8') as f:
|
||||
long_description = f.read()
|
||||
|
||||
class UploadCommand(Command):
|
||||
"""Support setup.py upload."""
|
||||
|
||||
description = 'Build and publish the package.'
|
||||
user_options = []
|
||||
|
||||
@staticmethod
|
||||
def status(s):
|
||||
"""Prints things in bold."""
|
||||
print('\033[1m{0}\033[0m'.format(s))
|
||||
|
||||
def initialize_options(self):
|
||||
pass
|
||||
|
||||
def finalize_options(self):
|
||||
pass
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
self.status('Removing previous builds…')
|
||||
rmtree(os.path.join(here, 'dist'))
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
self.status('Building Source and Wheel (universal) distribution…')
|
||||
os.system('{0} setup.py sdist bdist_wheel --universal'.format(sys.executable))
|
||||
|
||||
self.status('Uploading the package to PyPi via Twine…')
|
||||
os.system('twine upload dist/*')
|
||||
|
||||
self.status('Pushing git tags…')
|
||||
os.system('git tag v{0}'.format(__version__))
|
||||
os.system('git push --tags')
|
||||
|
||||
sys.exit()
|
||||
|
||||
setup(
|
||||
name="pytest-pypi",
|
||||
|
||||
# There are various approaches to referencing the version. For a discussion,
|
||||
# see http://packaging.python.org/en/latest/tutorial.html#version
|
||||
version=__version__,
|
||||
|
||||
description="Easily test your HTTP library against a local copy of pypi",
|
||||
long_description=long_description,
|
||||
|
||||
# The project URL.
|
||||
url='https://github.com/kennethreitz/pytest-pypi',
|
||||
|
||||
# Author details
|
||||
author='Kenneth Reitz',
|
||||
author_email='me@kennethreitz.org',
|
||||
|
||||
# Choose your license
|
||||
license='MIT',
|
||||
|
||||
classifiers=[
|
||||
'Development Status :: 3 - Alpha',
|
||||
'Intended Audience :: Developers',
|
||||
'Topic :: Software Development :: Testing',
|
||||
'Topic :: Software Development :: Libraries',
|
||||
'License :: OSI Approved :: MIT License',
|
||||
'Programming Language :: Python :: 2',
|
||||
'Programming Language :: Python :: 2.6',
|
||||
'Programming Language :: Python :: 2.7',
|
||||
'Programming Language :: Python :: 3',
|
||||
'Programming Language :: Python :: 3.4',
|
||||
'Programming Language :: Python :: 3.5',
|
||||
'Programming Language :: Python :: 3.6',
|
||||
],
|
||||
|
||||
# What does your project relate to?
|
||||
keywords='pytest-pypi testing pytest pypi',
|
||||
packages=find_packages(exclude=["contrib", "docs", "tests*"]),
|
||||
include_package_data = True, # include files listed in MANIFEST.in
|
||||
install_requires = ['Flask', 'six'],
|
||||
|
||||
# the following makes a plugin available to pytest
|
||||
entry_points = {
|
||||
'pytest11': [
|
||||
'pypi = pytest_pypi.plugin',
|
||||
]
|
||||
},
|
||||
cmdclass={
|
||||
'upload': UploadCommand,
|
||||
},
|
||||
)
|
||||
@@ -0,0 +1,10 @@
|
||||
# content of: tox.ini , put in same dir as setup.py
|
||||
|
||||
[tox]
|
||||
envlist = py26, py27, py33, py34, py35, py36, pypy, pypy3
|
||||
|
||||
[testenv]
|
||||
deps = pytest
|
||||
requests
|
||||
py26: httpbin==0.5.0
|
||||
commands = ./runtests.sh {posargs:tests/}
|
||||
+103
-103
@@ -25,6 +25,15 @@ except:
|
||||
|
||||
os.environ['PIPENV_DONT_USE_PYENV'] = '1'
|
||||
os.environ['PIPENV_IGNORE_VIRTUALENVS'] = '1'
|
||||
os.environ['PYPI_VENDOR_DIR'] = os.path.sep.join([os.path.dirname(__file__), 'pypi'])
|
||||
|
||||
from flask import Flask
|
||||
|
||||
class PYPI(object):
|
||||
"""docstring for PYPI"""
|
||||
def __init__(self, packages=None):
|
||||
super(PYPI, self).__init__()
|
||||
self.packages = packages or []
|
||||
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
@@ -41,7 +50,8 @@ def pip_src_dir(request):
|
||||
|
||||
class PipenvInstance():
|
||||
"""An instance of a Pipenv Project..."""
|
||||
def __init__(self, pipfile=True, chdir=False):
|
||||
def __init__(self, pypi=None, pipfile=True, chdir=False):
|
||||
self.pypi = pypi
|
||||
self.original_umask = os.umask(0o007)
|
||||
self.original_dir = os.path.abspath(os.curdir)
|
||||
self._path = TemporaryDirectory(suffix='project', prefix='pipenv')
|
||||
@@ -50,6 +60,9 @@ class PipenvInstance():
|
||||
self.pipfile_path = None
|
||||
self.chdir = chdir
|
||||
|
||||
if self.pypi:
|
||||
os.environ['PIPENV_TEST_INDEX'] = '{0}/simple'.format(self.pypi.url)
|
||||
|
||||
if pipfile:
|
||||
p_path = os.sep.join([self.path, 'Pipfile'])
|
||||
with open(p_path, 'a'):
|
||||
@@ -111,8 +124,8 @@ class TestPipenv:
|
||||
"""The ultimate testing class."""
|
||||
|
||||
@pytest.mark.cli
|
||||
def test_pipenv_where(self):
|
||||
with PipenvInstance() as p:
|
||||
def test_pipenv_where(self, pypi_secure):
|
||||
with PipenvInstance(pypi=pypi_secure) as p:
|
||||
assert normalize_drive(p.path) in p.pipenv('--where').out
|
||||
|
||||
@pytest.mark.cli
|
||||
@@ -137,15 +150,15 @@ class TestPipenv:
|
||||
assert not os.path.isdir(venv_path)
|
||||
|
||||
@pytest.mark.cli
|
||||
def test_pipenv_graph(self):
|
||||
with PipenvInstance() as p:
|
||||
def test_pipenv_graph(self, pypi):
|
||||
with PipenvInstance(pypi=pypi) as p:
|
||||
p.pipenv('install requests')
|
||||
assert 'requests' in p.pipenv('graph').out
|
||||
assert 'requests' in p.pipenv('graph --json').out
|
||||
|
||||
@pytest.mark.cli
|
||||
def test_pipenv_graph_reverse(self):
|
||||
with PipenvInstance() as p:
|
||||
def test_pipenv_graph_reverse(self, pypi):
|
||||
with PipenvInstance(pypi=pypi) as p:
|
||||
p.pipenv('install requests==2.18.4')
|
||||
output = p.pipenv('graph --reverse').out
|
||||
|
||||
@@ -168,8 +181,8 @@ class TestPipenv:
|
||||
assert 'Warning: Using both --reverse and --json together is not supported.' in c.err
|
||||
|
||||
@pytest.mark.cli
|
||||
def test_pipenv_check(self):
|
||||
with PipenvInstance() as p:
|
||||
def test_pipenv_check(self, pypi):
|
||||
with PipenvInstance(pypi=pypi) as p:
|
||||
p.pipenv('install requests==1.0.0')
|
||||
assert 'requests' in p.pipenv('check').out
|
||||
|
||||
@@ -201,19 +214,19 @@ class TestPipenv:
|
||||
|
||||
@pytest.mark.cli
|
||||
@pytest.mark.install
|
||||
def test_install_parse_error(self):
|
||||
with PipenvInstance() as p:
|
||||
def test_install_parse_error(self, pypi):
|
||||
with PipenvInstance(pypi=pypi) as p:
|
||||
# Make sure unparseable packages don't wind up in the pipfile
|
||||
# Escape $ for shell input
|
||||
c = p.pipenv('install tablib u/\\/p@r\$34b13+pkg')
|
||||
c = p.pipenv('install requests u/\\/p@r\$34b13+pkg')
|
||||
assert c.return_code != 0
|
||||
assert 'u/\\/p@r$34b13+pkg' not in p.pipfile['packages']
|
||||
|
||||
@pytest.mark.install
|
||||
@pytest.mark.setup
|
||||
@pytest.mark.skip(reason="this doesn't work on travis")
|
||||
def test_basic_setup(self):
|
||||
with PipenvInstance() as p:
|
||||
def test_basic_setup(self, pypi):
|
||||
with PipenvInstance(pypi=pypi) as p:
|
||||
with PipenvInstance(pipfile=False) as p:
|
||||
c = p.pipenv('install requests')
|
||||
assert c.return_code == 0
|
||||
@@ -225,22 +238,9 @@ class TestPipenv:
|
||||
assert 'urllib3' in p.lockfile['default']
|
||||
assert 'certifi' in p.lockfile['default']
|
||||
|
||||
@pytest.mark.spelling
|
||||
@pytest.mark.skip(reason="this is slightly non-deterministic")
|
||||
def test_spell_checking(self):
|
||||
with PipenvInstance() as p:
|
||||
c = p.pipenv('install flaskcors', block=False)
|
||||
c.expect(u'[Y//n]:')
|
||||
c.send('y')
|
||||
c.block()
|
||||
|
||||
assert c.return_code == 0
|
||||
assert 'flask-cors' in p.pipfile['packages']
|
||||
assert 'flask' in p.lockfile['default']
|
||||
|
||||
@pytest.mark.install
|
||||
def test_basic_install(self):
|
||||
with PipenvInstance() as p:
|
||||
def test_basic_install(self, pypi):
|
||||
with PipenvInstance(pypi=pypi) as p:
|
||||
c = p.pipenv('install requests')
|
||||
assert c.return_code == 0
|
||||
assert 'requests' in p.pipfile['packages']
|
||||
@@ -253,8 +253,8 @@ class TestPipenv:
|
||||
@pytest.mark.dev
|
||||
@pytest.mark.run
|
||||
@pytest.mark.install
|
||||
def test_basic_dev_install(self):
|
||||
with PipenvInstance() as p:
|
||||
def test_basic_dev_install(self, pypi):
|
||||
with PipenvInstance(pypi=pypi) as p:
|
||||
c = p.pipenv('install requests --dev')
|
||||
assert c.return_code == 0
|
||||
assert 'requests' in p.pipfile['dev-packages']
|
||||
@@ -269,9 +269,9 @@ class TestPipenv:
|
||||
|
||||
@pytest.mark.dev
|
||||
@pytest.mark.install
|
||||
def test_install_without_dev(self):
|
||||
def test_install_without_dev(self, pypi):
|
||||
"""Ensure that running `pipenv install` doesn't install dev packages"""
|
||||
with PipenvInstance() as p:
|
||||
with PipenvInstance(pypi=pypi) as p:
|
||||
with open(p.pipfile_path, 'w') as f:
|
||||
contents = """
|
||||
[packages]
|
||||
@@ -295,8 +295,8 @@ records = "*"
|
||||
|
||||
@pytest.mark.run
|
||||
@pytest.mark.uninstall
|
||||
def test_uninstall(self):
|
||||
with PipenvInstance() as p:
|
||||
def test_uninstall(self, pypi):
|
||||
with PipenvInstance(pypi=pypi) as p:
|
||||
c = p.pipenv('install requests')
|
||||
assert c.return_code == 0
|
||||
assert 'requests' in p.pipfile['packages']
|
||||
@@ -338,9 +338,9 @@ records = "*"
|
||||
|
||||
@pytest.mark.run
|
||||
@pytest.mark.uninstall
|
||||
def test_uninstall_all_dev(self):
|
||||
with PipenvInstance() as p:
|
||||
c = p.pipenv('install --dev requests pytest')
|
||||
def test_uninstall_all_dev(self, pypi):
|
||||
with PipenvInstance(pypi=pypi) as p:
|
||||
c = p.pipenv('install --dev requests flask')
|
||||
assert c.return_code == 0
|
||||
|
||||
c = p.pipenv('install tpfd')
|
||||
@@ -348,10 +348,10 @@ records = "*"
|
||||
|
||||
assert 'tpfd' in p.pipfile['packages']
|
||||
assert 'requests' in p.pipfile['dev-packages']
|
||||
assert 'pytest' in p.pipfile['dev-packages']
|
||||
assert 'flask' in p.pipfile['dev-packages']
|
||||
assert 'tpfd' in p.lockfile['default']
|
||||
assert 'requests' in p.lockfile['develop']
|
||||
assert 'pytest' in p.lockfile['develop']
|
||||
assert 'flask' in p.lockfile['develop']
|
||||
|
||||
|
||||
c = p.pipenv('uninstall --all-dev')
|
||||
@@ -372,8 +372,8 @@ records = "*"
|
||||
|
||||
@pytest.mark.extras
|
||||
@pytest.mark.install
|
||||
def test_extras_install(self):
|
||||
with PipenvInstance() as p:
|
||||
def test_extras_install(self, pypi):
|
||||
with PipenvInstance(pypi=pypi) as p:
|
||||
c = p.pipenv('install requests[socks]')
|
||||
assert c.return_code == 0
|
||||
assert 'requests' in p.pipfile['packages']
|
||||
@@ -388,8 +388,9 @@ records = "*"
|
||||
@pytest.mark.extras
|
||||
@pytest.mark.install
|
||||
@pytest.mark.local
|
||||
def test_local_extras_install(self):
|
||||
with PipenvInstance() as p:
|
||||
@pytest.mark.skip(reason="I'm not mocking this.")
|
||||
def test_local_extras_install(self, pypi):
|
||||
with PipenvInstance(pypi=pypi) as p:
|
||||
setup_py = os.path.join(p.path, 'setup.py')
|
||||
with open(setup_py, 'w') as fh:
|
||||
contents = """
|
||||
@@ -420,8 +421,8 @@ setup(
|
||||
|
||||
@pytest.mark.vcs
|
||||
@pytest.mark.install
|
||||
def test_basic_vcs_install(self):
|
||||
with PipenvInstance() as p:
|
||||
def test_basic_vcs_install(self, pypi):
|
||||
with PipenvInstance(pypi=pypi) as p:
|
||||
c = p.pipenv('install git+https://github.com/requests/requests.git#egg=requests')
|
||||
assert c.return_code == 0
|
||||
# edge case where normal package starts with VCS name shouldn't be flagged as vcs
|
||||
@@ -435,8 +436,8 @@ setup(
|
||||
@pytest.mark.e
|
||||
@pytest.mark.vcs
|
||||
@pytest.mark.install
|
||||
def test_editable_vcs_install(self, pip_src_dir):
|
||||
with PipenvInstance() as p:
|
||||
def test_editable_vcs_install(self, pip_src_dir, pypi):
|
||||
with PipenvInstance(pypi=pypi) as p:
|
||||
c = p.pipenv('install -e git+https://github.com/requests/requests.git#egg=requests')
|
||||
assert c.return_code == 0
|
||||
assert 'requests' in p.pipfile['packages']
|
||||
@@ -450,8 +451,8 @@ setup(
|
||||
|
||||
@pytest.mark.install
|
||||
@pytest.mark.pin
|
||||
def test_windows_pinned_pipfile(self):
|
||||
with PipenvInstance() as p:
|
||||
def test_windows_pinned_pipfile(self, pypi):
|
||||
with PipenvInstance(pypi=pypi) as p:
|
||||
with open(p.pipfile_path, 'w') as f:
|
||||
contents = """
|
||||
[packages]
|
||||
@@ -468,9 +469,9 @@ tablib = "<0.12"
|
||||
@pytest.mark.install
|
||||
@pytest.mark.vcs
|
||||
@pytest.mark.resolver
|
||||
def test_editable_vcs_install_in_pipfile_with_dependency_resolution_doesnt_traceback(self):
|
||||
def test_editable_vcs_install_in_pipfile_with_dependency_resolution_doesnt_traceback(self, pypi):
|
||||
# See https://github.com/pypa/pipenv/issues/1240
|
||||
with PipenvInstance() as p:
|
||||
with PipenvInstance(pypi=pypi) as p:
|
||||
with open(p.pipfile_path, 'w') as f:
|
||||
contents = """
|
||||
[packages]
|
||||
@@ -490,11 +491,11 @@ idna = "==2.6.0"
|
||||
|
||||
@pytest.mark.run
|
||||
@pytest.mark.install
|
||||
def test_multiprocess_bug_and_install(self):
|
||||
def test_multiprocess_bug_and_install(self, pypi):
|
||||
with temp_environ():
|
||||
os.environ['PIPENV_MAX_SUBPROCESS'] = '2'
|
||||
|
||||
with PipenvInstance() as p:
|
||||
with PipenvInstance(pypi=pypi) as p:
|
||||
with open(p.pipfile_path, 'w') as f:
|
||||
contents = """
|
||||
[packages]
|
||||
@@ -520,9 +521,9 @@ tpfd = "*"
|
||||
|
||||
@pytest.mark.sequential
|
||||
@pytest.mark.install
|
||||
def test_sequential_mode(self):
|
||||
def test_sequential_mode(self, pypi):
|
||||
|
||||
with PipenvInstance() as p:
|
||||
with PipenvInstance(pypi=pypi) as p:
|
||||
with open(p.pipfile_path, 'w') as f:
|
||||
contents = """
|
||||
[packages]
|
||||
@@ -549,8 +550,8 @@ tpfd = "*"
|
||||
@pytest.mark.install
|
||||
@pytest.mark.resolver
|
||||
@pytest.mark.backup_resolver
|
||||
def test_backup_resolver(self):
|
||||
with PipenvInstance() as p:
|
||||
def test_backup_resolver(self, pypi):
|
||||
with PipenvInstance(pypi=pypi) as p:
|
||||
with open(p.pipfile_path, 'w') as f:
|
||||
contents = """
|
||||
[packages]
|
||||
@@ -587,9 +588,9 @@ requests = {version = "*", markers="os_name=='splashwear'"}
|
||||
@pytest.mark.run
|
||||
@pytest.mark.alt
|
||||
@pytest.mark.install
|
||||
def test_specific_package_environment_markers(self):
|
||||
def test_specific_package_environment_markers(self, pypi):
|
||||
|
||||
with PipenvInstance() as p:
|
||||
with PipenvInstance(pypi=pypi) as p:
|
||||
with open(p.pipfile_path, 'w') as f:
|
||||
contents = """
|
||||
[packages]
|
||||
@@ -609,8 +610,8 @@ requests = {version = "*", os_name = "== 'splashwear'"}
|
||||
@pytest.mark.install
|
||||
@pytest.mark.vcs
|
||||
@pytest.mark.tablib
|
||||
def test_install_editable_git_tag(self, pip_src_dir):
|
||||
with PipenvInstance() as p:
|
||||
def test_install_editable_git_tag(self, pip_src_dir, pypi):
|
||||
with PipenvInstance(pypi=pypi) as p:
|
||||
c = p.pipenv('install -e git+https://github.com/kennethreitz/tablib.git@v0.12.1#egg=tablib')
|
||||
assert c.return_code == 0
|
||||
assert 'tablib' in p.pipfile['packages']
|
||||
@@ -622,9 +623,9 @@ requests = {version = "*", os_name = "== 'splashwear'"}
|
||||
@pytest.mark.run
|
||||
@pytest.mark.alt
|
||||
@pytest.mark.install
|
||||
def test_alternative_version_specifier(self):
|
||||
def test_alternative_version_specifier(self, pypi):
|
||||
|
||||
with PipenvInstance() as p:
|
||||
with PipenvInstance(pypi=pypi) as p:
|
||||
with open(p.pipfile_path, 'w') as f:
|
||||
contents = """
|
||||
[packages]
|
||||
@@ -646,26 +647,26 @@ requests = {version = "*"}
|
||||
|
||||
@pytest.mark.bad
|
||||
@pytest.mark.install
|
||||
def test_bad_packages(self):
|
||||
def test_bad_packages(self, pypi):
|
||||
|
||||
with PipenvInstance() as p:
|
||||
with PipenvInstance(pypi=pypi) as p:
|
||||
c = p.pipenv('install NotAPackage')
|
||||
assert c.return_code > 0
|
||||
|
||||
@pytest.mark.dotvenv
|
||||
def test_venv_in_project(self):
|
||||
def test_venv_in_project(self, pypi):
|
||||
|
||||
with temp_environ():
|
||||
os.environ['PIPENV_VENV_IN_PROJECT'] = '1'
|
||||
with PipenvInstance() as p:
|
||||
with PipenvInstance(pypi=pypi) as p:
|
||||
c = p.pipenv('install requests')
|
||||
assert c.return_code == 0
|
||||
|
||||
assert normalize_drive(p.path) in p.pipenv('--venv').out
|
||||
|
||||
@pytest.mark.dotvenv
|
||||
def test_reuse_previous_venv(self):
|
||||
with PipenvInstance(chdir=True) as p:
|
||||
def test_reuse_previous_venv(self, pypi):
|
||||
with PipenvInstance(chdir=True, pypi=pypi) as p:
|
||||
os.mkdir('.venv')
|
||||
c = p.pipenv('install requests')
|
||||
assert c.return_code == 0
|
||||
@@ -678,13 +679,14 @@ requests = {version = "*"}
|
||||
@pytest.mark.shell
|
||||
@pytest.mark.windows
|
||||
@pytest.mark.pew
|
||||
def test_shell_nested_venv_in_project(self):
|
||||
@pytest.mark.skip('Not mocking this.')
|
||||
def test_shell_nested_venv_in_project(self, pypi):
|
||||
import subprocess
|
||||
with temp_environ():
|
||||
os.environ['PIPENV_VENV_IN_PROJECT'] = '1'
|
||||
os.environ['PIPENV_IGNORE_VIRTUALENVS'] = '1'
|
||||
os.environ['PIPENV_SHELL_COMPAT'] = '1'
|
||||
with PipenvInstance(chdir=True) as p:
|
||||
with PipenvInstance(chdir=True, pypi=pypi) as p:
|
||||
# Signal to pew to look in the project directory for the environment
|
||||
os.environ['WORKON_HOME'] = p.path
|
||||
project = Project()
|
||||
@@ -762,33 +764,32 @@ requests = {version = "*"}
|
||||
@pytest.mark.code
|
||||
@pytest.mark.check
|
||||
@pytest.mark.unused
|
||||
def test_check_unused(self):
|
||||
def test_check_unused(self, pypi):
|
||||
|
||||
with PipenvInstance() as p:
|
||||
with PipenvInstance(chdir=True) as p:
|
||||
with PipenvInstance(chdir=True, pypi=pypi) as p:
|
||||
with open('__init__.py', 'w') as f:
|
||||
contents = """
|
||||
import tablib
|
||||
import records
|
||||
""".strip()
|
||||
f.write(contents)
|
||||
p.pipenv('install GitPython')
|
||||
p.pipenv('install requests')
|
||||
p.pipenv('install tablib')
|
||||
p.pipenv('install records')
|
||||
|
||||
assert all(pkg in p.pipfile['packages'] for pkg in ['requests', 'tablib', 'records', 'gitpython'])
|
||||
assert all(pkg in p.pipfile['packages'] for pkg in ['requests', 'tablib', 'records'])
|
||||
|
||||
c = p.pipenv('check --unused .')
|
||||
assert 'gitpython' in c.out
|
||||
assert 'tablib' not in c.out
|
||||
|
||||
@pytest.mark.extras
|
||||
@pytest.mark.install
|
||||
@pytest.mark.requirements
|
||||
def test_requirements_to_pipfile(self):
|
||||
@pytest.mark.skip(reason="Not mocking this.")
|
||||
def test_requirements_to_pipfile(self, pypi):
|
||||
|
||||
with PipenvInstance(pipfile=False, chdir=True) as p:
|
||||
with PipenvInstance(pipfile=False, chdir=True, pypi=pypi) as p:
|
||||
|
||||
# Write a requirements file
|
||||
with open('requirements.txt', 'w') as f:
|
||||
@@ -821,22 +822,21 @@ import records
|
||||
|
||||
@pytest.mark.lock
|
||||
@pytest.mark.requirements
|
||||
def test_lock_requirements_file(self):
|
||||
def test_lock_requirements_file(self, pypi):
|
||||
|
||||
with PipenvInstance() as p:
|
||||
with PipenvInstance(pypi=pypi) as p:
|
||||
with open(p.pipfile_path, 'w') as f:
|
||||
contents = """
|
||||
[packages]
|
||||
requests = "==2.14.0"
|
||||
flask = "==0.12.2"
|
||||
[dev-packages]
|
||||
pytest = "==3.1.1"
|
||||
flask = "==0.12.2"
|
||||
""".strip()
|
||||
f.write(contents)
|
||||
|
||||
req_list = ("requests==2.14.0", "flask==0.12.2")
|
||||
req_list = ("requests==2.14.0")
|
||||
|
||||
dev_req_list = ("pytest==3.1.1")
|
||||
dev_req_list = ("flask==0.12.2")
|
||||
|
||||
c = p.pipenv('lock -r')
|
||||
d = p.pipenv('lock -r -d')
|
||||
@@ -851,9 +851,9 @@ pytest = "==3.1.1"
|
||||
|
||||
@pytest.mark.lock
|
||||
@pytest.mark.complex
|
||||
def test_complex_lock_with_vcs_deps(self, pip_src_dir):
|
||||
def test_complex_lock_with_vcs_deps(self, pip_src_dir, pypi):
|
||||
|
||||
with PipenvInstance() as p:
|
||||
with PipenvInstance(pypi=pypi) as p:
|
||||
with open(p.pipfile_path, 'w') as f:
|
||||
contents = """
|
||||
[packages]
|
||||
@@ -885,9 +885,9 @@ requests = {git = "https://github.com/requests/requests", egg = "requests"}
|
||||
@pytest.mark.requirements
|
||||
@pytest.mark.complex
|
||||
@pytest.mark.maya
|
||||
def test_complex_deps_lock_and_install_properly(self):
|
||||
def test_complex_deps_lock_and_install_properly(self, pypi):
|
||||
|
||||
with PipenvInstance() as p:
|
||||
with PipenvInstance(pypi=pypi) as p:
|
||||
with open(p.pipfile_path, 'w') as f:
|
||||
contents = """
|
||||
[packages]
|
||||
@@ -904,10 +904,10 @@ maya = "*"
|
||||
@pytest.mark.lock
|
||||
@pytest.mark.requirements
|
||||
@pytest.mark.complex
|
||||
def test_complex_lock_changing_candidate(self):
|
||||
def test_complex_lock_changing_candidate(self, pypi):
|
||||
# The requests candidate will change from latest to <2.12.
|
||||
|
||||
with PipenvInstance() as p:
|
||||
with PipenvInstance(pypi=pypi) as p:
|
||||
with open(p.pipfile_path, 'w') as f:
|
||||
contents = """
|
||||
[packages]
|
||||
@@ -928,10 +928,10 @@ requests = "*"
|
||||
@pytest.mark.lock
|
||||
@pytest.mark.requirements
|
||||
@pytest.mark.complex
|
||||
def test_complex_lock_deep_extras(self):
|
||||
def test_complex_lock_deep_extras(self, pypi):
|
||||
# records[pandas] requires tablib[pandas] which requires pandas.
|
||||
|
||||
with PipenvInstance() as p:
|
||||
with PipenvInstance(pypi=pypi) as p:
|
||||
with open(p.pipfile_path, 'w') as f:
|
||||
contents = """
|
||||
[packages]
|
||||
@@ -948,9 +948,9 @@ records = {extras = ["pandas"], version = "==0.5.2"}
|
||||
|
||||
@pytest.mark.lock
|
||||
@pytest.mark.deploy
|
||||
def test_deploy_works(self):
|
||||
def test_deploy_works(self, pypi):
|
||||
|
||||
with PipenvInstance() as p:
|
||||
with PipenvInstance(pypi=pypi) as p:
|
||||
with open(p.pipfile_path, 'w') as f:
|
||||
contents = """
|
||||
[packages]
|
||||
@@ -976,9 +976,9 @@ requests = "==2.14.0"
|
||||
@pytest.mark.install
|
||||
@pytest.mark.files
|
||||
@pytest.mark.urls
|
||||
def test_urls_work(self):
|
||||
def test_urls_work(self, pypi):
|
||||
|
||||
with PipenvInstance() as p:
|
||||
with PipenvInstance(pypi=pypi) as p:
|
||||
|
||||
c = p.pipenv('install https://github.com/divio/django-cms/archive/release/3.4.x.zip')
|
||||
key = [k for k in p.pipfile['packages'].keys()][0]
|
||||
@@ -1043,8 +1043,8 @@ requests = "==2.14.0"
|
||||
@pytest.mark.install
|
||||
@pytest.mark.files
|
||||
@pytest.mark.urls
|
||||
def test_install_remote_requirements(self):
|
||||
with PipenvInstance() as p:
|
||||
def test_install_remote_requirements(self, pypi):
|
||||
with PipenvInstance(pypi=pypi) as p:
|
||||
# using a github hosted requirements.txt file
|
||||
c = p.pipenv('install -r https://raw.githubusercontent.com/kennethreitz/pipenv/3688148ac7cfecefb085c474b092c31d791952c1/tests/test_artifacts/requirements.txt')
|
||||
|
||||
@@ -1062,12 +1062,12 @@ requests = "==2.14.0"
|
||||
|
||||
@pytest.mark.install
|
||||
@pytest.mark.files
|
||||
def test_relative_paths(self):
|
||||
def test_relative_paths(self, pypi):
|
||||
file_name = 'tablib-0.12.1.tar.gz'
|
||||
test_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)))
|
||||
source_path = os.path.abspath(os.path.join(test_dir, 'test_artifacts', file_name))
|
||||
|
||||
with PipenvInstance() as p:
|
||||
with PipenvInstance(pypi=pypi) as p:
|
||||
artifact_dir = 'artifacts'
|
||||
artifact_path = os.path.join(p.path, artifact_dir)
|
||||
mkdir_p(artifact_path)
|
||||
@@ -1083,8 +1083,8 @@ requests = "==2.14.0"
|
||||
|
||||
@pytest.mark.install
|
||||
@pytest.mark.local_file
|
||||
def test_install_local_file_collision(self):
|
||||
with PipenvInstance() as p:
|
||||
def test_install_local_file_collision(self, pypi):
|
||||
with PipenvInstance(pypi=pypi) as p:
|
||||
target_package = 'alembic'
|
||||
fake_file = os.path.join(p.path, target_package)
|
||||
with open(fake_file, 'w') as f:
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import os
|
||||
|
||||
import pytest
|
||||
import pipenv.project
|
||||
import pipenv.core
|
||||
from pipenv.vendor import delegator
|
||||
@@ -7,16 +8,19 @@ from pipenv.vendor import delegator
|
||||
|
||||
class TestProject():
|
||||
|
||||
@pytest.mark.project
|
||||
def test_proper_names(self):
|
||||
proj = pipenv.project.Project()
|
||||
assert proj.virtualenv_location in proj.proper_names_location
|
||||
assert isinstance(proj.proper_names, list)
|
||||
|
||||
@pytest.mark.project
|
||||
def test_download_location(self):
|
||||
proj = pipenv.project.Project()
|
||||
assert proj.virtualenv_location in proj.download_location
|
||||
assert proj.download_location.endswith('downloads')
|
||||
|
||||
@pytest.mark.project
|
||||
def test_create_pipfile(self):
|
||||
proj = pipenv.project.Project(which=pipenv.core.which)
|
||||
|
||||
@@ -52,6 +56,7 @@ class TestProject():
|
||||
assert config_source_2['name'] == 'pip_index_1'
|
||||
assert config_source_2['verify_ssl'] is True
|
||||
|
||||
@pytest.mark.project
|
||||
def test_parsed_pipfile(self):
|
||||
proj = pipenv.project.Project()
|
||||
|
||||
@@ -76,6 +81,7 @@ class TestProject():
|
||||
assert 'packages' in pfile
|
||||
assert 'socks' in pfile['packages']['requests']['extras']
|
||||
|
||||
@pytest.mark.project
|
||||
def test_add_package_to_pipfile(self):
|
||||
proj = pipenv.project.Project()
|
||||
|
||||
@@ -107,6 +113,7 @@ class TestProject():
|
||||
assert 'click-completion' in p['packages']
|
||||
assert p['packages']['click-completion'] == '*'
|
||||
|
||||
@pytest.mark.project
|
||||
def test_remove_package_from_pipfile(self):
|
||||
proj = pipenv.project.Project()
|
||||
|
||||
@@ -139,6 +146,7 @@ class TestProject():
|
||||
|
||||
# assert 'dev-packages' not in p
|
||||
|
||||
@pytest.mark.project
|
||||
def test_internal_pipfile(self):
|
||||
proj = pipenv.project.Project()
|
||||
|
||||
@@ -161,6 +169,7 @@ class TestProject():
|
||||
|
||||
delegator.run('rm -fr test_internal_pipfile')
|
||||
|
||||
@pytest.mark.project
|
||||
def test_internal_lockfile(self):
|
||||
proj = pipenv.project.Project()
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user