Skip to content

Board

Bases: Board_

Interface for interacting with planka Boards and their included sub-objects

Note

All implemented public properties return API responses with accessed. This means that the values are not cached and will be updated on every access. If you wish to cache values, you are responsible for doing so. By default, property access will always provide the most up to date information.

Source code in src/plankapy/interfaces.py
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
class Board(Board_):
    """Interface for interacting with planka Boards and their included sub-objects

    Note:
        All implemented public properties return API responses with accessed. This means that the values are not cached 
        and will be updated on every access. If you wish to cache values, you are responsible for doing so. By default, 
        property access will always provide the most up to date information. 
    """

    roles = BoardRole.__args__

    @property
    def _included(self) -> JSONHandler.JSONResponse:
        """Included data for the board

        Warning:
            This property is meant to be used internally for building objects in the other properties
            It can be directly accessed, but it will only return JSON data and not objects

        Returns:
            Included data for the board
        """
        route = self.routes.get_board(id=self.id)
        return route()['included']

    @property
    def project(self) -> Project:
        """Project the board belongs to

        Note:
            All objects include a reference to their parent object and parent objects include a reference to their children
            This means that you can traverse the entire API structure from any object

        Returns:
            Project: Project instance
        """
        project_route = self.routes.get_project(id=self.projectId)
        return Project(**project_route()['item']).bind(self.routes)

    @property
    def users(self) -> QueryableList[User]:
        """All users in the board

        Returns:
            Queryable List of all users
        """
        return QueryableList([
            User(**user).bind(self.routes)
            for user in self._included['users']
        ])

    @property
    def editors(self) -> QueryableList[User]:
        """All users that can edit the board

        Returns:
            Queryable List of all editors
        """
        return QueryableList([
            user
            for user in self.users
            for boardMembership in self.boardMemberships
            if boardMembership.userId == user.id and boardMembership.role == 'editor'
        ])

    @property
    def viewers(self) -> QueryableList[User]:
        """All users that can view the board

        Returns:
            Queryable List of all viewers
        """
        return QueryableList([
            user
            for user in self.users
            for boardMembership in self.boardMemberships
            if boardMembership.userId == user.id and boardMembership.role == 'viewer'
        ])

    @property
    def boardMemberships(self) -> QueryableList[BoardMembership]:
        """All board memberships

        Note:
            This property is primarily here for internal use, '.editor' and '.viewer' properties 
            are derived from the board memberships

        Returns:
            Queryable List of all membership types (editor, viewer)
        """
        return QueryableList([
            BoardMembership(**boardMembership).bind(self.routes)
            for boardMembership in self._included['boardMemberships']
        ])

    @property
    def labels(self) -> QueryableList[Label]:
        """All labels in the board

        Returns:
            Queryable List of all labels in the board
        """
        return QueryableList([
            Label(**label).bind(self.routes)
            for label in self._included['labels']
        ])

    @property
    def lists(self) -> QueryableList[List]:
        """All lists in the board

        Returns:
            Queryable List of all lists in the board
        """
        return QueryableList([
            List(**_list).bind(self.routes)
            for _list in self._included['lists']
        ])

    @property
    def cards(self) -> QueryableList[Card]:
        """All cards in the board

        Returns:
            A list of all cards in the board
        """
        return QueryableList([
            Card(**card).bind(self.routes)
            for card in self._included['cards']
        ])

    @property
    def cardMemberships(self) -> QueryableList[CardMembership]:
        """All card -> user relationships in the board

        Note:
            This property is used by the `Card` class to determine its users

        Returns:
            A list of all card memberships in the board
        """
        return QueryableList([
            CardMembership(**cardMembership).bind(self.routes)
            for cardMembership in self._included['cardMemberships']
        ])

    @property
    def cardLabels(self) -> QueryableList[CardLabel]:
        """All card -> label relationships in the board

        Note:
            This property is used by the `Card` class to determine its labels

        Returns:
            A list of all card labels in the board
        """
        return QueryableList([
            CardLabel(**cardLabel).bind(self.routes)
            for cardLabel in self._included['cardLabels']
        ])

    @property
    def tasks(self) -> QueryableList[Task]:
        """All tasks in the board

        Note:
            This property is used by the `Card` class to determine its tasks

        Returns:
            A list of all card tasks in the board
        """
        return QueryableList([
            Task(**task).bind(self.routes)
            for task in self._included['tasks']
        ])

    @property
    def attachments(self) -> QueryableList[Attachment]:
        """All attachments in the board

        Note:
            This property is used by the `Card` class to determine its attachments

        Returns:
            A list of all card attachments in the board
        """
        return QueryableList([
            Attachment(**attachment).bind(self.routes)
            for attachment in self._included['attachments']
        ])

    @overload
    def create_list(self, _list: List) -> List: ...

    @overload
    def create_list(self, name: str, position: int) -> List: ...

    def create_list(self, *args, **kwargs) -> List:
        """Creates a new list in the board

        Args:
            name (str): Name of the list (required)
            position (int): Position of the list (default: 0)

        Args: Alternate
            list (List): List instance to create

        Returns:
            List: New list instance

        Example:
            ```python
            >>> new_list = board.create_list('My List')

            >>> l = List(name='My List', position=0)
            >>> new_list2 = board.create_list(l)
            ```
        """
        overload = parse_overload(args, kwargs, model='list', 
                                  options=('name', 'position'), 
                                  required=('name',))

        overload['position'] = overload.get('position', 0)
        overload['boardId'] = self.id

        route = self.routes.post_list(boardId=self.id)
        return List(**route(**overload)['item']).bind(self.routes)

    @overload
    def create_label(self, label: Label) -> Label: ...

    @overload
    def create_label(self, name: str, position: int=0, color: LabelColor=None) -> Label: ...

    def create_label(self, *args, **kwargs) -> Label:
        """Creates a new label in the board

        Args:
            name (str): Name of the label (required)
            position (int): Position of the label (default: 0)
            color (LabelColor): Color of the label (default: "berry-red")

        Args: Alternate
            label (Label): Label instance to create

        Returns:
            Label: New label instance

        Example:
            ```python
            >>> new_label = board.create_label('My Label')
            >>> label = Label(name='My Label', position=0, color='wet-moss')
            >>> new_label2 = board.create_label(label)
            ```
        """
        overload = parse_overload(args, kwargs, model='label', 
                                  options=('name', 'position', 'color'), 
                                  required=('name',)) # Only name requires user provided value

        # Required arguments with defaults must be manually assigned
        overload['position'] = overload.get('position', 0)
        overload['color'] = overload.get('color', choice(LabelColor.__args__))
        overload['boardId'] = self.id

        route = self.routes.post_label(boardId=self.id)
        return Label(**route(**overload)['item']).bind(self.routes)

    def add_user(self, user: User, role: BoardRole='viewer', canComment: bool=False) -> BoardMembership:
        """Adds a user to the board

        Args:
            user (User): User instance to add
            canComment (bool): Whether the user can comment on the board (default: False)

        Returns:
            BoardMembership: New board membership

        Raises:
            ValueError: If the role is invalid (must be 'viewer' or 'editor')
        """
        if role not in self.roles:
            raise ValueError(f'Invalid role: {role}')

        if role == 'editor':
            canComment = True
        route = self.routes.post_board_membership(boardId=self.id)
        return BoardMembership(**route(userId=user.id, boardId=self.id, canComment=canComment, role=role)['item']).bind(self.routes)

    @overload
    def remove_user(self, user: User) -> User: ...

    @overload
    def remove_user(self, userId: int) -> User: ...

    def remove_user(self, *args, **kwargs) -> User:
        """Remove a user from a board
        """
        overload = parse_overload(args, kwargs,
                                  model='user',
                                  options=('userId',),
                                  required=('userId',))

        if 'userId' not in overload: # Case if passed User
            overload['userId'] = overload['id']

        for member in self.boardMemberships:
            if member.userId == overload['userId']:
                member.delete()

    def delete(self) -> Board:
        """Deletes the board

        Danger:
            This action is irreversible and cannot be undone

        Returns:
            Board: Deleted board instance
        """
        self.refresh()
        route = self.routes.delete_board(id=self.id)
        route()
        return self

    @overload
    def update(self) -> Board: ...

    @overload
    def update(self, board: Board) -> Board: ...

    @overload
    def update(self, name: str=None, position: int=None) -> Board: ...

    def update(self, *args, **kwargs) -> Board:
        """Updates the board with new values

        Args:
            name (str): Name of the board (optional)
            position (int): Position of the board (optional)

        Args: Alternate
            board (Board): Board instance to update (required)

        Note:
            If no arguments are provided, the board will update itself with the current values
            stored in its attributes

        Returns:
            Board: Updated board instance
        """
        overload = parse_overload(
            args, kwargs, 
            model='board', 
            options=('name', 'position'),
            noarg=self)

        route = self.routes.patch_board(id=self.id)
        self.__init__(**route(**overload)['item'])
        return self

    def refresh(self) -> None:
        """Refreshes the board data"""
        route = self.routes.get_board(id=self.id)
        self.__init__(**route()['item'])

attachments property

All attachments in the board

Note

This property is used by the Card class to determine its attachments

Returns:

Type Description
QueryableList[Attachment]

A list of all card attachments in the board

boardMemberships property

All board memberships

Note

This property is primarily here for internal use, '.editor' and '.viewer' properties are derived from the board memberships

Returns:

Type Description
QueryableList[BoardMembership]

Queryable List of all membership types (editor, viewer)

cardLabels property

All card -> label relationships in the board

Note

This property is used by the Card class to determine its labels

Returns:

Type Description
QueryableList[CardLabel]

A list of all card labels in the board

cardMemberships property

All card -> user relationships in the board

Note

This property is used by the Card class to determine its users

Returns:

Type Description
QueryableList[CardMembership]

A list of all card memberships in the board

cards property

All cards in the board

Returns:

Type Description
QueryableList[Card]

A list of all cards in the board

editors property

All users that can edit the board

Returns:

Type Description
QueryableList[User]

Queryable List of all editors

labels property

All labels in the board

Returns:

Type Description
QueryableList[Label]

Queryable List of all labels in the board

lists property

All lists in the board

Returns:

Type Description
QueryableList[List]

Queryable List of all lists in the board

project property

Project the board belongs to

Note

All objects include a reference to their parent object and parent objects include a reference to their children This means that you can traverse the entire API structure from any object

Returns:

Name Type Description
Project Project

Project instance

tasks property

All tasks in the board

Note

This property is used by the Card class to determine its tasks

Returns:

Type Description
QueryableList[Task]

A list of all card tasks in the board

users property

All users in the board

Returns:

Type Description
QueryableList[User]

Queryable List of all users

viewers property

All users that can view the board

Returns:

Type Description
QueryableList[User]

Queryable List of all viewers

add_user(user, role='viewer', canComment=False)

Adds a user to the board

Parameters:

Name Type Description Default
user User

User instance to add

required
canComment bool

Whether the user can comment on the board (default: False)

False

Returns:

Name Type Description
BoardMembership BoardMembership

New board membership

Raises:

Type Description
ValueError

If the role is invalid (must be 'viewer' or 'editor')

Source code in src/plankapy/interfaces.py
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
def add_user(self, user: User, role: BoardRole='viewer', canComment: bool=False) -> BoardMembership:
    """Adds a user to the board

    Args:
        user (User): User instance to add
        canComment (bool): Whether the user can comment on the board (default: False)

    Returns:
        BoardMembership: New board membership

    Raises:
        ValueError: If the role is invalid (must be 'viewer' or 'editor')
    """
    if role not in self.roles:
        raise ValueError(f'Invalid role: {role}')

    if role == 'editor':
        canComment = True
    route = self.routes.post_board_membership(boardId=self.id)
    return BoardMembership(**route(userId=user.id, boardId=self.id, canComment=canComment, role=role)['item']).bind(self.routes)

create_label(*args, **kwargs)

create_label(label: Label) -> Label
create_label(name: str, position: int = 0, color: LabelColor = None) -> Label

Creates a new label in the board

Parameters:

Name Type Description Default
name str

Name of the label (required)

required
position int

Position of the label (default: 0)

required
color LabelColor

Color of the label (default: "berry-red")

required

Alternate

Name Type Description Default
label Label

Label instance to create

required

Returns:

Name Type Description
Label Label

New label instance

Example
>>> new_label = board.create_label('My Label')
>>> label = Label(name='My Label', position=0, color='wet-moss')
>>> new_label2 = board.create_label(label)
Source code in src/plankapy/interfaces.py
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
def create_label(self, *args, **kwargs) -> Label:
    """Creates a new label in the board

    Args:
        name (str): Name of the label (required)
        position (int): Position of the label (default: 0)
        color (LabelColor): Color of the label (default: "berry-red")

    Args: Alternate
        label (Label): Label instance to create

    Returns:
        Label: New label instance

    Example:
        ```python
        >>> new_label = board.create_label('My Label')
        >>> label = Label(name='My Label', position=0, color='wet-moss')
        >>> new_label2 = board.create_label(label)
        ```
    """
    overload = parse_overload(args, kwargs, model='label', 
                              options=('name', 'position', 'color'), 
                              required=('name',)) # Only name requires user provided value

    # Required arguments with defaults must be manually assigned
    overload['position'] = overload.get('position', 0)
    overload['color'] = overload.get('color', choice(LabelColor.__args__))
    overload['boardId'] = self.id

    route = self.routes.post_label(boardId=self.id)
    return Label(**route(**overload)['item']).bind(self.routes)

create_list(*args, **kwargs)

create_list(_list: List) -> List
create_list(name: str, position: int) -> List

Creates a new list in the board

Parameters:

Name Type Description Default
name str

Name of the list (required)

required
position int

Position of the list (default: 0)

required

Alternate

Name Type Description Default
list List

List instance to create

required

Returns:

Name Type Description
List List

New list instance

Example
>>> new_list = board.create_list('My List')

>>> l = List(name='My List', position=0)
>>> new_list2 = board.create_list(l)
Source code in src/plankapy/interfaces.py
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
def create_list(self, *args, **kwargs) -> List:
    """Creates a new list in the board

    Args:
        name (str): Name of the list (required)
        position (int): Position of the list (default: 0)

    Args: Alternate
        list (List): List instance to create

    Returns:
        List: New list instance

    Example:
        ```python
        >>> new_list = board.create_list('My List')

        >>> l = List(name='My List', position=0)
        >>> new_list2 = board.create_list(l)
        ```
    """
    overload = parse_overload(args, kwargs, model='list', 
                              options=('name', 'position'), 
                              required=('name',))

    overload['position'] = overload.get('position', 0)
    overload['boardId'] = self.id

    route = self.routes.post_list(boardId=self.id)
    return List(**route(**overload)['item']).bind(self.routes)

delete()

Deletes the board

Danger

This action is irreversible and cannot be undone

Returns:

Name Type Description
Board Board

Deleted board instance

Source code in src/plankapy/interfaces.py
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
def delete(self) -> Board:
    """Deletes the board

    Danger:
        This action is irreversible and cannot be undone

    Returns:
        Board: Deleted board instance
    """
    self.refresh()
    route = self.routes.delete_board(id=self.id)
    route()
    return self

refresh()

Refreshes the board data

Source code in src/plankapy/interfaces.py
1144
1145
1146
1147
def refresh(self) -> None:
    """Refreshes the board data"""
    route = self.routes.get_board(id=self.id)
    self.__init__(**route()['item'])

remove_user(*args, **kwargs)

remove_user(user: User) -> User
remove_user(userId: int) -> User

Remove a user from a board

Source code in src/plankapy/interfaces.py
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
def remove_user(self, *args, **kwargs) -> User:
    """Remove a user from a board
    """
    overload = parse_overload(args, kwargs,
                              model='user',
                              options=('userId',),
                              required=('userId',))

    if 'userId' not in overload: # Case if passed User
        overload['userId'] = overload['id']

    for member in self.boardMemberships:
        if member.userId == overload['userId']:
            member.delete()

update(*args, **kwargs)

update() -> Board
update(board: Board) -> Board
update(name: str = None, position: int = None) -> Board

Updates the board with new values

Parameters:

Name Type Description Default
name str

Name of the board (optional)

required
position int

Position of the board (optional)

required

Alternate

Name Type Description Default
board Board

Board instance to update (required)

required
Note

If no arguments are provided, the board will update itself with the current values stored in its attributes

Returns:

Name Type Description
Board Board

Updated board instance

Source code in src/plankapy/interfaces.py
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
def update(self, *args, **kwargs) -> Board:
    """Updates the board with new values

    Args:
        name (str): Name of the board (optional)
        position (int): Position of the board (optional)

    Args: Alternate
        board (Board): Board instance to update (required)

    Note:
        If no arguments are provided, the board will update itself with the current values
        stored in its attributes

    Returns:
        Board: Updated board instance
    """
    overload = parse_overload(
        args, kwargs, 
        model='board', 
        options=('name', 'position'),
        noarg=self)

    route = self.routes.patch_board(id=self.id)
    self.__init__(**route(**overload)['item'])
    return self