Changeset c632b1c


Ignore:
Timestamp:
Sep 9, 2012, 6:43:39 AM (14 years ago)
Author:
Alex Dehnert <adehnert@…>
Branches:
master, space-access, stable, stage
Children:
71e71e3
Parents:
7e45324
git-author:
Alex Dehnert <adehnert@…> (09/09/12 06:34:45)
git-committer:
Alex Dehnert <adehnert@…> (09/09/12 06:43:39)
Message:

Treat 4XX response codes as constitution failures

Fixes ASA-#57. This changes GroupConstitution?.update() to use urllib2. It also
improves the error handling to detect more errors (such as 404 response codes)
and store more information about the various errors.

Location:
asadb/groups
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • asadb/groups/gather_constitutions.py

    r5f07d50 rc632b1c  
    1313import subprocess
    1414
     15import django.contrib.auth.models
    1516import reversion
    1617
  • asadb/groups/models.py

    r7e45324 rc632b1c  
    1010import re
    1111import shutil
     12import urlparse
    1213import urllib
     14import urllib2
    1315
    1416import settings
    … …  
    136138    def record_failure(self, msg):
    137139        now = datetime.datetime.now()
    138         self.failure_date = now
     140        if not self.failure_date:
     141            self.failure_date = now
    139142        self.status_msg = msg
    140143        self.failure_reason = self.status_msg
    … …  
    156159        old_success = (self.failure_date is None)
    157160        if url:
    158             url_opener = urllib.FancyURLopener()
    159             now = datetime.datetime.now()
    160 
    161161            # Fetch the file
     162            error_msg = None
    162163            try:
    163                 tmp_path, headers = url_opener.retrieve(url)
     164                new_mimetype = None
     165                if url.startswith('/afs/') or url.startswith('/mit/'):
     166                    new_fp = open(url, 'rb')
     167                else:
     168                    new_fp = urllib2.urlopen(url)
     169                    if new_fp.info().getheader('Content-Type'):
     170                        new_mimetype = new_fp.info().gettype()
     171
     172                new_data = new_fp.read()
     173                new_fp.close()
     174            except urllib2.HTTPError, e:
     175                error_msg = "HTTPError: %s %s" % (e.code, e.msg)
     176            except urllib2.URLError, e:
     177                error_msg = "URLError: %s" % (e.reason)
    164178            except IOError:
    165                 self.record_failure("retrieval failed (IOError)")
    166                 success = False
    167                 return (success, self.status_msg, old_success, )
    168 
    169             # At this point, failures are our fault's, not the group's.
     179                error_msg = "IOError"
     180            except ValueError, e:
     181                if e.args[0].startswith('unknown url type'):
     182                    error_msg = "unknown url type"
     183                else:
     184                    raise
     185            if error_msg:
     186                self.record_failure(error_msg)
     187                return (False, self.status_msg, old_success, )
     188
     189            # At this point, failures are our fault, not the group's.
    170190            # We can let any errors bubble all the way up, rather than
    171191            # trying to catch and neatly record them
    … …  
    173193
    174194            # Find a destination, and how to put it there
    175             save_filename = self.compute_filename(tmp_path, headers, )
    176             dest_path = self.path_from_filename(self.dest_file)
    177             if tmp_path == url:
    178                 mover = shutil.copyfile
    179             else:
    180                 mover = shutil.move
     195            old_path = self.path_from_filename(self.dest_file)
     196            new_filename = self.compute_filename(url, new_mimetype, )
    181197
    182198            # Process the update
    183             if save_filename != self.dest_file:
    184                 if self.dest_file: os.remove(dest_path)
    185                 mover(tmp_path, self.path_from_filename(save_filename))
    186                 self.dest_file = save_filename
     199            if new_filename != self.dest_file: # new filename
     200                if self.dest_file:
     201                    if os.path.exists(old_path):
     202                        os.remove(old_path)
     203                    else:
     204                        print "Warning: %s doesn't exist, but is referenced by dest_file" % (old_path, )
     205                self.dest_file = new_filename
     206                new_path = self.path_from_filename(new_filename)
     207                with open(new_path, 'wb') as fp:
     208                    fp.write(new_data)
    187209                self.record_success("new path", updated=True)
    188             else:
    189                 if filecmp.cmp(tmp_path, dest_path, shallow=False, ):
     210            else: # old filename
     211                with open(old_path, 'rb') as old_fp:
     212                    old_data = old_fp.read()
     213                if old_data == new_data: # unchanged
    190214                    self.record_success("no change", updated=False)
    191                 else:
    192                     # changed
    193                     mover(tmp_path, dest_path)
     215                else: # changed
     216                    with open(old_path, 'wb') as fp:
     217                        fp.write(new_data)
    194218                    self.record_success("updated in place", updated=True)
    195219
    … …  
    200224        return (success, self.status_msg, old_success, )
    201225
    202     def compute_filename(self, tmp_path, headers, ):
     226    def compute_filename(self, url, mimetype):
    203227        slug = self.group.slug()
    204228        known_ext = set([
    … …  
    211235            '.txt'
    212236        ])
    213         basename, fileext = os.path.splitext(tmp_path)
     237
     238        # This probably breaks on Windows. But that's probably true of
     239        # everything...
     240        path = urlparse.urlparse(url).path
     241        basename, fileext = os.path.splitext(path)
     242
    214243        if fileext:
    215244            ext = fileext
    216245        else:
    217             if headers.getheader('Content-Type'):
    218                 extensions = mimetypes.guess_all_extensions(headers.gettype())
     246            if mimetype:
     247                extensions = mimetypes.guess_all_extensions(mimetype)
    219248                for extension in extensions:
    220249                    if extension in known_ext:
Note: See TracChangeset for help on using the changeset viewer.