Fastapi testing RuntimeError: Task attached to a different loop - python

I trying to test my endpoint with pytest
main.py:
from fastapi import FastAPI, status, HTTPException, Depends
from sqlalchemy.ext.asyncio import AsyncSession
from .schema import ClientIn, ClientOut, ClientInWithID, Client, ValidationErrorSchema
from . import clients
from .database import SessionLocal
app = FastAPI()
async def get_db() -> AsyncSession:
if hasattr(get_db, "db"):
db: AsyncSession = get_db.db
return db
db = SessionLocal()
setattr(get_db, "db", db)
return db
#app.post("/client/",
response_model=ClientOut,
tags=["client"],
responses={422: {"model": ValidationErrorSchema}}
)
async def create_client(client_in: ClientIn, db: AsyncSession = Depends(get_db)) -> Client:
client = await clients.create_client(db, client_in)
return client
#app.put("/client/",
response_model=ClientOut | None,
tags=["client"],
responses={422: {"model": ValidationErrorSchema}, 404: {}}
)
async def update_client(client: ClientInWithID, db: AsyncSession = Depends(get_db)) -> Client | None:
db_client = await clients.get_client_by_id(db, client.id)
if not db_client:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
return await clients.update_client(db, client)
test_main.py:
import pytest
from httpx import AsyncClient
from app import main
#pytest.mark.asyncio
async def test_create_client():
data = {
"phone_number": "+79009999999",
"phone_operator_code": 900,
"timezone": "Europe/Amsterdam",
"tag": {
"text": "Any text"
}
}
async with AsyncClient(app=main.app, base_url="http://localhost:8000") as client:
response = await client.post(url="client/", json=data)
assert response.status_code == 200
#pytest.mark.asyncio
async def test_update_client():
data = {
"id": 1,
"phone_number": "+79009900000",
"phone_operator_code": 900,
"timezone": "Europe/Amsterdam",
"tag": {
"text": "Fuck this shit"
}
}
async with AsyncClient(app=main.app, base_url="http://localhost:8000") as client:
response = await client.put(url="client/", json=data)
assert response.status_code == 200
I use sqlalchemy and its connects to postgres with asyncpg, cause of asyncpg I have error:
venv/lib/python3.11/site-packages/asyncpg/connection.py:565: in prepare
return await self._prepare(
venv/lib/python3.11/site-packages/asyncpg/connection.py:583: in _prepare
stmt = await self._get_statement(
venv/lib/python3.11/site-packages/asyncpg/connection.py:397: in _get_statement
statement = await self._protocol.prepare(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
> ???
E RuntimeError: Task <Task pending name='Task-3' coro=<test_update_client() running at /home/kryseyt/code/python/BackendTask1/tests/test_main.py:38> cb=[_run_until_complete_cb() at /home/kryseyt/.python3.11/lib/python3.11/asyncio/base_events.py:180]> got Future <Future pending cb=[Protocol._on_waiter_completed()]> attached to a different loop
asyncpg/protocol/protocol.pyx:168: RuntimeError
================================================ short test summary info =========================================
FAILED tests/test_main.py::test_update_client - RuntimeError: Task <Task pending name='Task-3' coro=<test_update_client() running at /home/kryseyt/code/python/BackendTask1/tests/test_main.py:38> cb=[_run_until_complet...
======================================================================== 1 failed, 1 passed in 5.82s =========================================================================
I this this happens cause there are creating another event loop for work with db, but what can I do with that?
Can I do something with this without mocking my database CRUD?

Try to add the "poolclass=NullPool" argument in the engine constructor.
from sqlalchemy.ext.asyncio import create_async_engine
from sqlalchemy.pool import NullPool
engine = create_async_engine(
"postgresql+asyncpg://user:pass#host/dbname",
poolclass=NullPool,
)
Sources:
https://docs.sqlalchemy.org/en/14/orm/extensions/asyncio.html#using-multiple-asyncio-event-loops
RuntimeError: Task ___ running at ___ at got Future <Future pending cb=[Protocol._on_waiter_completed()]> attached to a different loop

Related

Pytest asyncio event is bound to a different event loop, event loop is closed

I am trying to write some tests for my fastapi app
I am using the prisma-client-py for the database. I don't know if that changes anything
Everything works as they are supposed to apart from every first and last, they both fail with the same error:
RuntimeError: <asyncio.locks.Event object at 0x7f5696832950 [unset]> is bound to a different event loop
This is my conftest.py
import os
import asyncio
import pytest
from typing import Any, AsyncGenerator, Generator, Iterator
from fastapi import FastAPI
from fastapi.testclient import TestClient
from prisma import Prisma, register
from server.database.base import *
from server.config.exceptions import configure_exception_handlers
from server.config.settings import settings
from server.apis import apis
def start_application() -> FastAPI:
"""
Return a FastAPI app
"""
_app = FastAPI(
title=str(settings.TITLE),
description=str(settings.DESCRIPTION),
version=str(settings.VERSION),
)
configure_exception_handlers(_app)
_app.include_router(apis)
return _app
TEST_DB_DSN = "postgresql://postgres:postgres#localhost:5433/postgres"
prisma = Prisma(datasource={"url": TEST_DB_DSN})
async def initialize_db() -> None:
"""
Initialize the test database
"""
print("Initializing")
print("Creating all tables")
stream = os.popen(f"dotenv -e .env.test prisma db push --skip-generate")
output = stream.read()
print(output)
async def teardown_db(client: Prisma) -> None:
"""
Teardown the test database
"""
print("Teardown")
print("Dropping all tables")
stream = os.popen(
f'dotenv -e .env.test prisma db execute --url "{TEST_DB_DSN}" --file "./server/tests/utils/reset_db.sql" '
)
print("Creating all tables")
stream = os.popen(f"DB_DSN={TEST_DB_DSN} prisma db push --skip-generate")
output = stream.read()
print(output)
#pytest.fixture(scope="session")
def app() -> Generator[FastAPI, Any, None]:
"""
Initialize the app
"""
_app = start_application()
yield _app
#pytest.fixture(scope="module")
def event_loop() -> Iterator[asyncio.AbstractEventLoop]:
"""
Initialize the event loop
"""
loop = asyncio.get_event_loop_policy().new_event_loop()
yield loop
loop.close()
# Test client
#pytest.fixture(scope="module")
async def client(
app: FastAPI, event_loop: asyncio.BaseEventLoop
) -> AsyncGenerator[TestClient, None]:
"""
Initialize the test client
"""
await initialize_db()
register(prisma)
await prisma.connect()
with TestClient(app) as c:
yield c
await prisma.disconnect()
await teardown_db(client=prisma)
and below are my tests
import asyncio
from fastapi.testclient import TestClient
from jose import jwt
import pytest
from prisma.models import User
from server.config.mail import fm
from server.config.settings import settings
from server.constants.user_types import UserType
from server.helpers.security import create_email_confirmation_token
from server.apis.auth.repositories import AuthRepository
auth_repository = AuthRepository()
def check_mail(data, outbox):
assert data.get("password") is None
assert len(outbox) == 1
assert outbox[0]["subject"] == "Welcome to Mafflle - Verify your email"
assert outbox[0]["From"] == f"{settings.EMAIL_FROM_NAME} <{settings.EMAIL_FROM}>"
assert outbox[0]["To"] == data["email"]
#pytest.mark.asyncio
async def test_signup_user(client: TestClient, event_loop: asyncio.AbstractEventLoop):
"""
Test the /v1/auth/signup/ endpoint.
This endpoint should return a 201 status code and a
JSON response with the full user object.
"""
fm.config.SUPPRESS_SEND = 1
with fm.record_messages() as outbox:
payload = {
"username": "test_user",
"password": "Password123!",
"email": "testapp.sheyzi#gmail.com",
}
response = client.post("/v1/auth/signup/", json=payload)
data = response.json()
assert response.status_code == 201
assert data["username"] == "test_user"
assert data["email"] == "testapp.sheyzi#gmail.com"
assert data["user_type"] == "USER"
assert data["email_confirmed"] == False
assert data["is_active"] == True
check_mail(data, outbox)
# confirm email
confirmation_token = create_email_confirmation_token(data["email"])
params = {"token": confirmation_token}
response = client.get("/v1/auth/confirm-email/", params=params)
assert response.status_code == 200
#pytest.mark.asyncio
async def test_signup_business(
client: TestClient, event_loop: asyncio.AbstractEventLoop
):
"""
Test the /v1/auth/signup?user_type=business endpoint.
This endpoint should return a 201 status code and a
JSON response with the full user object.
"""
fm.config.SUPPRESS_SEND = 1
with fm.record_messages() as outbox:
payload = {
"username": "test_business",
"password": "Password123!",
"email": "blogsedap#gmail.com",
}
params = {"user_type": "BUSINESS"}
response = client.post("/v1/auth/signup/", params=params, json=payload)
data = response.json()
assert response.status_code == 201
assert data["username"] == "test_business"
assert data["email"] == "blogsedap#gmail.com"
assert data["user_type"] == "BUSINESS"
assert data["email_confirmed"] == False
assert data["is_active"] == True
check_mail(data, outbox)
def test_signup_user_with_existing_username(
client: TestClient, event_loop: asyncio.AbstractEventLoop
):
"""
Test the /v1/auth/signup endpoint with an existing username.
This endpoint should return a 400 status code and a
JSON response with the error message.
"""
payload = {
"username": "test_user",
"password": "Password123!",
"email": "testapp.sheyzi#gmail.com",
}
# Create a user first
client.post("/v1/auth/signup/", json=payload)
# Then try to create a user with the same username
response = client.post("/v1/auth/signup/", json=payload)
data = response.json()
assert response.status_code == 400
assert data["detail"] == "User with this username already exists."
def test_signup_user_with_existing_email(
client: TestClient, event_loop: asyncio.AbstractEventLoop
):
"""
Test the /v1/auth/signup endpoint with an existing email.
This endpoint should return a 400 status code and a
JSON response with the error message.
"""
payload = {
"username": "test_user_2",
"password": "Password123!",
"email": "blogsedap#gmail.com",
}
# Create a user first
client.post("/v1/auth/signup/", json=payload)
# Then try to create a user with the same email
response = client.post("/v1/auth/signup/", json=payload)
data = response.json()
assert response.status_code == 400
assert data["detail"] == "User with this email already exists."
def test_signup_user_with_invalid_password(
client: TestClient, event_loop: asyncio.AbstractEventLoop
):
"""
Test the /v1/auth/signup endpoint with an invalid password.
This endpoint should return a 400 status code and a
JSON response with the error message.
"""
payload = {
"username": "test_user_3",
"password": "Password",
"email": "test_app1#mafflle.com",
}
response = client.post("/v1/auth/signup/", json=payload)
data = response.json()
assert response.status_code == 400
assert (
data["detail"]
== "Password must be at least 8 characters long and contain at least one"
" number,one uppercase letter and one special character."
)
#pytest.mark.asyncio
async def test_login_user(client: TestClient, event_loop: asyncio.AbstractEventLoop):
"""
Test the /v1/auth/login endpoint.
This endpoint should return a 200 status code and a
JSON response with the full user object.
"""
# Create a user first
payload = {
"username": "test_user",
"password": "Password123!",
"email": "testapp.sheyzi#gmail.com",
}
client.post("/v1/auth/signup/", json=payload)
# login
payload = {"identity": "test_user", "password": "Password123!"}
response = client.post("/v1/auth/login/", json=payload)
assert response.status_code == 200
access_token = response.cookies["access_token"]
refresh_token = response.cookies["refresh_token"]
assert access_token is not None
assert refresh_token is not None
access_token_data = jwt.decode(
token=access_token, key=settings.AUTH_SECRET, algorithms=["HS256"]
)
assert access_token_data["scope"] == "access_token"
user = await auth_repository.get_user_by_id(user_id=access_token_data["sub"])
assert user is not None
assert user.username == "test_user"
assert user.email == "testapp.sheyzi#gmail.com"
assert user.user_type == UserType.USER
assert user.email_confirmed == True
assert user.is_active == True
# refresh token
refresh_token_data = jwt.decode(
token=refresh_token, key=settings.AUTH_SECRET, algorithms=["HS256"]
)
assert refresh_token_data["sub"] == str(user.id)
assert refresh_token_data["scope"] == "refresh_token"
This is my error/failure in detail
========================================================================== test session starts ==========================================================================
platform linux -- Python 3.10.4, pytest-7.1.2, pluggy-1.0.0 -- /home/sheyzi/code/mafflle/mafflle_backend/venv/bin/python3
cachedir: .pytest_cache
rootdir: /home/sheyzi/code/mafflle/mafflle_backend, configfile: pyproject.toml
plugins: asyncio-0.18.3, anyio-3.6.1
asyncio: mode=auto
collected 6 items
server/tests/test_authentication/test_users.py::test_signup_user FAILED [ 16%]
server/tests/test_authentication/test_users.py::test_signup_business PASSED [ 33%]
server/tests/test_authentication/test_users.py::test_signup_user_with_existing_username PASSED [ 50%]
server/tests/test_authentication/test_users.py::test_signup_user_with_existing_email PASSED [ 66%]
server/tests/test_authentication/test_users.py::test_signup_user_with_invalid_password PASSED [ 83%]
server/tests/test_authentication/test_users.py::test_login_user FAILED [100%]
=============================================================================== FAILURES ================================================================================
___________________________________________________________________________ test_signup_user ____________________________________________________________________________
client = <starlette.testclient.TestClient object at 0x7fb442d59870>, event_loop = <_UnixSelectorEventLoop running=False closed=False debug=False>
#pytest.mark.asyncio
async def test_signup_user(client: TestClient, event_loop: asyncio.AbstractEventLoop):
"""
Test the /v1/auth/signup/ endpoint.
This endpoint should return a 201 status code and a
JSON response with the full user object.
"""
fm.config.SUPPRESS_SEND = 1
with fm.record_messages() as outbox:
payload = {
"username": "test_user",
"password": "Password123!",
"email": "testapp.sheyzi#gmail.com",
}
> response = client.post("/v1/auth/signup/", json=payload)
server/tests/test_authentication/test_users.py:40:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.10/site-packages/requests/sessions.py:635: in post
return self.request("POST", url, data=data, json=json, **kwargs)
venv/lib/python3.10/site-packages/starlette/testclient.py:468: in request
return super().request(
venv/lib/python3.10/site-packages/requests/sessions.py:587: in request
resp = self.send(prep, **send_kwargs)
venv/lib/python3.10/site-packages/requests/sessions.py:701: in send
r = adapter.send(request, **kwargs)
venv/lib/python3.10/site-packages/starlette/testclient.py:266: in send
raise exc
venv/lib/python3.10/site-packages/starlette/testclient.py:263: in send
portal.call(self.app, scope, receive, send)
venv/lib/python3.10/site-packages/anyio/from_thread.py:283: in call
return cast(T_Retval, self.start_task_soon(func, *args).result())
/usr/lib/python3.10/concurrent/futures/_base.py:446: in result
return self.__get_result()
/usr/lib/python3.10/concurrent/futures/_base.py:391: in __get_result
raise self._exception
venv/lib/python3.10/site-packages/anyio/from_thread.py:219: in _call_func
retval = await retval
venv/lib/python3.10/site-packages/fastapi/applications.py:261: in __call__
await super().__call__(scope, receive, send)
venv/lib/python3.10/site-packages/starlette/applications.py:112: in __call__
await self.middleware_stack(scope, receive, send)
venv/lib/python3.10/site-packages/starlette/middleware/errors.py:181: in __call__
raise exc
venv/lib/python3.10/site-packages/starlette/middleware/errors.py:159: in __call__
await self.app(scope, receive, _send)
venv/lib/python3.10/site-packages/starlette/exceptions.py:82: in __call__
raise exc
venv/lib/python3.10/site-packages/starlette/exceptions.py:71: in __call__
await self.app(scope, receive, sender)
venv/lib/python3.10/site-packages/fastapi/middleware/asyncexitstack.py:21: in __call__
raise e
venv/lib/python3.10/site-packages/fastapi/middleware/asyncexitstack.py:18: in __call__
await self.app(scope, receive, send)
venv/lib/python3.10/site-packages/starlette/routing.py:656: in __call__
await route.handle(scope, receive, send)
venv/lib/python3.10/site-packages/starlette/routing.py:259: in handle
await self.app(scope, receive, send)
venv/lib/python3.10/site-packages/starlette/routing.py:61: in app
response = await func(request)
venv/lib/python3.10/site-packages/fastapi/routing.py:227: in app
raw_response = await run_endpoint_function(
venv/lib/python3.10/site-packages/fastapi/routing.py:160: in run_endpoint_function
return await dependant.call(**values)
server/apis/auth/router.py:30: in signup
return await self.auth_service.signup(
server/apis/auth/services.py:82: in signup
if await self.auth_repository.get_user_by_username_or_email(user.username):
server/apis/auth/repositories.py:66: in get_user_by_username_or_email
user = await User.prisma().find_first(
venv/lib/python3.10/site-packages/prisma/actions.py:1389: in find_first
resp = await self._client._execute(
venv/lib/python3.10/site-packages/prisma/client.py:353: in _execute
return await self._engine.query(builder.build())
venv/lib/python3.10/site-packages/prisma/engine/query.py:185: in query
return await self.request('POST', '/', content=content)
venv/lib/python3.10/site-packages/prisma/engine/http.py:96: in request
resp = await self.session.request(method, url, **kwargs)
venv/lib/python3.10/site-packages/prisma/_async_http.py:28: in request
return Response(await self.session.request(method, url, **kwargs))
venv/lib/python3.10/site-packages/httpx/_client.py:1506: in request
return await self.send(request, auth=auth, follow_redirects=follow_redirects)
venv/lib/python3.10/site-packages/httpx/_client.py:1593: in send
response = await self._send_handling_auth(
venv/lib/python3.10/site-packages/httpx/_client.py:1621: in _send_handling_auth
response = await self._send_handling_redirects(
venv/lib/python3.10/site-packages/httpx/_client.py:1658: in _send_handling_redirects
response = await self._send_single_request(request)
venv/lib/python3.10/site-packages/httpx/_client.py:1695: in _send_single_request
response = await transport.handle_async_request(request)
venv/lib/python3.10/site-packages/httpx/_transports/default.py:353: in handle_async_request
resp = await self._pool.handle_async_request(req)
venv/lib/python3.10/site-packages/httpcore/_async/connection_pool.py:253: in handle_async_request
raise exc
venv/lib/python3.10/site-packages/httpcore/_async/connection_pool.py:237: in handle_async_request
response = await connection.handle_async_request(request)
venv/lib/python3.10/site-packages/httpcore/_async/connection.py:90: in handle_async_request
return await self._connection.handle_async_request(request)
venv/lib/python3.10/site-packages/httpcore/_async/http11.py:102: in handle_async_request
raise exc
venv/lib/python3.10/site-packages/httpcore/_async/http11.py:81: in handle_async_request
) = await self._receive_response_headers(**kwargs)
venv/lib/python3.10/site-packages/httpcore/_async/http11.py:143: in _receive_response_headers
event = await self._receive_event(timeout=timeout)
venv/lib/python3.10/site-packages/httpcore/_async/http11.py:172: in _receive_event
data = await self._network_stream.read(
venv/lib/python3.10/site-packages/httpcore/backends/asyncio.py:31: in read
return await self._stream.receive(max_bytes=max_bytes)
venv/lib/python3.10/site-packages/anyio/_backends/_asyncio.py:1265: in receive
await self._protocol.read_event.wait()
/usr/lib/python3.10/asyncio/locks.py:211: in wait
fut = self._get_loop().create_future()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <asyncio.locks.Event object at 0x7fb442dda980 [set]>
def _get_loop(self):
loop = events._get_running_loop()
if self._loop is None:
with _global_lock:
if self._loop is None:
self._loop = loop
if loop is not self._loop:
> raise RuntimeError(f'{self!r} is bound to a different event loop')
E RuntimeError: <asyncio.locks.Event object at 0x7fb442dda980 [unset]> is bound to a different event loop
/usr/lib/python3.10/asyncio/mixins.py:30: RuntimeError
------------------------------------------------------------------------- Captured stdout setup -------------------------------------------------------------------------
Initializing
Creating all tables
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Datasource "db": PostgreSQL database "postgres", schema "public" at "localhost:5433"
🚀 Your database is now in sync with your schema. Done in 1.89s
____________________________________________________________________________ test_login_user ____________________________________________________________________________
client = <starlette.testclient.TestClient object at 0x7fb442d59870>, event_loop = <_UnixSelectorEventLoop running=False closed=False debug=False>
#pytest.mark.asyncio
async def test_login_user(client: TestClient, event_loop: asyncio.AbstractEventLoop):
"""
Test the /v1/auth/login endpoint.
This endpoint should return a 200 status code and a
JSON response with the full user object.
"""
# Create a user first
payload = {
"username": "test_user",
"password": "Password123!",
"email": "testapp.sheyzi#gmail.com",
}
client.post("/v1/auth/signup/", json=payload)
# login
payload = {"identity": "test_user", "password": "Password123!"}
response = client.post("/v1/auth/login/", json=payload)
assert response.status_code == 200
access_token = response.cookies["access_token"]
refresh_token = response.cookies["refresh_token"]
assert access_token is not None
assert refresh_token is not None
access_token_data = jwt.decode(
token=access_token, key=settings.AUTH_SECRET, algorithms=["HS256"]
)
assert access_token_data["scope"] == "access_token"
> user = await auth_repository.get_user_by_id(user_id=access_token_data["sub"])
server/tests/test_authentication/test_users.py:185:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
server/apis/auth/repositories.py:33: in get_user_by_id
user = await User.prisma().find_first(
venv/lib/python3.10/site-packages/prisma/actions.py:1389: in find_first
resp = await self._client._execute(
venv/lib/python3.10/site-packages/prisma/client.py:353: in _execute
return await self._engine.query(builder.build())
venv/lib/python3.10/site-packages/prisma/engine/query.py:185: in query
return await self.request('POST', '/', content=content)
venv/lib/python3.10/site-packages/prisma/engine/http.py:96: in request
resp = await self.session.request(method, url, **kwargs)
venv/lib/python3.10/site-packages/prisma/_async_http.py:28: in request
return Response(await self.session.request(method, url, **kwargs))
venv/lib/python3.10/site-packages/httpx/_client.py:1506: in request
return await self.send(request, auth=auth, follow_redirects=follow_redirects)
venv/lib/python3.10/site-packages/httpx/_client.py:1593: in send
response = await self._send_handling_auth(
venv/lib/python3.10/site-packages/httpx/_client.py:1621: in _send_handling_auth
response = await self._send_handling_redirects(
venv/lib/python3.10/site-packages/httpx/_client.py:1658: in _send_handling_redirects
response = await self._send_single_request(request)
venv/lib/python3.10/site-packages/httpx/_client.py:1695: in _send_single_request
response = await transport.handle_async_request(request)
venv/lib/python3.10/site-packages/httpx/_transports/default.py:353: in handle_async_request
resp = await self._pool.handle_async_request(req)
venv/lib/python3.10/site-packages/httpcore/_async/connection_pool.py:253: in handle_async_request
raise exc
venv/lib/python3.10/site-packages/httpcore/_async/connection_pool.py:237: in handle_async_request
response = await connection.handle_async_request(request)
venv/lib/python3.10/site-packages/httpcore/_async/connection.py:90: in handle_async_request
return await self._connection.handle_async_request(request)
venv/lib/python3.10/site-packages/httpcore/_async/http11.py:102: in handle_async_request
raise exc
venv/lib/python3.10/site-packages/httpcore/_async/http11.py:81: in handle_async_request
) = await self._receive_response_headers(**kwargs)
venv/lib/python3.10/site-packages/httpcore/_async/http11.py:143: in _receive_response_headers
event = await self._receive_event(timeout=timeout)
venv/lib/python3.10/site-packages/httpcore/_async/http11.py:172: in _receive_event
data = await self._network_stream.read(
venv/lib/python3.10/site-packages/httpcore/backends/asyncio.py:31: in read
return await self._stream.receive(max_bytes=max_bytes)
venv/lib/python3.10/site-packages/anyio/_backends/_asyncio.py:1265: in receive
await self._protocol.read_event.wait()
/usr/lib/python3.10/asyncio/locks.py:211: in wait
fut = self._get_loop().create_future()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <asyncio.locks.Event object at 0x7fb44038b7c0 [unset]>
def _get_loop(self):
loop = events._get_running_loop()
if self._loop is None:
with _global_lock:
if self._loop is None:
self._loop = loop
if loop is not self._loop:
> raise RuntimeError(f'{self!r} is bound to a different event loop')
E RuntimeError: <asyncio.locks.Event object at 0x7fb44038b7c0 [unset]> is bound to a different event loop
/usr/lib/python3.10/asyncio/mixins.py:30: RuntimeError
----------------------------------------------------------------------- Captured stdout teardown ------------------------------------------------------------------------
Teardown
Dropping all tables
Creating all tables
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Datasource "db": PostgreSQL database "mafflle_auth", schema "public" at "localhost:5432"
⚠️ There might be data loss when applying the changes:
• The values [ADMIN] on the enum `UserType` will be removed. If these variants are still used in the database, this will fail.
----------------------------------------------------------------------- Captured stderr teardown ------------------------------------------------------------------------
Error: Use the --accept-data-loss flag to ignore the data loss warnings like prisma db push --accept-data-loss
=========================================================================== warnings summary ============================================================================
venv/lib/python3.10/site-packages/aioredis/connection.py:11
/home/sheyzi/code/mafflle/mafflle_backend/venv/lib/python3.10/site-packages/aioredis/connection.py:11: DeprecationWarning: The distutils package is deprecated and slated for removal in Python 3.12. Use setuptools or check PEP 632 for potential alternatives
from distutils.version import StrictVersion
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
======================================================================== short test summary info ========================================================================
FAILED server/tests/test_authentication/test_users.py::test_signup_user - RuntimeError: <asyncio.locks.Event object at 0x7fb442dda980 [unset]> is bound to a different...
FAILED server/tests/test_authentication/test_users.py::test_login_user - RuntimeError: <asyncio.locks.Event object at 0x7fb44038b7c0 [unset]> is bound to a different ...
================================================================ 2 failed, 4 passed, 1 warning in 9.72s =================================================================
The first test always take way more time than the others

why mock is failing and asking for aws credential to run locally?

I am using below code for running test cases locally, but it is asking for aws credentials which I not supposed to give. Its like mock/moto is failing some how.
as I am new to this to python and itss library, I am unable to understand it deeper
import sys, os
import pprint
myPath = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, myPath + '/../')
from botocore.exceptions import ClientError
pprint.pprint(sys.path)
import pytest
from services.testrun_result_details import *
import json
from moto import *
from mock import MagicMock, patch
import boto3
#mock_dynamodb2
#patch('boto3.resource')
def test_success_response(dynamodb_test_testrun_results):
create_dynamodb_tables()
response = run_result_details_handler(EVENT_JSON, None)
assert response["statusCode"] == 200
---------------------------Error-------------------------
/usr/local/lib/python3.7/site-packages/botocore/signers.py:90: in handler
return self.sign(operation_name, request)
/usr/local/lib/python3.7/site-packages/botocore/signers.py:162: in sign
auth.add_auth(request)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <botocore.auth.SigV4Auth object at 0x7fab7fc2ee50>
request = <botocore.awsrequest.AWSRequest object at 0x7fab7fc48d90>
def add_auth(self, request):
if self.credentials is None:
> raise NoCredentialsError()
E botocore.exceptions.NoCredentialsError: Unable to locate credentials
/usr/local/lib/python3.7/site-packages/botocore/auth.py:373: NoCredentialsError
can anyone suggest me, how to resolve that issue?
I found the issue to be that my ~/.aws/credentials file did not have a default profile.
I added this, which fixed the issue:
[default]
aws_access_key_id = 123
aws_secret_access_key = ABC

Tornado test - access localhost through alternative IP

I got something really weird going on with Tornado
from tornado.web import Application
from tornado.testing import AsyncHTTPTestCase
import requests
import tornado
from tornado.ioloop import IOLoop
class MyTest(AsyncHTTPTestCase):
def get_app(self):
return Application()
#tornado.testing.gen_test(timeout=30)
async def test_pass(self):
response = await IOLoop.current().run_in_executor(None, requests.get,"http://127.0.0.1:" + str(self.get_http_port()) + "/foo")
print(response)
#tornado.testing.gen_test(timeout=30)
async def test_fail(self):
response = await IOLoop.current().run_in_executor(None, requests.get,"http://192.168.2.1:" + str(self.get_http_port()) + "/foo")
print(response)
The first test passes while the second one fails with
_____________________________________________________________ MyTest.test_fail _____________________________________________________________
self = <urllib3.connection.HTTPConnection object at 0x7fea40367e50>
def _new_conn(self):
"""Establish a socket connection and set nodelay settings on it.
:return: New socket connection.
"""
extra_kw = {}
if self.source_address:
extra_kw["source_address"] = self.source_address
if self.socket_options:
extra_kw["socket_options"] = self.socket_options
try:
conn = connection.create_connection(
> (self._dns_host, self.port), self.timeout, **extra_kw
)
../.virtualenvs/creative-preview/lib/python3.7/site-packages/urllib3/connection.py:170:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
address = ('192.168.2.1', 41809), timeout = None, source_address = None, socket_options = [(6, 1, 1)]
def create_connection(
address,
timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
source_address=None,
socket_options=None,
):
"""Connect to *address* and return the socket object.
Convenience function. Connect to *address* (a 2-tuple ``(host,
port)``) and return the socket object. Passing the optional
*timeout* parameter will set the timeout on the socket instance
before attempting to connect. If no *timeout* is supplied, the
global default timeout setting returned by :func:`socket.getdefaulttimeout`
is used. If *source_address* is set it must be a tuple of (host, port)
for the socket to bind as a source address before making the connection.
An host of '' or port 0 tells the OS to use the default.
"""
host, port = address
if host.startswith("["):
host = host.strip("[]")
err = None
# Using the value from allowed_gai_family() in the context of getaddrinfo lets
# us select whether to work with IPv4 DNS records, IPv6 records, or both.
# The original create_connection function always returns all records.
family = allowed_gai_family()
try:
host.encode("idna")
except UnicodeError:
return six.raise_from(
LocationParseError(u"'%s', label empty or too long" % host), None
)
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
af, socktype, proto, canonname, sa = res
sock = None
try:
sock = socket.socket(af, socktype, proto)
# If provided, set socket level options before connecting.
_set_socket_options(sock, socket_options)
if timeout is not socket._GLOBAL_DEFAULT_TIMEOUT:
sock.settimeout(timeout)
if source_address:
sock.bind(source_address)
sock.connect(sa)
return sock
except socket.error as e:
err = e
if sock is not None:
sock.close()
sock = None
if err is not None:
> raise err
../.virtualenvs/creative-preview/lib/python3.7/site-packages/urllib3/util/connection.py:96:
...
During handling of the above exception, another exception occurred:
self = <my_test.MyTest testMethod=test_fail>
#tornado.testing.gen_test(timeout=30)
async def test_fail(self):
> response = await IOLoop.current().run_in_executor(None, requests.get,"http://192.168.2.1:" + str(self.get_http_port()) + "/foo")
my_test.py:18:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/lib/python3.7/concurrent/futures/thread.py:57: in run
result = self.fn(*self.args, **self.kwargs)
../.virtualenvs/creative-preview/lib/python3.7/site-packages/requests/api.py:76: in get
return request('get', url, params=params, **kwargs)
../.virtualenvs/creative-preview/lib/python3.7/site-packages/requests/api.py:61: in request
return session.request(method=method, url=url, **kwargs)
../.virtualenvs/creative-preview/lib/python3.7/site-packages/requests/sessions.py:542: in request
resp = self.send(prep, **send_kwargs)
../.virtualenvs/creative-preview/lib/python3.7/site-packages/requests/sessions.py:655: in send
r = adapter.send(request, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <requests.adapters.HTTPAdapter object at 0x7fea4034dbd0>, request = <PreparedRequest [GET]>, stream = False
timeout = Timeout(connect=None, read=None, total=None), verify = True, cert = None, proxies = OrderedDict()
def send(self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None):
"""Sends PreparedRequest object. Returns Response object.
:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
:param stream: (optional) Whether to stream the request content.
:param timeout: (optional) How long to wait for the server to send
data before giving up, as a float, or a :ref:`(connect timeout,
read timeout) <timeouts>` tuple.
:type timeout: float or tuple or urllib3 Timeout object
:param verify: (optional) Either a boolean, in which case it controls whether
we verify the server's TLS certificate, or a string, in which case it
must be a path to a CA bundle to use
:param cert: (optional) Any user-provided SSL certificate to be trusted.
:param proxies: (optional) The proxies dictionary to apply to the request.
:rtype: requests.Response
"""
try:
conn = self.get_connection(request.url, proxies)
except LocationValueError as e:
raise InvalidURL(e, request=request)
self.cert_verify(conn, request.url, verify, cert)
url = self.request_url(request, proxies)
self.add_headers(request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies)
chunked = not (request.body is None or 'Content-Length' in request.headers)
if isinstance(timeout, tuple):
try:
connect, read = timeout
timeout = TimeoutSauce(connect=connect, read=read)
except ValueError as e:
# this may raise a string formatting error.
err = ("Invalid timeout {}. Pass a (connect, read) "
"timeout tuple, or a single float to set "
"both timeouts to the same value".format(timeout))
raise ValueError(err)
elif isinstance(timeout, TimeoutSauce):
pass
else:
timeout = TimeoutSauce(connect=timeout, read=timeout)
try:
if not chunked:
resp = conn.urlopen(
method=request.method,
url=url,
body=request.body,
headers=request.headers,
redirect=False,
assert_same_host=False,
preload_content=False,
decode_content=False,
retries=self.max_retries,
timeout=timeout
)
# Send the request.
else:
if hasattr(conn, 'proxy_pool'):
conn = conn.proxy_pool
low_conn = conn._get_conn(timeout=DEFAULT_POOL_TIMEOUT)
try:
low_conn.putrequest(request.method,
url,
skip_accept_encoding=True)
for header, value in request.headers.items():
low_conn.putheader(header, value)
low_conn.endheaders()
for i in request.body:
low_conn.send(hex(len(i))[2:].encode('utf-8'))
low_conn.send(b'\r\n')
low_conn.send(i)
low_conn.send(b'\r\n')
low_conn.send(b'0\r\n\r\n')
# Receive the response from the server
try:
# For Python 2.7, use buffering of HTTP responses
r = low_conn.getresponse(buffering=True)
except TypeError:
# For compatibility with Python 3.3+
r = low_conn.getresponse()
resp = HTTPResponse.from_httplib(
r,
pool=conn,
connection=low_conn,
preload_content=False,
decode_content=False
)
except:
# If we hit any problems here, clean up the connection.
# Then, reraise so that we can handle the actual exception.
low_conn.close()
raise
except (ProtocolError, socket.error) as err:
raise ConnectionError(err, request=request)
except MaxRetryError as e:
if isinstance(e.reason, ConnectTimeoutError):
# TODO: Remove this in 3.0.0: see #2811
if not isinstance(e.reason, NewConnectionError):
raise ConnectTimeout(e, request=request)
if isinstance(e.reason, ResponseError):
raise RetryError(e, request=request)
if isinstance(e.reason, _ProxyError):
raise ProxyError(e, request=request)
if isinstance(e.reason, _SSLError):
# This branch is for urllib3 v1.22 and later.
raise SSLError(e, request=request)
> raise ConnectionError(e, request=request)
E requests.exceptions.ConnectionError: HTTPConnectionPool(host='192.168.2.1', port=41809): Max retries exceeded with url: /foo (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7fea40367e50>: Failed to establish a new connection: [Errno 111] Connection refused'))
../.virtualenvs/creative-preview/lib/python3.7/site-packages/requests/adapters.py:516: ConnectionError
==================================================== 1 failed, 1 passed in 0.22 seconds ==================================================
192.168.2.1 is localhost as well (through docker0 interface). The weird thing is that if I run a simple http server python -m http.server then curl 127.0.0.1:8000 and curl 192.168.2.1:8000 both work, so it doesn't seem to be a docker related issue. So I really don't know what's going on
can you try curl -v 192.168.2.1:8000 (verbose) and check the output?
maybe you're redirected to localhost and it's not happened in your code.
What's your app listening host is? localhost or 0.0.0.0?
If you want to be able to connect from the local machine you need to ensure you're listening on 0.0.0.0.

aiohttp_client - RuntimeError: Timeout context manager should be used inside a task

What I'm Doing
I'm learning aiohttp by building a REST api which I'm testing with Pytest (and its async and aiohttp plugins).
For my first test (I'm going with TDD from outset) I have the following code:
#pytest.mark.asyncio
async def test_handle_user_create(
aiohttp_client, init_test_app, create_test_user_table
):
payload = {
"email": "tintin#gmail.com",
"username": "Tintin",
"password": "y0u != n00b1e",
}
client = await aiohttp_client(init_test_app)
resp = await client.post("/users/", json=payload)
...
aiohttp_client is the client fixture from pytest-aiohttp
init_test_app is a fixture which essentially mirrors the app I'm going to build
create_test_user_table is my fixture for creating a table for users in the test database
What's Going Wrong With It
My first test is throwing the following runtime error at the last line in the code block above:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
env36\lib\site-packages\aiohttp\test_utils.py:295: in request
method, self.make_url(path), **kwargs
env36\lib\site-packages\aiohttp\client.py:417: in _request
with timer:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <aiohttp.helpers.TimerContext object at 0x0000015DE23A3B38>
def __enter__(self) -> BaseTimerContext:
task = current_task(loop=self._loop)
if task is None:
> raise RuntimeError(
'Timeout context manager should be used '
'inside a task'
)
E RuntimeError: Timeout context manager should
be used inside a task
env36\lib\site-packages\aiohttp\helpers.py:568: RuntimeError
From the error message, I gather that the client is trying to use an async timeout context manager, but this fails because I'm not calling it inside a task.
I don't know whether my deduction is correct.
And then also, I'm not comfortable enough with asyncio to know how to resolve this.
I will be grateful if someone shows me the way out.
More Info
Here's the source code of my test file:
import asyncio
import sqlite3
from pathlib import Path
import pytest
from aiohttp import web
from app import router
#pytest.fixture(name="event_loop", scope="session")
def fixture_event_loop():
"""
Mock session scoped event loop.
Default event loop is function scoped, and won't work with
otherwisely scoped fixtures. Hence, the need for this overwrite.
"""
loop = asyncio.get_event_loop()
yield loop
loop.close()
#pytest.fixture(name="test_db_path", scope="session")
async def fixture_test_db_path():
return Path(__file__).absolute().parent.joinpath("test_db.sqlite")
#pytest.fixture(name="init_test_db_conn", scope="session")
async def fixture_init_test_db_conn(test_db_path):
"""
Mock initiator of test database connection.
"""
async def _init_test_db_conn(test_app):
with sqlite3.connect(str(test_db_path)) as conn:
test_app["DB_CONN"] = conn
yield
return _init_test_db_conn
#pytest.fixture(name="init_test_app", scope="session")
async def fixture_init_test_app(init_test_db_conn):
"""
Mock app for testing.
Substitute the test db for the development db for testing and
undo the substitution after all tests have been run.
"""
app = web.Application()
app.add_routes(router)
app.cleanup_ctx.append(init_test_db_conn)
return app
#pytest.fixture(name="create_test_user_table")
def fixture_create_test_user_table(test_db_path):
"""
Mock user table for tests. Scope at function level.
Drop table at end of each test.
"""
conn = sqlite3.connect(str(test_db_path))
conn.execute(
"""CREATE TABLE test_users (
id INTEGER PRIMARY KEY,
email TEXT NOT NULL UNIQUE,
username TEXT NOT NULL UNIQUE,
pwd_hash TEXT NOT NULL,
active INTEGER,
joined TEXT NOT NULL);
"""
)
yield
conn.execute("""DROP TABLE test_users;""")
#pytest.mark.asyncio
async def test_handle_user_create(
aiohttp_client, init_test_app, create_test_user_table
):
payload = {
"email": "tintin#gmail.com",
"username": "Tintin",
"password": "y0u != n00b1e",
}
client = await aiohttp_client(init_test_app)
resp = await client.post("/users/", json=payload)
assert resp.status == 200
resp_json = await resp.json()
assert resp_json["email"] == payload["email"]
assert resp_json["username"] == payload["username"]
assert resp_json["pwd_hash"] != payload["pwd_hash"]
assert resp_json["active"] == 0
client.close()
And here's a full trace of the runtime error (alongside deprecation warnings - which I'll appreciate getting help on, as well :) )
$ pytest
============================= test session starts =============================
platform win32 -- Python 3.6.8, pytest-5.3.5, py-1.8.1, pluggy-0.13.1
rootdir: C:\Users\Mfonism\Codeville\AIOHttp\curious_me
plugins: aiohttp-0.3.0, asyncio-0.10.0
collected 1 item
test_app.py F [100%]
================================== FAILURES ===================================
_______________________ test_handle_user_create[pyloop] _______________________
aiohttp_client = <function aiohttp_client.<locals>.go at 0x0000015DE239AD08>
init_test_app = <Application 0x15de23a0d30>, create_test_user_table = None
#pytest.mark.asyncio
async def test_handle_user_create(
aiohttp_client, init_test_app, create_test_user_table
):
payload = {
"email": "tintin#gmail.com",
"username": "Tintin",
"password": "y0u != n00b1e",
}
client = await aiohttp_client(init_test_app)
> resp = await client.post("/users/", json=payload)
test_app.py:89:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
env36\lib\site-packages\aiohttp\test_utils.py:295: in request
method, self.make_url(path), **kwargs
env36\lib\site-packages\aiohttp\client.py:417: in _request
with timer:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <aiohttp.helpers.TimerContext object at 0x0000015DE23A3B38>
def __enter__(self) -> BaseTimerContext:
task = current_task(loop=self._loop)
if task is None:
> raise RuntimeError('Timeout context manager should be used '
'inside a task')
E RuntimeError: Timeout context manager should be used inside a task
env36\lib\site-packages\aiohttp\helpers.py:568: RuntimeError
============================== warnings summary ===============================
test_app.py::test_handle_user_create[pyloop]
c:\users\mfonism\codeville\aiohttp\curious_me\env36\lib\site-packages\aiohttp\cookiejar.py:55: DeprecationWarning: The object should be created from async function
super().__init__(loop=loop)
test_app.py::test_handle_user_create[pyloop]
c:\users\mfonism\codeville\aiohttp\curious_me\env36\lib\site-packages\aiohttp\test_utils.py:247: DeprecationWarning: The object should be created from async function
**kwargs)
test_app.py::test_handle_user_create[pyloop]
c:\users\mfonism\codeville\aiohttp\curious_me\env36\lib\site-packages\aiohttp\connector.py:730: DeprecationWarning: The object should be created from async function
loop=loop)
test_app.py::test_handle_user_create[pyloop]
c:\users\mfonism\codeville\aiohttp\curious_me\env36\lib\site-packages\aiohttp\connector.py:735: DeprecationWarning: The object should be created from async function
resolver = DefaultResolver(loop=self._loop)
-- Docs: https://docs.pytest.org/en/latest/warnings.html
====== 1 failed, 4 warnings in 0.78s ======

Python IO module unknown encoding while unittesting GAE

I have written some unittests for my Python Google App Engine app. Below is a distillation of the problematic code.
class TestCase(unittest.TestCase):
def setUp(self):
from google.appengine.ext import testbed
self.testbed = testbed.Testbed()
self.testbed.activate()
self.testbed.init_urlfetch_stub()
self.testbed.init_blobstore_stub()
ndb.get_context().clear_cache()
def tearDown(self):
self.testbed.deactivate()
def testing(self):
from google.cloud import storage
client = storage.Client()
I am getting an encoding LookupError while opening a file (my gcloud application credentials) using the io library.
Here is the relevant stack trace and offending io code (from pytest):
self = <test_1.TestCase testMethod=testing>
def testing(self):
from google.cloud import storage
> client = storage.Client()
/Users/alex/projects/don/don_server/mobile/tests/test_1.py:66:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/Users/alex/projects/don/don_server/lib/google/cloud/storage/client.py:59: in __init__
_http=_http)
/Users/alex/projects/don/don_server/lib/google/cloud/client.py:223: in __init__
_ClientProjectMixin.__init__(self, project=project)
/Users/alex/projects/don/don_server/lib/google/cloud/client.py:177: in __init__
project = self._determine_default(project)
/Users/alex/projects/don/don_server/lib/google/cloud/client.py:190: in _determine_default
return _determine_default_project(project)
/Users/alex/projects/don/don_server/lib/google/cloud/_helpers.py:181: in _determine_default_project
_, project = google.auth.default()
/Users/alex/projects/don/don_server/lib/google/auth/_default.py:277: in default
credentials, project_id = checker()
/Users/alex/projects/don/don_server/lib/google/auth/_default.py:117: in _get_gcloud_sdk_credentials
credentials_filename)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
filename = '/Users/name/.config/gcloud/application_default_credentials.json'
def _load_credentials_from_file(filename):
"""Loads credentials from a file.
The credentials file must be a service account key or stored authorized
user credentials.
Args:
filename (str): The full path to the credentials file.
Returns:
Tuple[google.auth.credentials.Credentials, Optional[str]]: Loaded
credentials and the project ID. Authorized user credentials do not
have the project ID information.
Raises:
google.auth.exceptions.DefaultCredentialsError: if the file is in the
wrong format.
"""
> with io.open(filename, 'r') as file_obj:
E LookupError: unknown encoding:
I don't get this error in when I run this code on my GAE local development server. Furthermore when I open the credentials file using a shell (I checked the file attribute on the io module and it's the same) no error is raised.
For some reason the correct environment variables are not set on a Mac when running the unittests through pycharm. Adding the following code (from this answer) solved it for me:
import os
os.environ['LC_ALL'] = 'en_US.UTF-8'
os.environ['LANG'] = 'en_US.UTF-8'

Categories

Resources