appdb

auth = dmda.DomoAuth(
    domo_instance=os.environ["DOMO_INSTANCE"],
    access_token=os.environ["DOMO_ACCESS_TOKEN"],
)
auth
DomoAuth(domo_instance='domo-community', username=None)
collection_id = '0f68f250-df2c-4a15-98ef-9cdd851602eb'

Routes


source

AppDb_API_Exception

 AppDb_API_Exception (res, message=None)

Common base class for all non-exit exceptions.

Exported source
class AppDb_API_Exception(dmda.API_Exception):
    def __init__(self, res, message=None):

        super().__init__(res=res, message=message)

source

get_collections

 get_collections (auth:mbison.client.core.DomoAuth, debug_api:bool=False,
                  datastore_id:str=None)

retrieve collections

Type Default Details
auth DomoAuth
debug_api bool False
datastore_id str None filters for a specific datastoreId
Exported source
def get_collections(
    auth: dmda.DomoAuth,
    debug_api: bool = False,
    datastore_id : str = None, # filters for a specific datastoreId
):
    """retrieve collections"""

    endpoint = f"/api/datastores/v1/collections/"

    res =  dmda.domo_api_request(
        auth=auth,
        request_type="GET",
        endpoint= endpoint,
        debug_api=debug_api,
        params = {'datastoreId': datastore_id}
    )

    if not res.is_success and res.status == 400:
        raise AppDb_API_Exception(res, message = f"invalid datastoreId  - {datastore_id}?")

    if not res.is_success:
        raise AppDb_API_Exception(res)
    
    return res
res = get_collections(auth=auth, debug_api= False,
                    #   datastore_id = datastore_id
                      )
collections = res.response
collections[0:1]
[{'id': '3e6ba7a6-9261-44fd-8eef-987fdbb99e18',
  'datastoreId': 'de230a76-bc70-404e-b3f4-a6f7dea45723',
  'defaultPermissions': None,
  'requiredAuthorities': None,
  'owner': 826020125,
  'name': 'ColumnConfig',
  'datasourceId': None,
  'schema': None,
  'filters': None,
  'syncEnabled': False,
  'syncRequired': False,
  'fullReplaceRequired': False,
  'lastSync': None,
  'createdOn': '2020-11-20T17:58:42.550Z',
  'updatedOn': '2023-02-14T20:17:27.920Z',
  'updatedBy': 826020125}]

source

get_collection_by_id

 get_collection_by_id (auth:mbison.client.core.DomoAuth,
                       collection_id:str, debug_api:bool=False)
Exported source
def get_collection_by_id(
    auth: dmda.DomoAuth,
    collection_id : str,
    debug_api: bool = False,
):

    endpoint = f"/api/datastores/v1/collections/{collection_id}"

    res =  dmda.domo_api_request(
        auth=auth,
        request_type="GET",
        endpoint= endpoint,
        debug_api=debug_api,
    )

    if not res.is_success:
        raise AppDb_API_Exception(res)
    
    return res
res = get_collection_by_id(auth=auth, debug_api= False, 
                        #    collection_id =  collections[0]['id']
                           collection_id = '0f68f250-df2c-4a15-98ef-9cdd851602eb'
                             )

collection = res.response
collection
{'id': '0f68f250-df2c-4a15-98ef-9cdd851602eb',
 'datastoreId': '6aa87886-9167-4191-8491-c9b5bc8bece5',
 'defaultPermissions': 'read,read_content',
 'requiredAuthorities': {'CREATE': ['domoapps.edit'],
  'CREATE_CONTENT': ['domoapps.edit'],
  'DELETE': ['domoapps.edit'],
  'DELETE_CONTENT': ['domoapps.edit'],
  'UPDATE': ['domoapps.edit'],
  'UPDATE_CONTENT': ['domoapps.edit']},
 'owner': 1893952720,
 'name': 'ddx_app_client_code',
 'datasourceId': None,
 'schema': None,
 'filters': None,
 'syncEnabled': False,
 'syncRequired': False,
 'fullReplaceRequired': False,
 'lastSync': None,
 'createdOn': '2024-05-30T07:45:21.869Z',
 'updatedOn': '2024-05-30T07:45:21.869Z',
 'updatedBy': 1893952720}

source

query_collection_documents

 query_collection_documents (auth:mbison.client.core.DomoAuth,
                             collection_id:str, query:dict=None,
                             debug_api:bool=False)
Exported source
def query_collection_documents(
    auth: dmda.DomoAuth,
    collection_id: str,
    query : dict = None,
    debug_api : bool = False
):
    endpoint = f'/api/datastores/v2/collections/{collection_id}/documents/query'

    query = query or {}

    res =  dmda.domo_api_request(
        auth=auth,
        request_type="POST",
        endpoint= endpoint,
        debug_api=debug_api,
        body = query
    )

    if not res.is_success:
        raise AppDb_API_Exception(res)
    
    return res
res = query_collection_documents(auth=auth,
                                 debug_api= False,
                                 collection_id = collection['id']
                                 )

documents = res.response
documents
[{'id': '302663f9-c0bc-4413-894a-3075711b3600',
  'datastoreId': '6aa87886-9167-4191-8491-c9b5bc8bece5',
  'collectionId': '0f68f250-df2c-4a15-98ef-9cdd851602eb',
  'syncRequired': True,
  'owner': '1893952720',
  'createdBy': '1893952720',
  'createdOn': '2024-05-30T07:45:25.355Z',
  'updatedOn': '2024-05-30T10:14:07.365Z',
  'updatedBy': '1893952720',
  'content': {'htmlEasy': {'js': 'fakeEmail = "ar@test.com";\r\n// fakeEmail = domo.env.userEmail;\r\n\r\n//Available globals\r\nvar domo = window.domo; // For more on domo.js: https://developer.domo.com/docs/dev-studio-guides/domo-js#domo.get\r\nvar datasets = window.datasets;\r\n\r\nlet whoami = domo.env.userId\r\nconsole.log(whoami)\r\nwhoami = 612085674 //noah\r\n\r\nSQL_activityLog = "select `SOURCE_ID` as user_id, `Object_ID` as page_id, count(*) as viewCount FROM dataset1 where `Action` = \'VIEWED\' and `Object_Type` = \'PAGE\' and `SOURCE_ID` = \'" + whoami +"\'  GROUP BY `Object_ID`, `Source_ID` ORDER BY count(*)"\r\n\r\nfunction mergeRowsColumns(rows, columns) {\r\n  return rows.map((row) => {\r\n    let obj = {};\r\n    row.forEach((item, index) => {\r\n      obj[columns[index]] = item;\r\n    });\r\n    return obj;\r\n  });\r\n}\r\n\r\nconst get_data = async (sql_str, dataset_alias) => {\r\n  api_str = `/sql/v1/${dataset_alias}`;\r\n  console.log(api_str, sql_str);\r\n\r\n  res = await domo.post(api_str, sql_str, { contentType: "text/plain" });\r\n\r\n  return mergeRowsColumns((rows = res.rows), (columns = res.columns));\r\n};\r\n\r\nconst paint_links = (links)=> {\r\n  return links.reduce( (accum, link) =>  {\r\n    accum += `<div >${link.page_id}<div>`\r\n    return accum } \r\n    , "")\r\n}\r\n\r\nconst main = async () => {\r\n  const whodiv = document.getElementById(\'whoami\')\r\n  whodiv.innerHTML = whoami\r\n  \r\n  const mydiv = document.getElementById(\'myDiv\')\r\n  \r\n  const data = await get_data(sql_str = SQL_activityLog, \'dataset1\')\r\n  console.log(mydiv)\r\n  mydiv.innerHTML = paint_links(data)\r\n}\r\n\r\nmain()',
    'html': '<div>\n  <div id = "whoami"/>\n  <div id = "myDiv" />\n</div>',
    'css': '#myDiv {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  background: rgb(131,58,180);\n\tbackground: linear-gradient(90deg, rgba(121,64,161,1) 0%, rgba(228,88,80,1) 50%, rgba(251,141,52,1) 100%);\n  height: calc(100vh);\n}\n\nh1 {\n  color: white;\n}'}}}]

source

get_collection_document_by_id

 get_collection_document_by_id (auth:mbison.client.core.DomoAuth,
                                collection_id:str, document_id:str,
                                query:dict=None, debug_api:bool=False)
Exported source
def get_collection_document_by_id(
    auth: dmda.DomoAuth,
    collection_id: str,
    document_id : str,
    query : dict = None,
    debug_api : bool = False
):
    endpoint = f'/api/datastores/v2/collections/{collection_id}/documents/{document_id}'

    query = query or {}

    res =  dmda.domo_api_request(
        auth=auth,
        request_type="GET",
        endpoint= endpoint,
        debug_api=debug_api,
        body = query
    )

    if not res.is_success:
        raise AppDb_API_Exception(res)
    
    return res
res = get_collection_document_by_id(auth=auth,
                                 debug_api= False,
                                 collection_id = documents[0]['collectionId'],
                                 document_id = documents[0]['id']
                                 )

document = res.response
document
{'id': '302663f9-c0bc-4413-894a-3075711b3600',
 'datastoreId': '6aa87886-9167-4191-8491-c9b5bc8bece5',
 'collectionId': '0f68f250-df2c-4a15-98ef-9cdd851602eb',
 'syncRequired': True,
 'owner': '1893952720',
 'createdBy': '1893952720',
 'createdOn': '2024-05-30T07:45:25.355Z',
 'updatedOn': '2024-05-30T10:14:07.365Z',
 'updatedBy': '1893952720',
 'content': {'htmlEasy': {'js': 'fakeEmail = "ar@test.com";\r\n// fakeEmail = domo.env.userEmail;\r\n\r\n//Available globals\r\nvar domo = window.domo; // For more on domo.js: https://developer.domo.com/docs/dev-studio-guides/domo-js#domo.get\r\nvar datasets = window.datasets;\r\n\r\nlet whoami = domo.env.userId\r\nconsole.log(whoami)\r\nwhoami = 612085674 //noah\r\n\r\nSQL_activityLog = "select `SOURCE_ID` as user_id, `Object_ID` as page_id, count(*) as viewCount FROM dataset1 where `Action` = \'VIEWED\' and `Object_Type` = \'PAGE\' and `SOURCE_ID` = \'" + whoami +"\'  GROUP BY `Object_ID`, `Source_ID` ORDER BY count(*)"\r\n\r\nfunction mergeRowsColumns(rows, columns) {\r\n  return rows.map((row) => {\r\n    let obj = {};\r\n    row.forEach((item, index) => {\r\n      obj[columns[index]] = item;\r\n    });\r\n    return obj;\r\n  });\r\n}\r\n\r\nconst get_data = async (sql_str, dataset_alias) => {\r\n  api_str = `/sql/v1/${dataset_alias}`;\r\n  console.log(api_str, sql_str);\r\n\r\n  res = await domo.post(api_str, sql_str, { contentType: "text/plain" });\r\n\r\n  return mergeRowsColumns((rows = res.rows), (columns = res.columns));\r\n};\r\n\r\nconst paint_links = (links)=> {\r\n  return links.reduce( (accum, link) =>  {\r\n    accum += `<div >${link.page_id}<div>`\r\n    return accum } \r\n    , "")\r\n}\r\n\r\nconst main = async () => {\r\n  const whodiv = document.getElementById(\'whoami\')\r\n  whodiv.innerHTML = whoami\r\n  \r\n  const mydiv = document.getElementById(\'myDiv\')\r\n  \r\n  const data = await get_data(sql_str = SQL_activityLog, \'dataset1\')\r\n  console.log(mydiv)\r\n  mydiv.innerHTML = paint_links(data)\r\n}\r\n\r\nmain()',
   'html': '<div>\n  <div id = "whoami"/>\n  <div id = "myDiv" />\n</div>',
   'css': '#myDiv {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  background: rgb(131,58,180);\n\tbackground: linear-gradient(90deg, rgba(121,64,161,1) 0%, rgba(228,88,80,1) 50%, rgba(251,141,52,1) 100%);\n  height: calc(100vh);\n}\n\nh1 {\n  color: white;\n}'}}}

Classes


source

AppDbDocument

 AppDbDocument (auth:mbison.client.core.DomoAuth, _collection_id:str,
                _identity_columns:List[str], _id:str=None,
                _created_on_dt:datetime.datetime=None,
                _updated_on_dt:datetime.datetime=None, content:dict=None)
Exported source
def to_json(value):
    """
    converts complex dictionaries with nested classes to dictionary.
    assumes nested classes have a `to_json` method
    """

    if hasattr(value, "to_json"):
        return value.to_json()

    if isinstance(value, dict):
        return {key: to_json(v) for key, v in value.items()}

    if isinstance(value, list):
        return [to_json(v) for v in value]

    if isinstance(value, Number):
        return value

    return str(value)


@dataclass
class AppDbDocument:

    auth: dmda.DomoAuth = field(repr=False)

    # document metadata
    _collection_id: str
    _identity_columns: List[str]
    _id: str = None
    _created_on_dt: dt.datetime = None
    _updated_on_dt: dt.datetime = None

    content: dict = None

    def to_json(self):
        # TO DO - this is not a complete recursive implementation,  may need revision for complex dictionaries
        self.update_config()

        s = {"id": self._id, "collectionId": self._collection_id}

        for key, value in self.__dict__.items():
            if key.startswith("_") or key in ["auth"]:
                continue

            s.update({key: to_json(value)})

        return s

    def __eq__(self, other):
        if self.__class__.__name__ != other.__class__.__name__:
            return False

        if self._identity_columns:
            return all(
                getattr(self, col) == getattr(other.col)
                for col in self._identity_columns
            )

        return self._id == other._id

    @classmethod
    def _from_json(
        cls,
        auth: dmda.DomoAuth,
        content,
        new_cls,
        identity_columns,
        collection_id=None,
        document_id=None,
        metadata=None,
        created_on_dt=None,
        updated_on_dt=None,
    ):

        if metadata:
            collection_id = metadata.pop("collectionId")

            created_on_dt = dmut.convert_string_to_datetime(metadata.pop("createdOn"))

            updated_on_dt = dmut.convert_string_to_datetime(metadata.pop("updatedOn"))
            document_id = metadata["id"]

        return new_cls(
            auth=auth,
            _id=document_id,
            _identity_columns=identity_columns,
            _collection_id=collection_id,
            _created_on_dt=created_on_dt,
            _updated_on_dt=updated_on_dt,
            content=content,
            **(content if cls.__name__ != "AppDbDocument" else {})
        )

    @classmethod
    def _from_api(
        cls,
        auth: dmda.DomoAuth,
        obj,
        identity_columns: List[str] = None,
    ):
        content = obj.pop("content")

        return cls._from_json(
            auth=auth,
            content=content,
            new_cls=cls,
            identity_columns=identity_columns,
            metadata=obj,
        )

    @classmethod
    def from_json(
        cls,
        auth: dmda.DomoAuth,
        collection_id: str,
        content: dict,
        identity_columns: List[str] = None,
    ):
        return cls._from_json(
            auth=auth,
            content=content,
            new_cls=cls,
            identity_columns=identity_columns,
            collection_id=collection_id,
        )

    def update_config(self):
        self.content = {
            key: value
            for key, value in self.__dict__.items()
            if key not in ["auth", "content"] and not key.startswith("_")
        }
        return self.content

    @classmethod
    def get_by_id(
        cls,
        collection_id: str,
        document_id: str,
        auth: dmda.DomoAuth,
        identity_columns=None,
        debug_api: bool = False,
        return_raw: bool = False,
    ):
        res = get_collection_document_by_id(
            auth=auth,
            collection_id=collection_id,
            document_id=document_id,
            debug_api=debug_api,
        )

        if return_raw:
            return res

        return cls._from_api(
            auth=auth,
            obj=res.response,
            identity_columns=identity_columns or [],
        )

source

to_json

 to_json (value)

converts complex dictionaries with nested classes to dictionary. assumes nested classes have a to_json method

AppDbDocument.get_by_id(
    auth = auth,
    debug_api= False,
    collection_id = document['collectionId'],
    document_id = document['id'])
AppDbDocument(_collection_id='0f68f250-df2c-4a15-98ef-9cdd851602eb', _identity_columns=[], _id='302663f9-c0bc-4413-894a-3075711b3600', _created_on_dt=datetime.datetime(2024, 5, 30, 7, 45, 25, 355000, tzinfo=tzutc()), _updated_on_dt=datetime.datetime(2024, 5, 30, 10, 14, 7, 365000, tzinfo=tzutc()), content={'htmlEasy': {'js': 'fakeEmail = "ar@test.com";\r\n// fakeEmail = domo.env.userEmail;\r\n\r\n//Available globals\r\nvar domo = window.domo; // For more on domo.js: https://developer.domo.com/docs/dev-studio-guides/domo-js#domo.get\r\nvar datasets = window.datasets;\r\n\r\nlet whoami = domo.env.userId\r\nconsole.log(whoami)\r\nwhoami = 612085674 //noah\r\n\r\nSQL_activityLog = "select `SOURCE_ID` as user_id, `Object_ID` as page_id, count(*) as viewCount FROM dataset1 where `Action` = \'VIEWED\' and `Object_Type` = \'PAGE\' and `SOURCE_ID` = \'" + whoami +"\'  GROUP BY `Object_ID`, `Source_ID` ORDER BY count(*)"\r\n\r\nfunction mergeRowsColumns(rows, columns) {\r\n  return rows.map((row) => {\r\n    let obj = {};\r\n    row.forEach((item, index) => {\r\n      obj[columns[index]] = item;\r\n    });\r\n    return obj;\r\n  });\r\n}\r\n\r\nconst get_data = async (sql_str, dataset_alias) => {\r\n  api_str = `/sql/v1/${dataset_alias}`;\r\n  console.log(api_str, sql_str);\r\n\r\n  res = await domo.post(api_str, sql_str, { contentType: "text/plain" });\r\n\r\n  return mergeRowsColumns((rows = res.rows), (columns = res.columns));\r\n};\r\n\r\nconst paint_links = (links)=> {\r\n  return links.reduce( (accum, link) =>  {\r\n    accum += `<div >${link.page_id}<div>`\r\n    return accum } \r\n    , "")\r\n}\r\n\r\nconst main = async () => {\r\n  const whodiv = document.getElementById(\'whoami\')\r\n  whodiv.innerHTML = whoami\r\n  \r\n  const mydiv = document.getElementById(\'myDiv\')\r\n  \r\n  const data = await get_data(sql_str = SQL_activityLog, \'dataset1\')\r\n  console.log(mydiv)\r\n  mydiv.innerHTML = paint_links(data)\r\n}\r\n\r\nmain()', 'html': '<div>\n  <div id = "whoami"/>\n  <div id = "myDiv" />\n</div>', 'css': '#myDiv {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  background: rgb(131,58,180);\n\tbackground: linear-gradient(90deg, rgba(121,64,161,1) 0%, rgba(228,88,80,1) 50%, rgba(251,141,52,1) 100%);\n  height: calc(100vh);\n}\n\nh1 {\n  color: white;\n}'}})

source

AppDbCollection

 AppDbCollection (auth:mbison.client.core.DomoAuth, id:str, name:str,
                  created_on_dt:datetime.datetime,
                  updated_on_dt:datetime.datetime, schema:dict,
                  domo_documents:List[__main__.AppDbDocument]=None)
Exported source
@dataclass
class AppDbCollection:
    auth: dmda.DomoAuth = field(repr=False)
    id: str
    name: str

    created_on_dt: dt.datetime
    updated_on_dt: dt.datetime

    schema: dict

    domo_documents: List[AppDbDocument] = None

    @classmethod
    def _from_json(cls, auth, obj):

        return cls(
            auth=auth,
            id=obj["id"],
            name=obj["name"],
            created_on_dt=dmut.convert_string_to_datetime(obj["createdOn"]),
            updated_on_dt=dmut.convert_string_to_datetime(obj["updatedOn"]),
            schema=obj["schema"],
        )

    @classmethod
    def get_by_id(
        cls,
        auth: dmda.DomoAuth,
        collection_id,
        debug_api: bool = False,
        return_raw: bool = False,
    ):

        res = get_collection_by_id(
            auth=auth,
            collection_id=collection_id,
            debug_api=debug_api,
        )

        if return_raw:
            return res

        return cls._from_json(auth=auth, obj=res.response)

    def query_documents(
        self,
        debug_api: bool = False,
        query: dict=None,
        return_raw: bool = False,
    ):

        res = query_collection_documents(
            auth=self.auth,
            collection_id=self.id,
            debug_api=debug_api,
            query=query,
        )

        if return_raw:
            return res

        self.domo_documents = [
                AppDbDocument.get_by_id(
                    collection_id=self.id,
                    document_id=doc["id"], auth=self.auth
                )
                for doc in res.response
            ]
        
        return self.domo_documents

    def __eq__(self, other):
        if not isinstance(other, AppDbCollection):
            return False

        return self.id == other.id
domo_collection = AppDbCollection.get_by_id(auth = auth, 
                          collection_id= document['collectionId'],
                          debug_api= False
                          )

domo_collection.query_documents()
[AppDbDocument(_collection_id='0f68f250-df2c-4a15-98ef-9cdd851602eb', _identity_columns=[], _id='302663f9-c0bc-4413-894a-3075711b3600', _created_on_dt=datetime.datetime(2024, 5, 30, 7, 45, 25, 355000, tzinfo=tzutc()), _updated_on_dt=datetime.datetime(2024, 5, 30, 10, 14, 7, 365000, tzinfo=tzutc()), content={'htmlEasy': {'js': 'fakeEmail = "ar@test.com";\r\n// fakeEmail = domo.env.userEmail;\r\n\r\n//Available globals\r\nvar domo = window.domo; // For more on domo.js: https://developer.domo.com/docs/dev-studio-guides/domo-js#domo.get\r\nvar datasets = window.datasets;\r\n\r\nlet whoami = domo.env.userId\r\nconsole.log(whoami)\r\nwhoami = 612085674 //noah\r\n\r\nSQL_activityLog = "select `SOURCE_ID` as user_id, `Object_ID` as page_id, count(*) as viewCount FROM dataset1 where `Action` = \'VIEWED\' and `Object_Type` = \'PAGE\' and `SOURCE_ID` = \'" + whoami +"\'  GROUP BY `Object_ID`, `Source_ID` ORDER BY count(*)"\r\n\r\nfunction mergeRowsColumns(rows, columns) {\r\n  return rows.map((row) => {\r\n    let obj = {};\r\n    row.forEach((item, index) => {\r\n      obj[columns[index]] = item;\r\n    });\r\n    return obj;\r\n  });\r\n}\r\n\r\nconst get_data = async (sql_str, dataset_alias) => {\r\n  api_str = `/sql/v1/${dataset_alias}`;\r\n  console.log(api_str, sql_str);\r\n\r\n  res = await domo.post(api_str, sql_str, { contentType: "text/plain" });\r\n\r\n  return mergeRowsColumns((rows = res.rows), (columns = res.columns));\r\n};\r\n\r\nconst paint_links = (links)=> {\r\n  return links.reduce( (accum, link) =>  {\r\n    accum += `<div >${link.page_id}<div>`\r\n    return accum } \r\n    , "")\r\n}\r\n\r\nconst main = async () => {\r\n  const whodiv = document.getElementById(\'whoami\')\r\n  whodiv.innerHTML = whoami\r\n  \r\n  const mydiv = document.getElementById(\'myDiv\')\r\n  \r\n  const data = await get_data(sql_str = SQL_activityLog, \'dataset1\')\r\n  console.log(mydiv)\r\n  mydiv.innerHTML = paint_links(data)\r\n}\r\n\r\nmain()', 'html': '<div>\n  <div id = "whoami"/>\n  <div id = "myDiv" />\n</div>', 'css': '#myDiv {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  background: rgb(131,58,180);\n\tbackground: linear-gradient(90deg, rgba(121,64,161,1) 0%, rgba(228,88,80,1) 50%, rgba(251,141,52,1) 100%);\n  height: calc(100vh);\n}\n\nh1 {\n  color: white;\n}'}})]