introduce a py3 client

Summary: Introduce a py3 replacement for EdenClient.

Reviewed By: wez

Differential Revision: D22060644

fbshipit-source-id: 535a1f1addf3ac79de0471a688cef55567802d26
This commit is contained in:
Chad Austin 2020-09-15 11:39:35 -07:00 committed by Facebook GitHub Bot
parent 80e710e70d
commit 62f06c645a
2 changed files with 96 additions and 0 deletions

View File

@ -0,0 +1,70 @@
#!/usr/bin/env python3
# Copyright (c) Facebook, Inc. and its affiliates.
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2.
import os
from typing import Optional
from eden.fs.service.eden.clients import EdenService
from thrift.py3 import get_client
from thrift.py3.exceptions import TransportError, TransportErrorType
SOCKET_PATH = "socket"
class EdenNotRunningError(Exception):
def __init__(self, socket_path: str):
super(EdenNotRunningError, self).__init__(
f"edenfs daemon does not appear to be running: tried {socket_path}"
)
self.socket_path = socket_path
class EdenClient(EdenService):
"""
EdenClient is a subclass of EdenService that provides
some conveniences and helps deal with evolving Thrift APIs.
"""
socket_path: Optional[str] = None
async def __aenter__(self):
try:
return await super().__aenter__()
except TransportError as ex:
if ex.type == TransportErrorType.NOT_OPEN:
raise EdenNotRunningError(self.socket_path)
raise
def create_thrift_client(
eden_dir: Optional[str] = None,
socket_path: Optional[str] = None,
timeout: Optional[float] = None,
) -> EdenClient:
"""
Construct a thrift client to speak to the running eden server
instance associated with the specified mount point.
@return Returns an EdenService.Client.
"""
if socket_path is not None:
pass
elif eden_dir is not None:
socket_path = os.path.join(eden_dir, SOCKET_PATH)
else:
raise TypeError("one of eden_dir or socket_path is required")
if timeout is None:
# We used to set a default timeout here, but picking the right duration is hard,
# and safely retrying an arbitrary thrift call may not be safe. So we
# just leave the client with no timeout, unless one is given.
timeout = 0
client = get_client(EdenClient, path=socket_path, timeout=timeout)
client.socket_path = socket_path
return client

View File

@ -0,0 +1,26 @@
#!/usr/bin/env python3
# Copyright (c) Facebook, Inc. and its affiliates.
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2.
import os.path
import tempfile
import unittest
from eden.thrift.client import EdenNotRunningError, create_thrift_client
class EdenClientTest(unittest.IsolatedAsyncioTestCase):
async def test_raise_EdenNotRunningError_when_no_socket(self):
with tempfile.TemporaryDirectory() as td:
sockname = os.path.join(td, "sock")
with self.assertRaises(EdenNotRunningError) as cm:
async with create_thrift_client(socket_path=sockname):
pass
ex = cm.exception
self.assertEqual(sockname, ex.socket_path)
self.assertEqual(
"edenfs daemon does not appear to be running: tried " + sockname,
str(ex),
)