Skip to content

Commit

Permalink
Merge pull request #1 from someengineering/lloesche/delete
Browse files Browse the repository at this point in the history
Implement delete
  • Loading branch information
lloesche authored Sep 23, 2024
2 parents ce6d806 + 77f4ecf commit a450aea
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 7 deletions.
55 changes: 50 additions & 5 deletions fixattiosync/attiodata.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,35 @@ def __init__(self, api_key: str, default_limit: int = 500):
self.__people: dict[UUID, AttioPerson] = {}
self.__users: dict[UUID, AttioUser] = {}

def _headers(self) -> dict[str, str]:
return {
def _headers(self, json: bool = False) -> dict[str, str]:
headers = {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json",
"Accept": "application/json",
}
if json:
headers["Content-Type"] = "application/json"

return headers

def _delete_data(
self, endpoint: str, json: Optional[dict[str, Any]] = None, params: Optional[dict[str, str]] = None
) -> dict[str, Any]:
log.debug(f"Deleting data from {endpoint}")
url = self.base_url + endpoint
headers = self._headers(json=True) if json else self._headers(json=False)
response = requests.delete(url, headers=headers, json=json, params=params)
if response.status_code == 200:
return response.json() # type: ignore
else:
raise Exception(f"Error deleting data from {url}: {response.status_code} {response.text}")

def _post_data(
self, endpoint: str, json: Optional[dict[str, Any]] = None, params: Optional[dict[str, str]] = None
) -> dict[str, Any]:
log.debug(f"Fetching data from {endpoint}")
url = self.base_url + endpoint
response = requests.post(url, headers=self._headers(), json=json, params=params)
headers = self._headers(json=True) if json else self._headers(json=False)
response = requests.post(url, headers=headers, json=json, params=params)
if response.status_code == 200:
return response.json() # type: ignore
else:
Expand All @@ -41,12 +57,41 @@ def _put_data(
) -> dict[str, Any]:
log.debug(f"Putting data to {endpoint}")
url = self.base_url + endpoint
response = requests.put(url, headers=self._headers(), json=json, params=params)
headers = self._headers(json=True) if json else self._headers(json=False)
response = requests.put(url, headers=headers, json=json, params=params)
if response.status_code == 200:
return response.json() # type: ignore
else:
raise Exception(f"Error putting data to {url}: {response.status_code} {response.text}")

def delete_record(self, object_id: str, record_id: UUID) -> dict[str, Any]:
endpoint = f"objects/{object_id}/records/{record_id}"
match object_id:
case "users":
self_store = self.__users
case "people":
self_store = self.__people # type: ignore
case "workspaces":
self_store = self.__workspaces # type: ignore
case _:
raise ValueError(f"Unknown object_id: {object_id}")

response = self._delete_data(endpoint)
if record_id in self_store:
log.debug(f"Deleted {object_id} {record_id} in Attio, updating locally")
attio_obj = self_store[record_id]
if object_id == "users":
assert isinstance(attio_obj, AttioUser)
if attio_obj.person is not None:
assert isinstance(attio_obj.person, AttioPerson)
attio_obj.person.users.remove(attio_obj)
for workspace in attio_obj.workspaces:
workspace.users.remove(attio_obj)
del self_store[record_id]
else:
log.error(f"Deleted {object_id} {record_id} in Attio, not found locally")
return response

def assert_record(
self, object_id: str, matching_attribute: str, data: dict[str, Any]
) -> Union[AttioPerson, AttioUser, AttioWorkspace]:
Expand Down
4 changes: 4 additions & 0 deletions fixattiosync/attioresources.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ def optional_uuid(value: str) -> Optional[UUID]:
@dataclass
class AttioResource(ABC):
matching_attribute: ClassVar[str] = "record_id"
api_object: ClassVar[str] = ""

object_id: UUID
record_id: UUID
Expand All @@ -40,6 +41,7 @@ def make(cls: Type[Self], data: dict[str, Any]) -> Self:
@dataclass
class AttioWorkspace(AttioResource):
matching_attribute: ClassVar[str] = "workspace_id"
api_object: ClassVar[str] = "workspaces"

id: Optional[UUID]
name: Optional[str]
Expand Down Expand Up @@ -94,6 +96,7 @@ def make(cls: Type[Self], data: dict[str, Any]) -> Self:
@dataclass
class AttioPerson(AttioResource):
matching_attribute: ClassVar[str] = "email_addresses"
api_object: ClassVar[str] = "people"

full_name: Optional[str]
first_name: Optional[str]
Expand Down Expand Up @@ -145,6 +148,7 @@ def make(cls: Type[Self], data: dict[str, Any]) -> Self:
@dataclass
class AttioUser(AttioResource):
matching_attribute: ClassVar[str] = "user_id"
api_object: ClassVar[str] = "users"

id: Optional[UUID]
demo_workspace_viewed: Optional[bool]
Expand Down
19 changes: 17 additions & 2 deletions fixattiosync/sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,26 @@ def sync_fix_to_attio(fix: FixData, attio: AttioData, max_changes_percent: int =

for attio_workspace in obsolete_workspaces:
log.info(f"Deleting workspace {attio_workspace.name} ({attio_workspace.fix_workspace_id})")
# todo: delete workspace
try:
attio.delete_record(attio_workspace.api_object, attio_workspace.record_id)
except Exception as e:
log.error(f"Error deleting workspace {attio_workspace.name} ({attio_workspace.fix_workspace_id}): {e}")

for attio_user in obsolete_users:
log.info(f"Deleting user {attio_user.email} ({attio_user.user_id})")
# todo: delete user
try:
attio_person = attio_user.person
attio.delete_record(attio_user.api_object, attio_user.record_id)
if attio_person is not None:
assert isinstance(attio_person, AttioPerson)
if len(attio_person.users) == 0:
log.info(f"Deleting person {attio_person.email} ({attio_person.record_id}) with no users")
try:
attio.delete_record(attio_person.api_object, attio_person.record_id)
except Exception as e:
log.error(f"Error deleting person {attio_person.email} ({attio_person.record_id}): {e}")
except Exception as e:
log.error(f"Error deleting user {attio_user.email} ({attio_user.user_id}): {e}")


def workspaces_missing_in_attio(fix: FixData, attio: AttioData) -> list[FixWorkspace]:
Expand Down

0 comments on commit a450aea

Please sign in to comment.