Package Gnumed :: Package pycommon :: Module gmNetworkTools
[frames] | no frames]

Source Code for Module Gnumed.pycommon.gmNetworkTools

  1  # -*- coding: utf8 -*- 
  2  __doc__ = """GNUmed internetworking tools.""" 
  3   
  4  #=========================================================================== 
  5  __version__ = "$Revision: 1.98 $" 
  6  __author__ = "K. Hilbert <Karsten.Hilbert@gmx.net>" 
  7  __license__ = "GPL v2 or later (details at http://www.gnu.org)" 
  8   
  9  # std libs 
 10  import sys 
 11  import os.path 
 12  import logging 
 13  import urllib2 as wget 
 14  import urllib 
 15  import MimeWriter 
 16  import mimetypes 
 17  import mimetools 
 18  import StringIO 
 19  import zipfile 
 20   
 21   
 22  # GNUmed libs 
 23  if __name__ == '__main__': 
 24          sys.path.insert(0, '../../') 
 25  from Gnumed.pycommon import gmLog2 
 26  from Gnumed.pycommon import gmTools 
 27  from Gnumed.pycommon import gmShellAPI 
 28  from Gnumed.pycommon import gmCfg2 
 29   
 30   
 31  _log = logging.getLogger('gm.net') 
 32  #=========================================================================== 
33 -def download_file(url, filename=None, suffix=None):
34 35 if filename is None: 36 filename = gmTools.get_unique_filename(prefix = 'gm-dl-', suffix = suffix) 37 _log.debug('downloading [%s] into [%s]', url, filename) 38 39 try: 40 dl_name, headers = urllib.urlretrieve(url, filename) 41 except (ValueError, OSError, IOError): 42 _log.exception('cannot download from [%s]', url) 43 gmLog2.log_stack_trace() 44 return None 45 46 _log.debug(u'%s' % headers) 47 return dl_name
48 #===========================================================================
49 -def download_data_packs_list(url, filename=None):
50 return download_file(url, filename = filename, suffix = 'conf')
51 #---------------------------------------------------------------------------
52 -def download_data_pack(pack_url, filename=None, md5_url=None):
53 54 _log.debug('downloading data pack from: %s', pack_url) 55 dp_fname = download_file(pack_url, filename = filename, suffix = 'zip') 56 _log.debug('downloading MD5 from: %s', md5_url) 57 md5_fname = download_file(md5_url, filename = dp_fname + u'.md5') 58 59 md5_file = open(md5_fname, 'rU') 60 md5_expected = md5_file.readline().strip('\n') 61 md5_file.close() 62 _log.debug('expected MD5: %s', md5_expected) 63 md5_calculated = gmTools.file2md5(dp_fname, return_hex = True) 64 _log.debug('calculated MD5: %s', md5_calculated) 65 66 if md5_calculated != md5_expected: 67 _log.error('mismatch of expected vs calculated MD5: [%s] vs [%s]', md5_expected, md5_calculated) 68 return (False, (md5_expected, md5_calculated)) 69 70 return True, dp_fname
71 #---------------------------------------------------------------------------
72 -def unzip_data_pack(filename=None):
73 74 unzip_dir = os.path.splitext(filename)[0] 75 _log.debug('unzipping data pack into [%s]', unzip_dir) 76 gmTools.mkdir(unzip_dir) 77 try: 78 data_pack = zipfile.ZipFile(filename, 'r') 79 except (zipfile.BadZipfile): 80 _log.exception('cannot unzip data pack [%s]', filename) 81 gmLog2.log_stack_trace() 82 return None 83 84 data_pack.extractall(unzip_dir) 85 86 return unzip_dir
87 #---------------------------------------------------------------------------
88 -def install_data_pack(data_pack=None, conn=None):
89 from Gnumed.pycommon import gmPsql 90 psql = gmPsql.Psql(conn) 91 sql_script = os.path.join(data_pack['unzip_dir'], 'install-data-pack.sql') 92 return (psql.run(sql_script) == 0)
93 #===========================================================================
94 -def download_data_pack_old(url, target_dir=None):
95 96 if target_dir is None: 97 target_dir = gmTools.get_unique_filename(prefix = 'gm-dl-') 98 99 _log.debug('downloading [%s]', url) 100 _log.debug('unpacking into [%s]', target_dir) 101 102 gmTools.mkdir(directory = target_dir) 103 104 # FIXME: rewrite to use urllib.urlretrieve() and 105 106 paths = gmTools.gmPaths() 107 local_script = os.path.join(paths.local_base_dir, '..', 'external-tools', 'gm-download_data') 108 109 candidates = [u'gm-download_data', u'gm-download_data.bat', local_script, u'gm-download_data.bat'] 110 args = u' %s %s' % (url, target_dir) 111 112 success = gmShellAPI.run_first_available_in_shell ( 113 binaries = candidates, 114 args = args, 115 blocking = True, 116 run_last_one_anyway = True 117 ) 118 119 if success: 120 return True, target_dir 121 122 _log.error('download failed') 123 return False, None
124 #===========================================================================
125 -def check_for_update(url=None, current_branch=None, current_version=None, consider_latest_branch=False):
126 """Check for new releases at <url>. 127 128 Returns (bool, text). 129 True: new release available 130 False: up to date 131 None: don't know 132 """ 133 try: 134 remote_file = wget.urlopen(url) 135 except (wget.URLError, ValueError, OSError): 136 _log.exception("cannot retrieve version file from [%s]", url) 137 return (None, _('Cannot retrieve version information from:\n\n%s') % url) 138 139 _log.debug('retrieving version information from [%s]', url) 140 141 cfg = gmCfg2.gmCfgData() 142 try: 143 cfg.add_stream_source(source = 'gm-versions', stream = remote_file) 144 except (UnicodeDecodeError): 145 remote_file.close() 146 _log.exception("cannot read version file from [%s]", url) 147 return (None, _('Cannot read version information from:\n\n%s') % url) 148 149 remote_file.close() 150 151 latest_branch = cfg.get('latest branch', 'branch', source_order = [('gm-versions', 'return')]) 152 latest_release_on_latest_branch = cfg.get('branch %s' % latest_branch, 'latest release', source_order = [('gm-versions', 'return')]) 153 latest_release_on_current_branch = cfg.get('branch %s' % current_branch, 'latest release', source_order = [('gm-versions', 'return')]) 154 155 cfg.remove_source('gm-versions') 156 157 _log.info('current release: %s', current_version) 158 _log.info('current branch: %s', current_branch) 159 _log.info('latest release on current branch: %s', latest_release_on_current_branch) 160 _log.info('latest branch: %s', latest_branch) 161 _log.info('latest release on latest branch: %s', latest_release_on_latest_branch) 162 163 # anything known ? 164 no_release_information_available = ( 165 ( 166 (latest_release_on_current_branch is None) and 167 (latest_release_on_latest_branch is None) 168 ) or ( 169 not consider_latest_branch and 170 (latest_release_on_current_branch is None) 171 ) 172 ) 173 if no_release_information_available: 174 _log.warning('no release information available') 175 msg = _('There is no version information available from:\n\n%s') % url 176 return (None, msg) 177 178 # up to date ? 179 if consider_latest_branch: 180 _log.debug('latest branch taken into account') 181 if current_version >= latest_release_on_latest_branch: 182 _log.debug('up to date: current version >= latest version on latest branch') 183 return (False, None) 184 if latest_release_on_latest_branch is None: 185 if current_version >= latest_release_on_current_branch: 186 _log.debug('up to date: current version >= latest version on current branch and no latest branch available') 187 return (False, None) 188 else: 189 _log.debug('latest branch not taken into account') 190 if current_version >= latest_release_on_current_branch: 191 _log.debug('up to date: current version >= latest version on current branch') 192 return (False, None) 193 194 new_release_on_current_branch_available = ( 195 (latest_release_on_current_branch is not None) and 196 (latest_release_on_current_branch > current_version) 197 ) 198 _log.info('%snew release on current branch available', gmTools.bool2str(new_release_on_current_branch_available, '', 'no ')) 199 200 new_release_on_latest_branch_available = ( 201 (latest_branch is not None) 202 and 203 ( 204 (latest_branch > current_branch) or ( 205 (latest_branch == current_branch) and 206 (latest_release_on_latest_branch > current_version) 207 ) 208 ) 209 ) 210 _log.info('%snew release on latest branch available', gmTools.bool2str(new_release_on_latest_branch_available, '', 'no ')) 211 212 if not (new_release_on_current_branch_available or new_release_on_latest_branch_available): 213 _log.debug('up to date: no new releases available') 214 return (False, None) 215 216 # not up to date 217 msg = _('A new version of GNUmed is available.\n\n') 218 msg += _(' Your current version: "%s"\n') % current_version 219 if consider_latest_branch: 220 if new_release_on_current_branch_available: 221 msg += u'\n' 222 msg += _(' New version: "%s"') % latest_release_on_current_branch 223 msg += u'\n' 224 msg += _(' - bug fixes only\n') 225 msg += _(' - database fixups may be needed\n') 226 if new_release_on_latest_branch_available: 227 if current_branch != latest_branch: 228 msg += u'\n' 229 msg += _(' New version: "%s"') % latest_release_on_latest_branch 230 msg += u'\n' 231 msg += _(' - bug fixes and new features\n') 232 msg += _(' - database upgrade required\n') 233 else: 234 msg += u'\n' 235 msg += _(' New version: "%s"') % latest_release_on_current_branch 236 msg += u'\n' 237 msg += _(' - bug fixes only\n') 238 msg += _(' - database fixups may be needed\n') 239 240 msg += u'\n\n' 241 msg += _( 242 'Note, however, that this version may not yet\n' 243 'be available *pre-packaged* for your system.' 244 ) 245 246 msg += u'\n\n' 247 msg += _('Details are found on <http://wiki.gnumed.de>.\n') 248 msg += u'\n' 249 msg += _('Version information loaded from:\n\n %s') % url 250 251 return (True, msg)
252 #=========================================================================== 253 default_mail_sender = u'gnumed@gmx.net' 254 default_mail_receiver = u'gnumed-devel@gnu.org' 255 default_mail_server = u'mail.gmx.net' 256
257 -def send_mail(sender=None, receiver=None, message=None, server=None, auth=None, debug=False, subject=None, encoding='quoted-printable', attachments=None):
258 259 if message is None: 260 return False 261 262 message = message.lstrip().lstrip('\r\n').lstrip() 263 264 if sender is None: 265 sender = default_mail_sender 266 267 if receiver is None: 268 receiver = [default_mail_receiver] 269 270 if server is None: 271 server = default_mail_server 272 273 if subject is None: 274 subject = u'gmTools.py: send_mail() test' 275 276 msg = StringIO.StringIO() 277 writer = MimeWriter.MimeWriter(msg) 278 writer.addheader('To', u', '.join(receiver)) 279 writer.addheader('From', sender) 280 writer.addheader('Subject', subject[:50].replace('\r', '/').replace('\n', '/')) 281 writer.addheader('MIME-Version', '1.0') 282 283 writer.startmultipartbody('mixed') 284 285 # start with a text/plain part 286 part = writer.nextpart() 287 body = part.startbody('text/plain') 288 part.flushheaders() 289 body.write(message.encode(encoding)) 290 291 # now add the attachments 292 if attachments is not None: 293 for a in attachments: 294 filename = os.path.basename(a[0]) 295 try: 296 mtype = a[1] 297 encoding = a[2] 298 except IndexError: 299 mtype, encoding = mimetypes.guess_type(a[0]) 300 if mtype is None: 301 mtype = 'application/octet-stream' 302 encoding = 'base64' 303 elif mtype == 'text/plain': 304 encoding = 'quoted-printable' 305 else: 306 encoding = 'base64' 307 308 part = writer.nextpart() 309 part.addheader('Content-Transfer-Encoding', encoding) 310 body = part.startbody("%s; name=%s" % (mtype, filename)) 311 mimetools.encode(open(a[0], 'rb'), body, encoding) 312 313 writer.lastpart() 314 315 import smtplib 316 session = smtplib.SMTP(server) 317 session.set_debuglevel(debug) 318 if auth is not None: 319 session.login(auth['user'], auth['password']) 320 refused = session.sendmail(sender, receiver, msg.getvalue()) 321 session.quit() 322 msg.close() 323 if len(refused) != 0: 324 _log.error("refused recipients: %s" % refused) 325 return False 326 327 return True
328 #=========================================================================== 329 # main 330 #--------------------------------------------------------------------------- 331 if __name__ == '__main__': 332 333 if len(sys.argv) < 2: 334 sys.exit() 335 336 if sys.argv[1] != 'test': 337 sys.exit() 338 339 #-----------------------------------------------------------------------
340 - def test_send_mail():
341 msg = u""" 342 To: %s 343 From: %s 344 Subject: gmTools test suite mail 345 346 This is a test mail from the gmTools.py module. 347 """ % (default_mail_receiver, default_mail_sender) 348 print "mail sending succeeded:", send_mail ( 349 receiver = [default_mail_receiver, u'karsten.hilbert@gmx.net'], 350 message = msg, 351 auth = {'user': default_mail_sender, 'password': u'gnumed-at-gmx-net'}, # u'gm/bugs/gmx' 352 debug = True, 353 attachments = [sys.argv[0]] 354 )
355 #-----------------------------------------------------------------------
356 - def test_check_for_update():
357 358 test_data = [ 359 ('http://www.gnumed.de/downloads/gnumed-versions.txt', None, None, False), 360 ('file:///home/ncq/gm-versions.txt', None, None, False), 361 ('file:///home/ncq/gm-versions.txt', '0.2', '0.2.8.1', False), 362 ('file:///home/ncq/gm-versions.txt', '0.2', '0.2.8.1', True), 363 ('file:///home/ncq/gm-versions.txt', '0.2', '0.2.8.5', True) 364 ] 365 366 for test in test_data: 367 print "arguments:", test 368 found, msg = check_for_update(test[0], test[1], test[2], test[3]) 369 print msg 370 371 return
372 #-----------------------------------------------------------------------
373 - def test_dl_data_pack():
374 #url = 'file:./x-data_pack.zip' 375 #url = 'missing-file.zip' 376 url = 'gmTools.py' 377 dl_name = download_data_pack(url) 378 print url, "->", dl_name 379 unzip_dir = unzip_data_pack(dl_name) 380 print "unzipped into", unzip_dir
381 #----------------------------------------------------------------------- 382 #test_check_for_update() 383 #test_send_mail() 384 test_dl_data_pack() 385 386 #=========================================================================== 387