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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1656 by bh, Mon Aug 25 18:26:54 2003 UTC revision 2057 by bh, Tue Feb 10 15:51:57 2004 UTC
# Line 1  Line 1 
1  # Copyright (C) 2003 by Intevation GmbH  # Copyright (C) 2003, 2004 by Intevation GmbH
2  # Authors:  # Authors:
3  # Bernhard Herzog <[email protected]>  # Bernhard Herzog <[email protected]>
4  #  #
# Line 198  class PostgreSQLServer: Line 198  class PostgreSQLServer:
198          run_command(["pg_ctl", "-m", "fast", "-D", self.dbdir, "stop"],          run_command(["pg_ctl", "-m", "fast", "-D", self.dbdir, "stop"],
199                      os.path.join(self.dbdir, "pg_ctl-stop.log"))                      os.path.join(self.dbdir, "pg_ctl-stop.log"))
200    
201      def new_postgis_db(self, dbname, tables = None):      def new_postgis_db(self, dbname, tables = None, reference_systems = None):
202          """Create and return a new PostGISDatabase object using self as server          """Create and return a new PostGISDatabase object using self as server
203          """          """
204          db = PostGISDatabase(self, self.postgis_sql, dbname, tables = tables)          db = PostGISDatabase(self, self.postgis_sql, dbname, tables = tables,
205                                 reference_systems = reference_systems)
206          db.initdb()          db.initdb()
207          self.known_dbs[dbname] = db          self.known_dbs[dbname] = db
208          return db          return db
209    
210      def get_static_data_db(self, dbname, tables):      def get_static_data_db(self, dbname, tables, reference_systems):
211          """Return a PostGISDatabase for a database with the given static data          """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          If no databasse of the name dbname exists, create a new one via
# Line 216  class PostgreSQLServer: Line 217  class PostgreSQLServer:
217          indicated data, return that. If the already existing db uses          indicated data, return that. If the already existing db uses
218          different data raise a value error.          different data raise a value error.
219    
220          The tables argument should be a sequence of table specifications          If the database doesn't exist, create a new one via
221          where each specifications is a (tablename, shapefilename) pair.          self.new_postgis_db.
222    
223            The parameters tables and reference_systems have the same
224            meaning as for new_postgis_db.
225          """          """
226          db = self.known_dbs.get(dbname)          db = self.known_dbs.get(dbname)
227          if db is not None:          if db is not None:
228              if db.has_data(tables):              if db.has_data(tables, reference_systems):
229                  return db                  return db
230              raise ValueError("PostGISDatabase named %r doesn't have tables %r"              raise ValueError("PostGISDatabase named %r doesn't have tables %r"
231                               % (dbname, tables))                               % (dbname, tables))
232          return self.new_postgis_db(dbname, tables)          return self.new_postgis_db(dbname, tables, reference_systems)
233    
234      def get_default_static_data_db(self):      def get_default_static_data_db(self):
235          dbname = "PostGISStaticTests"          dbname = "PostGISStaticTests"
236          tables = [("landmarks", os.path.join("..", "Data", "iceland",          srids = [(1, "proj=longlat datum=WGS84")]
237                                               "cultural_landmark-point.shp")),          tables = [
238                    ("political", os.path.join("..", "Data", "iceland",              # Direct copies of the shapefiles. The shapeids are exactly
239                # the same, except where changed with "gid_offset", of
240                # course
241                ("landmarks", os.path.join("..", "Data", "iceland",
242                                           "cultural_landmark-point.shp"),
243                 [("gid_offset", 1000)]),
244                ("political", os.path.join("..", "Data", "iceland",
245                                               "political.shp")),                                               "political.shp")),
246                ("roads", os.path.join("..", "Data", "iceland",
247                                             "roads-line.shp")),
248    
249                    # The polygon data as a MULTIPOLYGON geometry type              # The polygon data as a MULTIPOLYGON geometry type
250                    ("political_multi", os.path.join("..", "Data", "iceland",              ("political_multi", os.path.join("..", "Data", "iceland",
251                                               "political.shp"),                                               "political.shp"),
252                     "MULTIPOLYGON"),               [("force_wkt_type", "MULTIPOLYGON")]),
253    
254                    ("roads", os.path.join("..", "Data", "iceland",              # Copy of landmarks but using an srid
255                                           "roads-line.shp"))]              ("landmarks_srid", os.path.join("..", "Data", "iceland",
256          return self.get_static_data_db(dbname, tables)                                         "cultural_landmark-point.shp"),
257                 [("gid_offset", 1000),
258                  ("srid", 1)]),
259                ]
260            return self.get_static_data_db(dbname, tables, srids)
261    
262      def connection_params(self, user):      def connection_params(self, user):
263          """Return the connection parameters for the given user          """Return the connection parameters for the given user
# Line 319  class PostGISDatabase: Line 335  class PostGISDatabase:
335    
336      """A PostGIS database in a PostgreSQLServer"""      """A PostGIS database in a PostgreSQLServer"""
337    
338      def __init__(self, server, postgis_sql, dbname, tables = None):      def __init__(self, server, postgis_sql, dbname, tables = None,
339                     reference_systems = ()):
340            """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    
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            """
366          self.server = server          self.server = server
367          self.postgis_sql = postgis_sql          self.postgis_sql = postgis_sql
368          self.dbname = dbname          self.dbname = dbname
369          self.tables = tables          self.tables = tables
370            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    
377      def initdb(self):      def initdb(self):
378          """Remove the old db directory and create and initialize a new database          """Remove the old db directory and create and initialize a new database
# Line 349  class PostGISDatabase: Line 398  class PostGISDatabase:
398    
399          self.server.execute_sql(self.dbname, "admin",          self.server.execute_sql(self.dbname, "admin",
400                                  "GRANT SELECT ON geometry_columns TO PUBLIC;")                                  "GRANT SELECT ON geometry_columns TO PUBLIC;")
401            self.server.execute_sql(self.dbname, "admin",
402                                    "GRANT SELECT ON spatial_ref_sys TO PUBLIC;")
403    
404            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          if self.tables is not None:          if self.tables is not None:
410              for info  in self.tables:              def unpack(item):
411                    extra = {"force_wkt_type": None, "gid_offset": 0,
412                             "srid": -1}
413                  if len(info) == 2:                  if len(info) == 2:
414                      tablename, shapefile = info                      tablename, shapefile = info
                     wkt_type = None  
415                  else:                  else:
416                      tablename, shapefile, wkt_type = info                      tablename, shapefile, kw = info
417                  upload_shapefile(shapefile, self, tablename,                      for key, val in kw:
418                                   force_wkt_type = wkt_type)                          extra[key] = val
419                    return tablename, shapefile, extra
420      def has_data(self, tables):  
421          return self.tables == tables              for info in self.tables:
422                    tablename, shapefile, kw = unpack(info)
423                    upload_shapefile(shapefile, self, tablename, **kw)
424    
425        def has_data(self, tables, reference_systems):
426            return (self.tables == tables
427                    and self.reference_systems == reference_systems)
428    
429    
430  def find_postgis_sql():  def find_postgis_sql():
# Line 420  def reason_for_not_running_tests(): Line 483  def reason_for_not_running_tests():
483         The name of the postgis_sql file is determined by find_postgis_sql()         The name of the postgis_sql file is determined by find_postgis_sql()
484       - psycopg can be imported successfully.       - psycopg can be imported successfully.
485      """      """
486        # 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      try:      try:
492          run_command(["pg_ctl", "--help"], None)          run_command(["pg_ctl", "--help"], None)
493      except RuntimeError:      except RuntimeError:
# Line 452  def skip_if_no_postgis(): Line 520  def skip_if_no_postgis():
520      if _cannot_run_postgis_tests:      if _cannot_run_postgis_tests:
521          raise support.SkipTest(_cannot_run_postgis_tests)          raise support.SkipTest(_cannot_run_postgis_tests)
522    
523    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  def coords_to_point(coords):  def coords_to_point(coords):
543      """Return string with a WKT representation of the point in coords"""      """Return string with a WKT representation of the point in coords"""
544      x, y = coords[0]      x, y = coords[0]
# Line 485  wkt_converter = { Line 572  wkt_converter = {
572      "MULTIPOLYGON": coords_to_multipolygon,      "MULTIPOLYGON": coords_to_multipolygon,
573      }      }
574    
575  def upload_shapefile(filename, db, tablename, force_wkt_type = None):  def upload_shapefile(filename, db, tablename, force_wkt_type = None,
576                         gid_offset = 0, srid = -1):
577        """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    
595        srid -- The srid of the spatial references system used by the table
596                and the data
597        """
598      import dbflib, shapelib      import dbflib, shapelib
599    
600      # We build this map here because we need shapelib which can only be      # We build this map here because we need shapelib which can only be
# Line 527  def upload_shapefile(filename, db, table Line 636  def upload_shapefile(filename, db, table
636      convert = wkt_converter[wkttype]      convert = wkt_converter[wkttype]
637    
638      cursor.execute("select AddGeometryColumn('%(dbname)s',"      cursor.execute("select AddGeometryColumn('%(dbname)s',"
639                     "'%(tablename)s', 'the_geom', '-1', '%(wkttype)s', 2);"                     "'%(tablename)s', 'the_geom', %(srid)d, '%(wkttype)s', 2);"
640                     % locals())                     % locals())
641    
642      insert_formats.append("GeometryFromText(%(the_geom)s, -1)")      insert_formats.append("GeometryFromText(%(the_geom)s, %(srid)d)")
643    
644      insert = ("INSERT INTO %s VALUES (%s)"      insert = ("INSERT INTO %s VALUES (%s)"
645                % (tablename, ", ".join(insert_formats)))                % (tablename, ", ".join(insert_formats)))
# Line 538  def upload_shapefile(filename, db, table Line 647  def upload_shapefile(filename, db, table
647      for i in range(numshapes):      for i in range(numshapes):
648          data = dbf.read_record(i)          data = dbf.read_record(i)
649          data["tablename"] = tablename          data["tablename"] = tablename
650          data["gid"] = i          data["gid"] = i + gid_offset
651            data["srid"] = srid
652          data["the_geom"] = convert(shp.read_object(i).vertices())          data["the_geom"] = convert(shp.read_object(i).vertices())
653          #print insert % data          #print insert % data
654          cursor.execute(insert, data)          cursor.execute(insert, data)

Legend:
Removed from v.1656  
changed lines
  Added in v.2057

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26