Commit 8a4cf33657f213a7836d52fd3569daf38a955541
1 parent
a41b332c
Exists in
master
and in
67 other branches
FIX: Resolved the problem with non-ascii characters in mask and surface name by …
…not appending its name on the file used to mantain them
Showing
5 changed files
with
228 additions
and
201 deletions
Show diff stats
.gitattributes
@@ -845,6 +845,7 @@ invesalius/.svnignore -text | @@ -845,6 +845,7 @@ invesalius/.svnignore -text | ||
845 | invesalius/data/bases.py -text | 845 | invesalius/data/bases.py -text |
846 | invesalius/data/co_registration.py -text | 846 | invesalius/data/co_registration.py -text |
847 | invesalius/data/converters.py -text | 847 | invesalius/data/converters.py -text |
848 | +invesalius/data/polydata_utils.py -text svneol=native#unset | ||
848 | invesalius/gui/import_network_panel.py -text | 849 | invesalius/gui/import_network_panel.py -text |
849 | invesalius/gui/preferences.py -text | 850 | invesalius/gui/preferences.py -text |
850 | invesalius/net/__init__.py -text | 851 | invesalius/net/__init__.py -text |
invesalius/data/mask.py
@@ -53,7 +53,7 @@ class Mask(): | @@ -53,7 +53,7 @@ class Mask(): | ||
53 | 53 | ||
54 | def SavePlist(self, dir_temp): | 54 | def SavePlist(self, dir_temp): |
55 | mask = {} | 55 | mask = {} |
56 | - filename = u'mask%d_%s' % (self.index, self.name) | 56 | + filename = u'mask_%d' % self.index |
57 | mask_filename = u'%s.dat' % filename | 57 | mask_filename = u'%s.dat' % filename |
58 | mask_filepath = os.path.join(dir_temp, mask_filename) | 58 | mask_filepath = os.path.join(dir_temp, mask_filename) |
59 | self._save_mask(mask_filepath) | 59 | self._save_mask(mask_filepath) |
invesalius/data/polydata_utils.py
1 | -#-------------------------------------------------------------------------- | ||
2 | -# Software: InVesalius - Software de Reconstrucao 3D de Imagens Medicas | ||
3 | -# Copyright: (C) 2001 Centro de Pesquisas Renato Archer | ||
4 | -# Homepage: http://www.softwarepublico.gov.br | ||
5 | -# Contact: invesalius@cti.gov.br | ||
6 | -# License: GNU - GPL 2 (LICENSE.txt/LICENCA.txt) | ||
7 | -#-------------------------------------------------------------------------- | ||
8 | -# Este programa e software livre; voce pode redistribui-lo e/ou | ||
9 | -# modifica-lo sob os termos da Licenca Publica Geral GNU, conforme | ||
10 | -# publicada pela Free Software Foundation; de acordo com a versao 2 | ||
11 | -# da Licenca. | ||
12 | -# | ||
13 | -# Este programa eh distribuido na expectativa de ser util, mas SEM | ||
14 | -# QUALQUER GARANTIA; sem mesmo a garantia implicita de | ||
15 | -# COMERCIALIZACAO ou de ADEQUACAO A QUALQUER PROPOSITO EM | ||
16 | -# PARTICULAR. Consulte a Licenca Publica Geral GNU para obter mais | ||
17 | -# detalhes. | ||
18 | -#-------------------------------------------------------------------------- | ||
19 | - | ||
20 | -import sys | ||
21 | - | ||
22 | -import vtk | ||
23 | -import wx | ||
24 | -from wx.lib.pubsub import pub as Publisher | ||
25 | - | ||
26 | -import vtk_utils as vu | ||
27 | - | ||
28 | -# Update progress value in GUI | ||
29 | -UpdateProgress = vu.ShowProgress() | ||
30 | - | ||
31 | -def ApplyDecimationFilter(polydata, reduction_factor): | ||
32 | - """ | ||
33 | - Reduce number of triangles of the given vtkPolyData, based on | ||
34 | - reduction_factor. | ||
35 | - """ | ||
36 | - # Important: vtkQuadricDecimation presented better results than | ||
37 | - # vtkDecimatePro | ||
38 | - decimation = vtk.vtkQuadricDecimation() | ||
39 | - decimation.SetInput(polydata) | ||
40 | - decimation.SetTargetReduction(reduction_factor) | ||
41 | - decimation.GetOutput().ReleaseDataFlagOn() | ||
42 | - decimation.AddObserver("ProgressEvent", lambda obj, evt: | ||
43 | - UpdateProgress(decimation, "Reducing number of triangles...")) | ||
44 | - return decimation.GetOutput() | ||
45 | - | ||
46 | -def ApplySmoothFilter(polydata, iterations, relaxation_factor): | ||
47 | - """ | ||
48 | - Smooth given vtkPolyData surface, based on iteration and relaxation_factor. | ||
49 | - """ | ||
50 | - smoother = vtk.vtkSmoothPolyDataFilter() | ||
51 | - smoother.SetInput(polydata) | ||
52 | - smoother.SetNumberOfIterations(iterations) | ||
53 | - smoother.SetFeatureAngle(80) | ||
54 | - smoother.SetRelaxationFactor(relaxation_factor) | ||
55 | - smoother.FeatureEdgeSmoothingOn() | ||
56 | - smoother.BoundarySmoothingOn() | ||
57 | - smoother.GetOutput().ReleaseDataFlagOn() | ||
58 | - smoother.AddObserver("ProgressEvent", lambda obj, evt: | ||
59 | - UpdateProgress(smoother, "Smoothing surface...")) | ||
60 | - | ||
61 | - return smoother.GetOutput() | ||
62 | - | ||
63 | - | ||
64 | - | ||
65 | -def FillSurfaceHole(polydata): | ||
66 | - """ | ||
67 | - Fill holes in the given polydata. | ||
68 | - """ | ||
69 | - # Filter used to detect and fill holes. Only fill | ||
70 | - print "Filling polydata" | ||
71 | - filled_polydata = vtk.vtkFillHolesFilter() | ||
72 | - filled_polydata.SetInput(polydata) | ||
73 | - filled_polydata.SetHoleSize(500) | ||
74 | - return filled_polydata.GetOutput() | ||
75 | - | ||
76 | -def CalculateSurfaceVolume(polydata): | ||
77 | - """ | ||
78 | - Calculate the volume from the given polydata | ||
79 | - """ | ||
80 | - # Filter used to calculate volume and area from a polydata | ||
81 | - measured_polydata = vtk.vtkMassProperties() | ||
82 | - measured_polydata.SetInput(polydata) | ||
83 | - return measured_polydata.GetVolume() | ||
84 | - | ||
85 | -def CalculateSurfaceArea(polydata): | ||
86 | - """ | ||
87 | - Calculate the volume from the given polydata | ||
88 | - """ | ||
89 | - # Filter used to calculate volume and area from a polydata | ||
90 | - measured_polydata = vtk.vtkMassProperties() | ||
91 | - measured_polydata.SetInput(polydata) | ||
92 | - return measured_polydata.GetSurfaceArea() | ||
93 | - | ||
94 | -def Merge(polydata_list): | ||
95 | - append = vtk.vtkAppendPolyData() | ||
96 | - | ||
97 | - for polydata in polydata_list: | ||
98 | - triangle = vtk.vtkTriangleFilter() | ||
99 | - triangle.SetInput(polydata) | ||
100 | - append.AddInput(triangle.GetOutput()) | ||
101 | - | ||
102 | - clean = vtk.vtkCleanPolyData() | ||
103 | - clean.SetInput(append.GetOutput()) | ||
104 | - | ||
105 | - return append.GetOutput() | ||
106 | - | ||
107 | -def Export(polydata, filename, bin=False): | ||
108 | - writer = vtk.vtkXMLPolyDataWriter() | ||
109 | - print filename, type(filename) | ||
110 | - writer.SetFileName(filename.encode('utf-8')) | ||
111 | - if bin: | ||
112 | - writer.SetDataModeToBinary() | ||
113 | - else: | ||
114 | - writer.SetDataModeToAscii() | ||
115 | - writer.SetInput(polydata) | ||
116 | - writer.Write() | ||
117 | - | ||
118 | -def Import(filename): | ||
119 | - reader = vtk.vtkXMLPolyDataReader() | ||
120 | - reader.SetFileName(filename.encode('utf-8')) | ||
121 | - reader.Update() | ||
122 | - return reader.GetOutput() | ||
123 | - | ||
124 | -def JoinSeedsParts(polydata, point_id_list): | ||
125 | - """ | ||
126 | - The function require vtkPolyData and point id | ||
127 | - from vtkPolyData. | ||
128 | - """ | ||
129 | - conn = vtk.vtkPolyDataConnectivityFilter() | ||
130 | - conn.SetInput(polydata) | ||
131 | - conn.SetExtractionModeToPointSeededRegions() | ||
132 | - UpdateProgress = vu.ShowProgress(1 + len(point_id_list)) | ||
133 | - pos = 1 | ||
134 | - for seed in point_id_list: | ||
135 | - conn.AddSeed(seed) | ||
136 | - UpdateProgress(pos, _("Analysing selected regions...")) | ||
137 | - pos += 1 | ||
138 | - | ||
139 | - conn.AddObserver("ProgressEvent", lambda obj, evt: | ||
140 | - UpdateProgress(conn, "Getting selected parts")) | ||
141 | - conn.Update() | ||
142 | - | ||
143 | - result = vtk.vtkPolyData() | ||
144 | - result.DeepCopy(conn.GetOutput()) | ||
145 | - result.Update() | ||
146 | - return result | ||
147 | - | ||
148 | -def SelectLargestPart(polydata): | ||
149 | - """ | ||
150 | - """ | ||
151 | - UpdateProgress = vu.ShowProgress(1) | ||
152 | - conn = vtk.vtkPolyDataConnectivityFilter() | ||
153 | - conn.SetInput(polydata) | ||
154 | - conn.SetExtractionModeToLargestRegion() | ||
155 | - conn.AddObserver("ProgressEvent", lambda obj, evt: | ||
156 | - UpdateProgress(conn, "Getting largest part...")) | ||
157 | - conn.Update() | ||
158 | - | ||
159 | - result = vtk.vtkPolyData() | ||
160 | - result.DeepCopy(conn.GetOutput()) | ||
161 | - result.Update() | ||
162 | - return result | ||
163 | - | ||
164 | -def SplitDisconectedParts(polydata): | ||
165 | - """ | ||
166 | - """ | ||
167 | - conn = vtk.vtkPolyDataConnectivityFilter() | ||
168 | - conn.SetInput(polydata) | ||
169 | - conn.SetExtractionModeToAllRegions() | ||
170 | - conn.Update() | ||
171 | - | ||
172 | - nregions = conn.GetNumberOfExtractedRegions() | ||
173 | - | ||
174 | - conn.SetExtractionModeToSpecifiedRegions() | ||
175 | - conn.Update() | ||
176 | - | ||
177 | - polydata_collection = [] | ||
178 | - | ||
179 | - # Update progress value in GUI | ||
180 | - progress = nregions -1 | ||
181 | - if progress: | ||
182 | - UpdateProgress = vu.ShowProgress(progress) | ||
183 | - | ||
184 | - for region in xrange(nregions): | ||
185 | - conn.InitializeSpecifiedRegionList() | ||
186 | - conn.AddSpecifiedRegion(region) | ||
187 | - conn.Update() | ||
188 | - | ||
189 | - p = vtk.vtkPolyData() | ||
190 | - p.DeepCopy(conn.GetOutput()) | ||
191 | - p.Update() | ||
192 | - | ||
193 | - polydata_collection.append(p) | ||
194 | - if progress: | ||
195 | - UpdateProgress(region, _("Splitting disconnected regions...")) | ||
196 | - | ||
197 | - return polydata_collection | 1 | +#-------------------------------------------------------------------------- |
2 | +# Software: InVesalius - Software de Reconstrucao 3D de Imagens Medicas | ||
3 | +# Copyright: (C) 2001 Centro de Pesquisas Renato Archer | ||
4 | +# Homepage: http://www.softwarepublico.gov.br | ||
5 | +# Contact: invesalius@cti.gov.br | ||
6 | +# License: GNU - GPL 2 (LICENSE.txt/LICENCA.txt) | ||
7 | +#-------------------------------------------------------------------------- | ||
8 | +# Este programa e software livre; voce pode redistribui-lo e/ou | ||
9 | +# modifica-lo sob os termos da Licenca Publica Geral GNU, conforme | ||
10 | +# publicada pela Free Software Foundation; de acordo com a versao 2 | ||
11 | +# da Licenca. | ||
12 | +# | ||
13 | +# Este programa eh distribuido na expectativa de ser util, mas SEM | ||
14 | +# QUALQUER GARANTIA; sem mesmo a garantia implicita de | ||
15 | +# COMERCIALIZACAO ou de ADEQUACAO A QUALQUER PROPOSITO EM | ||
16 | +# PARTICULAR. Consulte a Licenca Publica Geral GNU para obter mais | ||
17 | +# detalhes. | ||
18 | +#-------------------------------------------------------------------------- | ||
19 | + | ||
20 | +import sys | ||
21 | + | ||
22 | +import vtk | ||
23 | +import wx | ||
24 | +from wx.lib.pubsub import pub as Publisher | ||
25 | + | ||
26 | +import vtk_utils as vu | ||
27 | + | ||
28 | +# Update progress value in GUI | ||
29 | +UpdateProgress = vu.ShowProgress() | ||
30 | + | ||
31 | +def ApplyDecimationFilter(polydata, reduction_factor): | ||
32 | + """ | ||
33 | + Reduce number of triangles of the given vtkPolyData, based on | ||
34 | + reduction_factor. | ||
35 | + """ | ||
36 | + # Important: vtkQuadricDecimation presented better results than | ||
37 | + # vtkDecimatePro | ||
38 | + decimation = vtk.vtkQuadricDecimation() | ||
39 | + decimation.SetInput(polydata) | ||
40 | + decimation.SetTargetReduction(reduction_factor) | ||
41 | + decimation.GetOutput().ReleaseDataFlagOn() | ||
42 | + decimation.AddObserver("ProgressEvent", lambda obj, evt: | ||
43 | + UpdateProgress(decimation, "Reducing number of triangles...")) | ||
44 | + return decimation.GetOutput() | ||
45 | + | ||
46 | +def ApplySmoothFilter(polydata, iterations, relaxation_factor): | ||
47 | + """ | ||
48 | + Smooth given vtkPolyData surface, based on iteration and relaxation_factor. | ||
49 | + """ | ||
50 | + smoother = vtk.vtkSmoothPolyDataFilter() | ||
51 | + smoother.SetInput(polydata) | ||
52 | + smoother.SetNumberOfIterations(iterations) | ||
53 | + smoother.SetFeatureAngle(80) | ||
54 | + smoother.SetRelaxationFactor(relaxation_factor) | ||
55 | + smoother.FeatureEdgeSmoothingOn() | ||
56 | + smoother.BoundarySmoothingOn() | ||
57 | + smoother.GetOutput().ReleaseDataFlagOn() | ||
58 | + smoother.AddObserver("ProgressEvent", lambda obj, evt: | ||
59 | + UpdateProgress(smoother, "Smoothing surface...")) | ||
60 | + | ||
61 | + return smoother.GetOutput() | ||
62 | + | ||
63 | + | ||
64 | + | ||
65 | +def FillSurfaceHole(polydata): | ||
66 | + """ | ||
67 | + Fill holes in the given polydata. | ||
68 | + """ | ||
69 | + # Filter used to detect and fill holes. Only fill | ||
70 | + print "Filling polydata" | ||
71 | + filled_polydata = vtk.vtkFillHolesFilter() | ||
72 | + filled_polydata.SetInput(polydata) | ||
73 | + filled_polydata.SetHoleSize(500) | ||
74 | + return filled_polydata.GetOutput() | ||
75 | + | ||
76 | +def CalculateSurfaceVolume(polydata): | ||
77 | + """ | ||
78 | + Calculate the volume from the given polydata | ||
79 | + """ | ||
80 | + # Filter used to calculate volume and area from a polydata | ||
81 | + measured_polydata = vtk.vtkMassProperties() | ||
82 | + measured_polydata.SetInput(polydata) | ||
83 | + return measured_polydata.GetVolume() | ||
84 | + | ||
85 | +def CalculateSurfaceArea(polydata): | ||
86 | + """ | ||
87 | + Calculate the volume from the given polydata | ||
88 | + """ | ||
89 | + # Filter used to calculate volume and area from a polydata | ||
90 | + measured_polydata = vtk.vtkMassProperties() | ||
91 | + measured_polydata.SetInput(polydata) | ||
92 | + return measured_polydata.GetSurfaceArea() | ||
93 | + | ||
94 | +def Merge(polydata_list): | ||
95 | + append = vtk.vtkAppendPolyData() | ||
96 | + | ||
97 | + for polydata in polydata_list: | ||
98 | + triangle = vtk.vtkTriangleFilter() | ||
99 | + triangle.SetInput(polydata) | ||
100 | + append.AddInput(triangle.GetOutput()) | ||
101 | + | ||
102 | + clean = vtk.vtkCleanPolyData() | ||
103 | + clean.SetInput(append.GetOutput()) | ||
104 | + | ||
105 | + return append.GetOutput() | ||
106 | + | ||
107 | +def Export(polydata, filename, bin=False): | ||
108 | + writer = vtk.vtkXMLPolyDataWriter() | ||
109 | + print filename, type(filename) | ||
110 | + writer.SetFileName(filename.encode('utf-8')) | ||
111 | + if bin: | ||
112 | + writer.SetDataModeToBinary() | ||
113 | + else: | ||
114 | + writer.SetDataModeToAscii() | ||
115 | + writer.SetInput(polydata) | ||
116 | + writer.Write() | ||
117 | + | ||
118 | +def Import(filename): | ||
119 | + reader = vtk.vtkXMLPolyDataReader() | ||
120 | + if isinstance(filename, unicode): | ||
121 | + reader.SetFileName(filename.encode(wx.GetDefaultPyEncoding())) | ||
122 | + else: | ||
123 | + reader.SetFileName(filename) | ||
124 | + reader.Update() | ||
125 | + return reader.GetOutput() | ||
126 | + | ||
127 | +def JoinSeedsParts(polydata, point_id_list): | ||
128 | + """ | ||
129 | + The function require vtkPolyData and point id | ||
130 | + from vtkPolyData. | ||
131 | + """ | ||
132 | + conn = vtk.vtkPolyDataConnectivityFilter() | ||
133 | + conn.SetInput(polydata) | ||
134 | + conn.SetExtractionModeToPointSeededRegions() | ||
135 | + UpdateProgress = vu.ShowProgress(1 + len(point_id_list)) | ||
136 | + pos = 1 | ||
137 | + for seed in point_id_list: | ||
138 | + conn.AddSeed(seed) | ||
139 | + UpdateProgress(pos, _("Analysing selected regions...")) | ||
140 | + pos += 1 | ||
141 | + | ||
142 | + conn.AddObserver("ProgressEvent", lambda obj, evt: | ||
143 | + UpdateProgress(conn, "Getting selected parts")) | ||
144 | + conn.Update() | ||
145 | + | ||
146 | + result = vtk.vtkPolyData() | ||
147 | + result.DeepCopy(conn.GetOutput()) | ||
148 | + result.Update() | ||
149 | + return result | ||
150 | + | ||
151 | +def SelectLargestPart(polydata): | ||
152 | + """ | ||
153 | + """ | ||
154 | + UpdateProgress = vu.ShowProgress(1) | ||
155 | + conn = vtk.vtkPolyDataConnectivityFilter() | ||
156 | + conn.SetInput(polydata) | ||
157 | + conn.SetExtractionModeToLargestRegion() | ||
158 | + conn.AddObserver("ProgressEvent", lambda obj, evt: | ||
159 | + UpdateProgress(conn, "Getting largest part...")) | ||
160 | + conn.Update() | ||
161 | + | ||
162 | + result = vtk.vtkPolyData() | ||
163 | + result.DeepCopy(conn.GetOutput()) | ||
164 | + result.Update() | ||
165 | + return result | ||
166 | + | ||
167 | +def SplitDisconectedParts(polydata): | ||
168 | + """ | ||
169 | + """ | ||
170 | + conn = vtk.vtkPolyDataConnectivityFilter() | ||
171 | + conn.SetInput(polydata) | ||
172 | + conn.SetExtractionModeToAllRegions() | ||
173 | + conn.Update() | ||
174 | + | ||
175 | + nregions = conn.GetNumberOfExtractedRegions() | ||
176 | + | ||
177 | + conn.SetExtractionModeToSpecifiedRegions() | ||
178 | + conn.Update() | ||
179 | + | ||
180 | + polydata_collection = [] | ||
181 | + | ||
182 | + # Update progress value in GUI | ||
183 | + progress = nregions -1 | ||
184 | + if progress: | ||
185 | + UpdateProgress = vu.ShowProgress(progress) | ||
186 | + | ||
187 | + for region in xrange(nregions): | ||
188 | + conn.InitializeSpecifiedRegionList() | ||
189 | + conn.AddSpecifiedRegion(region) | ||
190 | + conn.Update() | ||
191 | + | ||
192 | + p = vtk.vtkPolyData() | ||
193 | + p.DeepCopy(conn.GetOutput()) | ||
194 | + p.Update() | ||
195 | + | ||
196 | + polydata_collection.append(p) | ||
197 | + if progress: | ||
198 | + UpdateProgress(region, _("Splitting disconnected regions...")) | ||
199 | + | ||
200 | + return polydata_collection |
invesalius/data/surface.py
@@ -63,7 +63,7 @@ class Surface(): | @@ -63,7 +63,7 @@ class Surface(): | ||
63 | self.name = name | 63 | self.name = name |
64 | 64 | ||
65 | def SavePlist(self, dir_temp): | 65 | def SavePlist(self, dir_temp): |
66 | - filename = 'surface_%d_%s' % (self.index, self.name) | 66 | + filename = 'surface_%d' % self.index |
67 | vtp_filename = filename + '.vtp' | 67 | vtp_filename = filename + '.vtp' |
68 | vtp_filepath = os.path.join(dir_temp, vtp_filename) | 68 | vtp_filepath = os.path.join(dir_temp, vtp_filename) |
69 | pu.Export(self.polydata, vtp_filepath, bin=True) | 69 | pu.Export(self.polydata, vtp_filepath, bin=True) |
invesalius/project.py
@@ -274,7 +274,7 @@ class Project(object): | @@ -274,7 +274,7 @@ class Project(object): | ||
274 | ow.SetInstance(fow) | 274 | ow.SetInstance(fow) |
275 | 275 | ||
276 | filelist = Extract(filename, tempfile.mkdtemp()) | 276 | filelist = Extract(filename, tempfile.mkdtemp()) |
277 | - dirpath = os.path.abspath(os.path.split(filelist[0])[0]).decode(wx.GetDefaultPyEncoding()) | 277 | + dirpath = os.path.abspath(os.path.split(filelist[0])[0]) |
278 | 278 | ||
279 | # Opening the main file from invesalius 3 project | 279 | # Opening the main file from invesalius 3 project |
280 | main_plist = os.path.join(dirpath ,'main.plist') | 280 | main_plist = os.path.join(dirpath ,'main.plist') |
@@ -335,9 +335,32 @@ def Compress(folder, filename): | @@ -335,9 +335,32 @@ def Compress(folder, filename): | ||
335 | tar.close() | 335 | tar.close() |
336 | shutil.move(tmpdir_+ ".inv3", filename) | 336 | shutil.move(tmpdir_+ ".inv3", filename) |
337 | os.chdir(current_dir) | 337 | os.chdir(current_dir) |
338 | - | 338 | + |
339 | def Extract(filename, folder): | 339 | def Extract(filename, folder): |
340 | tar = tarfile.open(filename, "r:gz") | 340 | tar = tarfile.open(filename, "r:gz") |
341 | + idir = os.path.split(tar.getnames()[0])[0] | ||
342 | + os.mkdir(os.path.join(folder, idir.decode('utf8'))) | ||
343 | + filelist = [] | ||
344 | + for t in tar.getmembers(): | ||
345 | + fsrc = tar.extractfile(t) | ||
346 | + | ||
347 | + fname = os.path.join(folder, t.name.decode('utf-8')) | ||
348 | + fdst = file(fname, 'wb') | ||
349 | + | ||
350 | + shutil.copyfileobj(fsrc, fdst) | ||
351 | + | ||
352 | + filelist.append(fname) | ||
353 | + fsrc.close() | ||
354 | + fdst.close() | ||
355 | + del fsrc | ||
356 | + del fdst | ||
357 | + tar.close() | ||
358 | + print filelist | ||
359 | + return filelist | ||
360 | + | ||
361 | + | ||
362 | +def Extract_(filename, folder): | ||
363 | + tar = tarfile.open(filename, "r:gz") | ||
341 | #tar.list(verbose=True) | 364 | #tar.list(verbose=True) |
342 | tar.extractall(folder) | 365 | tar.extractall(folder) |
343 | filelist = [os.path.join(folder, i) for i in tar.getnames()] | 366 | filelist = [os.path.join(folder, i) for i in tar.getnames()] |