class Viewbox():
    """
    Class representing a bounding box.
    Defaults to maximum bounds for WKID 4326.
    """

    def _validate(self):
        """
        Make sure numbers are actually numbers
        Return True if WKID is found and Viewbox is within maximum bounds.
        Return True if WKID is not found.
        Otherwise raise error.
        """

        return True #TODO: Find max bounds from WKID in PostGIS database

    def convert_srs(self, new_wkid):
        """Return a new Viewbox object with the specified SRS."""

        return self # TODO: convert SRS

    def __init__(self, left=-180, top=90, right=180, bottom=-90, wkid=4326):
        """
        :arg left: Minimum X value (default -180)
        :arg top: Maximum Y value (default 90)
        :arg right: Maximum X value (default 180)
        :arg bottom: Minimum Y value (default -90)
        :arg wkid: Well-known ID for spatial reference system (default 4326)
        """
        for k in locals().keys():
            if k != 'self': setattr(self, k, locals()[k])
        self._validate() 

    def to_bing_str(self):
        """
        Convert Viewbox object to a string that can be used by Bing
        as a query parameter.
        """

        vb = self.convert_srs(4326)
        return '%s,%s,%s,%s' % (vb.bottom, vb.left, vb.top, vb.right)

    def to_mapquest_str(self):
        """
        Convert Viewbox object to a string that can be used by
        MapQuest as a query parameter.
        """
        
        vb = self.convert_srs(4326)
        return '%s,%s,%s,%s' % (vb.left, vb.top, vb.right, vb.bottom)

    def to_esri_wgs_json(self):
        """
        Convert Viewbox object to a JSON string that can be used
        by the ESRI World Geocoding Service as a parameter.
        """
        try:
            return ('{ "xmin" : %s, '
                    '"ymin" : %s, '
                    '"xmax" : %s, '
                    '"ymax" : %s, '
                    '"spatialReference" : {"wkid" : %d} }'
                    % (self.left,
                       self.bottom,
                       self.top,
                       self.right,
                       self.wkid))
        except ValueError:
            raise Exception('One or more values could not be cast to a number. '
                            'Four bounding points must be real numbers. '
                            'WKID must be an integer.')
    
class PlaceQuery():
    """
    Class representing an address or place that will be passed to geocoders.
    """
    def __init__(self, query='', address='', city='', state='', postal='', country='', 
                viewbox=None, bounded=False, **kwargs):
        """
        :arg str query: A string containing the query to parse
                        and match to a coordinate on the map.
                        *ex: "340 N 12th St Philadelphia PA 19107"
                        or "Wolf Building, Philadelphia"*
        :arg str address: A string for the street line of an address.
                          *ex: "340 N 12th St"*
        :arg str city: A string specifying the populated place for the address.
                       This commonly refers to a city, but may refer to a suburb
                       or neighborhood in certain countries.
        :arg str state: A string for the state, province, territory, etc.
        :arg str postal: A string for the postal / ZIP Code
        :arg str country: A string for the country or region. Because the geocoder
                          uses the country to determine which geocoding service to use,
                          this is strongly recommended for efficency. ISO alpha-2 is
                          preferred, and is required by some geocoder services.
        :arg Viewbox viewbox: A Viewbox object indicating the preferred area
                              to find search results (default None)
        :arg bool bounded: Boolean indicating whether or not to only
                           return candidates within the given Viewbox (default False)

        :key float user_lat: A float representing the Latitude of the end-user.
        :key float user_lon: A float representing the Longitude of the end-user.
        :key str user_ip: A string representing the IP address of the end-user.
        :key str culture: Culture code to be used for the request (used by Bing).
                          For example, if set to 'de', the country for a U.S. address
                          would be returned as "Vereinigte Staaten Von Amerika"
                          instead of "United States".
    """
        for k in locals().keys():
            if k not in ['self', 'kwargs']: setattr(self, k, locals()[k])
        if query == '' and address == '' and city == '' and state == '' and postal == '':
            raise Exception('Must provide query or one or more of address, city, state, and postal.')
        for k in kwargs:
            setattr(self, k, kwargs[k])
            
    def __unicode__(self):
        return '%s%s' % (self.query, self.address)
    __str__ = __unicode__

class Candidate():
    """
    Class representing a candidate address returned from geocoders.
    Accepts arguments defined below, plus informal keyword arguments.

    Usage Example:

        c = Candidate('US_RoofTop', 91.5, '340 N 12th St, Philadelphia, PA, 19107',
            '-75.16', '39.95', some_key_foo='bar')
    """

    def __init__(self, locator='', score=0, match_addr='', x=None, y=None,
        wkid=4326, **kwargs):
        """
        :arg locator: Locator used for geocoding (default '')
                      We try to standardize this to
                       * `rooftop`,
                       * `interpolated`,
                       * `postal_specific`, and 
                       * `postal`.

        :arg score: Standardized score (default 0)
        :arg str match_addr: Address returned by geocoder (default '')
        :arg x: X-coordinate (longitude for lat-lon SRS) (default None)
        :arg y: Y-coordinate (latitude for lat-lon SRS) (default None)
        :arg wkid: Well-known ID for spatial reference system (default 4326)

        Keyword arguments can be added in order to be able to use postprocessors
        with API output fields are not well-fitting for one of the definitions
        above
        """

        for k in locals().keys():
            if k not in ['self', 'kwargs']: setattr(self, k, locals()[k])
        for k in kwargs:
            setattr(self, k, kwargs[k])

    def __unicode__(self):
        if self.match_addr == '':
            match_addr = '(no address specified)'
        else:
            match_addr = self.match_addr

        if self.x is None:
            x = '(no x coord specified)'
        else:
            x = self.x

        if self.y is None:
            y = '(no y coord specified)'
        else:
            y = self.y

        geoservice = 'via %s' % getattr(self, 'geoservice', '(no geoservice specfied')
        return '%s (%s, %s) %s' % (match_addr, x, y, geoservice)

    def __str__(self):
        return unicode(self).encode('utf-8')

@@ -1442,16 +1442,17 @@
         
+%60
 MapQuest
@@ -1452,16 +1452,74 @@
 apQuest 
+%3Chttp://www.mapquestapi.com/geocoding/#options%3E%60_%0A        
 as a que
@@ -1544,24 +1544,16 @@
     %22%22%22%0A
-        
 %0A       
@@ -5131,16 +5131,17 @@
 code__%0A%0A
+%0A
 class Ca

add mq link