/[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 2106 by bh, Fri Mar 12 12:59:33 2004 UTC revision 2589 by bh, Tue Mar 29 18:36:53 2005 UTC
# Line 1  Line 1 
1  # Copyright (C) 2003, 2004 by Intevation GmbH  # Copyright (C) 2003, 2004, 2005 by Intevation GmbH
2  # Authors:  # Authors:
3  # Bernhard Herzog <[email protected]>  # Bernhard Herzog <[email protected]>
4  #  #
# Line 17  import time Line 17  import time
17  import popen2  import popen2
18  import shutil  import shutil
19  import traceback  import traceback
20    import re
21    
22  import support  import support
23    
# Line 184  class PostgreSQLServer: Line 185  class PostgreSQLServer:
185              raise RuntimeError("postmaster didn't start")              raise RuntimeError("postmaster didn't start")
186    
187      def is_running(self):      def is_running(self):
188          """Return true a postmaster process is running on self.dbdir          """Return whether a postmaster process is running on self.dbdir
189    
190          This method runs pg_ctl status on the dbdir so even if the          This method runs pg_ctl status on the dbdir and returns True if
191          object has just been created it is possible that this method          that command succeeds and False otherwise.
192          returns true if there's still a postmaster process running for  
193          self.dbdir.          Note that it is possible that this method returns true even if
194            the PostgreSQLServer instance has just been created and
195            createdb() has not been called yet.  This can happen, for
196            instance, if the server has been started manually for debugging
197            purposes after a test suite run.
198          """          """
199          return run_boolean_command(["pg_ctl", "-D", self.dbdir, "status"])          return run_boolean_command(["pg_ctl", "-D", self.dbdir, "status"])
200    
# Line 246  class PostgreSQLServer: Line 251  class PostgreSQLServer:
251               [("gid_offset", 1000)]),               [("gid_offset", 1000)]),
252              ("political", os.path.join("..", "Data", "iceland",              ("political", os.path.join("..", "Data", "iceland",
253                                               "political.shp")),                                               "political.shp")),
254              ("roads", os.path.join("..", "Data", "iceland",              ("roads_multi", os.path.join("..", "Data", "iceland",
255                                           "roads-line.shp")),                                           "roads-line.shp")),
256    
257                # same as roads-multi but using LINESTRING instead of
258                # MULTILINESTRING
259                ("roads", os.path.join("..", "Data", "iceland",
260                                             "roads-line.shp"),
261                 [("force_wkt_type", "LINESTRING")]),
262    
263              # The polygon data as a MULTIPOLYGON geometry type              # The polygon data as a MULTIPOLYGON geometry type
264              ("political_multi", os.path.join("..", "Data", "iceland",              ("political_multi", os.path.join("..", "Data", "iceland",
265                                               "political.shp"),                                               "political.shp"),
# Line 299  class PostgreSQLServer: Line 310  class PostgreSQLServer:
310          return " ".join(params)          return " ".join(params)
311    
312      def execute_sql(self, dbname, user, sql):      def execute_sql(self, dbname, user, sql):
313          """Execute the sql statament          """Execute the sql statament and return a result for SELECT statements
314    
315          The user parameter us used as in connection_params. The dbname          The user parameter us used as in connection_params. The dbname
316          parameter must be the name of a database in the cluster.          parameter must be the name of a database in the cluster.  The
317            sql parameter is the SQL statement to execute as a string.  If
318            the string starts with 'select' (matched case insensitively) the
319            first row of the result will be returned.  Otherwise the return
320            value is None.
321          """          """
322          conn = psycopg.connect("dbname=%s " % dbname          conn = psycopg.connect("dbname=%s " % dbname
323                                 + self.connection_string(user))                                 + self.connection_string(user))
324          cursor = conn.cursor()          cursor = conn.cursor()
325          cursor.execute(sql)          cursor.execute(sql)
326            if sql.lower().startswith("select"):
327                row = cursor.fetchone()
328            else:
329                row = None
330          conn.commit()          conn.commit()
331          conn.close()          conn.close()
332            return row
333    
334        def server_version(self):
335            """Return the server version as a tuple (major, minor, patch)
336    
337            Each item in the tuple is an int.
338            """
339            result = self.execute_sql("template1", "admin", "SELECT version();")[0]
340            match = re.match(r"PostgreSQL (\d+\.\d+\.\d+)", result)
341            if match:
342                return tuple(map(int, match.group(1).split(".")))
343            else:
344                raise RutimeError("Cannot determine PostgreSQL server version"
345                                  " from %r" % result)
346    
347      def require_authentication(self, required):      def require_authentication(self, required):
348          """Switch authentication requirements on or off          """Switch authentication requirements on or off
# Line 321  class PostgreSQLServer: Line 354  class PostgreSQLServer:
354          corresponding call to switch it off again in the test case'          corresponding call to switch it off again in the test case'
355          tearDown method or in a finally: block.          tearDown method or in a finally: block.
356          """          """
357            # Starting with PostgreSQL 7.3 the pg_hba.conf file has an
358            # additional column with a username.  Query the server version
359            # and generate a file in the correct format.
360            if self.server_version() >= (7, 3):
361                user = "all"
362            else:
363                user = ""
364          if required:          if required:
365              contents = "local all password\n"              contents = "local all %s password\n" % user
366          else:          else:
367              contents = "local all trust\n"              contents = "local all %s trust\n" % user
368          f = open(os.path.join(self.dbdir, "pg_hba.conf"), "w")          f = open(os.path.join(self.dbdir, "pg_hba.conf"), "w")
369          f.write(contents)          f.write(contents)
370          f.close()          f.close()
# Line 356  class PostGISDatabase: Line 396  class PostGISDatabase:
396              server -- The PostgreSQLServer instance containing the              server -- The PostgreSQLServer instance containing the
397                  database                  database
398    
399              postgis_sql -- Filename of the postgis.sql file with the              postgis_sql -- Filename of the sql file with the postgis
400                  postgis initialization code                  initialization code
401    
402              dbname -- The name of the database              dbname -- The name of the database
403    
# Line 461  def find_postgis_sql(): Line 501  def find_postgis_sql():
501      """Return the name of the postgis_sql file      """Return the name of the postgis_sql file
502    
503      A postgis installation usually has the postgis_sql file in      A postgis installation usually has the postgis_sql file in
504      PostgreSQL's datadir (i.e. the directory where PostgreSQL keeps      PostgreSQL's $datadir (i.e. the directory where PostgreSQL keeps
505      static files, not the directory containing the databases).      static files, not the directory containing the databases).
506      Unfortunately there's no way to determine the name of this directory      Unfortunately there's no way to determine the name of this directory
507      with pg_config so we assume here that it's      with pg_config so we assume here that it's
508      $bindir/../share/postgresql/.      $bindir/../share/postgresql/.
509    
510        Furthermore, different versions of postgis place the file in
511        slightly different locations or may even use different names.  For
512        instance:
513    
514          postgis 0.7.5        $datadir/contrib/postgis.sql
515          postgis 0.8.1        $datadir/postgis.sql
516          postgis 1.0.0-rc1    $datadir/lwpostgis.sql
517          postgis 1.0.0-rc4    $datadir/contrib/lwpostgis.sql
518    
519        To support both versions, we look in both places and return the
520        first one found (looking under contrib first).  If the file is not
521        found the return value is None.
522      """      """
523      bindir = run_config_script("pg_config --bindir").strip()      bindir = run_config_script("pg_config --bindir").strip()
524      return os.path.join(bindir, "..", "share", "postgresql",      datadir = os.path.join(bindir, "..", "share", "postgresql")
525                          "contrib", "postgis.sql")      for filename in [os.path.join(datadir, "contrib", "postgis.sql"),
526                         os.path.join(datadir, "postgis.sql"),
527                         os.path.join(datadir, "lwpostgis.sql"),
528                         os.path.join(datadir, "contrib", "lwpostgis.sql")]:
529            if os.path.exists(filename):
530                return filename
531    
532    
533  _postgres_server = None  _postgres_server = None
534  def get_test_server():  def get_test_server():
# Line 581  def coords_to_polygon(coords): Line 640  def coords_to_polygon(coords):
640          poly.append(", ".join(["%r %r" % p for p in ring]))          poly.append(", ".join(["%r %r" % p for p in ring]))
641      return "POLYGON((%s))" % "), (".join(poly)      return "POLYGON((%s))" % "), (".join(poly)
642    
643    def coords_to_linestring(coords):
644        """Return string with a LINESTRING WKT representation of coords"""
645        if len(coords) > 1:
646            raise ValueError("A LINESTRING can only have one arc")
647        return "LINESTRING(%s)" % ", ".join(["%r %r" % p for p in coords[0]])
648    
649  def coords_to_multilinestring(coords):  def coords_to_multilinestring(coords):
650      """Return string with a WKT representation of the arc in coords"""      """Return string with a MULTILINESTRING WKT representation of coords"""
651      poly = []      poly = []
652      for ring in coords:      for ring in coords:
653          poly.append(", ".join(["%r %r" % p for p in ring]))          poly.append(", ".join(["%r %r" % p for p in ring]))
# Line 597  def coords_to_multipolygon(coords): Line 662  def coords_to_multipolygon(coords):
662    
663  wkt_converter = {  wkt_converter = {
664      "POINT": coords_to_point,      "POINT": coords_to_point,
665        "LINESTRING": coords_to_linestring,
666      "MULTILINESTRING": coords_to_multilinestring,      "MULTILINESTRING": coords_to_multilinestring,
667      "POLYGON": coords_to_polygon,      "POLYGON": coords_to_polygon,
668      "MULTIPOLYGON": coords_to_multipolygon,      "MULTIPOLYGON": coords_to_multipolygon,
# Line 615  def upload_shapefile(filename, db, table Line 681  def upload_shapefile(filename, db, table
681      tablename -- The name of the table to create and into which the data      tablename -- The name of the table to create and into which the data
682                  is to be inserted                  is to be inserted
683    
684      force_wkt_type -- If given the real WKT geometry type to use instead      force_wkt_type -- If given and not None, this is used as the WKT
685                  of the default that would be chosen based on the type of                  geometry type to use instead of the default that would
686                  the shapefile                  be chosen based on the type of the shapefile
687    
688      gid_offset -- A number to add to the shapeid to get the value for      gid_offset -- A number to add to the shapeid to get the value for
689                  the gid column (default 0)                  the gid column (default 0)

Legend:
Removed from v.2106  
changed lines
  Added in v.2589

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26