@@ -932,6 +932,7 @@ def __init__(self, *args, **kwargs):
932932 self .shp = None
933933 self .shx = None
934934 self .dbf = None
935+ self ._files_to_close = []
935936 self .shapeName = "Not specified"
936937 self ._offsets = []
937938 self .shpLength = None
@@ -998,6 +999,7 @@ def __init__(self, *args, **kwargs):
998999 fileobj .write (member .read ())
9991000 fileobj .seek (0 )
10001001 setattr (self , ext , fileobj )
1002+ self ._files_to_close .append (fileobj )
10011003 except :
10021004 pass
10031005 # Close and delete the temporary zipfile
@@ -1030,6 +1032,7 @@ def __init__(self, *args, **kwargs):
10301032 fileobj .write (resp .read ())
10311033 fileobj .seek (0 )
10321034 setattr (self , ext , fileobj )
1035+ self ._files_to_close .append (fileobj )
10331036 except HTTPError :
10341037 pass
10351038 if (self .shp or self .dbf ):
@@ -1202,9 +1205,11 @@ def load_shp(self, shapefile_name):
12021205 shp_ext = 'shp'
12031206 try :
12041207 self .shp = open ("%s.%s" % (shapefile_name , shp_ext ), "rb" )
1208+ self ._files_to_close .append (self .shp )
12051209 except IOError :
12061210 try :
12071211 self .shp = open ("%s.%s" % (shapefile_name , shp_ext .upper ()), "rb" )
1212+ self ._files_to_close .append (self .shp )
12081213 except IOError :
12091214 pass
12101215
@@ -1215,9 +1220,11 @@ def load_shx(self, shapefile_name):
12151220 shx_ext = 'shx'
12161221 try :
12171222 self .shx = open ("%s.%s" % (shapefile_name , shx_ext ), "rb" )
1223+ self ._files_to_close .append (self .shx )
12181224 except IOError :
12191225 try :
12201226 self .shx = open ("%s.%s" % (shapefile_name , shx_ext .upper ()), "rb" )
1227+ self ._files_to_close .append (self .shx )
12211228 except IOError :
12221229 pass
12231230
@@ -1228,28 +1235,26 @@ def load_dbf(self, shapefile_name):
12281235 dbf_ext = 'dbf'
12291236 try :
12301237 self .dbf = open ("%s.%s" % (shapefile_name , dbf_ext ), "rb" )
1238+ self ._files_to_close .append (self .dbf )
12311239 except IOError :
12321240 try :
12331241 self .dbf = open ("%s.%s" % (shapefile_name , dbf_ext .upper ()), "rb" )
1242+ self ._files_to_close .append (self .dbf )
12341243 except IOError :
12351244 pass
12361245
12371246 def __del__ (self ):
12381247 self .close ()
12391248
12401249 def close (self ):
1241- for attribute in ('shp' ,'shx' ,'dbf' ):
1242- try :
1243- obj = getattr (self , attribute )
1244- except AttributeError :
1245- # deepcopies fail to copy these attributes and raises exception during
1246- # garbage collection - https://github.com/mattijn/topojson/issues/120
1247- obj = None
1248- if obj and hasattr (obj , 'close' ):
1250+ # Close any files that the reader opened (but not those given by user)
1251+ for attribute in self ._files_to_close :
1252+ if hasattr (attribute , 'close' ):
12491253 try :
1250- obj .close ()
1254+ attribute .close ()
12511255 except IOError :
12521256 pass
1257+ self ._files_to_close = []
12531258
12541259 def __getFileObj (self , f ):
12551260 """Checks to see if the requested shapefile file object is
@@ -1786,6 +1791,7 @@ def __init__(self, target=None, shapeType=None, autoBalance=False, **kwargs):
17861791 self .fields = []
17871792 self .shapeType = shapeType
17881793 self .shp = self .shx = self .dbf = None
1794+ self ._files_to_close = []
17891795 if target :
17901796 target = pathlike_obj (target )
17911797 if not is_string (target ):
@@ -1866,13 +1872,22 @@ def close(self):
18661872 if self .dbf and dbf_open :
18671873 self .__dbfHeader ()
18681874
1869- # Close files
1875+ # Flush files
18701876 for attribute in (self .shp , self .shx , self .dbf ):
1877+ if hasattr (attribute , 'flush' ) and not (hasattr (attribute , 'closed' ) and attribute .closed ):
1878+ try :
1879+ attribute .flush ()
1880+ except IOError :
1881+ pass
1882+
1883+ # Close any files that the writer opened (but not those given by user)
1884+ for attribute in self ._files_to_close :
18711885 if hasattr (attribute , 'close' ):
18721886 try :
18731887 attribute .close ()
18741888 except IOError :
18751889 pass
1890+ self ._files_to_close = []
18761891
18771892 def __getFileObj (self , f ):
18781893 """Safety handler to verify file-like objects"""
@@ -1884,7 +1899,9 @@ def __getFileObj(self, f):
18841899 pth = os .path .split (f )[0 ]
18851900 if pth and not os .path .exists (pth ):
18861901 os .makedirs (pth )
1887- return open (f , "wb+" )
1902+ fp = open (f , "wb+" )
1903+ self ._files_to_close .append (fp )
1904+ return fp
18881905
18891906 def __shpFileLength (self ):
18901907 """Calculates the file length of the shp file."""
0 commit comments