Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement hex color conversion #1270

Merged
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
84 changes: 84 additions & 0 deletions gspread/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
Dict,
Iterable,
List,
Mapping,
Optional,
Tuple,
TypeVar,
Expand Down Expand Up @@ -718,6 +719,89 @@ def combined_merge_values(worksheet_metadata, values):
return new_values


def convert_hex_to_colors_dict(hex_color: str) -> Mapping[str, float]:
"""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_colors_dict("#3300CC")
{'red': 0.2, 'green': 0.0, 'blue': 0.8}

>>> convert_hex_to_colors_dict("#30C")
{'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]

alifeee marked this conversation as resolved.
Show resolved Hide resolved
# Expand 3 character hex.
if len(hex_color) == 3:
hex_color = "".join([char * 2 for char in hex_color])

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: float = 0.0, green: float = 0.0, blue: float = 0.0
) -> str:
"""Convert RGB color values to a hex color code.

:param float red: Red color value (0-1).
:param float green: Green color value (0-1).
:param float blue: Blue color value (0-1).

:returns: Hex color code in the format "#RRGGBB".
:rtype: str

:raises:
ValueError: If any color value is out of the accepted range (0-1).

Example:

>>> convert_colors_to_hex_value(0.2, 0, 0.8)
'#3300CC'

>>> convert_colors_to_hex_value(green=0.5)
'#008000'
"""

def to_hex(value: float) -> str:
"""
Convert an integer to a 2-digit uppercase hex string.
"""
hex_value = hex(round(value * 255))[2:]
return hex_value.upper().zfill(2)

if any(value < 0 or value > 1 for value in (red, green, blue)):
raise ValueError("Color value out of accepted range 0-1.")

return f"#{to_hex(red)}{to_hex(green)}{to_hex(blue)}"


if __name__ == "__main__":
import doctest

Expand Down
23 changes: 6 additions & 17 deletions gspread/worksheet.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -1516,26 +1517,20 @@ def update_title(self, title: str) -> JSONResponse:
self._properties["title"] = title
return response

def update_tab_color(self, color: Mapping[str, float]) -> JSONResponse:
def update_tab_color(self, color: str) -> JSONResponse:
"""Changes the worksheet's tab color.
Use clear_tab_color() to remove the color.

:param dict color: The red, green and blue values of the color, between 0 and 1.
:param str color: Hex color value.
"""
red, green, blue = color["red"], color["green"], color["blue"]
rgb_color = convert_hex_to_colors_dict(color)
body = {
"requests": [
{
"updateSheetProperties": {
"properties": {
"sheetId": self.id,
"tabColorStyle": {
"rgbColor": {
"red": red,
"green": green,
"blue": blue,
}
},
"tabColorStyle": {"rgbColor": rgb_color},
},
"fields": "tabColorStyle",
}
Expand All @@ -1545,13 +1540,7 @@ def update_tab_color(self, color: Mapping[str, float]) -> JSONResponse:

response = self.client.batch_update(self.spreadsheet_id, body)

sheet_color = {
"red": red,
"green": green,
"blue": blue,
}

self._properties["tabColorStyle"] = {"rgbColor": sheet_color}
self._properties["tabColorStyle"] = {"rgbColor": rgb_color}
return response

def clear_tab_color(self) -> JSONResponse:
Expand Down
Loading