def test_command_etag(self, mock_get, mock_command): """ Test the command when there is an existing ImportRecord record. We are particular interested in verifying that the command will correctly match etag values and determine if the remote file has changed. """ mock_get.return_value = self.mock_get_response # Sanity check self.assertEqual(ImportRecord.objects.count(), 0) # Set up our response headers etag = self.etags[0] mock_get.return_value = self.mock_get_response mock_get.return_value.headers.update({'etag': etag}) # Create a new ImportRecord record pi = ImportRecord() pi.etag = etag.strip('"') pi.url = self.default_url pi.save() # Invoke our management command. We should not expect it to # run an import since the etag of the previous import record # and the etag returned from the head request are the same. call_command('olccfetch', quiet=True) # Ensure our command *did not* request the response body. self.assertFalse(mock_get.return_value.iter_content.called) # Ensure our command *did not* call through to 'olccimport' self.assertFalse(mock_command.called) # Prepare our Mock response object to return a new etag etag = self.etags[1] mock_get.reset_mock() mock_get.return_value = self.mock_get_response mock_get.return_value.headers.update({'etag': etag}) # Invoke our management command. We should now expect it # to run an import and behave opposite to the previous case. call_command('olccfetch', quiet=True) # Ensure our command made a get request to the # default URL. self.assertTrue(mock_get.called) self.assertTrue(mock_get.return_value.iter_content.called) self.assertEqual(mock_get.call_count, 1) self.assertEqual(mock_get.call_args[0][0], self.default_url) # Verify that our import command was now called self.assertTrue(mock_command.called)
def test_force(self, mock_get, mock_command): """ Verify that the command will run an import when the force flag is set regardless of the etag returned. """ mock_get.return_value = self.mock_get_response # Sanity check self.assertEqual(ImportRecord.objects.count(), 0) # Set up our response headers etag = self.etags[0] mock_get.return_value = self.mock_get_response mock_get.return_value.headers.update({'etag': etag}) # Create a new ImportRecord record pi = ImportRecord() pi.etag = etag.strip('"') pi.url = self.default_url pi.save() # Invoke our management command. We should not expect it to # run an import since the etag of the previous import record # and the etag returned from the head request are the same. call_command('olccfetch', quiet=True, force=False) # Ensure our command was called but *did not* read the content # of the response, only the headers self.assertTrue(mock_get.called) self.assertTrue(mock_get.call_count, 1) self.assertEqual(mock_get.call_args[0][0], self.default_url) self.assertFalse(mock_get.iter_content.called) # Ensure our command *did not* call through to 'olccimport' self.assertFalse(mock_command.called) # Retry the request with the force flag updated call_command('olccfetch', quiet=True, force=True) self.assertTrue(mock_get.called) self.assertTrue(mock_command.called)
def handle(self, *args, **options): self.quiet = options.get('quiet', False) force = options.get('force', False) url = options.get('url') import_type = options.get('import_type') if not url: # Get default URL from settings! url = getattr(settings, 'OLCC_PRICE_LIST_URL') try: previous_import = None try: previous_import = ImportRecord.objects.filter(\ url=url).latest('created_at') except ImportRecord.DoesNotExist: pass # Make a HEAD request for the given URL r = requests.get(url, timeout=5, prefetch=False) # Get the ETag for the resource etag = "" if r.headers.has_key('etag'): etag = r.headers.get('etag') etag = etag.strip('"') else: print "The server did not include an ETag in the response!" # Determine if we should run the import should_import = False if not previous_import or (etag != previous_import.etag): should_import = True if should_import or force: self.uprint('Starting import from:\n\t"%s"' % url) # Create a temp file fd, path = tempfile.mkstemp() with os.fdopen(fd, 'wb') as f: # Write to the temp file for chunk in r.iter_content(chunk_size=10240): f.write(chunk) # Create new import record new_import = ImportRecord() new_import.url = url new_import.etag = etag new_import.save() # Start a new import. This must be done outside of the # context manager block above, so that the file handle # can be fully closed before 'olccimport' tries to # open a new one. call_command('olccimport', path, import_type=import_type, quiet=self.quiet) else: self.uprint("File not modified, skipping import.") except requests.exceptions.MissingSchema: print "Request failed! Invalid URL." except requests.ConnectionError: print "Request failed! ConnectionError." except requests.HTTPError: print "Request failed! HTTPError." except requests.Timeout: print "Request failed! Timeout." except requests.TooManyRedirects: print "Request failed! TooManyRedirects."