mirror of
https://github.com/kennethreitz/pipenv.git
synced 2026-06-05 14:50:16 +00:00
Remove pytest-pypi package included in tests/
This commit is contained in:
@@ -1,5 +0,0 @@
|
||||
pytest-pypi
|
||||
===========
|
||||
|
||||
Easily test your HTTP library against a local copy of PyPI.
|
||||
This is an internal pytest plugin of pipenv.
|
||||
@@ -1,4 +0,0 @@
|
||||
# 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
|
||||
@@ -1,4 +0,0 @@
|
||||
# pytest-pypi
|
||||
|
||||
Easily test your HTTP library against a local copy of PyPI.
|
||||
This is an internal pytest plugin of pipenv.
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,3 +0,0 @@
|
||||
[build-system]
|
||||
requires = ["setuptools", "wheel"]
|
||||
build-backend = "setuptools.build_meta:__legacy__"
|
||||
@@ -1,14 +0,0 @@
|
||||
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")
|
||||
@@ -1,239 +0,0 @@
|
||||
import collections
|
||||
import contextlib
|
||||
import io
|
||||
import json
|
||||
import os
|
||||
|
||||
from tarfile import is_tarfile
|
||||
from zipfile import is_zipfile
|
||||
|
||||
import distlib.wheel
|
||||
import requests
|
||||
from six.moves import xmlrpc_client
|
||||
|
||||
from flask import Flask, redirect, abort, render_template, send_file, jsonify
|
||||
|
||||
|
||||
ReleaseTuple = collections.namedtuple("ReleaseTuple", ["path", "requires_python", "hash"])
|
||||
|
||||
app = Flask(__name__)
|
||||
session = requests.Session()
|
||||
|
||||
packages = {}
|
||||
ARTIFACTS = {}
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def xml_pypi_server(server):
|
||||
transport = xmlrpc_client.Transport()
|
||||
client = xmlrpc_client.ServerProxy(server, transport)
|
||||
try:
|
||||
yield client
|
||||
finally:
|
||||
transport.close()
|
||||
|
||||
|
||||
def get_pypi_package_names():
|
||||
pypi_packages = set()
|
||||
with xml_pypi_server("https://pypi.org/pypi") as client:
|
||||
pypi_packages = set(client.list_packages())
|
||||
return pypi_packages
|
||||
|
||||
|
||||
class Package:
|
||||
"""Package represents a collection of releases from one or more directories"""
|
||||
|
||||
def __init__(self, name):
|
||||
super().__init__()
|
||||
self.name = name
|
||||
self.releases = {}
|
||||
self._package_dirs = set()
|
||||
|
||||
@property
|
||||
def json(self):
|
||||
for path, _ in self._package_dirs:
|
||||
try:
|
||||
with open(os.path.join(path, 'api.json')) as f:
|
||||
return json.load(f)
|
||||
except FileNotFoundError:
|
||||
r = session.get(f'https://pypi.org/pypi/{self.name}/json')
|
||||
response = r.json()
|
||||
releases = response["releases"]
|
||||
files = {
|
||||
pkg for pkg_dir in self._package_dirs
|
||||
for pkg in os.listdir(pkg_dir.path)
|
||||
}
|
||||
for release in list(releases.keys()):
|
||||
values = (
|
||||
r for r in releases[release] if r["filename"] in files
|
||||
)
|
||||
values = list(values)
|
||||
if values:
|
||||
releases[release] = values
|
||||
else:
|
||||
del releases[release]
|
||||
response["releases"] = releases
|
||||
with open(os.path.join(path, "api.json"), "w") as fh:
|
||||
json.dump(response, fh, indent=4)
|
||||
return response
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Package name={self.name!r} releases={len(self.releases)!r}"
|
||||
|
||||
def add_release(self, path_to_binary):
|
||||
path_to_binary = os.path.abspath(path_to_binary)
|
||||
path, release = os.path.split(path_to_binary)
|
||||
requires_python = ""
|
||||
hash_value = ""
|
||||
if path_to_binary.endswith(".whl"):
|
||||
pkg = distlib.wheel.Wheel(path_to_binary)
|
||||
md_dict = pkg.metadata.todict()
|
||||
requires_python = md_dict.get("requires_python", "")
|
||||
if requires_python.count(".") > 1:
|
||||
requires_python, _, _ = requires_python.rpartition(".")
|
||||
if os.path.isfile(path_to_binary + ".sha256"):
|
||||
with open(path_to_binary + ".sha256") as f:
|
||||
hash_value = f.read().strip()
|
||||
self.releases[release] = ReleaseTuple(path_to_binary, requires_python, hash_value)
|
||||
self._package_dirs.add(ReleaseTuple(path, requires_python, hash_value))
|
||||
|
||||
|
||||
class Artifact:
|
||||
"""Represents an artifact for download"""
|
||||
|
||||
def __init__(self, name):
|
||||
super().__init__()
|
||||
self.name = name
|
||||
self.files = {}
|
||||
self._artifact_dirs = set()
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Artifact name={self.name!r} files={len(self.files)!r}"
|
||||
|
||||
def add_file(self, path):
|
||||
path = os.path.abspath(path)
|
||||
base_path, fn = os.path.split(path)
|
||||
self.files[fn] = path
|
||||
self._artifact_dirs.add(base_path)
|
||||
|
||||
|
||||
def prepare_fixtures(path):
|
||||
path = os.path.abspath(path)
|
||||
if not (os.path.exists(path) and os.path.isdir(path)):
|
||||
raise ValueError(f"{path} is not a directory!")
|
||||
for root, dirs, files in os.walk(path):
|
||||
package_name, _, _ = os.path.relpath(root, start=path).partition(os.path.sep)
|
||||
if package_name not in ARTIFACTS:
|
||||
ARTIFACTS[package_name] = Artifact(package_name)
|
||||
for file in files:
|
||||
file_path = os.path.join(root, file)
|
||||
rel_path = os.path.relpath(file_path, start=path)
|
||||
_, _, subpkg = rel_path.partition(os.path.sep)
|
||||
subpkg, _, _ = subpkg.partition(os.path.sep)
|
||||
pkg, ext = os.path.splitext(subpkg)
|
||||
if not (is_tarfile(file_path) or is_zipfile(file_path) or ext == ".git"):
|
||||
continue
|
||||
if subpkg not in ARTIFACTS[package_name].files:
|
||||
ARTIFACTS[package_name].add_file(os.path.join(root, file))
|
||||
ARTIFACTS[package_name].add_file(os.path.join(root, file))
|
||||
|
||||
|
||||
def prepare_packages(path):
|
||||
"""Add packages in path to the registry."""
|
||||
path = os.path.abspath(path)
|
||||
if not (os.path.exists(path) and os.path.isdir(path)):
|
||||
raise ValueError(f"{path} is not a directory!")
|
||||
for root, dirs, files in os.walk(path):
|
||||
if all([setup_file in list(files) for setup_file in ("setup.py", "setup.cfg")]):
|
||||
continue
|
||||
for file in files:
|
||||
if not file.startswith('.') and not file.endswith('.json'):
|
||||
package_name = os.path.basename(root)
|
||||
if package_name and package_name == "fixtures":
|
||||
prepare_fixtures(root)
|
||||
continue
|
||||
package_name = package_name.replace("_", "-")
|
||||
if package_name not in packages:
|
||||
packages[package_name] = Package(package_name)
|
||||
|
||||
packages[package_name].add_release(os.path.join(root, file))
|
||||
# remaining = get_pypi_package_names() - set(list(packages.keys()))
|
||||
# for pypi_pkg in remaining:
|
||||
# packages[pypi_pkg] = Package(pypi_pkg)
|
||||
|
||||
|
||||
@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('/artifacts')
|
||||
def artifacts():
|
||||
return render_template('artifacts.html', artifacts=ARTIFACTS.values())
|
||||
|
||||
|
||||
@app.route('/simple/<package>/')
|
||||
def simple_package(package):
|
||||
if package in packages and packages[package].releases:
|
||||
return render_template('package.html', package=packages[package])
|
||||
else:
|
||||
try:
|
||||
r = requests.get(f"https://pypi.org/simple/{package}")
|
||||
r.raise_for_status()
|
||||
except Exception:
|
||||
abort(404)
|
||||
else:
|
||||
return render_template(
|
||||
'package_pypi.html', package_contents=r.text
|
||||
)
|
||||
|
||||
|
||||
@app.route('/artifacts/<artifact>/')
|
||||
def simple_artifact(artifact):
|
||||
if artifact in ARTIFACTS:
|
||||
return render_template('artifact.html', artifact=ARTIFACTS[artifact])
|
||||
else:
|
||||
abort(404)
|
||||
|
||||
|
||||
@app.route('/<package>/<release>')
|
||||
def serve_package(package, release):
|
||||
if package in packages:
|
||||
package = packages[package]
|
||||
|
||||
if release in package.releases:
|
||||
return send_file(package.releases[release].path)
|
||||
|
||||
abort(404)
|
||||
|
||||
|
||||
@app.route('/artifacts/<artifact>/<fn>')
|
||||
def serve_artifact(artifact, fn):
|
||||
if artifact in ARTIFACTS:
|
||||
artifact = ARTIFACTS[artifact]
|
||||
if fn in artifact.files:
|
||||
return send_file(artifact.files[fn])
|
||||
abort(404)
|
||||
|
||||
|
||||
@app.route('/pypi/<package>/json')
|
||||
def json_for_package(package):
|
||||
return jsonify(packages[package].json)
|
||||
# try:
|
||||
# except Exception:
|
||||
# r = session.get('https://pypi.org/pypi/{0}/json'.format(package))
|
||||
# return jsonify(r.json())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
PYPI_VENDOR_DIR = os.environ.get('PYPI_VENDOR_DIR', './pypi')
|
||||
PYPI_VENDOR_DIR = os.path.abspath(PYPI_VENDOR_DIR)
|
||||
prepare_packages(PYPI_VENDOR_DIR)
|
||||
prepare_fixtures(os.path.join(PYPI_VENDOR_DIR, "fixtures"))
|
||||
|
||||
app.run()
|
||||
@@ -1,22 +0,0 @@
|
||||
"""
|
||||
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.abspath(os.path.dirname(__file__)), 'certs', 'cacert.pem')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(where())
|
||||
@@ -1,63 +0,0 @@
|
||||
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-----
|
||||
@@ -1,73 +0,0 @@
|
||||
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-----
|
||||
@@ -1,28 +0,0 @@
|
||||
-----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-----
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
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())
|
||||
@@ -1,134 +0,0 @@
|
||||
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:
|
||||
"""
|
||||
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 f'{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().__init__(host, port, application, **kwargs)
|
||||
self.protocol = 'https'
|
||||
@@ -1,14 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Links for {{ artifact.name }}</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Links for {{ artifact.name }}</h1>
|
||||
{% for fn in artifact.files %}
|
||||
<a href="/{{ artifact.name }}/{{ fn }}">{{ fn }}</a>
|
||||
<br>
|
||||
{% endfor %}
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,13 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Artifact Index</title>
|
||||
</head>
|
||||
<body>
|
||||
{% for artifact in artifacts %}
|
||||
<a href="/artifacts/{{ artifact.name }}/" rel="internal">{{ artifact.name }}</a>
|
||||
<br>
|
||||
{% endfor %}
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,14 +0,0 @@
|
||||
<!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, value in package.releases.items() %}
|
||||
<a href="/{{ package.name }}/{{ release }}{%- if value.hash %}#sha256={{ value.hash }}{% endif %}"{%- if value.requires_python %} data-requires-python="{{ value.requires_python }}"{% endif %}>{{ release }}</a>
|
||||
<br>
|
||||
{% endfor %}
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,4 +0,0 @@
|
||||
|
||||
{% autoescape false %}
|
||||
{{ package_contents }}
|
||||
{% endautoescape %}
|
||||
@@ -1,13 +0,0 @@
|
||||
<!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>
|
||||
@@ -1 +0,0 @@
|
||||
__version__ = '0.1.1'
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
py.test $1 -v -s
|
||||
@@ -1,5 +0,0 @@
|
||||
[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
|
||||
@@ -1,107 +0,0 @@
|
||||
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(f'\033[1m{s}\033[0m')
|
||||
|
||||
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(f'{sys.executable} setup.py sdist bdist_wheel --universal')
|
||||
|
||||
self.status('Uploading the package to PyPI via Twine...')
|
||||
os.system('twine upload dist/*')
|
||||
|
||||
self.status('Pushing git tags...')
|
||||
os.system(f'git tag v{__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/pypa/pipenv/tree/master/tests/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',
|
||||
'importlib-metadata'],
|
||||
|
||||
# the following makes a plugin available to pytest
|
||||
entry_points = {
|
||||
'pytest11': [
|
||||
'pypi = pytest_pypi.plugin',
|
||||
]
|
||||
},
|
||||
cmdclass={
|
||||
'upload': UploadCommand,
|
||||
},
|
||||
)
|
||||
@@ -1,10 +0,0 @@
|
||||
# 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/}
|
||||
Reference in New Issue
Block a user