Skip to content

Commit

Permalink
Implement pypi simulator
Browse files Browse the repository at this point in the history
The pypi simulator is used to simulate the interactions between our code
and the real pypi.

Addresses are mocked, and for the moment it only simulates requests in
https://pypi.org/pypi/<YOUR PACKAGE>/json format.

Test json metadata must be downloaded in advance and placed in
tests/tests_e3/pypi_data/json.

Related to AdaCore#671
  • Loading branch information
leocardao committed Jan 24, 2024
1 parent f93c463 commit 5bc154a
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 0 deletions.
60 changes: 60 additions & 0 deletions tests/tests_e3/conftest.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
# type: ignore
from __future__ import annotations

import os
from os.path import abspath, dirname, join as path_join, isfile
import tempfile
import yaml
from json import loads as json_loads
from typing import TYPE_CHECKING
from re import compile as regex_compile

from e3.env import Env
from e3.fs import rm
Expand All @@ -10,6 +16,9 @@

import pytest

if TYPE_CHECKING:
from typing import Any

# When the variable RESULTS_DIR is set to
# an existing directory, the testsuite will
# generate results file in "anod" format
Expand Down Expand Up @@ -164,3 +173,54 @@ def pytest_sessionfinish(session, exitstatus):
# pytest docs, which is the closest thing to having an actual Python error in
# test code.
session.exitstatus = 3


class PypiResponse:
def __init__(self, text: str, status_code: int) -> None:
self.text = text
self.status_code = status_code

def json(self) -> Any:
return json_loads(self.text)


class PypiSimulator:
PYPI_URL = "https://pypi.org"
MATCHER = regex_compile(f"{PYPI_URL}/pypi/(?P<package>.*)/json")
DATA_DIR = path_join(dirname(abspath(__file__)), "pypi_data")

def __init__(self, requests_mock: Any) -> None:
self.requests_mock = requests_mock
self.requests_mock.stop()

@classmethod
def get_metadata(cls, *args: Any, **kwargs: Any) -> str:
m = cls.MATCHER.match(args[0])
if not m:
raise ValueError("mocked pypi received an unexpected request")
package = m.group("package")
path = path_join(cls.DATA_DIR, "json", f"{package}.json")
if not isfile(path):
return PypiResponse('{"message": "Not Found"}', 404)

try:
with open(path) as json_file:
text = json_file.read()
except Exception:
return PypiResponse('{"message": "Internal server error"}', 500)

return PypiResponse(text, 200)

def __enter__(self):
self.requests_mock.start()
self.requests_mock.get(self.MATCHER, json=self.get_metadata)
return self

def __exit__(self, type_t: Any, value: Any, traceback: Any):
self.requests_mock.stop()


@pytest.fixture(scope="function")
def pypi_server(requests_mock):
requests_mock.stop()
return PypiSimulator(requests_mock)
6 changes: 6 additions & 0 deletions tests/tests_e3/python/main_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,9 @@ def test_star_requirements():
pypi.add_wheel(wheel3.path)
pypi.add_requirement("src2==1.0.0")
assert len(pypi.closure()) == 2


def test_yanked(pypi_server):
with pypi_server:
print("OK")
raise AssertionError("Expected")
1 change: 1 addition & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ deps =
ptyprocess;platform_system == "Linux"
cov: pytest-cov
cov: coverage
requests-mock

passenv = CI,GITHUB_*,CODECOV_*
extras =
Expand Down

0 comments on commit 5bc154a

Please sign in to comment.