Django

Code

Show
Ignore:
Timestamp:
07/04/08 15:16:22 (5 months ago)
Author:
jbronn
Message:

gis: Merged revisions 7772-7808,7811-7814,7816-7823,7826-7829,7831-7833,7835 via svnmerge from trunk. Modified GeoWhereNode accordingly for changes in r7835.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/branches/gis

    • Property svnmerge-integrated changed from /django/trunk:1-7767 to /django/trunk:1-7835
  • django/branches/gis/django/contrib/auth/backends.py

    r7279 r7836  
     1try: 
     2    set 
     3except NameError: 
     4    from sets import Set as set # Python 2.3 fallback 
     5 
    16from django.db import connection 
    27from django.contrib.auth.models import User 
    38 
    4 try:  
    5     set  
    6 except NameError:  
    7     from sets import Set as set # Python 2.3 fallback 
    8          
     9 
    910class ModelBackend(object): 
    1011    """ 
    11     Authenticate against django.contrib.auth.models.User 
     12    Authenticates against django.contrib.auth.models.User. 
    1213    """ 
    1314    # TODO: Model, login attribute name and password attribute name should be 
     
    2223 
    2324    def get_group_permissions(self, user_obj): 
    24         "Returns a list of permission strings that this user has through his/her groups." 
     25        """ 
     26        Returns a set of permission strings that this user has through his/her 
     27        groups. 
     28        """ 
    2529        if not hasattr(user_obj, '_group_perm_cache'): 
    2630            cursor = connection.cursor() 
     
    5155            user_obj._group_perm_cache = set(["%s.%s" % (row[0], row[1]) for row in cursor.fetchall()]) 
    5256        return user_obj._group_perm_cache 
    53      
     57 
    5458    def get_all_permissions(self, user_obj): 
    5559        if not hasattr(user_obj, '_perm_cache'): 
     
    6266 
    6367    def has_module_perms(self, user_obj, app_label): 
    64         return bool(len([p for p in self.get_all_permissions(user_obj) if p[:p.index('.')] == app_label])) 
     68        """ 
     69        Returns True if user_obj has any permissions in the given app_label. 
     70        """ 
     71        for perm in self.get_all_permissions(user_obj): 
     72            if perm[:perm.index('.')] == app_label: 
     73                return True 
     74        return False 
    6575 
    6676    def get_user(self, user_id): 
  • django/branches/gis/django/contrib/auth/models.py

    r7642 r7836  
    9797        verbose_name = _('group') 
    9898        verbose_name_plural = _('groups') 
    99         ordering = ('name',) 
    10099 
    101100    class Admin: 
    102101        search_fields = ('name',) 
     102        ordering = ('name',) 
    103103 
    104104    def __unicode__(self): 
     
    154154        verbose_name = _('user') 
    155155        verbose_name_plural = _('users') 
    156         ordering = ('username',) 
    157156 
    158157    class Admin: 
     
    167166        list_filter = ('is_staff', 'is_superuser') 
    168167        search_fields = ('username', 'first_name', 'last_name', 'email') 
     168        ordering = ('username',) 
    169169 
    170170    def __unicode__(self): 
  • django/branches/gis/django/contrib/auth/tests.py

    r7642 r7836  
    11""" 
    2 >>> from models import User, AnonymousUser 
     2>>> from django.contrib.auth.models import User, AnonymousUser 
    33>>> u = User.objects.create_user('testuser', 'test@example.com', 'testpw') 
    44>>> u.has_usable_password() 
     
    5454u'!' 
    5555""" 
     56 
     57from django.test import TestCase 
     58from django.core import mail 
     59 
     60class PasswordResetTest(TestCase): 
     61    fixtures = ['authtestdata.json'] 
     62    urls = 'django.contrib.auth.urls' 
     63    def test_email_not_found(self): 
     64        "Error is raised if the provided email address isn't currently registered" 
     65        response = self.client.get('/password_reset/') 
     66        self.assertEquals(response.status_code, 200) 
     67        response = self.client.post('/password_reset/', {'email': 'not_a_real_email@email.com'}) 
     68        self.assertContains(response, "That e-mail address doesn't have an associated user account") 
     69        self.assertEquals(len(mail.outbox), 0) 
     70 
     71    def test_email_found(self): 
     72        "Email is sent if a valid email address is provided for password reset" 
     73        response = self.client.post('/password_reset/', {'email': 'staffmember@example.com'}) 
     74        self.assertEquals(response.status_code, 302) 
     75        self.assertEquals(len(mail.outbox), 1) 
  • django/branches/gis/django/contrib/flatpages/models.py

    r7768 r7836  
    99        help_text=_("Example: '/about/contact/'. Make sure to have leading and trailing slashes.")) 
    1010    title = models.CharField(_('title'), max_length=200) 
    11     content = models.TextField(_('content')
     11    content = models.TextField(_('content'), blank=True
    1212    enable_comments = models.BooleanField(_('enable comments')) 
    1313    template_name = models.CharField(_('template name'), max_length=70, blank=True, 
  • django/branches/gis/django/contrib/formtools/tests.py

    r7768 r7836  
    2222 
    2323class PreviewTests(TestCase): 
     24    urls = 'django.contrib.formtools.test_urls' 
    2425 
    2526    def setUp(self): 
    26         self._old_root_urlconf = settings.ROOT_URLCONF 
    27         settings.ROOT_URLCONF = 'django.contrib.formtools.test_urls' 
    2827        # Create a FormPreview instance to share between tests 
    2928        self.preview = preview.FormPreview(TestForm) 
     
    3130        self.input = input_template % (self.preview.unused_name('stage'), "%d") 
    3231 
    33     def tearDown(self): 
    34         settings.ROOT_URLCONF = self._old_root_urlconf 
    35          
    3632    def test_unused_name(self): 
    3733        """ 
  • django/branches/gis/django/contrib/gis/db/backend/mysql/query.py

    r7699 r7836  
    3939MYSQL_GIS_TERMS  = MYSQL_GIS_FUNCTIONS.keys() 
    4040MYSQL_GIS_TERMS += MISC_TERMS 
    41 MYSQL_GIS_TERMS = tuple(MYSQL_GIS_TERMS) # Making immutable 
     41MYSQL_GIS_TERMS = dict((term, None) for term in MYSQL_GIS_TERMS) # Making dictionary  
    4242 
    43 def get_geo_where_clause(lookup_type, table_prefix, field, value): 
     43def get_geo_where_clause(table_alias, name, lookup_type, geo_annot): 
    4444    "Returns the SQL WHERE clause for use in MySQL spatial SQL construction." 
    4545    # Getting the quoted field as `geo_col`. 
    46     geo_col = '%s.%s' % (qn(table_prefix), qn(field.column)) 
     46    geo_col = '%s.%s' % (qn(table_alias), qn(name)) 
    4747 
    4848    # See if a MySQL Geometry function matches the lookup type next 
     
    5555    # geometries in its spatial indices. 
    5656    if lookup_type == 'isnull': 
    57         return "%s IS %sNULL" % (geo_col, (not value and 'NOT ' or '')) 
     57        return "%s IS %sNULL" % (geo_col, (not geo_annot.value and 'NOT ' or '')) 
    5858 
    5959    raise TypeError("Got invalid lookup_type: %s" % repr(lookup_type)) 
  • django/branches/gis/django/contrib/gis/db/backend/oracle/query.py

    r7641 r7836  
    111111 
    112112#### The `get_geo_where_clause` function for Oracle #### 
    113 def get_geo_where_clause(lookup_type, table_prefix, field, value): 
     113def get_geo_where_clause(table_alias, name, lookup_type, geo_annot): 
    114114    "Returns the SQL WHERE clause for use in Oracle spatial SQL construction." 
    115115    # Getting the quoted table name as `geo_col`. 
    116     geo_col = '%s.%s' % (qn(table_prefix), qn(field.column)) 
     116    geo_col = '%s.%s' % (qn(table_alias), qn(name)) 
    117117 
    118118    # See if a Oracle Geometry function matches the lookup type next 
     
    127127 
    128128            # Ensuring that a tuple _value_ was passed in from the user 
    129             if not isinstance(value, tuple): 
     129            if not isinstance(geo_annot.value, tuple): 
    130130                raise TypeError('Tuple required for `%s` lookup type.' % lookup_type) 
    131             if len(value) != 2:  
     131            if len(geo_annot.value) != 2:  
    132132                raise ValueError('2-element tuple required for %s lookup type.' % lookup_type) 
    133133             
    134134            # Ensuring the argument type matches what we expect. 
    135             if not isinstance(value[1], arg_type): 
    136                 raise TypeError('Argument type should be %s, got %s instead.' % (arg_type, type(value[1]))) 
     135            if not isinstance(geo_annot.value[1], arg_type): 
     136                raise TypeError('Argument type should be %s, got %s instead.' % (arg_type, type(geo_annot.value[1]))) 
    137137 
    138138            if lookup_type == 'relate': 
    139139                # The SDORelate class handles construction for these queries,  
    140140                # and verifies the mask argument. 
    141                 return sdo_op(value[1]).as_sql(geo_col) 
     141                return sdo_op(geo_annot.value[1]).as_sql(geo_col) 
    142142            else: 
    143143                # Otherwise, just call the `as_sql` method on the SDOOperation instance. 
     
    150150    elif lookup_type == 'isnull': 
    151151        # Handling 'isnull' lookup type 
    152         return "%s IS %sNULL" % (geo_col, (not value and 'NOT ' or '')) 
     152        return "%s IS %sNULL" % (geo_col, (not geo_annot.value and 'NOT ' or '')) 
    153153 
    154154    raise TypeError("Got invalid lookup_type: %s" % repr(lookup_type)) 
  • django/branches/gis/django/contrib/gis/db/backend/postgis/query.py

    r7641 r7836  
    219219POSTGIS_TERMS += POSTGIS_GEOMETRY_FUNCTIONS.keys() # Adding on the Geometry Functions 
    220220POSTGIS_TERMS += MISC_TERMS # Adding any other miscellaneous terms (e.g., 'isnull') 
    221 POSTGIS_TERMS = tuple(POSTGIS_TERMS) # Making immutable 
     221POSTGIS_TERMS = dict((term, None) for term in POSTGIS_TERMS) # Making a dictionary for fast lookups 
    222222 
    223223# For checking tuple parameters -- not very pretty but gets job done. 
     
    229229 
    230230#### The `get_geo_where_clause` function for PostGIS. #### 
    231 def get_geo_where_clause(lookup_type, table_prefix, field, value): 
     231def get_geo_where_clause(table_alias, name, lookup_type, geo_annot): 
    232232    "Returns the SQL WHERE clause for use in PostGIS SQL construction." 
    233233    # Getting the quoted field as `geo_col`. 
    234     geo_col = '%s.%s' % (qn(table_prefix), qn(field.column)) 
     234    geo_col = '%s.%s' % (qn(table_alias), qn(name)) 
    235235    if lookup_type in POSTGIS_OPERATORS: 
    236236        # See if a PostGIS operator matches the lookup type. 
     
    249249 
    250250            # Ensuring that a tuple _value_ was passed in from the user 
    251             if not isinstance(value, (tuple, list)):  
     251            if not isinstance(geo_annot.value, (tuple, list)):  
    252252                raise TypeError('Tuple required for `%s` lookup type.' % lookup_type) 
     253            
    253254            # Number of valid tuple parameters depends on the lookup type. 
    254             nparams = len(value) 
     255            nparams = len(geo_annot.value) 
    255256            if not num_params(lookup_type, nparams): 
    256257                raise ValueError('Incorrect number of parameters given for `%s` lookup type.' % lookup_type) 
    257258             
    258259            # Ensuring the argument type matches what we expect. 
    259             if not isinstance(value[1], arg_type): 
    260                 raise TypeError('Argument type should be %s, got %s instead.' % (arg_type, type(value[1]))) 
     260            if not isinstance(geo_annot.value[1], arg_type): 
     261                raise TypeError('Argument type should be %s, got %s instead.' % (arg_type, type(geo_annot.value[1]))) 
    261262 
    262263            # For lookup type `relate`, the op instance is not yet created (has 
    263264            # to be instantiated here to check the pattern parameter). 
    264265            if lookup_type == 'relate':  
    265                 op = op(value[1]) 
     266                op = op(geo_annot.value[1]) 
    266267            elif lookup_type in DISTANCE_FUNCTIONS and lookup_type != 'dwithin': 
    267                 if field.geodetic: 
     268                if geo_annot.geodetic: 
    268269                    # Geodetic distances are only availble from Points to PointFields. 
    269                     if field._geom != 'POINT': 
     270                    if geo_annot.geom_type != 'POINT': 
    270271                        raise TypeError('PostGIS spherical operations are only valid on PointFields.') 
    271                     if value[0].geom_typeid != 0: 
     272                    if geo_annot.value[0].geom_typeid != 0: 
    272273                        raise TypeError('PostGIS geometry distance parameter is required to be of type Point.') 
    273274                    # Setting up the geodetic operation appropriately. 
    274                     if nparams == 3 and value[2] == 'spheroid': op = op[2] 
     275                    if nparams == 3 and geo_annot.value[2] == 'spheroid': op = op[2] 
    275276                    else: op = op[1] 
    276277                else: 
     
    282283    elif lookup_type == 'isnull': 
    283284        # Handling 'isnull' lookup type 
    284         return "%s IS %sNULL" % (geo_col, (not value and 'NOT ' or '')) 
     285        return "%s IS %sNULL" % (geo_col, (not geo_annot.value and 'NOT ' or '')) 
    285286 
    286287    raise TypeError("Got invalid lookup_type: %s" % repr(lookup_type)) 
  • django/branches/gis/django/contrib/gis/db/models/fields/__init__.py

    r7641 r7836  
    112112                raise ValueError('Could not create geometry from lookup value: %s' % str(value)) 
    113113        else: 
    114             raise TypeError('Cannot use parameter of `%s` type as lookup parameter.' % type(value)) 
     114            raise TypeError('Cannot use parameter of `%s` type as a geometry lookup parameter.' % type(value)) 
    115115 
    116116        # Assigning the SRID value. 
  • django/branches/gis/django/contrib/gis/db/models/sql/query.py

    r7699 r7836  
    104104        return result 
    105105 
    106     def get_default_columns(self, with_aliases=False, col_aliases=None): 
     106    def get_default_columns(self, with_aliases=False, col_aliases=None, 
     107                            start_alias=None, opts=None, as_pairs=False): 
    107108        """ 
    108109        Computes the default columns for selecting every field in the base 
     
    116117        """ 
    117118        result = [] 
    118         table_alias = self.tables[0] 
     119        if opts is None: 
     120            opts = self.model._meta 
     121        if start_alias: 
     122            table_alias = start_alias 
     123        else: 
     124            table_alias = self.tables[0] 
    119125        root_pk = self.model._meta.pk.column 
    120126        seen = {None: table_alias} 
    121         qn = self.quote_name_unless_alias 
    122         qn2 = self.connection.ops.quote_name 
    123127        aliases = set() 
    124128        for field, model in self.model._meta.get_fields_with_model(): 
     
    129133                        root_pk, model._meta.pk.column)) 
    130134                seen[model] = alias 
    131  
     135            if as_pairs: 
     136                result.append((alias, field.column)) 
     137                continue 
    132138            # This part of the function is customized for GeoQuery. We 
    133139            # see if there was any custom selection specified in the 
    134140            # dictionary, and set up the selection format appropriately. 
    135141            field_sel = self.get_field_select(field, alias) 
    136  
    137142            if with_aliases and field.column in col_aliases: 
    138143                c_alias = 'Col%d' % len(col_aliases) 
     
    146151                if with_aliases: 
    147152                    col_aliases.add(field.column) 
     153        if as_pairs: 
     154            return result, None 
    148155        return result, aliases 
    149156 
  • django/branches/gis/django/contrib/gis/db/models/sql/where.py

    r7641 r7836  
     1import datetime 
     2from django.db.models.fields import Field 
    13from django.db.models.sql.where import WhereNode 
    24from django.contrib.gis.db.backend import get_geo_where_clause, SpatialBackend 
    35 
     6class GeoAnnotation(object): 
     7    """ 
     8    The annotation used for GeometryFields; basically a placeholder 
     9    for metadata needed by the `get_geo_where_clause` of the spatial 
     10    backend. 
     11    """ 
     12    def __init__(self, field, value, where): 
     13        self.geodetic = field.geodetic 
     14        self.geom_type = field._geom 
     15        self.value = value 
     16        self.where = tuple(where) 
     17 
    418class GeoWhereNode(WhereNode): 
    519    """ 
    6     The GeoWhereNode calls the `get_geo_where_clause` from the appropriate 
    7     spatial backend in order to construct correct spatial SQL
     20    Used to represent the SQL where-clause for spatial databases -- 
     21    these are tied to the GeoQuery class that created it
    822    """ 
     23    def add(self, data, connector): 
     24        """ 
     25        This is overridden from the regular WhereNode to handle the  
     26        peculiarties of GeometryFields, because they need a special  
     27        annotation object that contains the spatial metadata from the  
     28        field so that the correct spatial SQL is generated. 
     29        """ 
     30        if not isinstance(data, (list, tuple)): 
     31            super(WhereNode, self).add(data, connector) 
     32            return 
     33 
     34        alias, col, field, lookup_type, value = data 
     35        # Do we have a geographic field? 
     36        geo_field = hasattr(field, '_geom') 
     37        if field: 
     38            if geo_field: 
     39                # `GeometryField.get_db_prep_lookup` returns a where clause 
     40                # substitution array in addition to the parameters. 
     41                where, params = field.get_db_prep_lookup(lookup_type, value) 
     42            else: 
     43                params = field.get_db_prep_lookup(lookup_type, value) 
     44            db_type = field.db_type() 
     45        else: 
     46            # This is possible when we add a comparison to NULL sometimes (we 
     47            # don't really need to waste time looking up the associated field 
     48            # object). 
     49            params = Field().get_db_prep_lookup(lookup_type, value) 
     50            db_type = None 
     51   
     52        if geo_field: 
     53            # The annotation will be a `GeoAnnotation` object that 
     54            # will contain the necessary geometry field metadata for 
     55            # the `get_geo_where_clause` to construct the appropriate 
     56            # spatial SQL when `make_atom` is called. 
     57            annotation = GeoAnnotation(field, value, where) 
     58        elif isinstance(value, datetime.datetime): 
     59            annotation = datetime.datetime 
     60        else: 
     61            annotation = bool(value) 
     62 
     63        super(WhereNode, self).add((alias, col, db_type, lookup_type, 
     64                                    annotation, params), connector) 
     65 
    966    def make_atom(self, child, qn): 
    10         table_alias, name, field, lookup_type, value = child 
    11         if hasattr(field, '_geom'): 
     67        table_alias, name, db_type, lookup_type, value_annot, params = child 
     68  
     69        if isinstance(value_annot, GeoAnnotation): 
    1270            if lookup_type in SpatialBackend.gis_terms: 
    1371                # Getting the geographic where clause; substitution parameters 
    1472                # will be populated in the GeoFieldSQL object returned by the 
    1573                # GeometryField. 
    16                 gwc = get_geo_where_clause(lookup_type, table_alias, field, value) 
    17                 where, params = field.get_db_prep_lookup(lookup_type, value) 
    18                 return gwc % tuple(where), params 
     74                gwc = get_geo_where_clause(table_alias, name, lookup_type, value_annot) 
     75                return gwc % value_annot.where, params 
    1976            else: 
    2077                raise TypeError('Invalid lookup type: %r' % lookup_type) 
  • django/branches/gis/django/contrib/gis/tests/distapp/tests.py

    r7666 r7836  
    8989                 
    9090            # Creating the query set. 
    91             qs = AustraliaCity.objects.filter(point__dwithin=(self.au_pnt, dist)).order_by('name') 
     91            qs = AustraliaCity.objects.order_by('name') 
    9292            if type_error: 
    9393                # A TypeError should be raised on PostGIS when trying to pass 
    9494                # Distance objects into a DWithin query using a geodetic field.   
    95                 self.assertRaises(TypeError, qs.count
     95                self.assertRaises(TypeError, AustraliaCity.objects.filter, point__dwithin=(self.au_pnt, dist)
    9696            else: 
    97                 self.assertEqual(au_cities, self.get_names(qs)) 
    98  
     97                self.assertEqual(au_cities, self.get_names(qs.filter(point__dwithin=(self.au_pnt, dist)))) 
     98                                  
    9999    def test03a_distance_method(self): 
    100100        "Testing the `distance` GeoQuerySet method on projected coordinate systems." 
     
    218218            # Too many params (4 in this case) should raise a ValueError. 
    219219            self.assertRaises(ValueError,  
    220                               AustraliaCity.objects.filter(point__distance_lte=('POINT(5 23)', D(km=100), 'spheroid', '4')).count
     220                              AustraliaCity.objects.filter, point__distance_lte=('POINT(5 23)', D(km=100), 'spheroid', '4')
    221221 
    222222        # Not enough params should raise a ValueError. 
    223223        self.assertRaises(ValueError, 
    224                           AustraliaCity.objects.filter(point__distance_lte=('POINT(5 23)',)).count
     224                          AustraliaCity.objects.filter, point__distance_lte=('POINT(5 23)',)
    225225 
    226226        # Getting all cities w/in 550 miles of Hobart. 
  • django/branches/gis/django/contrib/gis/tests/geoapp/tests.py

    r7699 r7836  
    199199    def test06_make_line(self): 
    200200        "Testing the `make_line` GeoQuerySet method." 
     201        if DISABLE: return 
    201202        # Ensuring that a `TypeError` is raised on models without PointFields. 
    202203        self.assertRaises(TypeError, State.objects.make_line) 
     
    382383        pnt2 = fromstr('POINT(-98.4919715741052 29.4333344025053)', srid=4326) 
    383384 
    384         # Testing bad argument tuples that should return a TypeError or 
    385         # a ValueError. 
    386         bad_args = [((pnt1, 0), TypeError), 
    387                     ((pnt2, 'T*T***FF*', 0), ValueError), 
    388                     ((23, 'foo'), ValueError), 
    389                     ] 
    390         for args, e in bad_args: 
    391             qs = Country.objects.filter(mpoly__relate=args) 
     385        # Not passing in a geometry as first param shoud  
     386        # raise a type error when initializing the GeoQuerySet 
     387        self.assertRaises(TypeError, Country.objects.filter, mpoly__relate=(23, 'foo')) 
     388        # Making sure the right exception is raised for the given 
     389        # bad arguments. 
     390        for bad_args, e in [((pnt1, 0), TypeError), ((pnt2, 'T*T***FF*', 0), ValueError)]: 
     391            qs = Country.objects.filter(mpoly__relate=bad_args) 
    392392            self.assertRaises(e, qs.count) 
    393393 
     
    472472    def test19_centroid(self): 
    473473        "Testing the `centroid` GeoQuerySet method." 
     474        if DISABLE: return 
    474475        qs = State.objects.exclude(poly__isnull=True).centroid() 
    475476        if oracle: tol = 0.1 
     
    480481    def test20_pointonsurface(self): 
    481482        "Testing the `point_on_surface` GeoQuerySet method." 
     483        if DISABLE: return 
    482484        # Reference values. 
    483485        if SpatialBackend.oracle: 
     
    498500    def test21_scale(self): 
    499501        "Testing the `scale` GeoQuerySet method." 
     502        if DISABLE: return 
    500503        xfac, yfac = 2, 3 
    501504        qs = Country.objects.scale(xfac, yfac, model_att='scaled') 
     
    510513    def test22_translate(self): 
    511514        "Testing the `translate` GeoQuerySet method." 
     515        if DISABLE: return 
    512516        xfac, yfac = 5, -23 
    513517        qs = Country.objects.translate(xfac, yfac, model_att='translated') 
     
    521525    def test23_numgeom(self): 
    522526        "Testing the `num_geom` GeoQuerySet method." 
     527        if DISABLE: return 
    523528        # Both 'countries' only have two geometries. 
    524529        for c in Country.objects.num_geom(): self.assertEqual(2, c.num_geom) 
     
    531536    def test24_numpoints(self): 
    532537        "Testing the `num_points` GeoQuerySet method." 
     538        if DISABLE: return 
    533539        for c in Country.objects.num_points(): self.assertEqual(c.mpoly.num_points, c.num_points) 
    534540        if postgis: 
     
    539545    def test25_geoset(self): 
    540546        "Testing the `difference`, `intersection`, `sym_difference`, and `union` GeoQuerySet methods." 
     547        if DISABLE: return 
    541548        geom = Point(5, 23) 
    542549        for c in Country.objects.all().intersection(geom).difference(geom).sym_difference(geom).union(geom):