def test_authenticator_add_repository( config: Config, mock_remote: None, http: type[httpretty.httpretty], with_simple_keyring: None, dummy_keyring: DummyBackend, ): config.merge({ "http-basic": { "source": { "username": "******", "password": "******" }, }, }) authenticator = Authenticator(config, NullIO()) authenticator.request( "get", "https://foo.bar/simple/a/1.0.0/a-1.0.0.whl", ) request = http.last_request() assert "Authorization" not in request.headers authenticator.add_repository("source", "https://foo.bar/simple/") authenticator.request( "get", "https://foo.bar/simple/a/1.0.0/a-1.0.0.whl", ) request = http.last_request() basic_auth = base64.b64encode(b"foo:bar").decode() assert request.headers["Authorization"] == f"Basic {basic_auth}"
def test_authenticator_request_retries_on_status_code( mocker: "MockerFixture", config: "Config", http: Type[httpretty.httpretty], status: int, attempts: int, ): sleep = mocker.patch("time.sleep") sdist_uri = f"https://foo.bar/files/{uuid.uuid4()!s}/foo-0.1.0.tar.gz" content = str(uuid.uuid4()) def callback( request: requests.Request, uri: str, response_headers: Dict ) -> List[Union[int, Dict, str]]: return [status, response_headers, content] httpretty.register_uri(httpretty.GET, sdist_uri, body=callback) authenticator = Authenticator(config, NullIO()) with pytest.raises(requests.exceptions.HTTPError) as excinfo: authenticator.request("get", sdist_uri) assert excinfo.value.response.status_code == status assert excinfo.value.response.text == content assert sleep.call_count == attempts
def __init__(self, poetry: "Poetry", io: Union["BufferedIO", "ConsoleIO"]) -> None: self._poetry = poetry self._package = poetry.package self._io = io self._uploader = Uploader(poetry, io) self._authenticator = Authenticator(poetry.config, self._io)
def test_authenticator_uses_username_only_credentials( config: Config, mock_remote: None, http: type[httpretty.httpretty], with_simple_keyring: None, ): config.merge({ "repositories": { "foo": { "url": "https://foo.bar/simple/" } }, "http-basic": { "foo": { "username": "******", "password": "******" } }, }) authenticator = Authenticator(config, NullIO()) authenticator.request("get", "https://[email protected]/files/foo-0.1.0.tar.gz") request = http.last_request() assert request.headers["Authorization"] == "Basic Zm9vMDAxOg=="
def test_authenticator_uses_certs_from_config_if_not_provided( config: Config, mock_remote: type[httpretty.httpretty], mock_config: Config, http: type[httpretty.httpretty], mocker: MockerFixture, cert: str | None, client_cert: str | None, ): configured_cert = "/path/to/cert" configured_client_cert = "/path/to/client-cert" mock_config.merge({ "certificates": { "foo": { "cert": configured_cert, "client-cert": configured_client_cert } }, }) authenticator = Authenticator(mock_config, NullIO()) url = "https://foo.bar/files/foo-0.1.0.tar.gz" session = authenticator.get_session(url) session_send = mocker.patch.object(session, "send") authenticator.request( "get", url, verify=cert, cert=client_cert, ) kwargs = session_send.call_args[1] assert Path(kwargs["verify"]) == Path(cert or configured_cert) assert Path(kwargs["cert"]) == Path(client_cert or configured_client_cert)
def __init__( self, env: Env, pool: Pool, config: Config, io: IO, parallel: bool = None, ) -> None: self._env = env self._io = io self._dry_run = False self._enabled = True self._verbose = False self._authenticator = Authenticator(config, self._io) self._chef = Chef(config, self._env) self._chooser = Chooser(pool, self._env, config) if parallel is None: parallel = config.get("installer.parallel", True) if parallel: self._max_workers = self._get_max_workers( desired_max_workers=config.get("installer.max-workers")) else: self._max_workers = 1 self._executor = ThreadPoolExecutor(max_workers=self._max_workers) self._total_operations = 0 self._executed_operations = 0 self._executed = {"install": 0, "update": 0, "uninstall": 0} self._skipped = {"install": 0, "update": 0, "uninstall": 0} self._sections = {} self._lock = threading.Lock() self._shutdown = False self._hashes: dict[str, str] = {}
def test_authenticator_uses_empty_strings_as_default_password( config: Config, mock_remote: None, http: type[httpretty.httpretty], with_simple_keyring: None, ): config.merge({ "repositories": { "foo": { "url": "https://foo.bar/simple/" } }, "http-basic": { "foo": { "username": "******" } }, }) authenticator = Authenticator(config, NullIO()) authenticator.request("get", "https://foo.bar/files/foo-0.1.0.tar.gz") request = http.last_request() assert request.headers["Authorization"] == "Basic YmFyOg=="
def test_authenticator_uses_credentials_from_config_if_not_provided( mock_config: Config, mock_remote: None, http: type[httpretty.httpretty]): authenticator = Authenticator(mock_config, NullIO()) authenticator.request("get", "https://foo.bar/files/foo-0.1.0.tar.gz") request = http.last_request() assert request.headers["Authorization"] == "Basic YmFyOmJheg=="
def test_authenticator_uses_url_provided_credentials( mock_config: Config, mock_remote: None, http: type[httpretty.httpretty]): authenticator = Authenticator(mock_config, NullIO()) authenticator.request( "get", "https://*****:*****@foo.bar/files/foo-0.1.0.tar.gz") request = http.last_request() assert request.headers["Authorization"] == "Basic Zm9vMDAxOmJhcjAwMg=="
def __init__( self, name: str, url: str, config: Config | None = None, disable_cache: bool = False, cert: Path | None = None, client_cert: Path | None = None, ) -> None: if name == "pypi": raise ValueError("The name [pypi] is reserved for repositories") self._packages = [] self._name = name self._url = url.rstrip("/") self._client_cert = client_cert self._cert = cert self._cache_dir = REPOSITORY_CACHE_DIR / name self._cache = CacheManager({ "default": "releases", "serializer": "json", "stores": { "releases": { "driver": "file", "path": str(self._cache_dir) }, "packages": { "driver": "dict" }, "matches": { "driver": "dict" }, }, }) self._authenticator = Authenticator( config=config or Config(use_environment=True)) self._session = CacheControl(self._authenticator.session, cache=FileCache( str(self._cache_dir / "_http"))) username, password = self._authenticator.get_credentials_for_url( self._url) if username is not None and password is not None: self._authenticator.session.auth = requests.auth.HTTPBasicAuth( username, password) if self._cert: self._authenticator.session.verify = str(self._cert) if self._client_cert: self._authenticator.session.cert = str(self._client_cert) self._disable_cache = disable_cache
def test_authenticator_uses_env_provided_credentials( config, environ, mock_remote, http, environment_repository_credentials): config.merge({"repositories": {"foo": {"url": "https://foo.bar/simple/"}}}) authenticator = Authenticator(config, NullIO()) authenticator.request("get", "https://foo.bar/files/foo-0.1.0.tar.gz") request = http.last_request() assert "Basic YmFyOmJheg==" == request.headers["Authorization"]
def test_authenticator_uses_username_only_credentials( mock_config: Config, mock_remote: None, http: type[httpretty.httpretty], with_simple_keyring: None, ): authenticator = Authenticator(mock_config, NullIO()) authenticator.request("get", "https://[email protected]/files/foo-0.1.0.tar.gz") request = http.last_request() assert request.headers["Authorization"] == "Basic Zm9vMDAxOg=="
def test_authenticator_uses_password_only_credentials(config, mock_remote, http): config.merge( { "repositories": {"foo": {"url": "https://foo.bar/simple/"}}, "http-basic": {"foo": {"username": "******", "password": "******"}}, } ) authenticator = Authenticator(config, NullIO()) authenticator.request("get", "https://:[email protected]/files/foo-0.1.0.tar.gz") request = http.last_request() assert "Basic OmJhcjAwMg==" == request.headers["Authorization"]
def test_authenticator_git_repositories( config: Config, mock_remote: None, http: type[httpretty.httpretty], with_simple_keyring: None, dummy_keyring: DummyBackend, ): config.merge({ "repositories": { "one": { "url": "https://foo.bar/org/one.git" }, "two": { "url": "https://foo.bar/org/two.git" }, }, "http-basic": { "one": { "username": "******", "password": "******" }, "two": { "username": "******", "password": "******" }, }, }) authenticator = Authenticator(config, NullIO()) one = authenticator.get_credentials_for_git_url( "https://foo.bar/org/one.git") assert one.username == "foo" assert one.password == "bar" two = authenticator.get_credentials_for_git_url( "https://foo.bar/org/two.git") assert two.username == "baz" assert two.password == "qux" two_ssh = authenticator.get_credentials_for_git_url( "ssh://[email protected]/org/two.git") assert not two_ssh.username assert not two_ssh.password three = authenticator.get_credentials_for_git_url( "https://foo.bar/org/three.git") assert not three.username assert not three.password
def __init__( self, name: str, url: str, config: Config | None = None, disable_cache: bool = False, ) -> None: super().__init__(name, disable_cache) self._url = url self._authenticator = Authenticator( config=config, cache_id=name, disable_cache=disable_cache, ) self._authenticator.add_repository(name, url)
def test_authenticator_uses_empty_strings_as_default_username( config, mock_remote, http ): config.merge( { "repositories": {"foo": {"url": "https://foo.bar/simple/"}}, "http-basic": {"foo": {"username": None, "password": "******"}}, } ) authenticator = Authenticator(config, NullIO()) authenticator.request("get", "https://foo.bar/files/foo-0.1.0.tar.gz") request = http.last_request() assert "Basic OmJhcg==" == request.headers["Authorization"]
def test_authenticator_request_raises_exception_when_attempts_exhausted( mocker, config, http): sleep = mocker.patch("time.sleep") sdist_uri = "https://foo.bar/files/{}/foo-0.1.0.tar.gz".format( str(uuid.uuid4())) def callback(*_, **__): raise requests.exceptions.ConnectionError(str(uuid.uuid4())) httpretty.register_uri(httpretty.GET, sdist_uri, body=callback) authenticator = Authenticator(config, NullIO()) with pytest.raises(requests.exceptions.ConnectionError): authenticator.request("get", sdist_uri) assert sleep.call_count == 5
def test_authenticator_uses_credentials_from_config_if_not_provided( config: "Config", mock_remote: None, http: Type[httpretty.httpretty] ): config.merge( { "repositories": {"foo": {"url": "https://foo.bar/simple/"}}, "http-basic": {"foo": {"username": "******", "password": "******"}}, } ) authenticator = Authenticator(config, NullIO()) authenticator.request("get", "https://foo.bar/files/foo-0.1.0.tar.gz") request = http.last_request() assert request.headers["Authorization"] == "Basic YmFyOmJheg=="
def test_authenticator_request_raises_exception_when_attempts_exhausted( mocker: "MockerFixture", config: "Config", http: Type[httpretty.httpretty] ): sleep = mocker.patch("time.sleep") sdist_uri = f"https://foo.bar/files/{uuid.uuid4()!s}/foo-0.1.0.tar.gz" def callback(*_: Any, **___: Any) -> None: raise requests.exceptions.ConnectionError(str(uuid.uuid4())) httpretty.register_uri(httpretty.GET, sdist_uri, body=callback) authenticator = Authenticator(config, NullIO()) with pytest.raises(requests.exceptions.ConnectionError): authenticator.request("get", sdist_uri) assert sleep.call_count == 5
def test_authenticator_azure_feed_guid_credentials( config: Config, mock_remote: None, http: type[httpretty.httpretty], with_simple_keyring: None, dummy_keyring: DummyBackend, ): config.merge({ "repositories": { "alpha": { "url": "https://foo.bar/org-alpha/_packaging/feed/pypi/simple/" }, "beta": { "url": "https://foo.bar/org-beta/_packaging/feed/pypi/simple/" }, }, "http-basic": { "alpha": { "username": "******", "password": "******" }, "beta": { "username": "******", "password": "******" }, }, }) authenticator = Authenticator(config, NullIO()) authenticator.request( "get", "https://foo.bar/org-alpha/_packaging/GUID/pypi/simple/a/1.0.0/a-1.0.0.whl", ) request = http.last_request() basic_auth = base64.b64encode(b"foo:bar").decode() assert request.headers["Authorization"] == f"Basic {basic_auth}" authenticator.request( "get", "https://foo.bar/org-beta/_packaging/GUID/pypi/simple/b/1.0.0/a-1.0.0.whl", ) request = http.last_request() basic_auth = base64.b64encode(b"baz:qux").decode() assert request.headers["Authorization"] == f"Basic {basic_auth}"
def test_authenticator_falls_back_to_keyring_netloc( config, mock_remote, http, with_simple_keyring, dummy_keyring ): config.merge( { "repositories": {"foo": {"url": "https://foo.bar/simple/"}}, } ) dummy_keyring.set_password("foo.bar", None, SimpleCredential(None, "bar")) authenticator = Authenticator(config, NullIO()) authenticator.request("get", "https://foo.bar/files/foo-0.1.0.tar.gz") request = http.last_request() assert "Basic OmJhcg==" == request.headers["Authorization"]
def test_authenticator_request_retries_on_exception(mocker, config, http): sleep = mocker.patch("time.sleep") sdist_uri = "https://foo.bar/files/{}/foo-0.1.0.tar.gz".format(str(uuid.uuid4())) content = str(uuid.uuid4()) seen = list() def callback(request, uri, response_headers): if seen.count(uri) < 2: seen.append(uri) raise requests.exceptions.ConnectionError("Disconnected") return [200, response_headers, content] httpretty.register_uri(httpretty.GET, sdist_uri, body=callback) authenticator = Authenticator(config, NullIO()) response = authenticator.request("get", sdist_uri) assert response.text == content assert sleep.call_count == 2
def test_authenticator_uses_env_provided_credentials( config: Config, environ: None, mock_remote: type[httpretty.httpretty], http: type[httpretty.httpretty], monkeypatch: MonkeyPatch, ): monkeypatch.setenv("POETRY_HTTP_BASIC_FOO_USERNAME", "bar") monkeypatch.setenv("POETRY_HTTP_BASIC_FOO_PASSWORD", "baz") config.merge({"repositories": {"foo": {"url": "https://foo.bar/simple/"}}}) authenticator = Authenticator(config, NullIO()) authenticator.request("get", "https://foo.bar/files/foo-0.1.0.tar.gz") request = http.last_request() assert request.headers["Authorization"] == "Basic YmFyOmJheg=="
def test_configured_repository_http_auth( mocker: MockerFixture, source_url: str, config: Config ) -> None: from poetry.vcs.git import backend spy_clone_legacy = mocker.spy(Git, "_clone_legacy") spy_get_transport_and_path = mocker.spy(backend, "get_transport_and_path") config.merge( { "repositories": {"git-repo": {"url": source_url}}, "http-basic": { "git-repo": { "username": GIT_USERNAME, "password": GIT_PASSWORD, } }, } ) dummy_git_config = ConfigFile() mocker.patch( "poetry.vcs.git.backend.Repo.get_config_stack", return_value=dummy_git_config, ) mocker.patch( "poetry.vcs.git.backend.get_default_authenticator", return_value=Authenticator(config=config), ) with Git.clone(url=source_url, branch="0.1") as repo: assert_version(repo, BRANCH_TO_REVISION_MAP["0.1"]) spy_clone_legacy.assert_not_called() spy_get_transport_and_path.assert_called_with( location=source_url, config=dummy_git_config, username=GIT_USERNAME, password=GIT_PASSWORD, ) spy_get_transport_and_path.assert_called_once()
def test_authenticator_request_retries_on_status_code(mocker, config, http, status, attempts): sleep = mocker.patch("time.sleep") sdist_uri = "https://foo.bar/files/{}/foo-0.1.0.tar.gz".format( str(uuid.uuid4())) content = str(uuid.uuid4()) def callback(request, uri, response_headers): return [status, response_headers, content] httpretty.register_uri(httpretty.GET, sdist_uri, body=callback) authenticator = Authenticator(config, NullIO()) with pytest.raises(requests.exceptions.HTTPError) as excinfo: authenticator.request("get", sdist_uri) assert excinfo.value.response.status_code == status assert excinfo.value.response.text == content assert sleep.call_count == attempts
def test_authenticator_falls_back_to_keyring_netloc( config: Config, mock_remote: None, repo: dict[str, dict[str, str]], http: type[httpretty.httpretty], with_simple_keyring: None, dummy_keyring: DummyBackend, ): config.merge({ "repositories": repo, }) dummy_keyring.set_password("foo.bar", None, SimpleCredential(None, "bar")) authenticator = Authenticator(config, NullIO()) authenticator.request("get", "https://foo.bar/files/foo-0.1.0.tar.gz") request = http.last_request() assert request.headers["Authorization"] == "Basic OmJhcg=="
def test_authenticator_request_retries_on_exception( mocker: MockerFixture, config: Config, http: type[httpretty.httpretty]): sleep = mocker.patch("time.sleep") sdist_uri = f"https://foo.bar/files/{uuid.uuid4()!s}/foo-0.1.0.tar.gz" content = str(uuid.uuid4()) seen = [] def callback(request: requests.Request, uri: str, response_headers: dict) -> list[int | dict | str]: if seen.count(uri) < 2: seen.append(uri) raise requests.exceptions.ConnectionError("Disconnected") return [200, response_headers, content] httpretty.register_uri(httpretty.GET, sdist_uri, body=callback) authenticator = Authenticator(config, NullIO()) response = authenticator.request("get", sdist_uri) assert response.text == content assert sleep.call_count == 2
def test_authenticator_uses_credentials_from_config_matched_by_url_path( config: Config, mock_remote: None, http: type[httpretty.httpretty]): config.merge({ "repositories": { "foo-alpha": { "url": "https://foo.bar/alpha/files/simple/" }, "foo-beta": { "url": "https://foo.bar/beta/files/simple/" }, }, "http-basic": { "foo-alpha": { "username": "******", "password": "******" }, "foo-beta": { "username": "******", "password": "******" }, }, }) authenticator = Authenticator(config, NullIO()) authenticator.request( "get", "https://foo.bar/alpha/files/simple/foo-0.1.0.tar.gz") request = http.last_request() basic_auth = base64.b64encode(b"bar:alpha").decode() assert request.headers["Authorization"] == f"Basic {basic_auth}" # Make request on second repository with the same netloc but different credentials authenticator.request( "get", "https://foo.bar/beta/files/simple/foo-0.1.0.tar.gz") request = http.last_request() basic_auth = base64.b64encode(b"baz:beta").decode() assert request.headers["Authorization"] == f"Basic {basic_auth}"
def test_authenticator_uses_empty_strings_as_default_username( config: Config, mock_remote: None, repo: dict[str, dict[str, str]], http: type[httpretty.httpretty], ): config.merge({ "repositories": repo, "http-basic": { "foo": { "username": None, "password": "******" } }, }) authenticator = Authenticator(config, NullIO()) authenticator.request("get", "https://foo.bar/files/foo-0.1.0.tar.gz") request = http.last_request() assert request.headers["Authorization"] == "Basic OmJhcg=="
def test_authenticator_uses_env_provided_credentials_matched_by_url_path( config: Config, environ: None, mock_remote: type[httpretty.httpretty], http: type[httpretty.httpretty], monkeypatch: MonkeyPatch, ): monkeypatch.setenv("POETRY_HTTP_BASIC_FOO_ALPHA_USERNAME", "bar") monkeypatch.setenv("POETRY_HTTP_BASIC_FOO_ALPHA_PASSWORD", "alpha") monkeypatch.setenv("POETRY_HTTP_BASIC_FOO_BETA_USERNAME", "baz") monkeypatch.setenv("POETRY_HTTP_BASIC_FOO_BETA_PASSWORD", "beta") config.merge({ "repositories": { "foo-alpha": { "url": "https://foo.bar/alpha/files/simple/" }, "foo-beta": { "url": "https://foo.bar/beta/files/simple/" }, } }) authenticator = Authenticator(config, NullIO()) authenticator.request( "get", "https://foo.bar/alpha/files/simple/foo-0.1.0.tar.gz") request = http.last_request() basic_auth = base64.b64encode(b"bar:alpha").decode() assert request.headers["Authorization"] == f"Basic {basic_auth}" authenticator.request( "get", "https://foo.bar/beta/files/simple/foo-0.1.0.tar.gz") request = http.last_request() basic_auth = base64.b64encode(b"baz:beta").decode() assert request.headers["Authorization"] == f"Basic {basic_auth}"