1 | #!/usr/bin/python |
---|
2 | # -*- coding: utf-8 -*- |
---|
3 | |
---|
4 | import os, popen2, fcntl, select, sys, os, pysvn, time |
---|
5 | # Prerequisitos: cliente do subversion instalado, e pysvn . |
---|
6 | from dialog import * |
---|
7 | |
---|
8 | # We should handle the new DIALOG_HELP and DIALOG_EXTRA return codes here. |
---|
9 | def handle_exit_code(d, code): |
---|
10 | # d is supposed to be a Dialog instance |
---|
11 | if code in (d.DIALOG_CANCEL, d.DIALOG_ESC): |
---|
12 | if code == d.DIALOG_CANCEL: |
---|
13 | msg = "Voce escolheu Cancelar. Voce quer encerrar " \ |
---|
14 | "este programa?" |
---|
15 | else: |
---|
16 | msg = "Voce pressionou ESC. Voce quer encerrar " \ |
---|
17 | "este programa?" |
---|
18 | # "No" or "ESC" will bring the user back to the demo. |
---|
19 | # DIALOG_ERROR is propagated as an exception and caught in main(). |
---|
20 | # So we only need to handle OK here. |
---|
21 | if d.yesno(msg) == d.DIALOG_OK: |
---|
22 | sys.exit(0) |
---|
23 | return 0 |
---|
24 | else: |
---|
25 | return 1 # code is d.DIALOG_OK |
---|
26 | |
---|
27 | # Funcao para exibir uma lista para selecionar so um item... |
---|
28 | def msg_box_radiolist(d,tit,msg): |
---|
29 | while 1: |
---|
30 | (code, tag) = d.radiolist(tit, width=65, choices=msg) |
---|
31 | |
---|
32 | if handle_exit_code(d, code): |
---|
33 | if not tag: |
---|
34 | continue |
---|
35 | break |
---|
36 | return tag |
---|
37 | |
---|
38 | def msg_box_inputbox(d,tit): |
---|
39 | while 1: |
---|
40 | (code, answer) = d.inputbox(tit, init="",width=76,height=20) |
---|
41 | if handle_exit_code(d, code): |
---|
42 | if not answer: |
---|
43 | continue |
---|
44 | break |
---|
45 | return answer |
---|
46 | |
---|
47 | #Função para solicitar ao usuario o tipo de distribuicao |
---|
48 | def mostra(d,escolhas): |
---|
49 | return d.menu("Selecione o tipo de distrbuicao desejada:",height=0,choices=escolhas) |
---|
50 | |
---|
51 | def msg_box_info(d,msg): |
---|
52 | d.infobox(msg,height=19,width=60) |
---|
53 | time.sleep(2) |
---|
54 | return |
---|
55 | |
---|
56 | def msg_box_sim_nao(d,msg): |
---|
57 | return d.yesno(msg,height=18,width=76) |
---|
58 | |
---|
59 | #As duas funcoes, a seguir, executam comandos e retornam resultado. |
---|
60 | def makeNonBlocking(fd): |
---|
61 | fl = fcntl.fcntl(fd, fcntl.F_GETFL) |
---|
62 | try: |
---|
63 | fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NDELAY) |
---|
64 | except AttributeError: |
---|
65 | fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.FNDELAY) |
---|
66 | |
---|
67 | def getCommandOutput(command): |
---|
68 | f=sys.stdout |
---|
69 | child = popen2.Popen3(command, 1) # Captura stdout e stderr do comando |
---|
70 | child.tochild.close( ) # nao necessitamos escrever para a stdin do processo iniciado pelo comando |
---|
71 | outfile = child.fromchild |
---|
72 | outfd = outfile.fileno( ) |
---|
73 | errfile = child.childerr |
---|
74 | errfd = errfile.fileno( ) |
---|
75 | makeNonBlocking(outfd) # Evitamos deadlocks tornando fd's nonblock. |
---|
76 | makeNonBlocking(errfd) |
---|
77 | outdata, errdata = [ ], [ ] |
---|
78 | outeof = erreof = False |
---|
79 | while True: |
---|
80 | f.write('.') |
---|
81 | f.flush() |
---|
82 | to_check = [outfd]*(not outeof) + [errfd]*(not erreof) |
---|
83 | ready = select.select(to_check, [ ], [ ]) # Espera por dados... |
---|
84 | if outfd in ready[0]: |
---|
85 | outchunk = outfile.read( ) |
---|
86 | if outchunk == '': |
---|
87 | outeof = True |
---|
88 | else: |
---|
89 | outdata.append(outchunk) |
---|
90 | if errfd in ready[0]: |
---|
91 | errchunk = errfile.read( ) |
---|
92 | if errchunk == '': |
---|
93 | erreof = True |
---|
94 | else: |
---|
95 | errdata.append(errchunk) |
---|
96 | if outeof and erreof: |
---|
97 | break |
---|
98 | select.select([ ],[ ],[ ],.1) # Seta um intervalo de tempo bem curto para os buffers serem preenchidos. |
---|
99 | err = child.wait( ) |
---|
100 | if err != 0: |
---|
101 | raise RuntimeError, '%r falhou com codigo %d\n%s' % ( |
---|
102 | command, err, ''.join(errdata)) |
---|
103 | return ''.join(outdata) |
---|
104 | |
---|
105 | |
---|
106 | #Callback para login no svn |
---|
107 | def Login_no_svn( realm, username, may_save ): |
---|
108 | from getpass import getpass |
---|
109 | global flag |
---|
110 | print 'Por favor, identifique-se' |
---|
111 | usuario = raw_input('Usuario:').strip() |
---|
112 | senha = getpass('Senha:').strip() |
---|
113 | if not flag: |
---|
114 | flag = True |
---|
115 | else: |
---|
116 | flag = False |
---|
117 | print 'Falhou acesso ao Subversion...\n' |
---|
118 | sys.exit(92) |
---|
119 | return True, usuario, senha, True |
---|
120 | |
---|
121 | def notify_svn( event_dict ): |
---|
122 | global chk_rev |
---|
123 | chk_rev = 0 |
---|
124 | if event_dict['action'] == pysvn.wc_notify_action.update_completed: |
---|
125 | chk_rev = event_dict['revision'].number |
---|
126 | return |
---|
127 | |
---|
128 | def get_log_message_svn(): |
---|
129 | global log_msg |
---|
130 | return True, log_msg |
---|
131 | |
---|
132 | #Rotina para recuperar dados do svn (log) e gerar arquivo html |
---|
133 | def r_svn_to_html(caminho,branch_origem,revisao_branch_origem,comentario_vrs,trac): |
---|
134 | arq_sai = caminho + os.sep + 'infodist' + os.sep + 'revisoes-svn.php' |
---|
135 | arq_sai_ultima = caminho + os.sep + 'infodist' + os.sep + 'ultima-revisao-svn.php' |
---|
136 | saida='' |
---|
137 | cor ='' |
---|
138 | linha = 0 |
---|
139 | |
---|
140 | try: |
---|
141 | cliente = pysvn.Client() |
---|
142 | #cliente.callback_get_login = Login_no_svn |
---|
143 | logs = cliente.log( branch_origem, revision_start=pysvn.Revision( pysvn.opt_revision_kind.number,revisao_branch_origem), |
---|
144 | revision_end=pysvn.Revision( pysvn.opt_revision_kind.number, 0 ), |
---|
145 | discover_changed_paths=True,strict_node_history=True,limit=0 ) |
---|
146 | except: |
---|
147 | print 'Erro Obtendo dados do svn para gerar revisoes-svn.php' |
---|
148 | sys.exit(93) |
---|
149 | |
---|
150 | fd = open(arq_sai, 'w') |
---|
151 | saida += '<?php ?>\n' |
---|
152 | saida += '<div align=CENTER>\n' |
---|
153 | saida += '<h3 align="center" style="color: #0000FF;margin-bottom: 0 ">Expresso Livre - Subversion </h3>\n' |
---|
154 | saida += '<table border="1" witdh="100%">\n' |
---|
155 | saida += '<tr bgcolor="#D3DCE3">\n' |
---|
156 | saida += '<td>Revisão</td><td><font color="#000066">Data</font></td><td><font color="#000066">Implementação - ' + comentario_vrs + '</font></td></tr>\n' |
---|
157 | for revisao in logs: |
---|
158 | linha += 1 |
---|
159 | if linha%2: |
---|
160 | cor = '#DDDDDD' |
---|
161 | else: |
---|
162 | cor = '#EEEEEE' |
---|
163 | saida += '<tr bgcolor="'+cor+'">\n' |
---|
164 | saida += '<td valign="top">'+str(revisao['revision'].number)+'</td>\n' |
---|
165 | saida += '<td valign="top">'+time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(revisao['date']))+'</td>\n' |
---|
166 | try: |
---|
167 | aux = revisao['message'] |
---|
168 | try: |
---|
169 | v = '#' + aux.split('#')[1].split(' ')[0] |
---|
170 | p = aux.find(v) |
---|
171 | if p > -1: |
---|
172 | aux1 = aux[:p] |
---|
173 | aux2 = aux[p+len(v):] |
---|
174 | saida += '<td>' + aux1 + '<a href="' + trac + aux.split('#')[1].split(' ')[0] + '" TARGET="_blank" >' + v + '</a>' + aux2 + '</td>' |
---|
175 | else: |
---|
176 | saida += '<td valign="top"><pre>'+aux+'</pre></td>\n' |
---|
177 | except: |
---|
178 | saida += '<td valign="top"><pre>'+aux+'</pre></td>\n' |
---|
179 | except: |
---|
180 | saida += '<td valign="top">Nao foi possivel obter a msg no subversion. Falha no encode...</td>\n' |
---|
181 | saida += '</tr>\n' |
---|
182 | saida += '</table>\n' |
---|
183 | saida += '</div>\n' |
---|
184 | fd.write(saida.encode('iso8859','replace')) |
---|
185 | fd.close() |
---|
186 | |
---|
187 | fd = open(arq_sai_ultima,'w') |
---|
188 | saida = '' |
---|
189 | saida += '<?php $ultima_revisao ="' + comentario_vrs + '" ?>\n' |
---|
190 | fd.write(saida.encode('iso8859','replace')) |
---|
191 | fd.close() |
---|
192 | |
---|
193 | # ########################################################################################## |
---|
194 | # INICIO |
---|
195 | # ########################################################################################## |
---|
196 | |
---|
197 | #Carrega arquivo com dados que configuram as distribuiçoes possÃveis... |
---|
198 | from ger2_conf import * |
---|
199 | |
---|
200 | # Pega identificador de cada distribuicao configurada... |
---|
201 | aux_tipo_distribuicao = parametros.keys() |
---|
202 | |
---|
203 | # Ordena |
---|
204 | aux_tipo_distribuicao.sort() |
---|
205 | |
---|
206 | tipo_distribuicao = {} |
---|
207 | |
---|
208 | |
---|
209 | # Tipo de distribuicao: uma entrada para cada distribuicao configurada... |
---|
210 | for i in range(0,len(aux_tipo_distribuicao)): |
---|
211 | tipo_distribuicao[str(i+1)] = aux_tipo_distribuicao[i] |
---|
212 | |
---|
213 | # ordena pelo enumerador..... |
---|
214 | Ks = tipo_distribuicao.keys() |
---|
215 | Ks.sort() |
---|
216 | escolhas = [] |
---|
217 | |
---|
218 | # Construindo itens do menu, uma entrada para cada distribuicao configurada... |
---|
219 | for t in Ks: |
---|
220 | escolhas.append([t,tipo_distribuicao[t],0]) |
---|
221 | |
---|
222 | flag = False |
---|
223 | rev='' |
---|
224 | params={} |
---|
225 | msg = '' |
---|
226 | |
---|
227 | |
---|
228 | # Construindo objeto para o dialog... |
---|
229 | d=Dialog() |
---|
230 | # Seta titulo geral.... |
---|
231 | d.add_persistent_args(["--backtitle", "Gera Distribuição"]) |
---|
232 | |
---|
233 | tit = 'Selecione uma das distribuiçoes configuradas:' |
---|
234 | opc = msg_box_radiolist(d,tit,escolhas) |
---|
235 | |
---|
236 | #opc = '1' # soh tem um item de parametro .... |
---|
237 | |
---|
238 | # Com base na selecao do usuario, carrega variaveis com valÃŽres configurados.... |
---|
239 | projeto = parametros[tipo_distribuicao[opc]]['projeto'] |
---|
240 | caminho = parametros[tipo_distribuicao[opc]]['caminho'] |
---|
241 | caminho1 = trabalho + os.sep + caminho |
---|
242 | trac= parametros[tipo_distribuicao[opc]]['trac'] |
---|
243 | s_ftp = parametros[tipo_distribuicao[opc]]['s_ftp'] |
---|
244 | s_path = parametros[tipo_distribuicao[opc]]['s_path'] |
---|
245 | prefixo = parametros[tipo_distribuicao[opc]]['prefixo'] |
---|
246 | script = parametros[tipo_distribuicao[opc]]['script'] |
---|
247 | aponta_tags = parametros[tipo_distribuicao[opc]]['tags'] |
---|
248 | |
---|
249 | # Seta titulo da distribuicao que sera efetuada... |
---|
250 | d.add_persistent_args(["--title", 'Distribuição ExpressoLivre' ]) |
---|
251 | |
---|
252 | # 1 - Prepara para buscar os branchs existentes.... |
---|
253 | msg = "\n\n\nBuscando os branchs em: \n\n" + projeto + "\n\n\nAguarde." |
---|
254 | msg_box_info(d,msg) |
---|
255 | |
---|
256 | try: |
---|
257 | cliente = pysvn.Client() |
---|
258 | #cliente.callback_get_login = Login_no_svn |
---|
259 | except: |
---|
260 | msg_box_info(d,'\nFalhou preparando acesso ao Subversion.') |
---|
261 | sys.exit(97) |
---|
262 | |
---|
263 | try: |
---|
264 | # Busca branchs no diretorio apontado por projeto. |
---|
265 | branchs = cliente.ls(projeto) |
---|
266 | msg = [] |
---|
267 | tab_branchs = {} |
---|
268 | # Cria lista para exibir ao usuario .... |
---|
269 | for branch in branchs: |
---|
270 | msg.append((os.path.split(branch['name'])[-1],'R' + str(branch['created_rev'].number),0)) |
---|
271 | tab_branchs[os.path.split(branch['name'])[-1]] = str(branch['created_rev'].number) |
---|
272 | except: |
---|
273 | msg_box_info(d,'\nErro buscando branchs.') |
---|
274 | sys.exit(95) |
---|
275 | |
---|
276 | tit = "Branchs obtidos em " + projeto |
---|
277 | |
---|
278 | # 2 - Mostra branchs para o usuario selecionar um ... |
---|
279 | n_branch_origem = msg_box_radiolist(d,tit,msg) |
---|
280 | |
---|
281 | revisao_branch_origem = tab_branchs[n_branch_origem] |
---|
282 | |
---|
283 | tb_br = n_branch_origem.split('.') |
---|
284 | |
---|
285 | if len(tb_br) < 3: |
---|
286 | tb_br.append('0000000') |
---|
287 | try: |
---|
288 | prefixo_br = '0000000'[0:7 - len(tb_br[0])] + tb_br[0] + '0000000'[0:7 - len(tb_br[1])] + tb_br[1] + '0000000'[0:7 - len(tb_br[2])] + tb_br[2] |
---|
289 | except: |
---|
290 | msg_box_info(d,'\nErro: Nome do branch fora do padrao.') |
---|
291 | sys.exit(96) |
---|
292 | |
---|
293 | |
---|
294 | branch_origem = projeto + '/' + n_branch_origem |
---|
295 | |
---|
296 | # 3 - Mostra tags do branch para o usuario selecionar uma .... |
---|
297 | # Busca tags no diretorio apontado por aponta_tags |
---|
298 | tags_localizados = cliente.ls(aponta_tags) |
---|
299 | msg = [] |
---|
300 | tab_aux = {} |
---|
301 | for tag in tags_localizados: |
---|
302 | tt = os.path.split(tag['name'])[-1] .split('.') |
---|
303 | nome_a = '' |
---|
304 | for i in tt: |
---|
305 | nome_a = nome_a +'0000000'[0:7 - len(i)] + i |
---|
306 | |
---|
307 | if prefixo_br <> nome_a[0:21]: |
---|
308 | continue |
---|
309 | |
---|
310 | tab_aux[nome_a] = [os.path.split(tag['name'])[-1] ,str(tag['created_rev'].number)] |
---|
311 | |
---|
312 | tab_aux_keys = tab_aux.keys() |
---|
313 | tab_aux_keys.sort() |
---|
314 | tab_aux_keys.reverse() |
---|
315 | |
---|
316 | tit = '\nTags existentes para o branch:' |
---|
317 | # Cria lista para exibir ao usuario ( maximo de 10).... |
---|
318 | i = len(tab_aux_keys) |
---|
319 | if i > 10: |
---|
320 | z=i # forca mostrar todos os tags. |
---|
321 | else: |
---|
322 | z = i |
---|
323 | msg = [] |
---|
324 | for x in range(0,z): |
---|
325 | msg.append((tab_aux[tab_aux_keys[x]][0], 'R' + tab_aux[tab_aux_keys[x]][1],0)) |
---|
326 | |
---|
327 | tit = 'Selecione um tag para gerar distribuicao do branch\n' + branch_origem + ' :' + '\n' |
---|
328 | |
---|
329 | if msg: |
---|
330 | nome_tag = msg_box_radiolist(d,tit,msg) |
---|
331 | rev_tag_escolhida = '' |
---|
332 | for item in msg: |
---|
333 | if item[0] == nome_tag: |
---|
334 | revisao_desejada = item[1][1:] |
---|
335 | break |
---|
336 | if revisao_desejada == '': |
---|
337 | print 'Erro....' |
---|
338 | sys.exit() |
---|
339 | tag_selecionada = aponta_tags + '/' + nome_tag |
---|
340 | item = 'Tag' |
---|
341 | else: |
---|
342 | nome_tag = n_branch_origem |
---|
343 | revisao_desejada = revisao_branch_origem |
---|
344 | tag_selecionada = projeto + '/' + n_branch_origem |
---|
345 | item = 'Brc' |
---|
346 | |
---|
347 | if item == 'Tag': |
---|
348 | msg = '\n\nA seguir, sera gerado arquivo de distribuicao:\nOrigem: Tag ' + nome_tag + '\n do branch ' + branch_origem + ',\n revisao ' + revisao_desejada + '\n\nContinuar?' |
---|
349 | else: |
---|
350 | msg = '\n\nA seguir, sera gerado arquivo de distribuicao:\nOrigem: Branch ' + branch_origem + ',\n revisao ' + revisao_desejada + '\n\nContinuar?' |
---|
351 | if msg_box_sim_nao(d,msg) != d.DIALOG_OK: |
---|
352 | sys.exit(98) |
---|
353 | |
---|
354 | #comentario_tag = item + ' ' + nome_tag + ' R' + revisao_desejada |
---|
355 | comentario_tag = nome_tag + ' R' + revisao_desejada |
---|
356 | comentario_tagx = nome_tag + '-R' + revisao_desejada |
---|
357 | |
---|
358 | msg_box_info(d,'\n\n\nProcessando a geracao da distribuição como solicitado.\n\n\nAguarde.') |
---|
359 | |
---|
360 | |
---|
361 | # Dados para executar o export: |
---|
362 | # |
---|
363 | revisao_branch_origem = revisao_desejada |
---|
364 | |
---|
365 | # Verifica a existencia de uma pasta de trabalho. |
---|
366 | # Nesta pasta serao gerados subdiretorios que vao conter as distribuiçoes. |
---|
367 | if not os.path.isdir(trabalho): |
---|
368 | os.makedirs(trabalho) |
---|
369 | |
---|
370 | if os.path.isdir(caminho1): |
---|
371 | retorno = getCommandOutput('rm -fR ' + caminho1) |
---|
372 | |
---|
373 | |
---|
374 | revisao = cliente.export(branch_origem, |
---|
375 | caminho1, |
---|
376 | force=False, |
---|
377 | revision=pysvn.Revision(pysvn.opt_revision_kind.number,revisao_branch_origem), |
---|
378 | native_eol=None, |
---|
379 | ignore_externals=False, |
---|
380 | recurse=True, |
---|
381 | peg_revision=pysvn.Revision(pysvn.opt_revision_kind.number, revisao_branch_origem)) |
---|
382 | |
---|
383 | if not os.path.exists(caminho1 + os.sep + 'infodist'): |
---|
384 | retorno = getCommandOutput('mkdir ' + caminho1 + os.sep + 'infodist') |
---|
385 | |
---|
386 | # 6 - Gera arquivo com informacoes do Subversion e dados de identificação da distribuição... |
---|
387 | r_svn_to_html(caminho1,branch_origem,revisao_branch_origem,comentario_tag,trac) |
---|
388 | |
---|
389 | # -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
---|
390 | |
---|
391 | # Se existir um nome de script no arquivo de configuração, vai tentar executar... |
---|
392 | if script != '': |
---|
393 | if os.path.isfile(script): |
---|
394 | msg = "\nExecutando o script " + script + " \n" |
---|
395 | msg_box_info(d,msg) |
---|
396 | retorno = getCommandOutput(script) |
---|
397 | msg_box_info(d,retorno) |
---|
398 | else: |
---|
399 | msg = "\nScript " + script + " nao foi localizado.\n" |
---|
400 | msg_box_info(d,msg) |
---|
401 | msg = '' |
---|
402 | #Solicita execucao do comando de compactaçao |
---|
403 | path_corrente = os.getcwd() |
---|
404 | os.chdir(trabalho) |
---|
405 | retorno = getCommandOutput("tar -zcf " + prefixo + comentario_tagx + ".tgz ./expresso") |
---|
406 | os.chdir(path_corrente) |
---|
407 | |
---|
408 | msg = msg + "\nFoi gerado o arquivo " + prefixo + comentario_tagx + ".tgz \n" |
---|
409 | msg_box_info(d,msg) |
---|
410 | |
---|
411 | if s_ftp != '': |
---|
412 | from ftplib import FTP |
---|
413 | servidor_ftp = s_ftp |
---|
414 | #Faz ftp para a maquina de distribuicao... |
---|
415 | msg = msg + 'Iniciando copia do arquivo gerado para ambiente de distribuicao(FTP)\n' |
---|
416 | msg_box_info(d,msg) |
---|
417 | try: |
---|
418 | ftp = FTP(servidor_ftp,'anonymous','') |
---|
419 | resp = ftp.cwd(s_path) |
---|
420 | msg = msg + resp + '\n' |
---|
421 | msg_box_info(d,msg) |
---|
422 | lista = ftp.nlst() |
---|
423 | if 'R'+str(revisao_branch_origem) in lista: |
---|
424 | ftp.cwd('R'+str(revisao_branch_origem)) |
---|
425 | # pode existir a pasta mas nao o arquivo.... |
---|
426 | try: |
---|
427 | resp = ftp.delete(prefixo+str(revisao_branch_origem)+'.tgz') |
---|
428 | except: |
---|
429 | pass |
---|
430 | msg = msg + resp + '\n' |
---|
431 | msg_box_info(d,msg) |
---|
432 | resp = ftp.cwd('../') |
---|
433 | msg = msg + resp + '\n' |
---|
434 | msg_box_info(d,msg) |
---|
435 | else: |
---|
436 | resp = ftp.mkd('R'+str(revisao_branch_origem)) |
---|
437 | msg = msg + resp + '\n' |
---|
438 | msg_box_info(d,msg) |
---|
439 | resp = ftp.cwd('R'+str(revisao_branch_origem)) |
---|
440 | msg = msg + resp + '\n' |
---|
441 | msg_box_info(d,msg) |
---|
442 | f = open(trabalho + os.sep + prefixo + comentario_tagx + '.tgz','rb') |
---|
443 | resp = ftp.storbinary('STOR ' + prefixo + comentario_tagx + '.tgz',f) |
---|
444 | msg = msg + resp + '\n' |
---|
445 | msg_box_info(d,msg) |
---|
446 | msg = msg + 'Verifique os dados abaixo:\n' |
---|
447 | msg_box_info(d,msg) |
---|
448 | resp = ftp.pwd() |
---|
449 | msg = msg + 'Diretorio de distribuicao R'+str(revisao_branch_origem)+' gerado em '+servidor_ftp+' : '+resp |
---|
450 | msg_box_info(d,msg) |
---|
451 | resp = ftp.retrlines('LIST') |
---|
452 | msg = msg + '\nConteudo gerado no diretorio acima : \n'+resp+'\n' |
---|
453 | msg_box_info(d,msg) |
---|
454 | ftp.close() |
---|
455 | |
---|
456 | except: |
---|
457 | msg = msg + '\nErro ao conectar no servidor FTP.\n\n\n' |
---|
458 | |
---|
459 | msg = msg + '\nProcessamento concluido.\n' |
---|
460 | msg_box_info(d,msg) |
---|
461 | # -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
---|