Shorten an URL using `is.gd - v.gd url shortener service <http://is.gd/developers.php>`_.
            
            :param url: URL that had to be shortened
            :type url: str.
            
            :param custom_url: if specified, the url generated will be http://is.gd/<custom_url> (or http://v.gd/<custom_url>).
            
                Please note that if this custom url is unavailable (because it is already used, for example), a :class:`gdshortener.GDShortURLError` will be raised
            
            :type custom_url: str.
            :param log_stat: States if the generated url has statistical analisys attached.
                If the stats are enabled, a special url will show the stats on this shortened url. This special url is returned as second parameters of this function.
                
                Please notice that a stat enabled shorten url counts double in .gd rate exceeding monitor system.
                
                More information on `.gd FAQ <http://is.gd/faq.php#stats>`_ and `.gd rate limit <http://is.gd/usagelimits.php>`_.
            :type log_stat: bool.
            :returns:  (str,str) -- Shortened URL obtained by .gd service and Stat URL if requested (otherwhise is ``None``).
            :raises: **IOError** when timeout with .gd service occurs
            
                **ValueError** if .gd response is malformed
                
                :class:`gdshortener.GDMalformedURLError` if the URL provided for shortening is malformed
                
                :class:`gdshortener.GDShortURLError` if the custom URL requested is not available
                
                :class:`gdshortener.GDRateLimitError` if the request rate is exceeded for .gd service
                
                :class:`gdshortener.GDGenericError` in case of generic error from .gd service (mainteinance)

def shorten(self, url, custom_url = None, log_stat = False):
        '''
            Shorten an URL using `is.gd - v.gd url shortener service <http://is.gd/developers.php>`_.
            
            :param url: URL that had to be shortened
            :type url: str.
            
            :param custom_url: if specified, the url generated will be http://is.gd/<custom_url> (or http://v.gd/<custom_url>).
            
                Please note that if this custom url is unavailable (because it is already used, for example), a :class:`gdshortener.GDShortURLError` will be raised
            
            :type custom_url: str.
            :param log_stat: States if the generated url has statistical analisys attached.
                If the stats are enabled, a special url will show the stats on this shortened url. This special url is returned as second parameters of this function.
                
                Please notice that a stat enabled shorten url counts double in .gd rate exceeding monitor system.
                
                More information on `.gd FAQ <http://is.gd/faq.php#stats>`_ and `.gd rate limit <http://is.gd/usagelimits.php>`_.
            :type log_stat: bool.
            :returns:  (str,str) -- Shortened URL obtained by .gd service and Stat URL if requested (otherwhise is ``None``).
            :raises: **IOError** when timeout with .gd service occurs
            
                **ValueError** if .gd response is malformed
                
                :class:`gdshortener.GDMalformedURLError` if the URL provided for shortening is malformed
                
                :class:`gdshortener.GDShortURLError` if the custom URL requested is not available
                
                :class:`gdshortener.GDRateLimitError` if the request rate is exceeded for .gd service
                
                :class:`gdshortener.GDGenericError` in case of generic error from .gd service (mainteinance)
            
        ''' 
        if url is None or not isinstance(url, basestring) or len(url.strip()) == 0:
            raise GDMalformedURLError('The URL that had to be shorten must be a non empty string')
        # Build data to post
        data = {
                'format':   'json',
                'url':      url,
                'logstats': 1 if log_stat else 0
                }
        if custom_url is not None and isinstance(custom_url, basestring) and len(custom_url.strip()) > 0:
            data['shorturl'] = custom_url
        opener = urllib2.build_opener()
        headers = { 'User-Agent' : self._user_agent }
        req = urllib2.Request("{0}/create.php".format(self.shortener_url), urllib.urlencode(data), headers)
        f_desc = opener.open(req, timeout = self._timeout)
        response = json.loads(f_desc.read())
        if 'shorturl' in response:
            # Success!
            return (str(response['shorturl']), None if not log_stat else '{0}/stats.php?url={1}'.format(self.shortener_url, str(response['shorturl'])[str(response['shorturl']).rindex('/') + 1:]))
        else:
            # Error
            error_code = int(response['errorcode'])
            error_description = str(response['errormessage'])
            if error_code == 1:
                raise GDMalformedURLError(error_description)
            if error_code == 2:
                raise GDShortURLError(error_description)
            if error_code == 3:
                raise GDRateLimitError(error_description)
            if error_code == 4:
                raise GDGenericError(error_description)