Code

Ticket #15277: 15277.4.patch

File 15277.4.patch, 10.7 KB (added by jpaulett, 3 years ago)

Test TimeField by having GDAL inspect a geo database model

  • deleted file django/contrib/gis/management/base.py

    diff --git django/contrib/gis/management/base.py django/contrib/gis/management/base.py
    deleted file mode 100644
    index c998063..0000000
    + -  
    1 from django.core.management.base import BaseCommand, CommandError 
    2  
    3 class ArgsCommand(BaseCommand): 
    4     """ 
    5     Command class for commands that take multiple arguments. 
    6     """ 
    7     args = '<arg arg ...>' 
    8  
    9     def handle(self, *args, **options): 
    10         if not args: 
    11             raise CommandError('Must provide the following arguments: %s' % self.args) 
    12         return self.handle_args(*args, **options) 
    13  
    14     def handle_args(self, *args, **options): 
    15         raise NotImplementedError() 
  • django/contrib/gis/management/commands/ogrinspect.py

    diff --git django/contrib/gis/management/commands/ogrinspect.py django/contrib/gis/management/commands/ogrinspect.py
    index 13f1c0a..bffb073 100644
     
    11import os 
    22from optparse import make_option 
    33from django.contrib.gis import gdal 
    4 from django.contrib.gis.management.base import ArgsCommand, CommandError 
     4from django.core.management.base import LabelCommand, CommandError 
    55 
    66def layer_option(option, opt, value, parser): 
    77    """ 
    def list_option(option, opt, value, parser): 
    2626        dest = [s for s in value.split(',')] 
    2727    setattr(parser.values, option.dest, dest) 
    2828     
    29 class Command(ArgsCommand): 
     29class Command(LabelCommand): 
    3030    help = ('Inspects the given OGR-compatible data source (e.g., a shapefile) and outputs\n' 
    3131            'a GeoDjango model with the given model name. For example:\n' 
    3232            ' ./manage.py ogrinspect zipcode.shp Zipcode') 
    3333    args = '[data_source] [model_name]' 
    3434 
    35     option_list = ArgsCommand.option_list + ( 
     35    option_list = LabelCommand.option_list + ( 
    3636        make_option('--blank', dest='blank', type='string', action='callback',   
    3737                    callback=list_option, default=False, 
    3838                    help='Use a comma separated list of OGR field names to add ' 
    class Command(ArgsCommand): 
    7272 
    7373    requires_model_validation = False 
    7474 
    75     def handle_args(self, *args, **options): 
     75    def handle(self, *args, **options): 
    7676        try: 
    7777            data_source, model_name = args 
    7878        except ValueError: 
    class Command(ArgsCommand): 
    8181        if not gdal.HAS_GDAL: 
    8282            raise CommandError('GDAL is required to inspect geospatial data sources.') 
    8383 
    84         # TODO: Support non file-based OGR datasources. 
    85         if not os.path.isfile(data_source): 
    86             raise CommandError('The given data source cannot be found: "%s"' % data_source) 
    87          
    8884        # Removing options with `None` values. 
    8985        options = dict([(k, v) for k, v in options.items() if not v is None]) 
    9086 
    class Command(ArgsCommand): 
    9793        # Whether the user wants to generate the LayerMapping dictionary as well. 
    9894        show_mapping = options.pop('mapping', False) 
    9995 
    100         # Popping the verbosity global option, as it's not accepted by `_ogrinspect`. 
     96        # Getting rid of settings that `_ogrinspect` doesn't like. 
    10197        verbosity = options.pop('verbosity', False) 
     98        settings = options.pop('settings', False) 
    10299 
    103100        # Returning the output of ogrinspect with the given arguments 
    104101        # and options. 
    class Command(ArgsCommand): 
    119116                           '%s_mapping = {' % model_name.lower()]) 
    120117            output.extend(["    '%s' : '%s'," % (rev_mapping[ogr_fld], ogr_fld) for ogr_fld in ds[options['layer_key']].fields]) 
    121118            output.extend(["    '%s' : '%s'," % (options['geom_name'], mapping_dict[options['geom_name']]), '}']) 
    122         return '\n'.join(output) 
     119        return '\n'.join(output) + '\n' 
  • django/contrib/gis/tests/__init__.py

    diff --git django/contrib/gis/tests/__init__.py django/contrib/gis/tests/__init__.py
    index 3d04242..75919b2 100644
    def geo_apps(namespace=True, runtests=False): 
    1717    from django.contrib.gis.geos import GEOS_PREPARE 
    1818    from django.contrib.gis.gdal import HAS_GDAL 
    1919 
    20     apps = ['geoapp', 'relatedapp'] 
     20    apps = ['geoapp', 'relatedapp', 'inspectapp'] 
    2121 
    2222    # No distance queries on MySQL. 
    2323    if not connection.ops.mysql: 
  • new file django/contrib/gis/tests/inspectapp/models.py

    diff --git django/contrib/gis/tests/inspectapp/__init__.py django/contrib/gis/tests/inspectapp/__init__.py
    new file mode 100644
    index 0000000..e69de29
    diff --git django/contrib/gis/tests/inspectapp/models.py django/contrib/gis/tests/inspectapp/models.py
    new file mode 100644
    index 0000000..0f1b0d4
    - +  
     1from django.contrib.gis.db import models 
     2 
     3class AllOGRFields(models.Model): 
     4    f_decimal = models.FloatField() 
     5    f_float = models.FloatField() 
     6    f_int = models.IntegerField() 
     7    f_char = models.CharField(max_length=10) 
     8    f_date = models.DateField() 
     9    f_datetime = models.DateTimeField() 
     10    f_time = models.TimeField() 
     11    geom = models.PolygonField() 
     12 
     13    objects = models.GeoManager() 
  • new file django/contrib/gis/tests/inspectapp/tests.py

    diff --git django/contrib/gis/tests/inspectapp/tests.py django/contrib/gis/tests/inspectapp/tests.py
    new file mode 100644
    index 0000000..c747e0a
    - +  
     1import os 
     2from django.contrib.gis.geometry.test_data import TEST_DATA 
     3from django.contrib.gis.tests.utils import no_spatialite 
     4from django.contrib.gis.utils.ogrinspect import ogrinspect 
     5from django.db import connections 
     6from django.utils import unittest 
     7from django.contrib.gis.tests.utils import ( 
     8    no_mysql, no_oracle, no_spatialite, 
     9    mysql, oracle, postgis, spatialite) 
     10from models import AllOGRFields 
     11 
     12 
     13class OGRInspectTest(unittest.TestCase): 
     14    def test_poly(self): 
     15        shp_file = os.path.join(TEST_DATA, 'test_poly', 'test_poly.shp') 
     16        model_def = ogrinspect(shp_file, 'MyModel') 
     17 
     18        expected = [ 
     19            '# This is an auto-generated Django model module created by ogrinspect.', 
     20            'from django.contrib.gis.db import models', 
     21            '', 
     22            'class MyModel(models.Model):', 
     23            '    float = models.FloatField()', 
     24            '    int = models.FloatField()', 
     25            '    str = models.CharField(max_length=80)', 
     26            '    geom = models.PolygonField(srid=-1)', 
     27            '    objects = models.GeoManager()', 
     28        ] 
     29 
     30        self.assertEqual(model_def, '\n'.join(expected)) 
     31 
     32    def test_date_field(self): 
     33        shp_file = os.path.join(TEST_DATA, 'cities', 'cities.shp') 
     34        model_def = ogrinspect(shp_file, 'City') 
     35 
     36        expected = [ 
     37            '# This is an auto-generated Django model module created by ogrinspect.', 
     38            'from django.contrib.gis.db import models', 
     39            '', 
     40            'class City(models.Model):', 
     41            '    name = models.CharField(max_length=80)', 
     42            '    population = models.FloatField()', 
     43            '    density = models.FloatField()', 
     44            '    created = models.DateField()', 
     45            '    geom = models.PointField(srid=-1)', 
     46            '    objects = models.GeoManager()', 
     47        ] 
     48 
     49        self.assertEqual(model_def, '\n'.join(expected)) 
     50 
     51    @no_spatialite 
     52    def test_time_field(self): 
     53        # writing shapefules via GDAL currently does not support writing OGRTime 
     54        # fields, so we need to actually use a database 
     55 
     56        model_def = ogrinspect(get_ogr_db_string(None), 'Measurement', 
     57                               layer_key=AllOGRFields._meta.db_table, 
     58                               decimal=['f_decimal']) 
     59 
     60        expected = [ 
     61            '# This is an auto-generated Django model module created by ogrinspect.', 
     62            'from django.contrib.gis.db import models', 
     63            '', 
     64            'class Measurement(models.Model):', 
     65            '    f_decimal = models.DecimalField(max_digits=0, decimal_places=0)', 
     66            '    f_int = models.IntegerField()', 
     67            '    f_datetime = models.DateTimeField()', 
     68            '    f_time = models.TimeField()', 
     69            '    f_float = models.FloatField()', 
     70            '    f_char = models.CharField(max_length=10)', 
     71            '    f_date = models.DateField()', 
     72            '    geom = models.PolygonField()', 
     73            '    objects = models.GeoManager()', 
     74        ] 
     75 
     76        self.assertEqual(model_def, '\n'.join(expected)) 
     77 
     78def get_ogr_db_string(model): 
     79    # construct the DB string that GDAL will use to inspect the database. 
     80    # GDAL will create its own connection to the database, so we re-use the 
     81    # connection settings from the Django test.  This approach is a bit fragile 
     82    # and can not work on sqlite test databases (since they are in memory) 
     83 
     84    db = connections.databases['default'] 
     85 
     86    # map from the django backend into the GDAL database identifier 
     87    # http://www.gdal.org/ogr/ogr_formats.html 
     88    driver = { 
     89        'django.contrib.gis.db.backends.postgis': 'PG', 
     90        'django.contrib.gis.db.backends.mysql': 'MYSQL', 
     91        'django.contrib.gis.db.backends.oracle': 'OCI', 
     92    }[db['ENGINE']] 
     93 
     94    # build the params of the connection string 
     95    params = ["dbname='{0}'".format(db['NAME'])] 
     96    def add(key, template): 
     97        value = db.get(key, None) 
     98        # don't add the parameter if it is not in django's settings 
     99        if value is not None: 
     100            params.append(template.format(value)) 
     101    add('HOST', "host='{0}'") 
     102    add('PORT', "port='{0}'") 
     103    add('USER', "user='{0}'") 
     104    add('PASSWORD', "password='{0}'") 
     105 
     106    return '%s:%s' % (driver, ' '.join(params)) 
     107 
  • django/contrib/gis/utils/ogrinspect.py

    diff --git django/contrib/gis/utils/ogrinspect.py django/contrib/gis/utils/ogrinspect.py
    index fe4443c..aa4e209 100644
    Author: Travis Pinney, Dane Springmeyer, & Justin Bronn 
    88from itertools import izip 
    99# Requires GDAL to use. 
    1010from django.contrib.gis.gdal import DataSource 
    11 from django.contrib.gis.gdal.field import OFTDate, OFTDateTime, OFTInteger, OFTReal, OFTString 
     11from django.contrib.gis.gdal.field import OFTDate, OFTDateTime, OFTInteger, OFTReal, OFTString, OFTTime 
    1212 
    1313def mapping(data_source, geom_name='geom', layer_key=0, multi_geom=False): 
    1414    """ 
    def _ogrinspect(data_source, model_name, geom_name='geom', layer_key=0, srid=Non 
    189189            yield '    %s = models.DateField(%s)' % (mfield, kwargs_str[2:]) 
    190190        elif field_type is OFTDateTime: 
    191191            yield '    %s = models.DateTimeField(%s)' % (mfield, kwargs_str[2:]) 
    192         elif field_type is OFTDate: 
     192        elif field_type is OFTTime: 
    193193            yield '    %s = models.TimeField(%s)' % (mfield, kwargs_str[2:]) 
    194194        else: 
    195195            raise TypeError('Unknown field type %s in %s' % (field_type, mfield))