diff --git a/gspread/utils.py b/gspread/utils.py index fb286a64d..12aebe841 100644 --- a/gspread/utils.py +++ b/gspread/utils.py @@ -695,6 +695,84 @@ def combined_merge_values(worksheet_metadata, values): return new_values +def convert_hex_to_colors_dict(hex_color: str): + """Convert a hex color code to RGB color values. + + :param str hex_color: Hex color code in the format "#RRGGBB". + + :returns: Dict containing the color's red, green and blue values between 0 and 1. + :rtype: dict + + :raises: + ValueError: If the input hex string is not in the correct format or length. + + Examples: + >>> convert_hex_to_color("#3300CC") + {'red': 0.2, 'green': 0.0, 'blue': 0.8} + + """ + hex_color = hex_color.lstrip("#") + + # Google API ColorStyle Reference: + # "The alpha value in the Color object isn't generally supported." + # https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/other#colorstyle + if len(hex_color) == 8: + hex_color = hex_color[:-2] + + if len(hex_color) != 6: + raise ValueError("Hex color code must be in the format '#RRGGBB'.") + + try: + rgb_color = { + "red": int(hex_color[0:2], 16) / 255, + "green": int(hex_color[2:4], 16) / 255, + "blue": int(hex_color[4:6], 16) / 255, + } + + return rgb_color + except ValueError: + raise ValueError(f"Invalid character in hex color string: #{hex_color}") + + +def convert_colors_to_hex_value(red=0, green=0, blue=0): + """Convert RGB color values to a hex color code. + + :param int red: Red color value (0-255). + :param int green: Green color value (0-255). + :param int blue: Blue color value (0-255). + + :returns: Hex color code in the format "#RRGGBB". + :rtype: str + + :raises: + ValueError: If any color value is out of the accepted range (0-255). + + Example: + + >>> convert_colors_to_hex_value(51, 0, 204) + '#3300CC' + + >>> convert_colors_to_hex_value(green=128) + '#008000' + """ + + def to_hex(value): + """ + Convert an integer to a 2-digit uppercase hex string. + """ + hex_value = hex(value)[2:] + return hex_value.upper().zfill(2) + + if any(value not in range(256) for value in (red, green, blue)): + raise ValueError("Color value out of accepted range 0-255.") + + r_hex = to_hex(red) + g_hex = to_hex(green) + b_hex = to_hex(blue) + hex_color = f"#{r_hex}{g_hex}{b_hex}" + return hex_color + + if __name__ == "__main__": import doctest diff --git a/gspread/worksheet.py b/gspread/worksheet.py index 94a20c255..43e5b8420 100644 --- a/gspread/worksheet.py +++ b/gspread/worksheet.py @@ -44,6 +44,7 @@ cast_to_a1_notation, cell_list_to_rect, combined_merge_values, + convert_hex_to_colors_dict, fill_gaps, finditem, numericise_all, @@ -1577,6 +1578,15 @@ def clear_tab_color(self) -> JSONResponse: self._properties.pop("tabColorStyle") return response + def set_tab_color(self, hex_color: str): + """Changes the worksheet's tab color. + Use clear_tab_color() to remove the color. + + :param str hex_color: Hex color code in the format "#RRGGBB". + """ + rgb_color = convert_hex_to_colors_dict(hex_color) + return self.update_tab_color(rgb_color) + def update_index(self, index: int) -> JSONResponse: """Updates the ``index`` property for the worksheet. diff --git a/tests/cassettes/WorksheetTest.test_set_tab_color.json b/tests/cassettes/WorksheetTest.test_set_tab_color.json new file mode 100644 index 000000000..ae307cec9 --- /dev/null +++ b/tests/cassettes/WorksheetTest.test_set_tab_color.json @@ -0,0 +1,594 @@ +{ + "version": 1, + "interactions": [ + { + "request": { + "method": "POST", + "uri": "https://www.googleapis.com/drive/v3/files?supportsAllDrives=True", + "body": "{\"name\": \"Test WorksheetTest test_set_tab_color\", \"mimeType\": \"application/vnd.google-apps.spreadsheet\"}", + "headers": { + "User-Agent": [ + "python-requests/2.31.0" + ], + "Accept-Encoding": [ + "gzip, deflate" + ], + "Accept": [ + "*/*" + ], + "Connection": [ + "keep-alive" + ], + "Content-Length": [ + "104" + ], + "Content-Type": [ + "application/json" + ], + "authorization": [ + "" + ] + } + }, + "response": { + "status": { + "code": 200, + "message": "OK" + }, + "headers": { + "Pragma": [ + "no-cache" + ], + "Cache-Control": [ + "no-cache, no-store, max-age=0, must-revalidate" + ], + "Content-Type": [ + "application/json; charset=UTF-8" + ], + "Server": [ + "ESF" + ], + "X-Frame-Options": [ + "SAMEORIGIN" + ], + "X-XSS-Protection": [ + "0" + ], + "Expires": [ + "Mon, 01 Jan 1990 00:00:00 GMT" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Transfer-Encoding": [ + "chunked" + ], + "Alt-Svc": [ + "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000" + ], + "Vary": [ + "Origin, X-Origin" + ], + "Date": [ + "Sat, 12 Aug 2023 10:09:37 GMT" + ], + "content-length": [ + "191" + ] + }, + "body": { + "string": "{\n \"kind\": \"drive#file\",\n \"id\": \"1H7Y2DzAdUFZpPkr4fYY6ZoG5fkwQlnq0J6EweBpbebs\",\n \"name\": \"Test WorksheetTest test_set_tab_color\",\n \"mimeType\": \"application/vnd.google-apps.spreadsheet\"\n}\n" + } + } + }, + { + "request": { + "method": "GET", + "uri": "https://sheets.googleapis.com/v4/spreadsheets/1H7Y2DzAdUFZpPkr4fYY6ZoG5fkwQlnq0J6EweBpbebs?includeGridData=false", + "body": null, + "headers": { + "User-Agent": [ + "python-requests/2.31.0" + ], + "Accept-Encoding": [ + "gzip, deflate" + ], + "Accept": [ + "*/*" + ], + "Connection": [ + "keep-alive" + ], + "authorization": [ + "" + ] + } + }, + "response": { + "status": { + "code": 200, + "message": "OK" + }, + "headers": { + "Cache-Control": [ + "private" + ], + "Content-Type": [ + "application/json; charset=UTF-8" + ], + "Server": [ + "ESF" + ], + "X-Frame-Options": [ + "SAMEORIGIN" + ], + "X-XSS-Protection": [ + "0" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Transfer-Encoding": [ + "chunked" + ], + "Alt-Svc": [ + "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000" + ], + "Vary": [ + "Origin", + "X-Origin", + "Referer" + ], + "Date": [ + "Sat, 12 Aug 2023 10:09:38 GMT" + ], + "content-length": [ + "3335" + ] + }, + "body": { + "string": "{\n \"spreadsheetId\": \"1H7Y2DzAdUFZpPkr4fYY6ZoG5fkwQlnq0J6EweBpbebs\",\n \"properties\": {\n \"title\": \"Test WorksheetTest test_set_tab_color\",\n \"locale\": \"en_US\",\n \"autoRecalc\": \"ON_CHANGE\",\n \"timeZone\": \"Etc/GMT\",\n \"defaultFormat\": {\n \"backgroundColor\": {\n \"red\": 1,\n \"green\": 1,\n \"blue\": 1\n },\n \"padding\": {\n \"top\": 2,\n \"right\": 3,\n \"bottom\": 2,\n \"left\": 3\n },\n \"verticalAlignment\": \"BOTTOM\",\n \"wrapStrategy\": \"OVERFLOW_CELL\",\n \"textFormat\": {\n \"foregroundColor\": {},\n \"fontFamily\": \"arial,sans,sans-serif\",\n \"fontSize\": 10,\n \"bold\": false,\n \"italic\": false,\n \"strikethrough\": false,\n \"underline\": false,\n \"foregroundColorStyle\": {\n \"rgbColor\": {}\n }\n },\n \"backgroundColorStyle\": {\n \"rgbColor\": {\n \"red\": 1,\n \"green\": 1,\n \"blue\": 1\n }\n }\n },\n \"spreadsheetTheme\": {\n \"primaryFontFamily\": \"Arial\",\n \"themeColors\": [\n {\n \"colorType\": \"TEXT\",\n \"color\": {\n \"rgbColor\": {}\n }\n },\n {\n \"colorType\": \"BACKGROUND\",\n \"color\": {\n \"rgbColor\": {\n \"red\": 1,\n \"green\": 1,\n \"blue\": 1\n }\n }\n },\n {\n \"colorType\": \"ACCENT1\",\n \"color\": {\n \"rgbColor\": {\n \"red\": 0.25882354,\n \"green\": 0.52156866,\n \"blue\": 0.95686275\n }\n }\n },\n {\n \"colorType\": \"ACCENT2\",\n \"color\": {\n \"rgbColor\": {\n \"red\": 0.91764706,\n \"green\": 0.2627451,\n \"blue\": 0.20784314\n }\n }\n },\n {\n \"colorType\": \"ACCENT3\",\n \"color\": {\n \"rgbColor\": {\n \"red\": 0.9843137,\n \"green\": 0.7372549,\n \"blue\": 0.015686275\n }\n }\n },\n {\n \"colorType\": \"ACCENT4\",\n \"color\": {\n \"rgbColor\": {\n \"red\": 0.20392157,\n \"green\": 0.65882355,\n \"blue\": 0.3254902\n }\n }\n },\n {\n \"colorType\": \"ACCENT5\",\n \"color\": {\n \"rgbColor\": {\n \"red\": 1,\n \"green\": 0.42745098,\n \"blue\": 0.003921569\n }\n }\n },\n {\n \"colorType\": \"ACCENT6\",\n \"color\": {\n \"rgbColor\": {\n \"red\": 0.27450982,\n \"green\": 0.7411765,\n \"blue\": 0.7764706\n }\n }\n },\n {\n \"colorType\": \"LINK\",\n \"color\": {\n \"rgbColor\": {\n \"red\": 0.06666667,\n \"green\": 0.33333334,\n \"blue\": 0.8\n }\n }\n }\n ]\n }\n },\n \"sheets\": [\n {\n \"properties\": {\n \"sheetId\": 0,\n \"title\": \"Sheet1\",\n \"index\": 0,\n \"sheetType\": \"GRID\",\n \"gridProperties\": {\n \"rowCount\": 1000,\n \"columnCount\": 26\n }\n }\n }\n ],\n \"spreadsheetUrl\": \"https://docs.google.com/spreadsheets/d/1H7Y2DzAdUFZpPkr4fYY6ZoG5fkwQlnq0J6EweBpbebs/edit\"\n}\n" + } + } + }, + { + "request": { + "method": "GET", + "uri": "https://sheets.googleapis.com/v4/spreadsheets/1H7Y2DzAdUFZpPkr4fYY6ZoG5fkwQlnq0J6EweBpbebs?includeGridData=false", + "body": null, + "headers": { + "User-Agent": [ + "python-requests/2.31.0" + ], + "Accept-Encoding": [ + "gzip, deflate" + ], + "Accept": [ + "*/*" + ], + "Connection": [ + "keep-alive" + ], + "authorization": [ + "" + ] + } + }, + "response": { + "status": { + "code": 200, + "message": "OK" + }, + "headers": { + "Cache-Control": [ + "private" + ], + "Content-Type": [ + "application/json; charset=UTF-8" + ], + "Server": [ + "ESF" + ], + "X-Frame-Options": [ + "SAMEORIGIN" + ], + "X-XSS-Protection": [ + "0" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Transfer-Encoding": [ + "chunked" + ], + "Alt-Svc": [ + "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000" + ], + "Vary": [ + "Origin", + "X-Origin", + "Referer" + ], + "Date": [ + "Sat, 12 Aug 2023 10:09:38 GMT" + ], + "content-length": [ + "3335" + ] + }, + "body": { + "string": "{\n \"spreadsheetId\": \"1H7Y2DzAdUFZpPkr4fYY6ZoG5fkwQlnq0J6EweBpbebs\",\n \"properties\": {\n \"title\": \"Test WorksheetTest test_set_tab_color\",\n \"locale\": \"en_US\",\n \"autoRecalc\": \"ON_CHANGE\",\n \"timeZone\": \"Etc/GMT\",\n \"defaultFormat\": {\n \"backgroundColor\": {\n \"red\": 1,\n \"green\": 1,\n \"blue\": 1\n },\n \"padding\": {\n \"top\": 2,\n \"right\": 3,\n \"bottom\": 2,\n \"left\": 3\n },\n \"verticalAlignment\": \"BOTTOM\",\n \"wrapStrategy\": \"OVERFLOW_CELL\",\n \"textFormat\": {\n \"foregroundColor\": {},\n \"fontFamily\": \"arial,sans,sans-serif\",\n \"fontSize\": 10,\n \"bold\": false,\n \"italic\": false,\n \"strikethrough\": false,\n \"underline\": false,\n \"foregroundColorStyle\": {\n \"rgbColor\": {}\n }\n },\n \"backgroundColorStyle\": {\n \"rgbColor\": {\n \"red\": 1,\n \"green\": 1,\n \"blue\": 1\n }\n }\n },\n \"spreadsheetTheme\": {\n \"primaryFontFamily\": \"Arial\",\n \"themeColors\": [\n {\n \"colorType\": \"TEXT\",\n \"color\": {\n \"rgbColor\": {}\n }\n },\n {\n \"colorType\": \"BACKGROUND\",\n \"color\": {\n \"rgbColor\": {\n \"red\": 1,\n \"green\": 1,\n \"blue\": 1\n }\n }\n },\n {\n \"colorType\": \"ACCENT1\",\n \"color\": {\n \"rgbColor\": {\n \"red\": 0.25882354,\n \"green\": 0.52156866,\n \"blue\": 0.95686275\n }\n }\n },\n {\n \"colorType\": \"ACCENT2\",\n \"color\": {\n \"rgbColor\": {\n \"red\": 0.91764706,\n \"green\": 0.2627451,\n \"blue\": 0.20784314\n }\n }\n },\n {\n \"colorType\": \"ACCENT3\",\n \"color\": {\n \"rgbColor\": {\n \"red\": 0.9843137,\n \"green\": 0.7372549,\n \"blue\": 0.015686275\n }\n }\n },\n {\n \"colorType\": \"ACCENT4\",\n \"color\": {\n \"rgbColor\": {\n \"red\": 0.20392157,\n \"green\": 0.65882355,\n \"blue\": 0.3254902\n }\n }\n },\n {\n \"colorType\": \"ACCENT5\",\n \"color\": {\n \"rgbColor\": {\n \"red\": 1,\n \"green\": 0.42745098,\n \"blue\": 0.003921569\n }\n }\n },\n {\n \"colorType\": \"ACCENT6\",\n \"color\": {\n \"rgbColor\": {\n \"red\": 0.27450982,\n \"green\": 0.7411765,\n \"blue\": 0.7764706\n }\n }\n },\n {\n \"colorType\": \"LINK\",\n \"color\": {\n \"rgbColor\": {\n \"red\": 0.06666667,\n \"green\": 0.33333334,\n \"blue\": 0.8\n }\n }\n }\n ]\n }\n },\n \"sheets\": [\n {\n \"properties\": {\n \"sheetId\": 0,\n \"title\": \"Sheet1\",\n \"index\": 0,\n \"sheetType\": \"GRID\",\n \"gridProperties\": {\n \"rowCount\": 1000,\n \"columnCount\": 26\n }\n }\n }\n ],\n \"spreadsheetUrl\": \"https://docs.google.com/spreadsheets/d/1H7Y2DzAdUFZpPkr4fYY6ZoG5fkwQlnq0J6EweBpbebs/edit\"\n}\n" + } + } + }, + { + "request": { + "method": "POST", + "uri": "https://sheets.googleapis.com/v4/spreadsheets/1H7Y2DzAdUFZpPkr4fYY6ZoG5fkwQlnq0J6EweBpbebs/values/%27Sheet1%27:clear", + "body": null, + "headers": { + "User-Agent": [ + "python-requests/2.31.0" + ], + "Accept-Encoding": [ + "gzip, deflate" + ], + "Accept": [ + "*/*" + ], + "Connection": [ + "keep-alive" + ], + "Content-Length": [ + "0" + ], + "authorization": [ + "" + ] + } + }, + "response": { + "status": { + "code": 200, + "message": "OK" + }, + "headers": { + "Cache-Control": [ + "private" + ], + "Content-Type": [ + "application/json; charset=UTF-8" + ], + "Server": [ + "ESF" + ], + "X-Frame-Options": [ + "SAMEORIGIN" + ], + "X-XSS-Protection": [ + "0" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Transfer-Encoding": [ + "chunked" + ], + "Alt-Svc": [ + "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000" + ], + "Vary": [ + "Origin", + "X-Origin", + "Referer" + ], + "Date": [ + "Sat, 12 Aug 2023 10:09:38 GMT" + ], + "content-length": [ + "107" + ] + }, + "body": { + "string": "{\n \"spreadsheetId\": \"1H7Y2DzAdUFZpPkr4fYY6ZoG5fkwQlnq0J6EweBpbebs\",\n \"clearedRange\": \"Sheet1!A1:Z1000\"\n}\n" + } + } + }, + { + "request": { + "method": "GET", + "uri": "https://sheets.googleapis.com/v4/spreadsheets/1H7Y2DzAdUFZpPkr4fYY6ZoG5fkwQlnq0J6EweBpbebs?fields=sheets.properties.tabColorStyle", + "body": null, + "headers": { + "User-Agent": [ + "python-requests/2.31.0" + ], + "Accept-Encoding": [ + "gzip, deflate" + ], + "Accept": [ + "*/*" + ], + "Connection": [ + "keep-alive" + ], + "authorization": [ + "" + ] + } + }, + "response": { + "status": { + "code": 200, + "message": "OK" + }, + "headers": { + "Cache-Control": [ + "private" + ], + "Content-Type": [ + "application/json; charset=UTF-8" + ], + "x-l2-request-path": [ + "l2-managed-6" + ], + "Server": [ + "ESF" + ], + "X-Frame-Options": [ + "SAMEORIGIN" + ], + "X-XSS-Protection": [ + "0" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Transfer-Encoding": [ + "chunked" + ], + "Alt-Svc": [ + "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000" + ], + "Vary": [ + "Origin", + "X-Origin", + "Referer" + ], + "Date": [ + "Sat, 12 Aug 2023 10:09:39 GMT" + ], + "content-length": [ + "57" + ] + }, + "body": { + "string": "{\n \"sheets\": [\n {\n \"properties\": {}\n }\n ]\n}\n" + } + } + }, + { + "request": { + "method": "POST", + "uri": "https://sheets.googleapis.com/v4/spreadsheets/1H7Y2DzAdUFZpPkr4fYY6ZoG5fkwQlnq0J6EweBpbebs:batchUpdate", + "body": "{\"requests\": [{\"updateSheetProperties\": {\"properties\": {\"sheetId\": 0, \"tabColorStyle\": {\"rgbColor\": {\"red\": 1.0, \"green\": 0.0, \"blue\": 0.4980392156862745}}}, \"fields\": \"tabColorStyle\"}}]}", + "headers": { + "User-Agent": [ + "python-requests/2.31.0" + ], + "Accept-Encoding": [ + "gzip, deflate" + ], + "Accept": [ + "*/*" + ], + "Connection": [ + "keep-alive" + ], + "Content-Length": [ + "187" + ], + "Content-Type": [ + "application/json" + ], + "authorization": [ + "" + ] + } + }, + "response": { + "status": { + "code": 200, + "message": "OK" + }, + "headers": { + "Cache-Control": [ + "private" + ], + "Content-Type": [ + "application/json; charset=UTF-8" + ], + "Server": [ + "ESF" + ], + "X-Frame-Options": [ + "SAMEORIGIN" + ], + "X-XSS-Protection": [ + "0" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Transfer-Encoding": [ + "chunked" + ], + "Alt-Svc": [ + "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000" + ], + "Vary": [ + "Origin", + "X-Origin", + "Referer" + ], + "Date": [ + "Sat, 12 Aug 2023 10:09:39 GMT" + ], + "content-length": [ + "97" + ] + }, + "body": { + "string": "{\n \"spreadsheetId\": \"1H7Y2DzAdUFZpPkr4fYY6ZoG5fkwQlnq0J6EweBpbebs\",\n \"replies\": [\n {}\n ]\n}\n" + } + } + }, + { + "request": { + "method": "GET", + "uri": "https://sheets.googleapis.com/v4/spreadsheets/1H7Y2DzAdUFZpPkr4fYY6ZoG5fkwQlnq0J6EweBpbebs?fields=sheets.properties.tabColorStyle", + "body": null, + "headers": { + "User-Agent": [ + "python-requests/2.31.0" + ], + "Accept-Encoding": [ + "gzip, deflate" + ], + "Accept": [ + "*/*" + ], + "Connection": [ + "keep-alive" + ], + "authorization": [ + "" + ] + } + }, + "response": { + "status": { + "code": 200, + "message": "OK" + }, + "headers": { + "Cache-Control": [ + "private" + ], + "Content-Type": [ + "application/json; charset=UTF-8" + ], + "x-l2-request-path": [ + "l2-managed-6" + ], + "Server": [ + "ESF" + ], + "X-Frame-Options": [ + "SAMEORIGIN" + ], + "X-XSS-Protection": [ + "0" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Transfer-Encoding": [ + "chunked" + ], + "Alt-Svc": [ + "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000" + ], + "Vary": [ + "Origin", + "X-Origin", + "Referer" + ], + "Date": [ + "Sat, 12 Aug 2023 10:09:39 GMT" + ], + "content-length": [ + "190" + ] + }, + "body": { + "string": "{\n \"sheets\": [\n {\n \"properties\": {\n \"tabColorStyle\": {\n \"rgbColor\": {\n \"red\": 1,\n \"blue\": 0.49803922\n }\n }\n }\n }\n ]\n}\n" + } + } + }, + { + "request": { + "method": "DELETE", + "uri": "https://www.googleapis.com/drive/v3/files/1H7Y2DzAdUFZpPkr4fYY6ZoG5fkwQlnq0J6EweBpbebs?supportsAllDrives=True", + "body": null, + "headers": { + "User-Agent": [ + "python-requests/2.31.0" + ], + "Accept-Encoding": [ + "gzip, deflate" + ], + "Accept": [ + "*/*" + ], + "Connection": [ + "keep-alive" + ], + "Content-Length": [ + "0" + ], + "authorization": [ + "" + ] + } + }, + "response": { + "status": { + "code": 204, + "message": "No Content" + }, + "headers": { + "Pragma": [ + "no-cache" + ], + "Cache-Control": [ + "no-cache, no-store, max-age=0, must-revalidate" + ], + "Content-Type": [ + "text/html" + ], + "Server": [ + "ESF" + ], + "X-Frame-Options": [ + "SAMEORIGIN" + ], + "Content-Length": [ + "0" + ], + "X-XSS-Protection": [ + "0" + ], + "Expires": [ + "Mon, 01 Jan 1990 00:00:00 GMT" + ], + "X-Content-Type-Options": [ + "nosniff" + ], + "Alt-Svc": [ + "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000" + ], + "Vary": [ + "Origin, X-Origin" + ], + "Date": [ + "Sat, 12 Aug 2023 10:09:40 GMT" + ] + }, + "body": { + "string": "" + } + } + } + ] +} diff --git a/tests/utils_test.py b/tests/utils_test.py index 0d193185d..ec66aa355 100644 --- a/tests/utils_test.py +++ b/tests/utils_test.py @@ -259,3 +259,39 @@ def test_combine_merge_values(self): actual_combine = utils.combined_merge_values(sheet_metadata, sheet_data) self.assertEqual(actual_combine, expected_combine) + + def test_convert_colors_to_hex_value(self): + color = {"red": 255, "green": 128, "blue": 0} + expected_hex = "#FF8000" + + # successful convert from colors + hex = utils.convert_colors_to_hex_value(**color) + self.assertEqual(hex, expected_hex) + + # successful convert from partial input + hex = utils.convert_colors_to_hex_value(green=255) + self.assertEqual(hex, "#00FF00") + + # throw ValueError on color values out of range (0-255) + with self.assertRaises(ValueError): + utils.convert_colors_to_hex_value(123, 0, -50) + + def test_convert_hex_to_color(self): + hex = "#FF8000" + expected_color = {"red": 1, "green": 128 / 255, "blue": 0} + + # successful convert from hex to color + rgbcolor = utils.convert_hex_to_colors_dict(hex) + self.assertEqual(rgbcolor, expected_color) + + # successful ignore alpha + rgbcolor = utils.convert_hex_to_colors_dict(f"{hex}42") + self.assertEqual(rgbcolor, expected_color) + + # raise ValueError on invalid hex length + with self.assertRaises(ValueError): + utils.convert_hex_to_colors_dict("123456abcdef") + + # raise ValueError on invalid hex characters + with self.assertRaises(ValueError): + utils.convert_hex_to_colors_dict("axbcde") diff --git a/tests/worksheet_test.py b/tests/worksheet_test.py index 85d0789a1..cd7bb10a4 100644 --- a/tests/worksheet_test.py +++ b/tests/worksheet_test.py @@ -282,6 +282,52 @@ def test_update_tab_color(self): self.assertEqual(color_after, pink_color_from_google) self.assertEqual(color_param_after, pink_color) + @pytest.mark.vcr() + def test_set_tab_color(self): + # Set the color. + # Get the color. + # Assert the color is the set and changed by google. + + # Returned as param from google. + pink_color = { + "red": 1.0, + "green": 0.0, + "blue": 127 / 255, + } + + pink_color_hex = "#FF007F" + + pink_color_from_google = { + "red": 1, + "blue": 0.49803922, # 127/255 + } + + params = {"fields": "sheets.properties.tabColorStyle"} + res = self.spreadsheet.fetch_sheet_metadata(params=params) + color_before = ( + res["sheets"][0]["properties"] + .get("tabColorStyle", {}) + .get("rgbColor", None) + ) + color_param_before = self.sheet.tab_color + + self.sheet.set_tab_color(pink_color_hex) + + res = self.spreadsheet.fetch_sheet_metadata(params=params) + color_after = ( + res["sheets"][0]["properties"] + .get("tabColorStyle", {}) + .get("rgbColor", None) + ) + color_param_after = self.sheet.tab_color + + # params are set to whatever the user sets them to + # google returns up to 8 digits after the decimal point. + self.assertEqual(color_before, None) + self.assertEqual(color_param_before, None) + self.assertEqual(color_after, pink_color_from_google) + self.assertEqual(color_param_after, pink_color) + @pytest.mark.vcr() def test_clear_tab_color(self): # Set the color.