v.unpack.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. ############################################################################
  4. #
  5. # MODULE: v.unpack
  6. # AUTHOR(S): Luca Delucchi
  7. #
  8. # PURPOSE: Unpack up a vector map packed with v.pack
  9. # COPYRIGHT: (C) 2010-2013 by the GRASS Development Team
  10. #
  11. # This program is free software under the GNU General
  12. # Public License (>=v2). Read the file COPYING that
  13. # comes with GRASS for details.
  14. #
  15. #############################################################################
  16. #%module
  17. #% description: Unpacks a vector map packed with v.pack.
  18. #% keywords: vector, import, copying
  19. #%end
  20. #%option G_OPT_F_INPUT
  21. #% gisprompt: old,bin,file
  22. #% description: Name of input pack file
  23. #% required : yes
  24. #%end
  25. #%option G_OPT_V_OUTPUT
  26. #% label: Name for output vector map
  27. #% description: Default: taken from input file internals
  28. #% required : no
  29. #%end
  30. #%flag
  31. #% key: o
  32. #% description: Override projection check (use current location's projection)
  33. #%end
  34. import os
  35. import sys
  36. import shutil
  37. import tarfile
  38. import atexit
  39. from grass.script.utils import diff_files, try_rmdir
  40. from grass.script import core as grass
  41. from grass.script import db as grassdb
  42. def cleanup():
  43. try_rmdir(tmp_dir)
  44. def main():
  45. infile = options['input']
  46. # create temporary directory
  47. global tmp_dir
  48. tmp_dir = grass.tempdir()
  49. grass.debug('tmp_dir = %s' % tmp_dir)
  50. # check if the input file exists
  51. if not os.path.exists(infile):
  52. grass.fatal(_("File <%s> not found") % infile)
  53. # copy the files to tmp dir
  54. input_base = os.path.basename(infile)
  55. shutil.copyfile(infile, os.path.join(tmp_dir, input_base))
  56. os.chdir(tmp_dir)
  57. tar = tarfile.TarFile.open(name=input_base, mode='r')
  58. try:
  59. data_name = tar.getnames()[0]
  60. except:
  61. grass.fatal(_("Pack file unreadable"))
  62. # set the output name
  63. if options['output']:
  64. map_name = options['output']
  65. else:
  66. map_name = data_name
  67. # grass env
  68. gisenv = grass.gisenv()
  69. mset_dir = os.path.join(gisenv['GISDBASE'],
  70. gisenv['LOCATION_NAME'],
  71. gisenv['MAPSET'])
  72. new_dir = os.path.join(mset_dir, 'vector', map_name)
  73. gfile = grass.find_file(name=map_name, element='vector', mapset='.')
  74. overwrite = os.getenv('GRASS_OVERWRITE')
  75. if gfile['file'] and overwrite != '1':
  76. grass.fatal(_("Vector map <%s> already exists") % map_name)
  77. elif overwrite == '1' and gfile['file']:
  78. grass.warning(_("Vector map <%s> already exists and will be overwritten") % map_name)
  79. grass.run_command('g.remove', quiet=True, flags='f', type='vect', name=map_name)
  80. shutil.rmtree(new_dir, True)
  81. # extract data
  82. tar.extractall()
  83. if os.path.exists(os.path.join(map_name, 'coor')):
  84. pass
  85. elif os.path.exists(os.path.join(map_name, 'cell')):
  86. grass.fatal(_("This GRASS GIS pack file contains raster data. Use "
  87. "r.unpack to unpack <%s>" % map_name))
  88. else:
  89. grass.fatal(_("Pack file unreadable"))
  90. # check projection compatibility in a rather crappy way
  91. loc_proj = os.path.join(mset_dir, '..', 'PERMANENT', 'PROJ_INFO')
  92. loc_proj_units = os.path.join(mset_dir, '..', 'PERMANENT', 'PROJ_UNITS')
  93. diff_result_1 = diff_result_2 = None
  94. if not grass.compare_key_value_text_files(filename_a=os.path.join(tmp_dir, 'PROJ_INFO'),
  95. filename_b=loc_proj, proj=True):
  96. diff_result_1 = diff_files(os.path.join(tmp_dir, 'PROJ_INFO'),
  97. loc_proj)
  98. if not grass.compare_key_value_text_files(filename_a=os.path.join(tmp_dir, 'PROJ_UNITS'),
  99. filename_b=loc_proj_units,
  100. units=True):
  101. diff_result_2 = diff_files(os.path.join(tmp_dir, 'PROJ_UNITS'),
  102. loc_proj_units)
  103. if diff_result_1 or diff_result_2:
  104. if flags['o']:
  105. grass.warning(_("Projection information does not match. Proceeding..."))
  106. else:
  107. if diff_result_1:
  108. grass.warning(_("Difference between PROJ_INFO file of packed map "
  109. "and of current location:\n{diff}").format(diff=''.join(diff_result_1)))
  110. if diff_result_2:
  111. grass.warning(_("Difference between PROJ_UNITS file of packed map "
  112. "and of current location:\n{diff}").format(diff=''.join(diff_result_2)))
  113. grass.fatal(_("Projection information does not match. Aborting."))
  114. # new db
  115. fromdb = os.path.join(tmp_dir, 'db.sqlite')
  116. # copy file
  117. shutil.copytree(data_name, new_dir)
  118. # exist fromdb
  119. if os.path.exists(fromdb):
  120. # the db connection in the output mapset
  121. dbconn = grassdb.db_connection()
  122. todb = dbconn['database']
  123. # return all tables
  124. list_fromtable = grass.read_command('db.tables', driver='sqlite',
  125. database=fromdb).splitlines()
  126. # return the list of old connection for extract layer number and key
  127. dbln = open(os.path.join(new_dir, 'dbln'), 'r')
  128. dbnlist = dbln.readlines()
  129. dbln.close()
  130. # check if dbf or sqlite directory exists
  131. if dbconn['driver'] == 'dbf' and not os.path.exists(os.path.join(mset_dir, 'dbf')):
  132. os.mkdir(os.path.join(mset_dir, 'dbf'))
  133. elif dbconn['driver'] == 'sqlite' and not os.path.exists(os.path.join(mset_dir, 'sqlite')):
  134. os.mkdir(os.path.join(mset_dir, 'sqlite'))
  135. # for each old connection
  136. for t in dbnlist:
  137. # it split the line of each connection, to found layer number and key
  138. if len(t.split('|')) != 1:
  139. values = t.split('|')
  140. else:
  141. values = t.split(' ')
  142. from_table = values[1]
  143. layer = values[0].split('/')[0]
  144. # we need to take care about the table name in case of several layer
  145. if options["output"]:
  146. if len(dbnlist) > 1:
  147. to_table = "%s_%s" % (map_name, layer)
  148. else:
  149. to_table = map_name
  150. else:
  151. to_table = from_table
  152. grass.verbose(_("Coping table <%s> as table <%s>") % (from_table,
  153. to_table))
  154. # copy the table in the default database
  155. if 0 != grass.run_command('db.copy', to_driver=dbconn['driver'],
  156. to_database=todb, to_table=to_table,
  157. from_driver='sqlite',
  158. from_database=fromdb,
  159. from_table=from_table):
  160. grass.fatal(_("Unable to copy table <%s> as table <%s>") % (from_table, to_table))
  161. grass.verbose(_("Connect table <%s> to vector map <%s> at layer <%s>") %
  162. (to_table, map_name, layer))
  163. # and connect the new tables with the right layer
  164. if 0 != grass.run_command('v.db.connect', flags='o', quiet=True,
  165. driver=dbconn['driver'], database=todb,
  166. map=map_name, key=values[2],
  167. layer=layer, table=to_table):
  168. grass.fatal(_("Unable to connect table <%s> to vector map <%s>") %
  169. (to_table, map_name))
  170. grass.message(_("Vector map <%s> succesfully unpacked") % map_name)
  171. if __name__ == "__main__":
  172. options, flags = grass.parser()
  173. atexit.register(cleanup)
  174. sys.exit(main())