v.unpack.py 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  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 import core as grass
  40. from grass.script import db as grassdb
  41. def cleanup():
  42. grass.try_rmdir(tmp_dir)
  43. def main():
  44. infile = options['input']
  45. # create temporary directory
  46. global tmp_dir
  47. tmp_dir = grass.tempdir()
  48. grass.debug('tmp_dir = %s' % tmp_dir)
  49. # check if the input file exists
  50. if not os.path.exists(infile):
  51. grass.fatal(_("File <%s> not found") % infile)
  52. # copy the files to tmp dir
  53. input_base = os.path.basename(infile)
  54. shutil.copyfile(infile, os.path.join(tmp_dir, input_base))
  55. os.chdir(tmp_dir)
  56. tar = tarfile.TarFile.open(name=input_base, mode='r')
  57. try:
  58. data_name = tar.getnames()[0]
  59. except:
  60. grass.fatal(_("Pack file unreadable"))
  61. # set the output name
  62. if options['output']:
  63. map_name = options['output']
  64. else:
  65. map_name = data_name
  66. # grass env
  67. gisenv = grass.gisenv()
  68. mset_dir = os.path.join(gisenv['GISDBASE'],
  69. gisenv['LOCATION_NAME'],
  70. gisenv['MAPSET'])
  71. new_dir = os.path.join(mset_dir, 'vector', map_name)
  72. gfile = grass.find_file(name=map_name, element='vector', mapset='.')
  73. overwrite = os.getenv('GRASS_OVERWRITE')
  74. if gfile['file'] and overwrite != '1':
  75. grass.fatal(_("Vector map <%s> already exists") % map_name)
  76. elif overwrite == '1' and gfile['file']:
  77. grass.warning(_("Vector map <%s> already exists and will be overwritten") % map_name)
  78. grass.run_command('g.remove', quiet=True, vect=map_name)
  79. shutil.rmtree(new_dir, True)
  80. # extract data
  81. tar.extractall()
  82. # check projection compatibility in a rather crappy way
  83. loc_proj = os.path.join(mset_dir, '..', 'PERMANENT', 'PROJ_INFO')
  84. loc_proj_units = os.path.join(mset_dir, '..', 'PERMANENT', 'PROJ_UNITS')
  85. diff_result_1 = diff_result_2 = None
  86. if not grass.compare_key_value_text_files(filename_a=os.path.join(tmp_dir,'PROJ_INFO'),
  87. filename_b=loc_proj, proj=True):
  88. diff_result_1 = grass.diff_files(os.path.join(tmp_dir, 'PROJ_INFO'),
  89. loc_proj)
  90. if not grass.compare_key_value_text_files(filename_a=os.path.join(tmp_dir,'PROJ_UNITS'),
  91. filename_b=loc_proj_units,
  92. units=True):
  93. diff_result_2 = grass.diff_files(os.path.join(tmp_dir, 'PROJ_UNITS'),
  94. loc_proj_units)
  95. if diff_result_1 or diff_result_2:
  96. if flags['o']:
  97. grass.warning(_("Projection information does not match. Proceeding..."))
  98. else:
  99. if diff_result_1:
  100. grass.warning(_("Difference between PROJ_INFO file of packed map "
  101. "and of current location:\n{diff}").format(diff=''.join(diff_result_1)))
  102. if diff_result_2:
  103. grass.warning(_("Difference between PROJ_UNITS file of packed map "
  104. "and of current location:\n{diff}").format(diff=''.join(diff_result_2)))
  105. grass.fatal(_("Projection information does not match. Aborting."))
  106. # new db
  107. fromdb = os.path.join(tmp_dir, 'db.sqlite')
  108. # copy file
  109. shutil.copytree(data_name, new_dir)
  110. # exist fromdb
  111. if os.path.exists(fromdb):
  112. # the db connection in the output mapset
  113. dbconn = grassdb.db_connection()
  114. todb = dbconn['database']
  115. # return all tables
  116. list_fromtable = grass.read_command('db.tables', driver='sqlite',
  117. database=fromdb).splitlines()
  118. # return the list of old connection for extract layer number and key
  119. dbln = open(os.path.join(new_dir, 'dbln'), 'r')
  120. dbnlist = dbln.readlines()
  121. dbln.close()
  122. # check if dbf or sqlite directory exists
  123. if dbconn['driver'] == 'dbf' and not os.path.exists(os.path.join(mset_dir, 'dbf')):
  124. os.mkdir(os.path.join(mset_dir, 'dbf'))
  125. elif dbconn['driver'] == 'sqlite' and not os.path.exists(os.path.join(mset_dir, 'sqlite')):
  126. os.mkdir(os.path.join(mset_dir, 'sqlite'))
  127. # for each old connection
  128. for t in dbnlist:
  129. # it split the line of each connection, to found layer number and key
  130. if len(t.split('|')) != 1:
  131. values = t.split('|')
  132. else:
  133. values = t.split(' ')
  134. from_table = values[1]
  135. layer = values[0].split('/')[0]
  136. # we need to take care about the table name in case of several layer
  137. if options["output"]:
  138. if len(dbnlist) > 1:
  139. to_table = "%s_%s" % (map_name, layer)
  140. else:
  141. to_table = map_name
  142. else:
  143. to_table = from_table
  144. grass.verbose(_("Coping table <%s> as table <%s>") % (from_table,
  145. to_table))
  146. # copy the table in the default database
  147. if 0 != grass.run_command('db.copy', to_driver=dbconn['driver'],
  148. to_database=todb, to_table=to_table,
  149. from_driver='sqlite',
  150. from_database=fromdb,
  151. from_table=from_table):
  152. grass.fatal(_("Unable to copy table <%s> as table <%s>") % (from_table, to_table))
  153. grass.verbose(_("Connect table <%s> to vector map <%s> at layer <%s>") % \
  154. (to_table, map_name, layer))
  155. # and connect the new tables with the right layer
  156. if 0 != grass.run_command('v.db.connect', flags='o', quiet=True,
  157. driver=dbconn['driver'], database=todb,
  158. map=map_name, key=values[2],
  159. layer=layer, table=to_table):
  160. grass.fatal(_("Unable to connect table <%s> to vector map <%s>") % \
  161. (to_table, map_name))
  162. grass.message(_("Vector map <%s> succesfully unpacked") % map_name)
  163. if __name__ == "__main__":
  164. options, flags = grass.parser()
  165. atexit.register(cleanup)
  166. sys.exit(main())