summaryrefslogtreecommitdiff
path: root/lib/python2.7/site-packages/django/contrib/gis/utils
diff options
context:
space:
mode:
authorttt2017-05-13 00:29:47 +0530
committerttt2017-05-13 00:29:47 +0530
commitabf599be33b383a6a5baf9493093b2126a622ac8 (patch)
tree4c5ab6e0d935d5e65fabcf0258e4a00dd20a5afa /lib/python2.7/site-packages/django/contrib/gis/utils
downloadSBHS-2018-Rpi-abf599be33b383a6a5baf9493093b2126a622ac8.tar.gz
SBHS-2018-Rpi-abf599be33b383a6a5baf9493093b2126a622ac8.tar.bz2
SBHS-2018-Rpi-abf599be33b383a6a5baf9493093b2126a622ac8.zip
added all server files
Diffstat (limited to 'lib/python2.7/site-packages/django/contrib/gis/utils')
-rw-r--r--lib/python2.7/site-packages/django/contrib/gis/utils/__init__.py17
-rw-r--r--lib/python2.7/site-packages/django/contrib/gis/utils/layermapping.py596
-rw-r--r--lib/python2.7/site-packages/django/contrib/gis/utils/ogrinfo.py53
-rw-r--r--lib/python2.7/site-packages/django/contrib/gis/utils/ogrinspect.py225
-rw-r--r--lib/python2.7/site-packages/django/contrib/gis/utils/srs.py80
-rw-r--r--lib/python2.7/site-packages/django/contrib/gis/utils/wkt.py57
6 files changed, 1028 insertions, 0 deletions
diff --git a/lib/python2.7/site-packages/django/contrib/gis/utils/__init__.py b/lib/python2.7/site-packages/django/contrib/gis/utils/__init__.py
new file mode 100644
index 0000000..c6617d2
--- /dev/null
+++ b/lib/python2.7/site-packages/django/contrib/gis/utils/__init__.py
@@ -0,0 +1,17 @@
+"""
+ This module contains useful utilities for GeoDjango.
+"""
+# Importing the utilities that depend on GDAL, if available.
+from django.contrib.gis.gdal import HAS_GDAL
+if HAS_GDAL:
+ from django.contrib.gis.utils.ogrinfo import ogrinfo, sample
+ from django.contrib.gis.utils.ogrinspect import mapping, ogrinspect
+ from django.contrib.gis.utils.srs import add_postgis_srs, add_srs_entry
+ try:
+ # LayerMapping requires DJANGO_SETTINGS_MODULE to be set,
+ # so this needs to be in try/except.
+ from django.contrib.gis.utils.layermapping import LayerMapping, LayerMapError
+ except:
+ pass
+
+from django.contrib.gis.utils.wkt import precision_wkt
diff --git a/lib/python2.7/site-packages/django/contrib/gis/utils/layermapping.py b/lib/python2.7/site-packages/django/contrib/gis/utils/layermapping.py
new file mode 100644
index 0000000..a502aa2
--- /dev/null
+++ b/lib/python2.7/site-packages/django/contrib/gis/utils/layermapping.py
@@ -0,0 +1,596 @@
+# LayerMapping -- A Django Model/OGR Layer Mapping Utility
+"""
+ The LayerMapping class provides a way to map the contents of OGR
+ vector files (e.g. SHP files) to Geographic-enabled Django models.
+
+ For more information, please consult the GeoDjango documentation:
+ http://geodjango.org/docs/layermapping.html
+"""
+import sys
+from decimal import Decimal
+from django.core.exceptions import ObjectDoesNotExist
+from django.db import connections, router
+from django.contrib.gis.db.models import GeometryField
+from django.contrib.gis.gdal import (CoordTransform, DataSource,
+ OGRException, OGRGeometry, OGRGeomType, SpatialReference)
+from django.contrib.gis.gdal.field import (
+ OFTDate, OFTDateTime, OFTInteger, OFTReal, OFTString, OFTTime)
+from django.db import models, transaction
+from django.utils import six
+from django.utils.encoding import force_text
+
+
+# LayerMapping exceptions.
+class LayerMapError(Exception): pass
+class InvalidString(LayerMapError): pass
+class InvalidDecimal(LayerMapError): pass
+class InvalidInteger(LayerMapError): pass
+class MissingForeignKey(LayerMapError): pass
+
+class LayerMapping(object):
+ "A class that maps OGR Layers to GeoDjango Models."
+
+ # Acceptable 'base' types for a multi-geometry type.
+ MULTI_TYPES = {1 : OGRGeomType('MultiPoint'),
+ 2 : OGRGeomType('MultiLineString'),
+ 3 : OGRGeomType('MultiPolygon'),
+ OGRGeomType('Point25D').num : OGRGeomType('MultiPoint25D'),
+ OGRGeomType('LineString25D').num : OGRGeomType('MultiLineString25D'),
+ OGRGeomType('Polygon25D').num : OGRGeomType('MultiPolygon25D'),
+ }
+
+ # Acceptable Django field types and corresponding acceptable OGR
+ # counterparts.
+ FIELD_TYPES = {
+ models.AutoField : OFTInteger,
+ models.IntegerField : (OFTInteger, OFTReal, OFTString),
+ models.FloatField : (OFTInteger, OFTReal),
+ models.DateField : OFTDate,
+ models.DateTimeField : OFTDateTime,
+ models.EmailField : OFTString,
+ models.TimeField : OFTTime,
+ models.DecimalField : (OFTInteger, OFTReal),
+ models.CharField : OFTString,
+ models.SlugField : OFTString,
+ models.TextField : OFTString,
+ models.URLField : OFTString,
+ models.BigIntegerField : (OFTInteger, OFTReal, OFTString),
+ models.SmallIntegerField : (OFTInteger, OFTReal, OFTString),
+ models.PositiveSmallIntegerField : (OFTInteger, OFTReal, OFTString),
+ }
+
+ def __init__(self, model, data, mapping, layer=0,
+ source_srs=None, encoding='utf-8',
+ transaction_mode='commit_on_success',
+ transform=True, unique=None, using=None):
+ """
+ A LayerMapping object is initialized using the given Model (not an instance),
+ a DataSource (or string path to an OGR-supported data file), and a mapping
+ dictionary. See the module level docstring for more details and keyword
+ argument usage.
+ """
+ # Getting the DataSource and the associated Layer.
+ if isinstance(data, six.string_types):
+ self.ds = DataSource(data, encoding=encoding)
+ else:
+ self.ds = data
+ self.layer = self.ds[layer]
+
+ self.using = using if using is not None else router.db_for_write(model)
+ self.spatial_backend = connections[self.using].ops
+
+ # Setting the mapping & model attributes.
+ self.mapping = mapping
+ self.model = model
+
+ # Checking the layer -- intitialization of the object will fail if
+ # things don't check out before hand.
+ self.check_layer()
+
+ # Getting the geometry column associated with the model (an
+ # exception will be raised if there is no geometry column).
+ if self.spatial_backend.mysql:
+ transform = False
+ else:
+ self.geo_field = self.geometry_field()
+
+ # Checking the source spatial reference system, and getting
+ # the coordinate transformation object (unless the `transform`
+ # keyword is set to False)
+ if transform:
+ self.source_srs = self.check_srs(source_srs)
+ self.transform = self.coord_transform()
+ else:
+ self.transform = transform
+
+ # Setting the encoding for OFTString fields, if specified.
+ if encoding:
+ # Making sure the encoding exists, if not a LookupError
+ # exception will be thrown.
+ from codecs import lookup
+ lookup(encoding)
+ self.encoding = encoding
+ else:
+ self.encoding = None
+
+ if unique:
+ self.check_unique(unique)
+ transaction_mode = 'autocommit' # Has to be set to autocommit.
+ self.unique = unique
+ else:
+ self.unique = None
+
+ # Setting the transaction decorator with the function in the
+ # transaction modes dictionary.
+ self.transaction_mode = transaction_mode
+ if transaction_mode == 'autocommit':
+ self.transaction_decorator = None
+ elif transaction_mode == 'commit_on_success':
+ self.transaction_decorator = transaction.atomic
+ else:
+ raise LayerMapError('Unrecognized transaction mode: %s' % transaction_mode)
+
+ #### Checking routines used during initialization ####
+ def check_fid_range(self, fid_range):
+ "This checks the `fid_range` keyword."
+ if fid_range:
+ if isinstance(fid_range, (tuple, list)):
+ return slice(*fid_range)
+ elif isinstance(fid_range, slice):
+ return fid_range
+ else:
+ raise TypeError
+ else:
+ return None
+
+ def check_layer(self):
+ """
+ This checks the Layer metadata, and ensures that it is compatible
+ with the mapping information and model. Unlike previous revisions,
+ there is no need to increment through each feature in the Layer.
+ """
+ # The geometry field of the model is set here.
+ # TODO: Support more than one geometry field / model. However, this
+ # depends on the GDAL Driver in use.
+ self.geom_field = False
+ self.fields = {}
+
+ # Getting lists of the field names and the field types available in
+ # the OGR Layer.
+ ogr_fields = self.layer.fields
+ ogr_field_types = self.layer.field_types
+
+ # Function for determining if the OGR mapping field is in the Layer.
+ def check_ogr_fld(ogr_map_fld):
+ try:
+ idx = ogr_fields.index(ogr_map_fld)
+ except ValueError:
+ raise LayerMapError('Given mapping OGR field "%s" not found in OGR Layer.' % ogr_map_fld)
+ return idx
+
+ # No need to increment through each feature in the model, simply check
+ # the Layer metadata against what was given in the mapping dictionary.
+ for field_name, ogr_name in self.mapping.items():
+ # Ensuring that a corresponding field exists in the model
+ # for the given field name in the mapping.
+ try:
+ model_field = self.model._meta.get_field(field_name)
+ except models.fields.FieldDoesNotExist:
+ raise LayerMapError('Given mapping field "%s" not in given Model fields.' % field_name)
+
+ # Getting the string name for the Django field class (e.g., 'PointField').
+ fld_name = model_field.__class__.__name__
+
+ if isinstance(model_field, GeometryField):
+ if self.geom_field:
+ raise LayerMapError('LayerMapping does not support more than one GeometryField per model.')
+
+ # Getting the coordinate dimension of the geometry field.
+ coord_dim = model_field.dim
+
+ try:
+ if coord_dim == 3:
+ gtype = OGRGeomType(ogr_name + '25D')
+ else:
+ gtype = OGRGeomType(ogr_name)
+ except OGRException:
+ raise LayerMapError('Invalid mapping for GeometryField "%s".' % field_name)
+
+ # Making sure that the OGR Layer's Geometry is compatible.
+ ltype = self.layer.geom_type
+ if not (ltype.name.startswith(gtype.name) or self.make_multi(ltype, model_field)):
+ raise LayerMapError('Invalid mapping geometry; model has %s%s, '
+ 'layer geometry type is %s.' %
+ (fld_name, '(dim=3)' if coord_dim == 3 else '', ltype))
+
+ # Setting the `geom_field` attribute w/the name of the model field
+ # that is a Geometry. Also setting the coordinate dimension
+ # attribute.
+ self.geom_field = field_name
+ self.coord_dim = coord_dim
+ fields_val = model_field
+ elif isinstance(model_field, models.ForeignKey):
+ if isinstance(ogr_name, dict):
+ # Is every given related model mapping field in the Layer?
+ rel_model = model_field.rel.to
+ for rel_name, ogr_field in ogr_name.items():
+ idx = check_ogr_fld(ogr_field)
+ try:
+ rel_field = rel_model._meta.get_field(rel_name)
+ except models.fields.FieldDoesNotExist:
+ raise LayerMapError('ForeignKey mapping field "%s" not in %s fields.' %
+ (rel_name, rel_model.__class__.__name__))
+ fields_val = rel_model
+ else:
+ raise TypeError('ForeignKey mapping must be of dictionary type.')
+ else:
+ # Is the model field type supported by LayerMapping?
+ if not model_field.__class__ in self.FIELD_TYPES:
+ raise LayerMapError('Django field type "%s" has no OGR mapping (yet).' % fld_name)
+
+ # Is the OGR field in the Layer?
+ idx = check_ogr_fld(ogr_name)
+ ogr_field = ogr_field_types[idx]
+
+ # Can the OGR field type be mapped to the Django field type?
+ if not issubclass(ogr_field, self.FIELD_TYPES[model_field.__class__]):
+ raise LayerMapError('OGR field "%s" (of type %s) cannot be mapped to Django %s.' %
+ (ogr_field, ogr_field.__name__, fld_name))
+ fields_val = model_field
+
+ self.fields[field_name] = fields_val
+
+ def check_srs(self, source_srs):
+ "Checks the compatibility of the given spatial reference object."
+
+ if isinstance(source_srs, SpatialReference):
+ sr = source_srs
+ elif isinstance(source_srs, self.spatial_backend.spatial_ref_sys()):
+ sr = source_srs.srs
+ elif isinstance(source_srs, (int, six.string_types)):
+ sr = SpatialReference(source_srs)
+ else:
+ # Otherwise just pulling the SpatialReference from the layer
+ sr = self.layer.srs
+
+ if not sr:
+ raise LayerMapError('No source reference system defined.')
+ else:
+ return sr
+
+ def check_unique(self, unique):
+ "Checks the `unique` keyword parameter -- may be a sequence or string."
+ if isinstance(unique, (list, tuple)):
+ # List of fields to determine uniqueness with
+ for attr in unique:
+ if not attr in self.mapping: raise ValueError
+ elif isinstance(unique, six.string_types):
+ # Only a single field passed in.
+ if unique not in self.mapping: raise ValueError
+ else:
+ raise TypeError('Unique keyword argument must be set with a tuple, list, or string.')
+
+ #### Keyword argument retrieval routines ####
+ def feature_kwargs(self, feat):
+ """
+ Given an OGR Feature, this will return a dictionary of keyword arguments
+ for constructing the mapped model.
+ """
+ # The keyword arguments for model construction.
+ kwargs = {}
+
+ # Incrementing through each model field and OGR field in the
+ # dictionary mapping.
+ for field_name, ogr_name in self.mapping.items():
+ model_field = self.fields[field_name]
+
+ if isinstance(model_field, GeometryField):
+ # Verify OGR geometry.
+ try:
+ val = self.verify_geom(feat.geom, model_field)
+ except OGRException:
+ raise LayerMapError('Could not retrieve geometry from feature.')
+ elif isinstance(model_field, models.base.ModelBase):
+ # The related _model_, not a field was passed in -- indicating
+ # another mapping for the related Model.
+ val = self.verify_fk(feat, model_field, ogr_name)
+ else:
+ # Otherwise, verify OGR Field type.
+ val = self.verify_ogr_field(feat[ogr_name], model_field)
+
+ # Setting the keyword arguments for the field name with the
+ # value obtained above.
+ kwargs[field_name] = val
+
+ return kwargs
+
+ def unique_kwargs(self, kwargs):
+ """
+ Given the feature keyword arguments (from `feature_kwargs`) this routine
+ will construct and return the uniqueness keyword arguments -- a subset
+ of the feature kwargs.
+ """
+ if isinstance(self.unique, six.string_types):
+ return {self.unique : kwargs[self.unique]}
+ else:
+ return dict((fld, kwargs[fld]) for fld in self.unique)
+
+ #### Verification routines used in constructing model keyword arguments. ####
+ def verify_ogr_field(self, ogr_field, model_field):
+ """
+ Verifies if the OGR Field contents are acceptable to the Django
+ model field. If they are, the verified value is returned,
+ otherwise the proper exception is raised.
+ """
+ if (isinstance(ogr_field, OFTString) and
+ isinstance(model_field, (models.CharField, models.TextField))):
+ if self.encoding:
+ # The encoding for OGR data sources may be specified here
+ # (e.g., 'cp437' for Census Bureau boundary files).
+ val = force_text(ogr_field.value, self.encoding)
+ else:
+ val = ogr_field.value
+ if model_field.max_length and len(val) > model_field.max_length:
+ raise InvalidString('%s model field maximum string length is %s, given %s characters.' %
+ (model_field.name, model_field.max_length, len(val)))
+ elif isinstance(ogr_field, OFTReal) and isinstance(model_field, models.DecimalField):
+ try:
+ # Creating an instance of the Decimal value to use.
+ d = Decimal(str(ogr_field.value))
+ except:
+ raise InvalidDecimal('Could not construct decimal from: %s' % ogr_field.value)
+
+ # Getting the decimal value as a tuple.
+ dtup = d.as_tuple()
+ digits = dtup[1]
+ d_idx = dtup[2] # index where the decimal is
+
+ # Maximum amount of precision, or digits to the left of the decimal.
+ max_prec = model_field.max_digits - model_field.decimal_places
+
+ # Getting the digits to the left of the decimal place for the
+ # given decimal.
+ if d_idx < 0:
+ n_prec = len(digits[:d_idx])
+ else:
+ n_prec = len(digits) + d_idx
+
+ # If we have more than the maximum digits allowed, then throw an
+ # InvalidDecimal exception.
+ if n_prec > max_prec:
+ raise InvalidDecimal('A DecimalField with max_digits %d, decimal_places %d must round to an absolute value less than 10^%d.' %
+ (model_field.max_digits, model_field.decimal_places, max_prec))
+ val = d
+ elif isinstance(ogr_field, (OFTReal, OFTString)) and isinstance(model_field, models.IntegerField):
+ # Attempt to convert any OFTReal and OFTString value to an OFTInteger.
+ try:
+ val = int(ogr_field.value)
+ except:
+ raise InvalidInteger('Could not construct integer from: %s' % ogr_field.value)
+ else:
+ val = ogr_field.value
+ return val
+
+ def verify_fk(self, feat, rel_model, rel_mapping):
+ """
+ Given an OGR Feature, the related model and its dictionary mapping,
+ this routine will retrieve the related model for the ForeignKey
+ mapping.
+ """
+ # TODO: It is expensive to retrieve a model for every record --
+ # explore if an efficient mechanism exists for caching related
+ # ForeignKey models.
+
+ # Constructing and verifying the related model keyword arguments.
+ fk_kwargs = {}
+ for field_name, ogr_name in rel_mapping.items():
+ fk_kwargs[field_name] = self.verify_ogr_field(feat[ogr_name], rel_model._meta.get_field(field_name))
+
+ # Attempting to retrieve and return the related model.
+ try:
+ return rel_model.objects.using(self.using).get(**fk_kwargs)
+ except ObjectDoesNotExist:
+ raise MissingForeignKey('No ForeignKey %s model found with keyword arguments: %s' % (rel_model.__name__, fk_kwargs))
+
+ def verify_geom(self, geom, model_field):
+ """
+ Verifies the geometry -- will construct and return a GeometryCollection
+ if necessary (for example if the model field is MultiPolygonField while
+ the mapped shapefile only contains Polygons).
+ """
+ # Downgrade a 3D geom to a 2D one, if necessary.
+ if self.coord_dim != geom.coord_dim:
+ geom.coord_dim = self.coord_dim
+
+ if self.make_multi(geom.geom_type, model_field):
+ # Constructing a multi-geometry type to contain the single geometry
+ multi_type = self.MULTI_TYPES[geom.geom_type.num]
+ g = OGRGeometry(multi_type)
+ g.add(geom)
+ else:
+ g = geom
+
+ # Transforming the geometry with our Coordinate Transformation object,
+ # but only if the class variable `transform` is set w/a CoordTransform
+ # object.
+ if self.transform: g.transform(self.transform)
+
+ # Returning the WKT of the geometry.
+ return g.wkt
+
+ #### Other model methods ####
+ def coord_transform(self):
+ "Returns the coordinate transformation object."
+ SpatialRefSys = self.spatial_backend.spatial_ref_sys()
+ try:
+ # Getting the target spatial reference system
+ target_srs = SpatialRefSys.objects.using(self.using).get(srid=self.geo_field.srid).srs
+
+ # Creating the CoordTransform object
+ return CoordTransform(self.source_srs, target_srs)
+ except Exception as msg:
+ new_msg = 'Could not translate between the data source and model geometry: %s' % msg
+ six.reraise(LayerMapError, LayerMapError(new_msg), sys.exc_info()[2])
+
+ def geometry_field(self):
+ "Returns the GeometryField instance associated with the geographic column."
+ # Use the `get_field_by_name` on the model's options so that we
+ # get the correct field instance if there's model inheritance.
+ opts = self.model._meta
+ fld, model, direct, m2m = opts.get_field_by_name(self.geom_field)
+ return fld
+
+ def make_multi(self, geom_type, model_field):
+ """
+ Given the OGRGeomType for a geometry and its associated GeometryField,
+ determine whether the geometry should be turned into a GeometryCollection.
+ """
+ return (geom_type.num in self.MULTI_TYPES and
+ model_field.__class__.__name__ == 'Multi%s' % geom_type.django)
+
+ def save(self, verbose=False, fid_range=False, step=False,
+ progress=False, silent=False, stream=sys.stdout, strict=False):
+ """
+ Saves the contents from the OGR DataSource Layer into the database
+ according to the mapping dictionary given at initialization.
+
+ Keyword Parameters:
+ verbose:
+ If set, information will be printed subsequent to each model save
+ executed on the database.
+
+ fid_range:
+ May be set with a slice or tuple of (begin, end) feature ID's to map
+ from the data source. In other words, this keyword enables the user
+ to selectively import a subset range of features in the geographic
+ data source.
+
+ step:
+ If set with an integer, transactions will occur at every step
+ interval. For example, if step=1000, a commit would occur after
+ the 1,000th feature, the 2,000th feature etc.
+
+ progress:
+ When this keyword is set, status information will be printed giving
+ the number of features processed and sucessfully saved. By default,
+ progress information will pe printed every 1000 features processed,
+ however, this default may be overridden by setting this keyword with an
+ integer for the desired interval.
+
+ stream:
+ Status information will be written to this file handle. Defaults to
+ using `sys.stdout`, but any object with a `write` method is supported.
+
+ silent:
+ By default, non-fatal error notifications are printed to stdout, but
+ this keyword may be set to disable these notifications.
+
+ strict:
+ Execution of the model mapping will cease upon the first error
+ encountered. The default behavior is to attempt to continue.
+ """
+ # Getting the default Feature ID range.
+ default_range = self.check_fid_range(fid_range)
+
+ # Setting the progress interval, if requested.
+ if progress:
+ if progress is True or not isinstance(progress, int):
+ progress_interval = 1000
+ else:
+ progress_interval = progress
+
+ def _save(feat_range=default_range, num_feat=0, num_saved=0):
+ if feat_range:
+ layer_iter = self.layer[feat_range]
+ else:
+ layer_iter = self.layer
+
+ for feat in layer_iter:
+ num_feat += 1
+ # Getting the keyword arguments
+ try:
+ kwargs = self.feature_kwargs(feat)
+ except LayerMapError as msg:
+ # Something borked the validation
+ if strict: raise
+ elif not silent:
+ stream.write('Ignoring Feature ID %s because: %s\n' % (feat.fid, msg))
+ else:
+ # Constructing the model using the keyword args
+ is_update = False
+ if self.unique:
+ # If we want unique models on a particular field, handle the
+ # geometry appropriately.
+ try:
+ # Getting the keyword arguments and retrieving
+ # the unique model.
+ u_kwargs = self.unique_kwargs(kwargs)
+ m = self.model.objects.using(self.using).get(**u_kwargs)
+ is_update = True
+
+ # Getting the geometry (in OGR form), creating
+ # one from the kwargs WKT, adding in additional
+ # geometries, and update the attribute with the
+ # just-updated geometry WKT.
+ geom = getattr(m, self.geom_field).ogr
+ new = OGRGeometry(kwargs[self.geom_field])
+ for g in new: geom.add(g)
+ setattr(m, self.geom_field, geom.wkt)
+ except ObjectDoesNotExist:
+ # No unique model exists yet, create.
+ m = self.model(**kwargs)
+ else:
+ m = self.model(**kwargs)
+
+ try:
+ # Attempting to save.
+ m.save(using=self.using)
+ num_saved += 1
+ if verbose: stream.write('%s: %s\n' % ('Updated' if is_update else 'Saved', m))
+ except SystemExit:
+ raise
+ except Exception as msg:
+ if strict:
+ # Bailing out if the `strict` keyword is set.
+ if not silent:
+ stream.write('Failed to save the feature (id: %s) into the model with the keyword arguments:\n' % feat.fid)
+ stream.write('%s\n' % kwargs)
+ raise
+ elif not silent:
+ stream.write('Failed to save %s:\n %s\nContinuing\n' % (kwargs, msg))
+
+ # Printing progress information, if requested.
+ if progress and num_feat % progress_interval == 0:
+ stream.write('Processed %d features, saved %d ...\n' % (num_feat, num_saved))
+
+ # Only used for status output purposes -- incremental saving uses the
+ # values returned here.
+ return num_saved, num_feat
+
+ if self.transaction_decorator is not None:
+ _save = self.transaction_decorator(_save)
+
+ nfeat = self.layer.num_feat
+ if step and isinstance(step, int) and step < nfeat:
+ # Incremental saving is requested at the given interval (step)
+ if default_range:
+ raise LayerMapError('The `step` keyword may not be used in conjunction with the `fid_range` keyword.')
+ beg, num_feat, num_saved = (0, 0, 0)
+ indices = range(step, nfeat, step)
+ n_i = len(indices)
+
+ for i, end in enumerate(indices):
+ # Constructing the slice to use for this step; the last slice is
+ # special (e.g, [100:] instead of [90:100]).
+ if i+1 == n_i: step_slice = slice(beg, None)
+ else: step_slice = slice(beg, end)
+
+ try:
+ num_feat, num_saved = _save(step_slice, num_feat, num_saved)
+ beg = end
+ except:
+ stream.write('%s\nFailed to save slice: %s\n' % ('=-' * 20, step_slice))
+ raise
+ else:
+ # Otherwise, just calling the previously defined _save() function.
+ _save()
diff --git a/lib/python2.7/site-packages/django/contrib/gis/utils/ogrinfo.py b/lib/python2.7/site-packages/django/contrib/gis/utils/ogrinfo.py
new file mode 100644
index 0000000..d9c3e09
--- /dev/null
+++ b/lib/python2.7/site-packages/django/contrib/gis/utils/ogrinfo.py
@@ -0,0 +1,53 @@
+"""
+This module includes some utility functions for inspecting the layout
+of a GDAL data source -- the functionality is analogous to the output
+produced by the `ogrinfo` utility.
+"""
+
+from django.contrib.gis.gdal import DataSource
+from django.contrib.gis.gdal.geometries import GEO_CLASSES
+
+def ogrinfo(data_source, num_features=10):
+ """
+ Walks the available layers in the supplied `data_source`, displaying
+ the fields for the first `num_features` features.
+ """
+
+ # Checking the parameters.
+ if isinstance(data_source, str):
+ data_source = DataSource(data_source)
+ elif isinstance(data_source, DataSource):
+ pass
+ else:
+ raise Exception('Data source parameter must be a string or a DataSource object.')
+
+ for i, layer in enumerate(data_source):
+ print("data source : %s" % data_source.name)
+ print("==== layer %s" % i)
+ print(" shape type: %s" % GEO_CLASSES[layer.geom_type.num].__name__)
+ print(" # features: %s" % len(layer))
+ print(" srs: %s" % layer.srs)
+ extent_tup = layer.extent.tuple
+ print(" extent: %s - %s" % (extent_tup[0:2], extent_tup[2:4]))
+ print("Displaying the first %s features ====" % num_features)
+
+ width = max(*map(len,layer.fields))
+ fmt = " %%%ss: %%s" % width
+ for j, feature in enumerate(layer[:num_features]):
+ print("=== Feature %s" % j)
+ for fld_name in layer.fields:
+ type_name = feature[fld_name].type_name
+ output = fmt % (fld_name, type_name)
+ val = feature.get(fld_name)
+ if val:
+ if isinstance(val, str):
+ val_fmt = ' ("%s")'
+ else:
+ val_fmt = ' (%s)'
+ output += val_fmt % val
+ else:
+ output += ' (None)'
+ print(output)
+
+# For backwards compatibility.
+sample = ogrinfo
diff --git a/lib/python2.7/site-packages/django/contrib/gis/utils/ogrinspect.py b/lib/python2.7/site-packages/django/contrib/gis/utils/ogrinspect.py
new file mode 100644
index 0000000..b7cfafd
--- /dev/null
+++ b/lib/python2.7/site-packages/django/contrib/gis/utils/ogrinspect.py
@@ -0,0 +1,225 @@
+"""
+This module is for inspecting OGR data sources and generating either
+models for GeoDjango and/or mapping dictionaries for use with the
+`LayerMapping` utility.
+"""
+from django.utils.six.moves import zip
+# Requires GDAL to use.
+from django.contrib.gis.gdal import DataSource
+from django.contrib.gis.gdal.field import OFTDate, OFTDateTime, OFTInteger, OFTReal, OFTString, OFTTime
+from django.utils import six
+
+def mapping(data_source, geom_name='geom', layer_key=0, multi_geom=False):
+ """
+ Given a DataSource, generates a dictionary that may be used
+ for invoking the LayerMapping utility.
+
+ Keyword Arguments:
+ `geom_name` => The name of the geometry field to use for the model.
+
+ `layer_key` => The key for specifying which layer in the DataSource to use;
+ defaults to 0 (the first layer). May be an integer index or a string
+ identifier for the layer.
+
+ `multi_geom` => Boolean (default: False) - specify as multigeometry.
+ """
+ if isinstance(data_source, six.string_types):
+ # Instantiating the DataSource from the string.
+ data_source = DataSource(data_source)
+ elif isinstance(data_source, DataSource):
+ pass
+ else:
+ raise TypeError('Data source parameter must be a string or a DataSource object.')
+
+ # Creating the dictionary.
+ _mapping = {}
+
+ # Generating the field name for each field in the layer.
+ for field in data_source[layer_key].fields:
+ mfield = field.lower()
+ if mfield[-1:] == '_': mfield += 'field'
+ _mapping[mfield] = field
+ gtype = data_source[layer_key].geom_type
+ if multi_geom and gtype.num in (1, 2, 3): prefix = 'MULTI'
+ else: prefix = ''
+ _mapping[geom_name] = prefix + str(gtype).upper()
+ return _mapping
+
+def ogrinspect(*args, **kwargs):
+ """
+ Given a data source (either a string or a DataSource object) and a string
+ model name this function will generate a GeoDjango model.
+
+ Usage:
+
+ >>> from django.contrib.gis.utils import ogrinspect
+ >>> ogrinspect('/path/to/shapefile.shp','NewModel')
+
+ ...will print model definition to stout
+
+ or put this in a python script and use to redirect the output to a new
+ model like:
+
+ $ python generate_model.py > myapp/models.py
+
+ # generate_model.py
+ from django.contrib.gis.utils import ogrinspect
+ shp_file = 'data/mapping_hacks/world_borders.shp'
+ model_name = 'WorldBorders'
+
+ print(ogrinspect(shp_file, model_name, multi_geom=True, srid=4326,
+ geom_name='shapes', blank=True))
+
+ Required Arguments
+ `datasource` => string or DataSource object to file pointer
+
+ `model name` => string of name of new model class to create
+
+ Optional Keyword Arguments
+ `geom_name` => For specifying the model name for the Geometry Field.
+ Otherwise will default to `geom`
+
+ `layer_key` => The key for specifying which layer in the DataSource to use;
+ defaults to 0 (the first layer). May be an integer index or a string
+ identifier for the layer.
+
+ `srid` => The SRID to use for the Geometry Field. If it can be determined,
+ the SRID of the datasource is used.
+
+ `multi_geom` => Boolean (default: False) - specify as multigeometry.
+
+ `name_field` => String - specifies a field name to return for the
+ `__unicode__`/`__str__` function (which will be generated if specified).
+
+ `imports` => Boolean (default: True) - set to False to omit the
+ `from django.contrib.gis.db import models` code from the
+ autogenerated models thus avoiding duplicated imports when building
+ more than one model by batching ogrinspect()
+
+ `decimal` => Boolean or sequence (default: False). When set to True
+ all generated model fields corresponding to the `OFTReal` type will
+ be `DecimalField` instead of `FloatField`. A sequence of specific
+ field names to generate as `DecimalField` may also be used.
+
+ `blank` => Boolean or sequence (default: False). When set to True all
+ generated model fields will have `blank=True`. If the user wants to
+ give specific fields to have blank, then a list/tuple of OGR field
+ names may be used.
+
+ `null` => Boolean (default: False) - When set to True all generated
+ model fields will have `null=True`. If the user wants to specify
+ give specific fields to have null, then a list/tuple of OGR field
+ names may be used.
+
+ Note: This routine calls the _ogrinspect() helper to do the heavy lifting.
+ """
+ return '\n'.join(s for s in _ogrinspect(*args, **kwargs))
+
+def _ogrinspect(data_source, model_name, geom_name='geom', layer_key=0, srid=None,
+ multi_geom=False, name_field=None, imports=True,
+ decimal=False, blank=False, null=False):
+ """
+ Helper routine for `ogrinspect` that generates GeoDjango models corresponding
+ to the given data source. See the `ogrinspect` docstring for more details.
+ """
+ # Getting the DataSource
+ if isinstance(data_source, six.string_types):
+ data_source = DataSource(data_source)
+ elif isinstance(data_source, DataSource):
+ pass
+ else:
+ raise TypeError('Data source parameter must be a string or a DataSource object.')
+
+ # Getting the layer corresponding to the layer key and getting
+ # a string listing of all OGR fields in the Layer.
+ layer = data_source[layer_key]
+ ogr_fields = layer.fields
+
+ # Creating lists from the `null`, `blank`, and `decimal`
+ # keyword arguments.
+ def process_kwarg(kwarg):
+ if isinstance(kwarg, (list, tuple)):
+ return [s.lower() for s in kwarg]
+ elif kwarg:
+ return [s.lower() for s in ogr_fields]
+ else:
+ return []
+ null_fields = process_kwarg(null)
+ blank_fields = process_kwarg(blank)
+ decimal_fields = process_kwarg(decimal)
+
+ # Gets the `null` and `blank` keywords for the given field name.
+ def get_kwargs_str(field_name):
+ kwlist = []
+ if field_name.lower() in null_fields: kwlist.append('null=True')
+ if field_name.lower() in blank_fields: kwlist.append('blank=True')
+ if kwlist: return ', ' + ', '.join(kwlist)
+ else: return ''
+
+ # For those wishing to disable the imports.
+ if imports:
+ yield '# This is an auto-generated Django model module created by ogrinspect.'
+ yield 'from django.contrib.gis.db import models'
+ yield ''
+
+ yield 'class %s(models.Model):' % model_name
+
+ for field_name, width, precision, field_type in zip(ogr_fields, layer.field_widths, layer.field_precisions, layer.field_types):
+ # The model field name.
+ mfield = field_name.lower()
+ if mfield[-1:] == '_': mfield += 'field'
+
+ # Getting the keyword args string.
+ kwargs_str = get_kwargs_str(field_name)
+
+ if field_type is OFTReal:
+ # By default OFTReals are mapped to `FloatField`, however, they
+ # may also be mapped to `DecimalField` if specified in the
+ # `decimal` keyword.
+ if field_name.lower() in decimal_fields:
+ yield ' %s = models.DecimalField(max_digits=%d, decimal_places=%d%s)' % (mfield, width, precision, kwargs_str)
+ else:
+ yield ' %s = models.FloatField(%s)' % (mfield, kwargs_str[2:])
+ elif field_type is OFTInteger:
+ yield ' %s = models.IntegerField(%s)' % (mfield, kwargs_str[2:])
+ elif field_type is OFTString:
+ yield ' %s = models.CharField(max_length=%s%s)' % (mfield, width, kwargs_str)
+ elif field_type is OFTDate:
+ yield ' %s = models.DateField(%s)' % (mfield, kwargs_str[2:])
+ elif field_type is OFTDateTime:
+ yield ' %s = models.DateTimeField(%s)' % (mfield, kwargs_str[2:])
+ elif field_type is OFTTime:
+ yield ' %s = models.TimeField(%s)' % (mfield, kwargs_str[2:])
+ else:
+ raise TypeError('Unknown field type %s in %s' % (field_type, mfield))
+
+ # TODO: Autodetection of multigeometry types (see #7218).
+ gtype = layer.geom_type
+ if multi_geom and gtype.num in (1, 2, 3):
+ geom_field = 'Multi%s' % gtype.django
+ else:
+ geom_field = gtype.django
+
+ # Setting up the SRID keyword string.
+ if srid is None:
+ if layer.srs is None:
+ srid_str = 'srid=-1'
+ else:
+ srid = layer.srs.srid
+ if srid is None:
+ srid_str = 'srid=-1'
+ elif srid == 4326:
+ # WGS84 is already the default.
+ srid_str = ''
+ else:
+ srid_str = 'srid=%s' % srid
+ else:
+ srid_str = 'srid=%s' % srid
+
+ yield ' %s = models.%s(%s)' % (geom_name, geom_field, srid_str)
+ yield ' objects = models.GeoManager()'
+
+ if name_field:
+ yield ''
+ yield ' def __%s__(self): return self.%s' % (
+ 'str' if six.PY3 else 'unicode', name_field)
diff --git a/lib/python2.7/site-packages/django/contrib/gis/utils/srs.py b/lib/python2.7/site-packages/django/contrib/gis/utils/srs.py
new file mode 100644
index 0000000..fe2f291
--- /dev/null
+++ b/lib/python2.7/site-packages/django/contrib/gis/utils/srs.py
@@ -0,0 +1,80 @@
+from django.contrib.gis.gdal import SpatialReference
+
+def add_srs_entry(srs, auth_name='EPSG', auth_srid=None, ref_sys_name=None,
+ database=None):
+ """
+ This function takes a GDAL SpatialReference system and adds its information
+ to the `spatial_ref_sys` table of the spatial backend. Doing this enables
+ database-level spatial transformations for the backend. Thus, this utility
+ is useful for adding spatial reference systems not included by default with
+ the backend -- for example, the so-called "Google Maps Mercator Projection"
+ is excluded in PostGIS 1.3 and below, and the following adds it to the
+ `spatial_ref_sys` table:
+
+ >>> from django.contrib.gis.utils import add_srs_entry
+ >>> add_srs_entry(900913)
+
+ Keyword Arguments:
+ auth_name:
+ This keyword may be customized with the value of the `auth_name` field.
+ Defaults to 'EPSG'.
+
+ auth_srid:
+ This keyword may be customized with the value of the `auth_srid` field.
+ Defaults to the SRID determined by GDAL.
+
+ ref_sys_name:
+ For SpatiaLite users only, sets the value of the `ref_sys_name` field.
+ Defaults to the name determined by GDAL.
+
+ database:
+ The name of the database connection to use; the default is the value
+ of `django.db.DEFAULT_DB_ALIAS` (at the time of this writing, it's value
+ is 'default').
+ """
+ from django.db import connections, DEFAULT_DB_ALIAS
+ if not database:
+ database = DEFAULT_DB_ALIAS
+ connection = connections[database]
+
+ if not hasattr(connection.ops, 'spatial_version'):
+ raise Exception('The `add_srs_entry` utility only works '
+ 'with spatial backends.')
+ if connection.ops.oracle or connection.ops.mysql:
+ raise Exception('This utility does not support the '
+ 'Oracle or MySQL spatial backends.')
+ SpatialRefSys = connection.ops.spatial_ref_sys()
+
+ # If argument is not a `SpatialReference` instance, use it as parameter
+ # to construct a `SpatialReference` instance.
+ if not isinstance(srs, SpatialReference):
+ srs = SpatialReference(srs)
+
+ if srs.srid is None:
+ raise Exception('Spatial reference requires an SRID to be '
+ 'compatible with the spatial backend.')
+
+ # Initializing the keyword arguments dictionary for both PostGIS
+ # and SpatiaLite.
+ kwargs = {'srid' : srs.srid,
+ 'auth_name' : auth_name,
+ 'auth_srid' : auth_srid or srs.srid,
+ 'proj4text' : srs.proj4,
+ }
+
+ # Backend-specific fields for the SpatialRefSys model.
+ if connection.ops.postgis:
+ kwargs['srtext'] = srs.wkt
+ if connection.ops.spatialite:
+ kwargs['ref_sys_name'] = ref_sys_name or srs.name
+
+ # Creating the spatial_ref_sys model.
+ try:
+ # Try getting via SRID only, because using all kwargs may
+ # differ from exact wkt/proj in database.
+ sr = SpatialRefSys.objects.using(database).get(srid=srs.srid)
+ except SpatialRefSys.DoesNotExist:
+ sr = SpatialRefSys.objects.using(database).create(**kwargs)
+
+# Alias is for backwards-compatibility purposes.
+add_postgis_srs = add_srs_entry
diff --git a/lib/python2.7/site-packages/django/contrib/gis/utils/wkt.py b/lib/python2.7/site-packages/django/contrib/gis/utils/wkt.py
new file mode 100644
index 0000000..d60eed3
--- /dev/null
+++ b/lib/python2.7/site-packages/django/contrib/gis/utils/wkt.py
@@ -0,0 +1,57 @@
+"""
+ Utilities for manipulating Geometry WKT.
+"""
+
+from django.utils import six
+
+def precision_wkt(geom, prec):
+ """
+ Returns WKT text of the geometry according to the given precision (an
+ integer or a string). If the precision is an integer, then the decimal
+ places of coordinates WKT will be truncated to that number:
+
+ >>> pnt = Point(5, 23)
+ >>> pnt.wkt
+ 'POINT (5.0000000000000000 23.0000000000000000)'
+ >>> precision(geom, 1)
+ 'POINT (5.0 23.0)'
+
+ If the precision is a string, it must be valid Python format string
+ (e.g., '%20.7f') -- thus, you should know what you're doing.
+ """
+ if isinstance(prec, int):
+ num_fmt = '%%.%df' % prec
+ elif isinstance(prec, six.string_types):
+ num_fmt = prec
+ else:
+ raise TypeError
+
+ # TODO: Support 3D geometries.
+ coord_fmt = ' '.join([num_fmt, num_fmt])
+
+ def formatted_coords(coords):
+ return ','.join([coord_fmt % c[:2] for c in coords])
+
+ def formatted_poly(poly):
+ return ','.join(['(%s)' % formatted_coords(r) for r in poly])
+
+ def formatted_geom(g):
+ gtype = str(g.geom_type).upper()
+ yield '%s(' % gtype
+ if gtype == 'POINT':
+ yield formatted_coords((g.coords,))
+ elif gtype in ('LINESTRING', 'LINEARRING'):
+ yield formatted_coords(g.coords)
+ elif gtype in ('POLYGON', 'MULTILINESTRING'):
+ yield formatted_poly(g)
+ elif gtype == 'MULTIPOINT':
+ yield formatted_coords(g.coords)
+ elif gtype == 'MULTIPOLYGON':
+ yield ','.join(['(%s)' % formatted_poly(p) for p in g])
+ elif gtype == 'GEOMETRYCOLLECTION':
+ yield ','.join([''.join([wkt for wkt in formatted_geom(child)]) for child in g])
+ else:
+ raise TypeError
+ yield ')'
+
+ return ''.join([wkt for wkt in formatted_geom(geom)])