Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/django/contrib/gis/management/commands/ogrinspect.py: 2%
48 statements
« prev ^ index » next coverage.py v7.0.5, created at 2023-01-17 06:13 +0000
« prev ^ index » next coverage.py v7.0.5, created at 2023-01-17 06:13 +0000
1import argparse
3from django.contrib.gis import gdal
4from django.core.management.base import BaseCommand, CommandError
5from django.utils.inspect import get_func_args
8class LayerOptionAction(argparse.Action):
9 """
10 Custom argparse action for the `ogrinspect` `layer_key` keyword option
11 which may be an integer or a string.
12 """
14 def __call__(self, parser, namespace, value, option_string=None):
15 try:
16 setattr(namespace, self.dest, int(value))
17 except ValueError:
18 setattr(namespace, self.dest, value)
21class ListOptionAction(argparse.Action):
22 """
23 Custom argparse action for `ogrinspect` keywords that require
24 a string list. If the string is 'True'/'true' then the option
25 value will be a boolean instead.
26 """
28 def __call__(self, parser, namespace, value, option_string=None):
29 if value.lower() == "true":
30 setattr(namespace, self.dest, True)
31 else:
32 setattr(namespace, self.dest, value.split(","))
35class Command(BaseCommand):
36 help = (
37 "Inspects the given OGR-compatible data source (e.g., a shapefile) and "
38 "outputs\na GeoDjango model with the given model name. For example:\n"
39 " ./manage.py ogrinspect zipcode.shp Zipcode"
40 )
42 requires_system_checks = []
44 def add_arguments(self, parser):
45 parser.add_argument("data_source", help="Path to the data source.")
46 parser.add_argument("model_name", help="Name of the model to create.")
47 parser.add_argument(
48 "--blank",
49 action=ListOptionAction,
50 default=False,
51 help="Use a comma separated list of OGR field names to add "
52 "the `blank=True` option to the field definition. Set to `true` "
53 "to apply to all applicable fields.",
54 )
55 parser.add_argument(
56 "--decimal",
57 action=ListOptionAction,
58 default=False,
59 help="Use a comma separated list of OGR float fields to "
60 "generate `DecimalField` instead of the default "
61 "`FloatField`. Set to `true` to apply to all OGR float fields.",
62 )
63 parser.add_argument(
64 "--geom-name",
65 default="geom",
66 help="Specifies the model name for the Geometry Field (defaults to `geom`)",
67 )
68 parser.add_argument(
69 "--layer",
70 dest="layer_key",
71 action=LayerOptionAction,
72 default=0,
73 help="The key for specifying which layer in the OGR data "
74 "source to use. Defaults to 0 (the first layer). May be "
75 "an integer or a string identifier for the layer.",
76 )
77 parser.add_argument(
78 "--multi-geom",
79 action="store_true",
80 help="Treat the geometry in the data source as a geometry collection.",
81 )
82 parser.add_argument(
83 "--name-field",
84 help="Specifies a field name to return for the __str__() method.",
85 )
86 parser.add_argument(
87 "--no-imports",
88 action="store_false",
89 dest="imports",
90 help="Do not include `from django.contrib.gis.db import models` statement.",
91 )
92 parser.add_argument(
93 "--null",
94 action=ListOptionAction,
95 default=False,
96 help="Use a comma separated list of OGR field names to add "
97 "the `null=True` option to the field definition. Set to `true` "
98 "to apply to all applicable fields.",
99 )
100 parser.add_argument(
101 "--srid",
102 help="The SRID to use for the Geometry Field. If it can be "
103 "determined, the SRID of the data source is used.",
104 )
105 parser.add_argument(
106 "--mapping",
107 action="store_true",
108 help="Generate mapping dictionary for use with `LayerMapping`.",
109 )
111 def handle(self, *args, **options):
112 data_source, model_name = options.pop("data_source"), options.pop("model_name")
114 # Getting the OGR DataSource from the string parameter.
115 try:
116 ds = gdal.DataSource(data_source)
117 except gdal.GDALException as msg:
118 raise CommandError(msg)
120 # Returning the output of ogrinspect with the given arguments
121 # and options.
122 from django.contrib.gis.utils.ogrinspect import _ogrinspect, mapping
124 # Filter options to params accepted by `_ogrinspect`
125 ogr_options = {
126 k: v
127 for k, v in options.items()
128 if k in get_func_args(_ogrinspect) and v is not None
129 }
130 output = [s for s in _ogrinspect(ds, model_name, **ogr_options)]
132 if options["mapping"]:
133 # Constructing the keyword arguments for `mapping`, and
134 # calling it on the data source.
135 kwargs = {
136 "geom_name": options["geom_name"],
137 "layer_key": options["layer_key"],
138 "multi_geom": options["multi_geom"],
139 }
140 mapping_dict = mapping(ds, **kwargs)
141 # This extra legwork is so that the dictionary definition comes
142 # out in the same order as the fields in the model definition.
143 rev_mapping = {v: k for k, v in mapping_dict.items()}
144 output.extend(
145 [
146 "",
147 "",
148 "# Auto-generated `LayerMapping` dictionary for %s model"
149 % model_name,
150 "%s_mapping = {" % model_name.lower(),
151 ]
152 )
153 output.extend(
154 " '%s': '%s'," % (rev_mapping[ogr_fld], ogr_fld)
155 for ogr_fld in ds[options["layer_key"]].fields
156 )
157 output.extend(
158 [
159 " '%s': '%s',"
160 % (options["geom_name"], mapping_dict[options["geom_name"]]),
161 "}",
162 ]
163 )
164 return "\n".join(output)