Skip to content

Commit

Permalink
Merge pull request #1270 from idonec/feature/release_6_0_0
Browse files Browse the repository at this point in the history
Implement hex color conversion
  • Loading branch information
lavigne958 authored Sep 10, 2023
2 parents 7abf1e2 + 1b87cb2 commit 608789f
Show file tree
Hide file tree
Showing 5 changed files with 807 additions and 39 deletions.
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]

# 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 @@ -1521,26 +1522,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 @@ -1550,13 +1545,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

0 comments on commit 608789f

Please sign in to comment.