Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
python -m pip install --upgrade pip
pip install pipenv
pipenv install --dev --deploy --system
pip install requests
pip install urllib3

- name: Run Tests
run: |
Expand Down
2 changes: 1 addition & 1 deletion Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ pylint = "*"
pytest = "*"

[packages]
requests = "*"
urllib3 = "*"

[requires]
599 changes: 239 additions & 360 deletions Pipfile.lock

Large diffs are not rendered by default.

4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ For an overview of the Monday API, [click here](https://developer.monday.com/api

#### Requirements
- Python >= 3.11
- urllib3 >= 2.6.0

#### Getting started
`pip install monday`
Expand Down Expand Up @@ -54,6 +55,3 @@ monday.items.create_item(board_id='12345678', group_id='today', item_name='Do a
<!-- prettier-ignore-end -->

<!-- ALL-CONTRIBUTORS-LIST:END -->

### Bug Reports
TBD
51 changes: 28 additions & 23 deletions docs/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,20 @@ monday

<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->

|All Contributors| A monday.com Python Client Library
|All Contributors|

For an overview of the Monday API, `click
here <https://developer.monday.com/api-reference/docs>`__.
A monday.com Python Client Library

For an overview of the Monday API, `click here <https://developer.monday.com/api-reference/docs>`__.

Requirements
^^^^^^^^^^^^
============

- Python >= 3.11
- Python >= 3.11
- urllib3 >= 2.6.0

Getting started
^^^^^^^^^^^^^^^
===============

``pip install monday``

Expand All @@ -30,11 +32,20 @@ Getting started

monday.items.create_item(board_id='12345678', group_id='today', item_name='Do a thing')

Custom Timeout
--------------

To specify a custom timeout (default: 60 seconds), you can pass the ``timeout`` parameter:

.. code:: python

monday = MondayClient('your token', timeout=120)

Available methods
^^^^^^^^^^^^^^^^^
=================

Items Resource (monday.items)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-----------------------------

- ``create_item(board_id, group_id, item_name, column_values=None, create_labels_if_missing=False)``
- Create an item on a board in the given group with name item_name.
Expand Down Expand Up @@ -71,7 +82,7 @@ Items Resource (monday.items)
- ``delete_item_by_id(item_id)`` - Delete the item by item_id.

Updates Resource (monday.updates)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
---------------------------------

- ``create_update(item_id, update_body)`` - Create an update attached
to a given item.
Expand All @@ -84,14 +95,14 @@ Updates Resource (monday.updates)
set by you. Default is 100 updates

Tags Resource (monday.tags)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
---------------------------

- ``fetch_tags(tag_ids=None)`` - Fetch all tags associated with an
account. Optionally takes a list containing tag ids (if you know
them). Returns IDs, names, and colors.

Boards Resource (monday.boards)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-------------------------------

- ``fetch_boards(**kwargs)`` - Fetch boards associated with an account.
Returns boards and their groups, tags, and columns. Accepts keyword
Expand Down Expand Up @@ -138,14 +149,14 @@ Boards Resource (monday.boards)
with the given name and kind by (and optional) workspace id.

Users Resource (monday.users)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-----------------------------

- ``fetch_users(**kwargs)`` - Fetch user information associated with an
account. See Monday API docs for a list of accepted keyword
arguments.

Workspaces Resource (monday.workspaces)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
---------------------------------------

- ``get_workspaces()`` - Get all workspaces.

Expand All @@ -165,7 +176,7 @@ Workspaces Resource (monday.workspaces)
given teams from the given workspace.

Groups Resource (monday.groups)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-------------------------------

- ``get_groups_by_board([board_ids])`` - Get all groups associated with
a certain board or boards. Accepts a single id or a comma separated
Expand All @@ -187,21 +198,21 @@ Groups Resource (monday.groups)
board.

Notifications Resource (monday.notifications)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
---------------------------------------------

- ``create_notification(user_id, target_id, text, target_type)`` - The
create_notification mutation allows to trigger a notification within
the platform (will also send out an email if the recipient’s email
preferences are set up accordingly).

Additional Resources and Code Samples
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-------------------------------------

- `Read and format all of the items on a
board <https://github.com/ProdPerfect/monday/wiki/Code-Examples#whole-board-formatting-example>`__

Contributors
------------
============

.. raw:: html

Expand Down Expand Up @@ -369,11 +380,5 @@ Taylor Cochran💻

<!-- ALL-CONTRIBUTORS-LIST:END -->

Bug Reports
~~~~~~~~~~~

TBD

.. |All Contributors| image:: https://img.shields.io/badge/all_contributors-9-orange.svg?style=flat-square
:target: #contributors-

41 changes: 28 additions & 13 deletions monday/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,26 @@
"""

from .__version__ import __version__
from .resources import CustomResource, ItemResource, ColumnsResource, UpdateResource, TagResource, BoardResource, \
UserResource, GroupResource, ComplexityResource, WorkspaceResource, NotificationResource, MeResource
from .resources import (
BoardResource,
ColumnsResource,
ComplexityResource,
CustomResource,
GroupResource,
ItemResource,
MeResource,
NotificationResource,
TagResource,
UpdateResource,
UserResource,
WorkspaceResource,
)

_DEFAULT_HEADERS = {"API-Version": "2026-01"}

_DEFAULT_HEADERS = {
"API-Version": "2026-01"
}

DEFAULT_TIMEOUT = 60

class MondayClient:
def __init__(self, token, headers=None, timeout=DEFAULT_TIMEOUT):
def __init__(self, token, headers=None, timeout=None):
"""
:param token: API token for the new :class:`BaseResource` object.
:param headers: (optional) headers for the new :class:`BaseResource` object.
Expand All @@ -34,13 +43,19 @@ def __init__(self, token, headers=None, timeout=DEFAULT_TIMEOUT):
self.boards = BoardResource(token=token, headers=headers, timeout=timeout)
self.users = UserResource(token=token, headers=headers, timeout=timeout)
self.groups = GroupResource(token=token, headers=headers, timeout=timeout)
self.complexity = ComplexityResource(token=token, headers=headers, timeout=timeout)
self.workspaces = WorkspaceResource(token=token, headers=headers, timeout=timeout)
self.notifications = NotificationResource(token=token, headers=headers, timeout=timeout)
self.complexity = ComplexityResource(
token=token, headers=headers, timeout=timeout
)
self.workspaces = WorkspaceResource(
token=token, headers=headers, timeout=timeout
)
self.notifications = NotificationResource(
token=token, headers=headers, timeout=timeout
)
self.me = MeResource(token=token, headers=headers, timeout=timeout)

def __str__(self):
return f'MondayClient {__version__}'
return f"MondayClient {__version__}"

def __repr__(self):
return f'MondayClient {__version__}'
return f"MondayClient {__version__}"
7 changes: 7 additions & 0 deletions monday/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
TOKEN_HEADER = "Authorization"

DEFAULT_TIMEOUT = 60

DEFAULT_PAGE_LIMIT_ITEMS = 500

HTTP_MAX_SIZE = 10
71 changes: 40 additions & 31 deletions monday/graphqlclient/client.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
import json
import requests

from monday.exceptions import MondayQueryError

TOKEN_HEADER = 'Authorization'
import urllib3

DEFAULT_TIMEOUT = 60

DEFAULT_PAGE_LIMIT_ITEMS = 500
from monday.constants import DEFAULT_TIMEOUT, HTTP_MAX_SIZE, TOKEN_HEADER
from monday.exceptions import MondayQueryError


class GraphQLClient:
Expand All @@ -16,6 +12,7 @@ def __init__(self, endpoint, timeout=DEFAULT_TIMEOUT):
self.timeout = timeout
self.token = None
self.headers = {}
self._http = urllib3.PoolManager(maxsize=HTTP_MAX_SIZE)

def execute(self, query, variables=None):
return self._send(query, variables)
Expand All @@ -27,34 +24,46 @@ def inject_headers(self, headers):
self.headers = headers

def _send(self, query, variables):
payload = {'query': query}
headers = self.headers.copy()
files = None

if self.token is not None:
headers[TOKEN_HEADER] = self.token

if variables is None:
headers.setdefault('Content-Type', 'application/json')

payload = json.dumps({'query': query}).encode('utf-8')

elif variables.get('file', None) is not None:
headers.setdefault('content', 'multipart/form-data')

files = [
('variables[file]', (variables['file'], open(variables['file'], 'rb')))
]

try:
response = requests.request("POST", self.endpoint, headers=headers, data=payload, files=files, timeout=self.timeout)
response.raise_for_status()
response_data = response.json()
self._throw_on_error(response_data)
return response_data
except (requests.HTTPError, json.JSONDecodeError, MondayQueryError) as e:
raise e
if variables is not None and variables.get("file") is not None:
file_path = variables["file"]
with open(file_path, "rb") as f:
file_data = f.read()

response = self._http.request(
"POST",
self.endpoint,
headers=headers,
fields={"query": query, "variables[file]": (file_path, file_data)},
timeout=self.timeout,
)
else:
headers.setdefault("Content-Type", "application/json")
body = json.dumps({"query": query}).encode("utf-8")

response = self._http.request(
"POST",
self.endpoint,
headers=headers,
body=body,
timeout=self.timeout,
)

if response.status >= 400:
raise urllib3.exceptions.HTTPError(
f"HTTP {response.status}: {response.data.decode('utf-8')}"
)

response_data = json.loads(response.data.decode("utf-8"))
self._throw_on_error(response_data)
return response_data

def _throw_on_error(self, response_data):
if 'errors' in response_data:
raise MondayQueryError(response_data['errors'][0]['message'], response_data['errors'])
if "errors" in response_data:
raise MondayQueryError(
response_data["errors"][0]["message"], response_data["errors"]
)
9 changes: 6 additions & 3 deletions monday/resources/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@


class BaseResource:
def __init__(self, token, headers, timeout):
def __init__(self, token, headers, timeout=None):
self._token = token
self.client = GraphQLClient(_URLS['prod'], timeout=timeout)
self.file_upload_client = GraphQLClient(_URLS['file'], timeout=timeout)
kwargs = {}
if timeout is not None:
kwargs['timeout'] = timeout
self.client = GraphQLClient(_URLS['prod'], **kwargs)
self.file_upload_client = GraphQLClient(_URLS['file'], **kwargs)
self.client.inject_token(token)
self.client.inject_headers(headers)
self.file_upload_client.inject_token(token)
Expand Down
Loading
Loading