docs: def from_grid_locator(locator):
      """Calculate geodesic latitude/longitude from Maidenhead locator.
  
      Args:
          locator (str): Maidenhead locator string
  
      Returns:
          tuple of float: Geodesic latitude and longitude values
  
      Raises:
          ValueError: Incorrect grid locator length
          ValueError: Invalid values in locator string
      """
      if not len(locator) in (4, 6, 8):
          raise ValueError('Locator must be 4, 6 or 8 characters long %r'
                           % locator)
  
      # Convert the locator string to a list, because we need it to be mutable to
      # munge the values
      locator = list(locator)
  
      # Convert characters to numeric value, fields are always uppercase
      locator[0] = ord(locator[0]) - 65
      locator[1] = ord(locator[1]) - 65
  
      # Values for square are always integers
      locator[2] = int(locator[2])
      locator[3] = int(locator[3])
  
      if len(locator) >= 6:
          # Some people use uppercase for the subsquare data, in spite of
          # lowercase being the accepted style, so handle that too.
          locator[4] = ord(locator[4].lower()) - 97
          locator[5] = ord(locator[5].lower()) - 97
  
      if len(locator) == 8:
          # Extended square values are always integers
          locator[6] = int(locator[6])
          locator[7] = int(locator[7])
  
      # Check field values within 'A'(0) to 'R'(17), and square values are within
      # 0 to 9
      if not 0 <= locator[0] <= 17 \
         or not 0 <= locator[1] <= 17 \
         or not 0 <= locator[2] <= 9 \
         or not 0 <= locator[3] <= 9:
          raise ValueError('Invalid values in locator %r' % locator)
  
      # Check subsquare values are within 'a'(0) to 'x'(23)
      if len(locator) >= 6:
          if not 0 <= locator[4] <= 23 \
             or not 0 <= locator[5] <= 23:
              raise ValueError('Invalid values in locator %r' % locator)
  
      # Extended square values must be within 0 to 9
      if len(locator) == 8:
          if not 0 <= locator[6] <= 9 \
             or not 0 <= locator[7] <= 9:
              raise ValueError('Invalid values in locator %r' % locator)
  
      longitude = LONGITUDE_FIELD * locator[0] \
          + LONGITUDE_SQUARE * locator[2]
      latitude = LATITUDE_FIELD * locator[1] \
          + LATITUDE_SQUARE * locator[3]
  
      if len(locator) >= 6:
          longitude += LONGITUDE_SUBSQUARE * locator[4]
          latitude += LATITUDE_SUBSQUARE * locator[5]
  
      if len(locator) == 8:
          longitude += LONGITUDE_EXTSQUARE * locator[6] + LONGITUDE_EXTSQUARE / 2
          latitude += LATITUDE_EXTSQUARE * locator[7] + LATITUDE_EXTSQUARE / 2
      else:
          longitude += LONGITUDE_EXTSQUARE * 5
          latitude += LATITUDE_EXTSQUARE * 5
  
      # Rebase longitude and latitude to normal geodesic
      longitude -= 180
      latitude -= 90
  
      return latitude, longitude