/[thuban]/branches/WIP-pyshapelib-bramz/test/postgissupport.py
ViewVC logotype

Annotation of /branches/WIP-pyshapelib-bramz/test/postgissupport.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2057 - (hide annotations)
Tue Feb 10 15:51:57 2004 UTC (21 years ago) by bh
Original Path: trunk/thuban/test/postgissupport.py
File MIME type: text/x-python
File size: 24449 byte(s)
* Thuban/Model/postgisdb.py (quote_identifier): Fix typo in
doc-string
(PostGISShapeStore._fetch_table_information): New. Extend
inherited method to retrieve srid
(PostGISShapeStore.BoundingBox): Handle tables without data.
extent yields NULL for those
(PostGISShapeStore.ShapesInRegion): Use the srid of the table.

* test/test_postgis_db.py
(TestPostGISSpecialCases.test_shapestore_empty_table): New test
for the special case of a table without any data
(TestPostGISShapestorePointSRID): New class with tests for a table
that uses srids
(PolygonTests): Fix a doc-string typo

* test/postgissupport.py (PostGISDatabase.__init__): New parameter
reference_systems with a specification of spacial reference
systems to create in the new db.
(PostgreSQLServer.new_postgis_db)
(PostgreSQLServer.get_static_data_db): New parameter
reference_systems to be passed through ultimately to
PostGISDatabase.  In new_postgis_db also check whether an existing
db already has the right srids
(PostgreSQLServer.get_default_static_data_db): Add srids and a
table that uses srids
(PostGISDatabase.initdb): Create the entries for the reference
systems
(PostGISDatabase.has_data): Add reference_systems parameter to
check for those too
(upload_shapefile): New parameter srid to create tables with a
specific srid

1 bh 2057 # Copyright (C) 2003, 2004 by Intevation GmbH
2 bh 1605 # Authors:
3     # Bernhard Herzog <[email protected]>
4     #
5     # This program is free software under the GPL (>=v2)
6     # Read the file COPYING coming with the software for details.
7    
8     """Support module for tests that use a live PostGIS database"""
9    
10     __version__ = "$Revision$"
11     # $Source$
12     # $Id$
13    
14     import sys
15     import os
16     import time
17     import popen2
18     import shutil
19     import traceback
20    
21     import support
22    
23     try:
24     import psycopg
25     except ImportError:
26     psycopg = None
27    
28     #
29     # Helper code
30     #
31    
32     def run_config_script(cmdline):
33     """Run command cmdline and return its stdout or none in case of errors"""
34     pipe = os.popen(cmdline)
35     result = pipe.read()
36     if pipe.close() is not None:
37     raise RuntimeError('Command %r failed' % cmdline)
38     return result
39    
40     def run_command(command, outfilename = None):
41     """Run command as a subprocess and send its stdout and stderr to outfile
42    
43     The subprocess is run synchroneously so the function returns once
44     the subprocess has termninated. If the process' exit code is not
45     zero raise a RuntimeError.
46    
47     If outfilename is None stdout and stderr are still captured but they
48     are ignored and not written to any file.
49     """
50     proc = popen2.Popen4(command)
51     proc.tochild.close()
52     output = proc.fromchild.read()
53     status = proc.wait()
54     if outfilename is not None:
55     outfile = open(outfilename, "w")
56     outfile.write(output)
57     outfile.close()
58     if not os.WIFEXITED(status) or os.WEXITSTATUS(status) != 0:
59     if outfilename:
60     message = "see %s" % outfilename
61     else:
62     message = output
63     raise RuntimeError("command %r exited with code %d.\n%s"
64     % (command, status, message))
65    
66    
67     def run_boolean_command(command):
68     """
69     Run command as a subprocess silently and return whether it ran successfully
70    
71     Silently means that all output is captured and ignored. The exit
72     status is true if the command ran successfull, i.e. it terminated by
73     exiting and returned as zero exit code and false other wise
74     """
75     try:
76     run_command(command, None)
77     return 1
78     except RuntimeError:
79     pass
80     return 0
81    
82    
83     #
84     # PostgreSQL and database
85     #
86    
87     class PostgreSQLServer:
88    
89     """A PostgreSQL server
90    
91     Instances of this class represent a PostgreSQL server with postgis
92     extensions run explicitly for the test cases. Such a server has its
93     own database directory and its own directory for the unix sockets so
94     that it doesn't interfere with any other PostgreSQL server already
95     running on the system.
96     """
97    
98     def __init__(self, dbdir, port, postgis_sql, socket_dir):
99     """Initialize the PostgreSQLServer object
100    
101     Parameters:
102    
103     dbdir -- The directory for the databases
104     port -- The port to use
105     postgis_sql -- The name of the file with the SQL statements to
106     initialize a database for postgis.
107     socket_dir -- The directory for the socket files.
108    
109     When connecting to the database server use the port and host
110     instance variables.
111     """
112     self.dbdir = dbdir
113     self.port = port
114     self.postgis_sql = postgis_sql
115     self.socket_dir = socket_dir
116    
117     # For the client side the socket directory can be used as the
118 bh 1634 # host if the name starts with a slash.
119 bh 1605 self.host = os.path.abspath(socket_dir)
120    
121 bh 1634 # name and password for the admin and an unprivileged user
122     self.admin_name = "postgres"
123     self.admin_password = "postgres"
124     self.user_name = "observer"
125     self.user_password = "telescope"
126    
127 bh 1605 # Map db names to db objects
128     self.known_dbs = {}
129    
130     def createdb(self):
131     """Create the database in dbdir and start the server.
132    
133     First check whether the dbdir already exists and if necessary
134     stop an already running postmaster and remove the dbdir
135     directory completely. Then create a new database cluster in the
136     dbdir and start a postmaster.
137     """
138     if os.path.isdir(self.dbdir):
139     if self.is_running():
140     self.shutdown()
141     shutil.rmtree(self.dbdir)
142     os.mkdir(self.dbdir)
143    
144 bh 1634 run_command(["initdb", "-D", self.dbdir, "-U", self.admin_name],
145 bh 1605 os.path.join(self.dbdir, "initdb.log"))
146    
147     extra_opts = "-p %d" % self.port
148     if self.socket_dir is not None:
149     extra_opts += " -k %s" % self.socket_dir
150     run_command(["pg_ctl", "-D", self.dbdir,
151     "-l", os.path.join(self.dbdir, "logfile"),
152     "-o", extra_opts, "start"],
153     os.path.join(self.dbdir, "pg_ctl-start.log"))
154     # the -w option of pg_ctl doesn't work properly when the port is
155     # not the default port, so we have to implement waiting for the
156     # server ourselves
157     self.wait_for_postmaster()
158    
159 bh 1634 self.alter_user(self.admin_name, self.admin_password)
160     self.create_user(self.user_name, self.user_password)
161    
162 bh 1605 def wait_for_postmaster(self):
163     """Return when the database server is running
164    
165     Internal method to wait until the postmaster process has been
166     started and is ready for client connections.
167     """
168     max_count = 60
169     count = 0
170     while count < max_count:
171     try:
172     run_command(["psql", "-l", "-p", str(self.port),
173 bh 1634 "-h", self.host, "-U", self.admin_name],
174 bh 1605 os.path.join(self.dbdir, "psql-%d.log" % count))
175 bh 1634 except RuntimeError:
176     pass
177 bh 1605 except:
178 bh 1634 traceback.print_exc()
179 bh 1605 else:
180     break
181     time.sleep(0.5)
182     count += 1
183     else:
184     raise RuntimeError("postmaster didn't start")
185    
186     def is_running(self):
187     """Return true a postmaster process is running on self.dbdir
188    
189     This method runs pg_ctl status on the dbdir so even if the
190     object has just been created it is possible that this method
191     returns true if there's still a postmaster process running for
192     self.dbdir.
193     """
194     return run_boolean_command(["pg_ctl", "-D", self.dbdir, "status"])
195    
196     def shutdown(self):
197     """Stop the postmaster running for self.dbdir"""
198     run_command(["pg_ctl", "-m", "fast", "-D", self.dbdir, "stop"],
199     os.path.join(self.dbdir, "pg_ctl-stop.log"))
200    
201 bh 2057 def new_postgis_db(self, dbname, tables = None, reference_systems = None):
202 bh 1605 """Create and return a new PostGISDatabase object using self as server
203     """
204 bh 2057 db = PostGISDatabase(self, self.postgis_sql, dbname, tables = tables,
205     reference_systems = reference_systems)
206 bh 1605 db.initdb()
207     self.known_dbs[dbname] = db
208     return db
209    
210 bh 2057 def get_static_data_db(self, dbname, tables, reference_systems):
211 bh 1605 """Return a PostGISDatabase for a database with the given static data
212    
213     If no databasse of the name dbname exists, create a new one via
214     new_postgis_db and upload the data.
215    
216     If a database of the name dbname already exists and uses the
217     indicated data, return that. If the already existing db uses
218     different data raise a value error.
219    
220 bh 2057 If the database doesn't exist, create a new one via
221     self.new_postgis_db.
222    
223     The parameters tables and reference_systems have the same
224     meaning as for new_postgis_db.
225 bh 1605 """
226     db = self.known_dbs.get(dbname)
227     if db is not None:
228 bh 2057 if db.has_data(tables, reference_systems):
229 bh 1605 return db
230     raise ValueError("PostGISDatabase named %r doesn't have tables %r"
231     % (dbname, tables))
232 bh 2057 return self.new_postgis_db(dbname, tables, reference_systems)
233 bh 1605
234     def get_default_static_data_db(self):
235     dbname = "PostGISStaticTests"
236 bh 2057 srids = [(1, "proj=longlat datum=WGS84")]
237 bh 1662 tables = [
238     # Direct copies of the shapefiles. The shapeids are exactly
239 bh 2057 # the same, except where changed with "gid_offset", of
240     # course
241 bh 1662 ("landmarks", os.path.join("..", "Data", "iceland",
242     "cultural_landmark-point.shp"),
243     [("gid_offset", 1000)]),
244     ("political", os.path.join("..", "Data", "iceland",
245 bh 1605 "political.shp")),
246 bh 1662 ("roads", os.path.join("..", "Data", "iceland",
247     "roads-line.shp")),
248 bh 1656
249 bh 1662 # The polygon data as a MULTIPOLYGON geometry type
250     ("political_multi", os.path.join("..", "Data", "iceland",
251 bh 1656 "political.shp"),
252 bh 1662 [("force_wkt_type", "MULTIPOLYGON")]),
253 bh 2057
254     # Copy of landmarks but using an srid
255     ("landmarks_srid", os.path.join("..", "Data", "iceland",
256     "cultural_landmark-point.shp"),
257     [("gid_offset", 1000),
258     ("srid", 1)]),
259 bh 1662 ]
260 bh 2057 return self.get_static_data_db(dbname, tables, srids)
261 bh 1605
262 bh 1634 def connection_params(self, user):
263     """Return the connection parameters for the given user
264 bh 1605
265 bh 1634 The return value is a dictionary suitable as keyword argument
266     list to PostGISConnection. The user parameter may be either
267     'admin' to connect as admin or 'user' to connect as an
268     unprivileged user.
269     """
270     return {"host": self.host, "port": self.port,
271     "user": getattr(self, user + "_name"),
272     "password": getattr(self, user + "_password")}
273 bh 1605
274 bh 1634 def connection_string(self, user):
275     """Return (part of) the connection string to pass to psycopg.connect
276 bh 1605
277 bh 1634 The string contains host, port, user and password. The user
278     parameter must be either 'admin' or 'user', as for
279     connection_params.
280     """
281     params = []
282     for key, value in self.connection_params(user).items():
283     # FIXME: this doesn't do quiting correctly but that
284     # shouldn't be much of a problem (people shouldn't be using
285     # single quotes in filenames anyway :) )
286     params.append("%s='%s'" % (key, value))
287     return " ".join(params)
288    
289     def execute_sql(self, dbname, user, sql):
290     """Execute the sql statament
291    
292     The user parameter us used as in connection_params. The dbname
293     parameter must be the name of a database in the cluster.
294     """
295     conn = psycopg.connect("dbname=%s " % dbname
296     + self.connection_string(user))
297     cursor = conn.cursor()
298     cursor.execute(sql)
299     conn.commit()
300     conn.close()
301    
302     def require_authentication(self, required):
303     """Switch authentication requirements on or off
304    
305     When started for the first time no passwords are required. Some
306     tests want to explicitly test whether Thuban's password
307     infrastructure works and switch password authentication on
308     explicitly. When switching it on, there should be a
309     corresponding call to switch it off again in the test case'
310     tearDown method or in a finally: block.
311     """
312     if required:
313     contents = "local all password\n"
314     else:
315     contents = "local all trust\n"
316     f = open(os.path.join(self.dbdir, "pg_hba.conf"), "w")
317     f.write(contents)
318     f.close()
319     run_command(["pg_ctl", "-D", self.dbdir, "reload"],
320     os.path.join(self.dbdir, "pg_ctl-reload.log"))
321    
322    
323     def create_user(self, username, password):
324     """Create user username with password in the database"""
325     self.execute_sql("template1", "admin",
326     "CREATE USER %s PASSWORD '%s';" % (username,password))
327    
328     def alter_user(self, username, password):
329     """Change the user username's password in the database"""
330     self.execute_sql("template1", "admin",
331     "ALTER USER %s PASSWORD '%s';" % (username,password))
332    
333    
334 bh 1605 class PostGISDatabase:
335    
336     """A PostGIS database in a PostgreSQLServer"""
337    
338 bh 2057 def __init__(self, server, postgis_sql, dbname, tables = None,
339     reference_systems = ()):
340 bh 1662 """Initialize the PostGISDatabase
341    
342     Parameters:
343    
344     server -- The PostgreSQLServer instance containing the
345     database
346    
347     postgis_sql -- Filename of the postgis.sql file with the
348     postgis initialization code
349    
350     dbname -- The name of the database
351    
352     tables -- Optional description of tables to create in the
353     new database. If given it should be a list of
354     (tablename, shapefilename) pairs meaning that a table
355     tablename will be created with the contents of the given
356     shapefile or (tablename, shapefilename, extraargs)
357     triples. The extraargs should be a list of key, value
358     pairs to use as keyword arguments to upload_shapefile.
359 bh 2057
360     reference_systems -- Optional description of spatial
361     reference systems. If given, it should be a sequence of
362     (srid, params) pairs where srid is the srid defined by
363     the proj4 paramter string params. The srid can be given
364     as an extra parameter in the tables list.
365 bh 1662 """
366 bh 1605 self.server = server
367     self.postgis_sql = postgis_sql
368     self.dbname = dbname
369     self.tables = tables
370 bh 2057 if reference_systems:
371     self.reference_systems = reference_systems
372     else:
373     # Make sure that it's a sequence we can iterate over even if
374     # the parameter's None
375     self.reference_systems = ()
376 bh 1605
377     def initdb(self):
378     """Remove the old db directory and create and initialize a new database
379     """
380     run_command(["createdb", "-p", str(self.server.port),
381 bh 1634 "-h", self.server.host, "-U", self.server.admin_name,
382     self.dbname],
383 bh 1605 os.path.join(self.server.dbdir, "createdb.log"))
384     run_command(["createlang", "-p", str(self.server.port),
385 bh 1634 "-h", self.server.host, "-U", self.server.admin_name,
386     "plpgsql", self.dbname],
387 bh 1605 os.path.join(self.server.dbdir, "createlang.log"))
388     # for some reason psql doesn't exit with an error code if the
389     # file given as -f doesn't exist, so we check manually by trying
390     # to open it before we run psql
391     f = open(self.postgis_sql)
392     f.close()
393     del f
394     run_command(["psql", "-f", self.postgis_sql, "-d", self.dbname,
395 bh 1634 "-p", str(self.server.port), "-h", self.server.host,
396     "-U", self.server.admin_name],
397 bh 1605 os.path.join(self.server.dbdir, "psql.log"))
398    
399 bh 1634 self.server.execute_sql(self.dbname, "admin",
400     "GRANT SELECT ON geometry_columns TO PUBLIC;")
401 bh 2057 self.server.execute_sql(self.dbname, "admin",
402     "GRANT SELECT ON spatial_ref_sys TO PUBLIC;")
403 bh 1634
404 bh 2057 for srid, params in self.reference_systems:
405     self.server.execute_sql(self.dbname, "admin",
406     "INSERT INTO spatial_ref_sys VALUES"
407     " (%d, '', %d, '', '%s');"
408     % (srid, srid, params))
409 bh 1605 if self.tables is not None:
410 bh 1662 def unpack(item):
411 bh 2057 extra = {"force_wkt_type": None, "gid_offset": 0,
412     "srid": -1}
413 bh 1656 if len(info) == 2:
414     tablename, shapefile = info
415     else:
416 bh 1662 tablename, shapefile, kw = info
417     for key, val in kw:
418     extra[key] = val
419     return tablename, shapefile, extra
420 bh 1605
421 bh 1662 for info in self.tables:
422     tablename, shapefile, kw = unpack(info)
423     upload_shapefile(shapefile, self, tablename, **kw)
424    
425 bh 2057 def has_data(self, tables, reference_systems):
426     return (self.tables == tables
427     and self.reference_systems == reference_systems)
428 bh 1605
429    
430     def find_postgis_sql():
431     """Return the name of the postgis_sql file
432    
433     A postgis installation usually has the postgis_sql file in
434     PostgreSQL's datadir (i.e. the directory where PostgreSQL keeps
435     static files, not the directory containing the databases).
436     Unfortunately there's no way to determine the name of this directory
437     with pg_config so we assume here that it's
438     $bindir/../share/postgresql/.
439     """
440     bindir = run_config_script("pg_config --bindir").strip()
441     return os.path.join(bindir, "..", "share", "postgresql",
442     "contrib", "postgis.sql")
443    
444     _postgres_server = None
445     def get_test_server():
446     """Return the test database server object.
447    
448     If it doesn't exist yet, create it first.
449    
450     The server will use the directory postgis under the temp dir (as
451     defined by support.create_temp_dir()) for the database cluster.
452     Sockets will be created in tempdir.
453     """
454     global _postgres_server
455     if _postgres_server is None:
456     tempdir = support.create_temp_dir()
457     dbdir = os.path.join(tempdir, "postgis")
458     socket_dir = tempdir
459    
460     _postgres_server = PostgreSQLServer(dbdir, 6543, find_postgis_sql(),
461     socket_dir = socket_dir)
462     _postgres_server.createdb()
463    
464     return _postgres_server
465    
466     def shutdown_test_server():
467     """Shutdown the test server if it is running"""
468     global _postgres_server
469     if _postgres_server is not None:
470     _postgres_server.shutdown()
471     _postgres_server = None
472    
473    
474     def reason_for_not_running_tests():
475     """
476     Determine whether postgis tests can be run and return a reason they can't
477    
478     There's no fool-proof way to reliably determine this short of
479     actually running the tests but we try the following here:
480    
481     - test whether pg_ctl --help can be run successfully
482     - test whether the postgis_sql can be opened
483     The name of the postgis_sql file is determined by find_postgis_sql()
484     - psycopg can be imported successfully.
485     """
486 bh 1679 # run_command currently uses Popen4 which is not available under
487     # Windows, for example.
488     if not hasattr(popen2, "Popen4"):
489     return "Can't run PostGIS test because popen2.Popen4 does not exist"
490    
491 bh 1605 try:
492     run_command(["pg_ctl", "--help"], None)
493     except RuntimeError:
494     return "Can't run PostGIS tests because pg_ctl fails"
495    
496     try:
497     postgis_sql = find_postgis_sql()
498     except:
499     return "Can't run PostGIS tests because postgis.sql can't be found"
500    
501     try:
502     f = open(postgis_sql)
503     f.close()
504     except:
505     return "Can't run PostGIS tests because postgis.sql can't be opened"
506    
507     # The test for psycopg was already done when this module was
508     # imported so we only have to check whether it was successful
509     if psycopg is None:
510     return "Can't run PostGIS tests because psycopg can't be imported"
511    
512     return ""
513    
514    
515     _cannot_run_postgis_tests = None
516     def skip_if_no_postgis():
517     global _cannot_run_postgis_tests
518     if _cannot_run_postgis_tests is None:
519     _cannot_run_postgis_tests = reason_for_not_running_tests()
520     if _cannot_run_postgis_tests:
521     raise support.SkipTest(_cannot_run_postgis_tests)
522    
523 bh 1947 def skip_if_addgeometrycolumn_does_not_use_quote_ident():
524     """Skip a test if the AddGeometryColumn function doesn't use quote_ident
525    
526     If the AddGeometryColumn function doesn't use quote_ident it doesn't
527     support unusual table or column names properly, that is, it will
528     fail with errors for names that contain spaces or double quotes.
529    
530     The test performed by this function is a bit simplistic because it
531     only tests whether the string 'quote_ident' occurs anywhere in the
532     postgis.sql file. This will hopefully works because when this was
533     fixed in postgis CVS AddGeometryColumn was the first function to use
534     quote_ident.
535     """
536     f = file(find_postgis_sql())
537     content = f.read()
538     f.close()
539     if content.find("quote_ident") < 0:
540     raise support.SkipTest("AddGeometryColumn doesn't use quote_ident")
541    
542 bh 1656 def coords_to_point(coords):
543 bh 1605 """Return string with a WKT representation of the point in coords"""
544     x, y = coords[0]
545     return "POINT(%r %r)" % (x, y)
546    
547 bh 1656 def coords_to_polygon(coords):
548 bh 1605 """Return string with a WKT representation of the polygon in coords"""
549     poly = []
550     for ring in coords:
551     poly.append(", ".join(["%r %r" % p for p in ring]))
552     return "POLYGON((%s))" % "), (".join(poly)
553    
554 bh 1656 def coords_to_multilinestring(coords):
555 bh 1605 """Return string with a WKT representation of the arc in coords"""
556     poly = []
557     for ring in coords:
558     poly.append(", ".join(["%r %r" % p for p in ring]))
559     return "MULTILINESTRING((%s))" % "), (".join(poly)
560    
561 bh 1656 def coords_to_multipolygon(coords):
562     """Return string with a WKT representation of the polygon in coords"""
563     poly = []
564     for ring in coords:
565     poly.append(", ".join(["%r %r" % p for p in ring]))
566     return "MULTIPOLYGON(((%s)))" % ")), ((".join(poly)
567    
568     wkt_converter = {
569     "POINT": coords_to_point,
570     "MULTILINESTRING": coords_to_multilinestring,
571     "POLYGON": coords_to_polygon,
572     "MULTIPOLYGON": coords_to_multipolygon,
573     }
574    
575 bh 1662 def upload_shapefile(filename, db, tablename, force_wkt_type = None,
576 bh 2057 gid_offset = 0, srid = -1):
577 bh 1662 """Upload a shapefile into a new database table
578    
579     Parameters:
580    
581     filename -- The name of the shapefile
582    
583     db -- The PostGISDatabase instance representing the database
584    
585     tablename -- The name of the table to create and into which the data
586     is to be inserted
587    
588     force_wkt_type -- If given the real WKT geometry type to use instead
589     of the default that would be chosen based on the type of
590     the shapefile
591    
592     gid_offset -- A number to add to the shapeid to get the value for
593     the gid column (default 0)
594 bh 2057
595     srid -- The srid of the spatial references system used by the table
596     and the data
597 bh 1662 """
598 bh 1605 import dbflib, shapelib
599    
600 bh 1656 # We build this map here because we need shapelib which can only be
601     # imported after support.initthuban has been called which we can't
602     # easily do in this module because it's imported by support.
603     shp_to_wkt = {
604     shapelib.SHPT_POINT: "POINT",
605     shapelib.SHPT_ARC: "MULTILINESTRING",
606     shapelib.SHPT_POLYGON: "POLYGON",
607     }
608    
609 bh 1605 server = db.server
610     dbname = db.dbname
611 bh 1634 conn = psycopg.connect("dbname=%s " % dbname
612     + db.server.connection_string("admin"))
613 bh 1605 cursor = conn.cursor()
614    
615     shp = shapelib.ShapeFile(filename)
616     dbf = dbflib.DBFFile(filename)
617     typemap = {dbflib.FTString: "VARCHAR",
618     dbflib.FTInteger: "INTEGER",
619     dbflib.FTDouble: "DOUBLE PRECISION"}
620    
621     insert_formats = ["%(gid)s"]
622     fields = ["gid INT"]
623     for i in range(dbf.field_count()):
624     ftype, name, width, prec = dbf.field_info(i)
625     fields.append("%s %s" % (name, typemap[ftype]))
626     insert_formats.append("%%(%s)s" % name)
627     stmt = "CREATE TABLE %s (\n %s\n);" % (tablename,
628     ",\n ".join(fields))
629     cursor.execute(stmt)
630     #print stmt
631    
632     numshapes, shapetype, mins, maxs = shp.info()
633 bh 1656 wkttype = shp_to_wkt[shapetype]
634     if force_wkt_type:
635     wkttype = force_wkt_type
636     convert = wkt_converter[wkttype]
637 bh 1605
638     cursor.execute("select AddGeometryColumn('%(dbname)s',"
639 bh 2057 "'%(tablename)s', 'the_geom', %(srid)d, '%(wkttype)s', 2);"
640 bh 1605 % locals())
641    
642 bh 2057 insert_formats.append("GeometryFromText(%(the_geom)s, %(srid)d)")
643 bh 1605
644     insert = ("INSERT INTO %s VALUES (%s)"
645     % (tablename, ", ".join(insert_formats)))
646    
647     for i in range(numshapes):
648     data = dbf.read_record(i)
649     data["tablename"] = tablename
650 bh 1662 data["gid"] = i + gid_offset
651 bh 2057 data["srid"] = srid
652 bh 1605 data["the_geom"] = convert(shp.read_object(i).vertices())
653     #print insert % data
654     cursor.execute(insert, data)
655    
656 bh 1634 cursor.execute("GRANT SELECT ON %s TO PUBLIC;" % tablename)
657    
658 bh 1605 conn.commit()

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26