Group

class based approach to interacting with Domo Groups
auth = dmda.DomoTokenAuth(
    domo_instance=os.environ["DOMO_INSTANCE"],
    domo_access_token=os.environ["DOMO_ACCESS_TOKEN"],
)

groups = (await group_routes.get_all_groups(auth=auth)).response
group = next((group for group in groups if 'test' in group['name'].lower() ))

group_id = group["groupId"]

Domo Group


source

DomoGroup

 DomoGroup (auth:domolibrary.client.DomoAuth.DomoAuth=None, id:str=None,
            name:str=None, type:str=None, is_system:bool=None,
            description:str=None, members_id_ls:list[str]=<factory>,
            owner_id_ls:list[str]=<factory>,
            members_ls:list[dict]=<factory>,
            owner_ls:list[dict]=<factory>,
            custom_attributes:dict=<factory>, Membership:domolibrary.class
            es.DomoMembership.GroupMembership=None)

source

Group_Class_Error

 Group_Class_Error (cls_instance, message:str=None, entity_id:str=None)

base exception

GET Methods

sample get_by_id

await DomoGroup.get_by_id(auth=auth, group_id=group_id, return_raw=False)
DomoGroup(id=1814479647, name='Admin Test', type='closed', is_system=False, description='', custom_attributes={})

sample get_members

group = DomoGroup(id=group_id, auth=auth)

pd.DataFrame((await group.Membership.get_members(return_raw = True)).response)
(await group.Membership.get_members())[0:5]
[Membership_Entity(entity=DomoUser(id='1216550715', display_name='8:26 - go to sleep', email_address='test4@domo.com', role_id=2, department='test', title=None, avatar_key='/api/content/v1/avatar/USER/1216550715', phone_number='152', web_landing_page=None, web_mobile_landing_page=None, employee_id=None, employee_number=None, hire_date=None, reports_to=None, publisher_domain=None, subscriber_domain=None, virtual_user_id=None, created_dt=datetime.datetime(2022, 10, 5, 3, 0, 21), last_activity_dt=datetime.datetime(2024, 1, 22, 20, 2, 32, 453000), custom_attributes={}, role=DomoRole(id=2, name='Privileged', description='Full access except for editing users and settings owners', is_system_role=True, is_default_role=None, grants=[], membership_ls=[]), domo_api_clients=None, domo_access_tokens=None)),
 Membership_Entity(entity=DomoUser(id='128618865', display_name='9:02 - no really go to bed', email_address='test6@domo.com', role_id=2, department=None, title=None, avatar_key='/api/content/v1/avatar/USER/128618865', phone_number=None, web_landing_page=None, web_mobile_landing_page=None, employee_id=None, employee_number=None, hire_date=None, reports_to=None, publisher_domain=None, subscriber_domain=None, virtual_user_id=None, created_dt=datetime.datetime(2022, 10, 5, 3, 3, 47), last_activity_dt=datetime.datetime(2024, 1, 22, 20, 2, 43, 348000), custom_attributes={}, role=DomoRole(id=2, name='Privileged', description='Full access except for editing users and settings owners', is_system_role=True, is_default_role=None, grants=[], membership_ls=[]), domo_api_clients=None, domo_access_tokens=None)),
 Membership_Entity(entity=DomoUser(id='1447682110', display_name='Aaron Brown', email_address='abrown@aimsplus.com', role_id=2, department=None, title=None, avatar_key='/api/content/v1/avatar/USER/1447682110', phone_number=None, web_landing_page=None, web_mobile_landing_page=None, employee_id=None, employee_number=None, hire_date=None, reports_to=None, publisher_domain=None, subscriber_domain=None, virtual_user_id=None, created_dt=datetime.datetime(2023, 11, 2, 18, 1, 10), last_activity_dt=datetime.datetime(2024, 1, 22, 20, 2, 51, 952000), custom_attributes={}, role=DomoRole(id=2, name='Privileged', description='Full access except for editing users and settings owners', is_system_role=True, is_default_role=None, grants=[], membership_ls=[]), domo_api_clients=None, domo_access_tokens=None)),
 Membership_Entity(entity=DomoUser(id='1628021317', display_name='Aaron Dean', email_address='aaron.dean@rxa.io', role_id=2097317660, department=None, title=None, avatar_key='/api/content/v1/avatar/USER/1628021317', phone_number=None, web_landing_page=None, web_mobile_landing_page=None, employee_id=None, employee_number=None, hire_date=None, reports_to=None, publisher_domain=None, subscriber_domain=None, virtual_user_id=None, created_dt=datetime.datetime(2022, 6, 23, 15, 41, 52), last_activity_dt=datetime.datetime(2024, 1, 22, 20, 3, 2, 259000), custom_attributes={}, role=DomoRole(id=2097317660, name='Community_Default_Priviliged', description='Full access except for editing users and settings owners', is_system_role=0, is_default_role=None, grants=[], membership_ls=[]), domo_api_clients=None, domo_access_tokens=None)),
 Membership_Entity(entity=DomoUser(id='1825354355', display_name='Aaron Lemley', email_address='alemley@thisisoutcast.com', role_id=2, department=None, title=None, avatar_key='/api/content/v1/avatar/USER/1825354355', phone_number=None, web_landing_page=None, web_mobile_landing_page=None, employee_id=None, employee_number=None, hire_date=None, reports_to=None, publisher_domain=None, subscriber_domain=None, virtual_user_id=None, created_dt=datetime.datetime(2023, 9, 7, 21, 24), last_activity_dt=datetime.datetime(2024, 1, 22, 20, 3, 10, 724000), custom_attributes={}, role=DomoRole(id=2, name='Privileged', description='Full access except for editing users and settings owners', is_system_role=True, is_default_role=None, grants=[], membership_ls=[]), domo_api_clients=None, domo_access_tokens=None))]

CRUD Methods

group_name = "Test Group ac"
domo_group = None
try:
    domo_group = await DomoGroup.create_from_name(group_name=group_name, auth=auth)
    print(domo_group)
except Group_CRUD_Error as e:
    print(e)
🛑  Group_CRUD_Error 🛑 - function: DomoGroup.get_traceback || status 400 || Test Group ac already exists. Choose a different group_name at domo-community
domo_group = await DomoGroup.get_by_id(group_id=group_id, auth=auth)

try:
    await domo_group.update_metadata(
        auth=auth,
        # group_name="Test Group ABCs",
        group_type="open",
        description=f"updated via API on {dt.date.today()}",
        debug_api=False,
    )

except (Group_CRUD_Error, Group_Class_Error) as e:
    print(e)
🛑  Group_Class_Error 🛑 - function: 🛑 DomoGroup 🛑 1814479647 || probably cannot change group_type to 'open' from current type 'closed' consider passing `addtional_parameters` || error

Membership

domo_users = await dmu.DomoUsers.all_users(auth=auth)
domo_users[0:5]
[DomoUser(id='None', display_name='monitor', email_address='monitor@domo.com', role_id=1, department=None, title=None, avatar_key=None, phone_number=None, web_landing_page=None, web_mobile_landing_page=None, employee_id=None, employee_number=None, hire_date=None, reports_to=None, publisher_domain=None, subscriber_domain=None, virtual_user_id=None, created_dt=datetime.datetime(1970, 1, 17, 22, 53, 40, 854000), last_activity_dt=None, custom_attributes={}, role=None, domo_api_clients=None, domo_access_tokens=None),
 DomoUser(id='1003855998', display_name='Christine Hsieh', email_address='christine.hsieh@hellofresh.com', role_id=2, department=None, title=None, avatar_key=None, phone_number=None, web_landing_page=None, web_mobile_landing_page=None, employee_id=None, employee_number=None, hire_date=None, reports_to=None, publisher_domain=None, subscriber_domain=None, virtual_user_id=None, created_dt=datetime.datetime(1970, 1, 20, 13, 33, 2, 284000), last_activity_dt=None, custom_attributes={}, role=None, domo_api_clients=None, domo_access_tokens=None),
 DomoUser(id='1005321923', display_name='Matthew Lambourne', email_address='matthew.lambourne@frankandoak.com', role_id=2, department=None, title='Financial Controller', avatar_key=None, phone_number=None, web_landing_page=None, web_mobile_landing_page=None, employee_id=None, employee_number=None, hire_date=None, reports_to=None, publisher_domain=None, subscriber_domain=None, virtual_user_id=None, created_dt=datetime.datetime(1970, 1, 20, 15, 51, 8, 818000), last_activity_dt=None, custom_attributes={}, role=None, domo_api_clients=None, domo_access_tokens=None),
 DomoUser(id='1006847540', display_name='Marc-Anton Clavel', email_address='marcanton.clavel@domo.com', role_id=2, department='Domo Client Services', title='Executive Analytics', avatar_key=None, phone_number=None, web_landing_page=None, web_mobile_landing_page=None, employee_id=None, employee_number=None, hire_date=None, reports_to=None, publisher_domain=None, subscriber_domain=None, virtual_user_id=None, created_dt=datetime.datetime(1970, 1, 19, 17, 36, 19, 73000), last_activity_dt=None, custom_attributes={}, role=None, domo_api_clients=None, domo_access_tokens=None),
 DomoUser(id='1009228622', display_name='fz_RestaurantManager14@fz.com', email_address='RestaurantManager14@fz.com', role_id=5, department=None, title=None, avatar_key=None, phone_number=None, web_landing_page=None, web_mobile_landing_page=None, employee_id=None, employee_number='14', hire_date=None, reports_to=None, publisher_domain=None, subscriber_domain=None, virtual_user_id=None, created_dt=datetime.datetime(1970, 1, 20, 17, 24, 19, 972000), last_activity_dt=None, custom_attributes={}, role=None, domo_api_clients=None, domo_access_tokens=None)]
group = DomoGroup(id=group_id, auth=auth)

await group.Membership.get_owners()

print(group.owner_id_ls)  # does not differentiate between users and groups

group.owner_ls
[822382906, '55874022']
[DomoGroup(id=822382906, name='Grant: Manage all groups', type='system', is_system=True, description='Create, edit and delete any groups. Add and remove people from any group.', custom_attributes={}),
 DomoUser(id='55874022', display_name='Grant Smith', email_address='grantsmith@gmail.com', role_id=1, department='', title='', avatar_key='/api/content/v1/avatar/USER/55874022', phone_number='0', web_landing_page=None, web_mobile_landing_page=None, employee_id=None, employee_number=None, hire_date=1618632000000, reports_to='596117551', publisher_domain=None, subscriber_domain=None, virtual_user_id=None, created_dt=datetime.datetime(2020, 5, 8, 17, 55, 28), last_activity_dt=datetime.datetime(2025, 1, 13, 20, 0, 34, 770000), custom_attributes={}, role=DomoRole(id=1, name='Admin', description='Full access to everything', is_system_role=True, is_default_role=None, grants=[], membership_ls=[]), domo_api_clients=None, domo_access_tokens=None)]
domo_group = await DomoGroup.get_by_id(auth=auth, group_id=group_id)

print(
    f"validate old membership {', '.join([str(id) for id in domo_group.members_id_ls])}"
)

new_membership = await dmu.DomoUsers.by_id(
    user_ids=[domo_user.id for domo_user in domo_users], auth=auth, only_allow_one=False
)

(await domo_group.Membership.add_members(add_user_ls=new_membership, debug_api=False))[0:5]
validate old membership 
[Membership_Entity(entity=DomoUser(id='1216550715', display_name='8:26 - go to sleep', email_address='test4@domo.com', role_id=2, department='test', title=None, avatar_key='/api/content/v1/avatar/USER/1216550715', phone_number='152', web_landing_page=None, web_mobile_landing_page=None, employee_id=None, employee_number=None, hire_date=None, reports_to=None, publisher_domain=None, subscriber_domain=None, virtual_user_id=None, created_dt=datetime.datetime(2022, 10, 5, 3, 0, 21), last_activity_dt=datetime.datetime(2024, 1, 22, 20, 2, 32, 453000), custom_attributes={}, role=DomoRole(id=2, name='Privileged', description='Full access except for editing users and settings owners', is_system_role=True, is_default_role=None, grants=[], membership_ls=[]), domo_api_clients=None, domo_access_tokens=None)),
 Membership_Entity(entity=DomoUser(id='128618865', display_name='9:02 - no really go to bed', email_address='test6@domo.com', role_id=2, department=None, title=None, avatar_key='/api/content/v1/avatar/USER/128618865', phone_number=None, web_landing_page=None, web_mobile_landing_page=None, employee_id=None, employee_number=None, hire_date=None, reports_to=None, publisher_domain=None, subscriber_domain=None, virtual_user_id=None, created_dt=datetime.datetime(2022, 10, 5, 3, 3, 47), last_activity_dt=datetime.datetime(2024, 1, 22, 20, 2, 43, 348000), custom_attributes={}, role=DomoRole(id=2, name='Privileged', description='Full access except for editing users and settings owners', is_system_role=True, is_default_role=None, grants=[], membership_ls=[]), domo_api_clients=None, domo_access_tokens=None)),
 Membership_Entity(entity=DomoUser(id='1447682110', display_name='Aaron Brown', email_address='abrown@aimsplus.com', role_id=2, department=None, title=None, avatar_key='/api/content/v1/avatar/USER/1447682110', phone_number=None, web_landing_page=None, web_mobile_landing_page=None, employee_id=None, employee_number=None, hire_date=None, reports_to=None, publisher_domain=None, subscriber_domain=None, virtual_user_id=None, created_dt=datetime.datetime(2023, 11, 2, 18, 1, 10), last_activity_dt=datetime.datetime(2024, 1, 22, 20, 2, 51, 952000), custom_attributes={}, role=DomoRole(id=2, name='Privileged', description='Full access except for editing users and settings owners', is_system_role=True, is_default_role=None, grants=[], membership_ls=[]), domo_api_clients=None, domo_access_tokens=None)),
 Membership_Entity(entity=DomoUser(id='1628021317', display_name='Aaron Dean', email_address='aaron.dean@rxa.io', role_id=2097317660, department=None, title=None, avatar_key='/api/content/v1/avatar/USER/1628021317', phone_number=None, web_landing_page=None, web_mobile_landing_page=None, employee_id=None, employee_number=None, hire_date=None, reports_to=None, publisher_domain=None, subscriber_domain=None, virtual_user_id=None, created_dt=datetime.datetime(2022, 6, 23, 15, 41, 52), last_activity_dt=datetime.datetime(2024, 1, 22, 20, 3, 2, 259000), custom_attributes={}, role=DomoRole(id=2097317660, name='Community_Default_Priviliged', description='Full access except for editing users and settings owners', is_system_role=0, is_default_role=None, grants=[], membership_ls=[]), domo_api_clients=None, domo_access_tokens=None)),
 Membership_Entity(entity=DomoUser(id='1825354355', display_name='Aaron Lemley', email_address='alemley@thisisoutcast.com', role_id=2, department=None, title=None, avatar_key='/api/content/v1/avatar/USER/1825354355', phone_number=None, web_landing_page=None, web_mobile_landing_page=None, employee_id=None, employee_number=None, hire_date=None, reports_to=None, publisher_domain=None, subscriber_domain=None, virtual_user_id=None, created_dt=datetime.datetime(2023, 9, 7, 21, 24), last_activity_dt=datetime.datetime(2024, 1, 22, 20, 3, 10, 724000), custom_attributes={}, role=DomoRole(id=2, name='Privileged', description='Full access except for editing users and settings owners', is_system_role=True, is_default_role=None, grants=[], membership_ls=[]), domo_api_clients=None, domo_access_tokens=None))]

sample remove_members

domo_group = await DomoGroup.get_by_id(auth=auth, group_id=group_id)

print(
    f"validate old membership {', '.join([str(id) for id in domo_group.members_id_ls])}"
)


remove_membership = await dmu.DomoUsers.by_id(
    user_ids=[domo_user.id for domo_user in domo_users], auth=auth, only_allow_one=False
)

try:
    print((await domo_group.Membership.remove_members(remove_user_ls=remove_membership))[0:5]

except dmde.DomoError as e:
    print(e)
  Cell In[16], line 13
    print((await domo_group.Membership.remove_members(remove_user_ls=remove_membership))[0:5]
         ^
SyntaxError: '(' was never closed
# group_id =551922257

group_id = 2124036480

domo_group = await DomoGroup.get_by_id(auth=auth, group_id=group_id)

owner = await dmu.DomoUser.get_by_id(
    user_id=auth.user_id,
    auth=auth,
)

(await domo_group.Membership.add_owners(add_owner_ls=[owner], debug_api=False))[0:5]

sample set_members

domo_group = await DomoGroup.get_by_id(auth=auth, group_id=group_id)

print(
    f"validate old membership {', '.join([str(id) for id in domo_group.members_id_ls])}"
)

set_membership = await dmu.DomoUsers.by_id(
    user_ids=[domo_user.id for domo_user in domo_users],
    auth=auth,
    only_allow_one=False,
)

(await domo_group.Membership.add_members(add_user_ls=set_membership))[0:5]
---------------------------------------------------------------------------
CancelledError                            Traceback (most recent call last)
Cell In[21], line 13
      3 print(
      4     f"validate old membership {', '.join([str(id) for id in domo_group.members_id_ls])}"
      5 )
      7 set_membership = await dmu.DomoUsers.by_id(
      8     user_ids=[domo_user.id for domo_user in domo_users],
      9     auth=auth,
     10     only_allow_one=False,
     11 )
---> 13 (await domo_group.Membership.add_members(add_user_ls=set_membership))[0:5]

File /workspaces/domolibrary/domolibrary/classes/DomoMembership.py:281, in add_members(self, add_user_ls, return_raw, debug_api, session, debug_num_stacks_to_drop)
    278 for domo_user in add_user_ls:    
    279     self._add_member(domo_user)
--> 281 res = await self.update(
    282     debug_api=debug_api,
    283     session=session,
    284     debug_num_stacks_to_drop=debug_num_stacks_to_drop + 1,
    285 )
    287 if return_raw:
    288     return res

File /workspaces/domolibrary/domolibrary/classes/DomoMembership.py:221, in GroupMembership.update(self, update_payload, debug_api, session, debug_num_stacks_to_drop)
    214 async def update(
    215     self,
    216     update_payload : dict = None,
   (...)
    219     debug_num_stacks_to_drop: int = 2,
    220 ):
--> 221     res = await group_routes.update_group_membership(
    222         auth=self.auth,
    223         update_payload=update_payload,
    224         group_id=self.parent_id,
    225         add_member_arr=self._list_to_json(self._add_member_ls),
    226         remove_member_arr=self._list_to_json(self._remove_member_ls),
    227         add_owner_arr=self._list_to_json(self._add_owner_ls),
    228         remove_owner_arr=self._list_to_json(self._remove_owner_ls),
    229         debug_api=debug_api,
    230         session=session,
    231         debug_num_stacks_to_drop=debug_num_stacks_to_drop,
    232     )
    234     self._reset_obj()
    236     return res

File /workspaces/domolibrary/domolibrary/client/get_data.py:447, in route_function.<locals>.wrapper(parent_class, debug_num_stacks_to_drop, debug_api, session, *args, **kwargs)
    438 @wraps(func)
    439 async def wrapper(
    440     *args: Any,
   (...)
    445     **kwargs: Any,
    446 ) -> Any:
--> 447     result = await func(
    448         *args,
    449         parent_class=parent_class,
    450         debug_num_stacks_to_drop=debug_num_stacks_to_drop,
    451         debug_api=debug_api,
    452         session=session,
    453         **kwargs,
    454     )
    456     if not isinstance(result, rgd.ResponseGetData):
    457         raise RouteFunction_ResponseTypeError(result)

File /workspaces/domolibrary/domolibrary/routes/group.py:594, in update_group_membership(auth, group_id, update_payload, add_member_arr, remove_member_arr, add_owner_arr, remove_owner_arr, debug_api, session, parent_class, debug_num_stacks_to_drop)
    584 update_payload = update_payload or generate_body_update_group_membership(
    585     group_id=group_id,
    586     add_member_arr=add_member_arr,
   (...)
    589     remove_owner_arr=remove_owner_arr
    590 )
    592 url = f"https://{auth.domo_instance}.domo.com/api/content/v2/groups/access"
--> 594 res = await gd.get_data(
    595     auth=auth,
    596     url=url,
    597     method="PUT",
    598     body=update_payload,
    599     debug_api=debug_api,
    600     session=session,
    601     num_stacks_to_drop=debug_num_stacks_to_drop,
    602     parent_class=parent_class,
    603 )
    605 if not res.is_success:
    606     raise Group_CRUD_Error(res=res)

File /workspaces/domolibrary/domolibrary/utils/chunk_execution.py:31, in run_with_retry.<locals>.actual_decorator.<locals>.wrapper(*args, **kwargs)
     29 try:
     30     retry +=1
---> 31     return await run_fn( *args, **kwargs)
     33 except httpx.ConnectTimeout as e:
     34     print(f"connect timeout - retry attempt {retry} - {e}")

File /workspaces/domolibrary/domolibrary/client/get_data.py:141, in get_data(url, method, auth, content_type, headers, body, params, debug_api, session, return_raw, is_follow_redirects, timeout, parent_class, num_stacks_to_drop, debug_traceback, is_verify)
    131         res = httpx.request(
    132             method="DELETE",
    133             url=url,
   (...)
    138             timeout=timeout,
    139         )
    140     else:
--> 141         res = await getattr(session, method.lower())(
    142             url=url,
    143             headers=headers,
    144             json=body,
    145             params=params,
    146             follow_redirects=is_follow_redirects,
    147             timeout=timeout,
    148         )
    150 elif body:
    151     if debug_api:

File ~/.local/lib/python3.12/site-packages/httpx/_client.py:1896, in AsyncClient.put(self, url, content, data, files, json, params, headers, cookies, auth, follow_redirects, timeout, extensions)
   1875 async def put(
   1876     self,
   1877     url: URL | str,
   (...)
   1889     extensions: RequestExtensions | None = None,
   1890 ) -> Response:
   1891     """
   1892     Send a `PUT` request.
   1893 
   1894     **Parameters**: See `httpx.request`.
   1895     """
-> 1896     return await self.request(
   1897         "PUT",
   1898         url,
   1899         content=content,
   1900         data=data,
   1901         files=files,
   1902         json=json,
   1903         params=params,
   1904         headers=headers,
   1905         cookies=cookies,
   1906         auth=auth,
   1907         follow_redirects=follow_redirects,
   1908         timeout=timeout,
   1909         extensions=extensions,
   1910     )

File ~/.local/lib/python3.12/site-packages/httpx/_client.py:1540, in AsyncClient.request(self, method, url, content, data, files, json, params, headers, cookies, auth, follow_redirects, timeout, extensions)
   1525     warnings.warn(message, DeprecationWarning, stacklevel=2)
   1527 request = self.build_request(
   1528     method=method,
   1529     url=url,
   (...)
   1538     extensions=extensions,
   1539 )
-> 1540 return await self.send(request, auth=auth, follow_redirects=follow_redirects)

File ~/.local/lib/python3.12/site-packages/httpx/_client.py:1629, in AsyncClient.send(self, request, stream, auth, follow_redirects)
   1625 self._set_timeout(request)
   1627 auth = self._build_request_auth(request, auth)
-> 1629 response = await self._send_handling_auth(
   1630     request,
   1631     auth=auth,
   1632     follow_redirects=follow_redirects,
   1633     history=[],
   1634 )
   1635 try:
   1636     if not stream:

File ~/.local/lib/python3.12/site-packages/httpx/_client.py:1657, in AsyncClient._send_handling_auth(self, request, auth, follow_redirects, history)
   1654 request = await auth_flow.__anext__()
   1656 while True:
-> 1657     response = await self._send_handling_redirects(
   1658         request,
   1659         follow_redirects=follow_redirects,
   1660         history=history,
   1661     )
   1662     try:
   1663         try:

File ~/.local/lib/python3.12/site-packages/httpx/_client.py:1694, in AsyncClient._send_handling_redirects(self, request, follow_redirects, history)
   1691 for hook in self._event_hooks["request"]:
   1692     await hook(request)
-> 1694 response = await self._send_single_request(request)
   1695 try:
   1696     for hook in self._event_hooks["response"]:

File ~/.local/lib/python3.12/site-packages/httpx/_client.py:1730, in AsyncClient._send_single_request(self, request)
   1725     raise RuntimeError(
   1726         "Attempted to send an sync request with an AsyncClient instance."
   1727     )
   1729 with request_context(request=request):
-> 1730     response = await transport.handle_async_request(request)
   1732 assert isinstance(response.stream, AsyncByteStream)
   1733 response.request = request

File ~/.local/lib/python3.12/site-packages/httpx/_transports/default.py:394, in AsyncHTTPTransport.handle_async_request(self, request)
    381 req = httpcore.Request(
    382     method=request.method,
    383     url=httpcore.URL(
   (...)
    391     extensions=request.extensions,
    392 )
    393 with map_httpcore_exceptions():
--> 394     resp = await self._pool.handle_async_request(req)
    396 assert isinstance(resp.stream, typing.AsyncIterable)
    398 return Response(
    399     status_code=resp.status,
    400     headers=resp.headers,
    401     stream=AsyncResponseStream(resp.stream),
    402     extensions=resp.extensions,
    403 )

File ~/.local/lib/python3.12/site-packages/httpcore/_async/connection_pool.py:256, in AsyncConnectionPool.handle_async_request(self, request)
    253         closing = self._assign_requests_to_connections()
    255     await self._close_connections(closing)
--> 256     raise exc from None
    258 # Return the response. Note that in this case we still have to manage
    259 # the point at which the response is closed.
    260 assert isinstance(response.stream, typing.AsyncIterable)

File ~/.local/lib/python3.12/site-packages/httpcore/_async/connection_pool.py:236, in AsyncConnectionPool.handle_async_request(self, request)
    232 connection = await pool_request.wait_for_connection(timeout=timeout)
    234 try:
    235     # Send the request on the assigned connection.
--> 236     response = await connection.handle_async_request(
    237         pool_request.request
    238     )
    239 except ConnectionNotAvailable:
    240     # In some cases a connection may initially be available to
    241     # handle a request, but then become unavailable.
    242     #
    243     # In this case we clear the connection and try again.
    244     pool_request.clear_connection()

File ~/.local/lib/python3.12/site-packages/httpcore/_async/connection.py:103, in AsyncHTTPConnection.handle_async_request(self, request)
    100     self._connect_failed = True
    101     raise exc
--> 103 return await self._connection.handle_async_request(request)

File ~/.local/lib/python3.12/site-packages/httpcore/_async/http11.py:136, in AsyncHTTP11Connection.handle_async_request(self, request)
    134     async with Trace("response_closed", logger, request) as trace:
    135         await self._response_closed()
--> 136 raise exc

File ~/.local/lib/python3.12/site-packages/httpcore/_async/http11.py:106, in AsyncHTTP11Connection.handle_async_request(self, request)
     95     pass
     97 async with Trace(
     98     "receive_response_headers", logger, request, kwargs
     99 ) as trace:
    100     (
    101         http_version,
    102         status,
    103         reason_phrase,
    104         headers,
    105         trailing_data,
--> 106     ) = await self._receive_response_headers(**kwargs)
    107     trace.return_value = (
    108         http_version,
    109         status,
    110         reason_phrase,
    111         headers,
    112     )
    114 network_stream = self._network_stream

File ~/.local/lib/python3.12/site-packages/httpcore/_async/http11.py:177, in AsyncHTTP11Connection._receive_response_headers(self, request)
    174 timeout = timeouts.get("read", None)
    176 while True:
--> 177     event = await self._receive_event(timeout=timeout)
    178     if isinstance(event, h11.Response):
    179         break

File ~/.local/lib/python3.12/site-packages/httpcore/_async/http11.py:217, in AsyncHTTP11Connection._receive_event(self, timeout)
    214     event = self._h11_state.next_event()
    216 if event is h11.NEED_DATA:
--> 217     data = await self._network_stream.read(
    218         self.READ_NUM_BYTES, timeout=timeout
    219     )
    221     # If we feed this case through h11 we'll raise an exception like:
    222     #
    223     #     httpcore.RemoteProtocolError: can't handle event type
   (...)
    227     # perspective. Instead we handle this case distinctly and treat
    228     # it as a ConnectError.
    229     if data == b"" and self._h11_state.their_state == h11.SEND_RESPONSE:

File ~/.local/lib/python3.12/site-packages/httpcore/_backends/anyio.py:35, in AnyIOStream.read(self, max_bytes, timeout)
     33 with anyio.fail_after(timeout):
     34     try:
---> 35         return await self._stream.receive(max_bytes=max_bytes)
     36     except anyio.EndOfStream:  # pragma: nocover
     37         return b""

File ~/.local/lib/python3.12/site-packages/anyio/streams/tls.py:204, in TLSStream.receive(self, max_bytes)
    203 async def receive(self, max_bytes: int = 65536) -> bytes:
--> 204     data = await self._call_sslobject_method(self._ssl_object.read, max_bytes)
    205     if not data:
    206         raise EndOfStream

File ~/.local/lib/python3.12/site-packages/anyio/streams/tls.py:147, in TLSStream._call_sslobject_method(self, func, *args)
    144     if self._write_bio.pending:
    145         await self.transport_stream.send(self._write_bio.read())
--> 147     data = await self.transport_stream.receive()
    148 except EndOfStream:
    149     self._read_bio.write_eof()

File ~/.local/lib/python3.12/site-packages/anyio/_backends/_asyncio.py:1289, in SocketStream.receive(self, max_bytes)
   1283 if (
   1284     not self._protocol.read_event.is_set()
   1285     and not self._transport.is_closing()
   1286     and not self._protocol.is_at_eof
   1287 ):
   1288     self._transport.resume_reading()
-> 1289     await self._protocol.read_event.wait()
   1290     self._transport.pause_reading()
   1291 else:

File /usr/local/python/3.12.1/lib/python3.12/asyncio/locks.py:212, in Event.wait(self)
    210 self._waiters.append(fut)
    211 try:
--> 212     await fut
    213     return True
    214 finally:

CancelledError: 

sample add_owners

domo_group = await DomoGroup.get_by_id(auth=auth, group_id=group_id)

await domo_group.Membership.get_owners()

print(f"validate old ownership {', '.join([str(id) for id in domo_group.owner_id_ls])}")

new_ownership_user = await dmu.DomoUsers.by_id(
    user_ids=[auth.user_id], auth=auth, only_allow_one=False
)

(await domo_group.Membership.add_owners(
        add_owner_ls=new_ownership_user
))[0:5]

sample remove_owners

domo_group = await DomoGroup.get_by_id(auth=auth, group_id=group_id)

try:

    print(
        f"validate old ownership {', '.join([str(id) for id in domo_group.owner_id_ls])}"
    )

    remove_owner = await dmu.DomoUsers.by_id(
        user_ids=[auth.user_id], auth=auth, only_allow_one=False
    )

    print(await domo_group.Membership.remove_owners(remove_owner_ls=remove_owner))

except SearchUser_NoResults as e:
    print(e)

set_ownership

await domo_group.Membership.add_owner_manage_all_groups_role()
domo_group = await DomoGroup.get_by_id(auth=auth, group_id=group_id)

print(
    f"validate old ownership {', '.join([str(id) for id in domo_group.members_id_ls])}"
)

set_ownership = await dmce.gather_with_concurrency(
    n=60,
    *[DomoGroup.get_by_id(group_id=group_id, auth=auth) for group_id in [group_id]],
)

try:
    print(await domo_group.Membership.add_owners(add_owner_ls=set_ownership))


except Exception as e:
    print(e)

Domo Groups


source

DomoGroups

 DomoGroups (auth:domolibrary.client.DomoAuth.DomoAuth,
             is_hide_system_groups:bool=None,
             groups:List[__main__.DomoGroup]=None)

get_all_groups

sample implementation of get all groups

domo_groups = DomoGroups(auth=auth)
(await domo_groups.get())[0:5]
domo_groups = DomoGroups(auth=auth)

await domo_groups.search_by_name(group_name = 'April 2023 Cohort')
domo_group = DomoGroups(auth=auth)

all_groups_with_hidden = await domo_group.get(is_hide_system_groups=True)

all_groups = await domo_group.get(is_hide_system_groups=False)


print(
    f"there are {len(all_groups)} standard groups, and {len(all_groups_with_hidden)} groups including system groups"
)

CRUD Groups

sample upsert

domo_groups =DomoGroups(auth = auth)
try:
    await domo_groups.upsert(
        group_name="test_DO_NOT_DELETE", 
        description=f"updated via upsert_group on {dt.date.today()}",
        debug_api=False
    )

except dmde.DomoError as e:
    print(e)
domo_groups = DomoGroups(auth =auth)
try:
    domo_group = await domo_groups.upsert(
        group_name="hello world",
        description=f"updated via API on {dt.date.today()}",
        debug_api=True

    )

    await domo_group.delete(debug_api=False)

except dmde.DomoError as e:
    print(e)