def test_upload_secure_session(): with IaRequestsMock(assert_all_requests_are_fired=False) as rsps: s = get_session(config={'general': {'secure': True}}) rsps.add_metadata_mock('nasa') item = s.get_item('nasa') with IaRequestsMock(assert_all_requests_are_fired=False) as rsps: rsps.add(responses.PUT, S3_URL_RE) r = item.upload(NASA_METADATA_PATH) assert r[0].url == 'https://s3.us.archive.org/nasa/nasa.json'
def test_ia_upload_keep_directories(tmpdir_ch, caplog): os.mkdir('foo') with open('foo/test.txt', 'w') as fh: fh.write('foo') with open('test.csv', 'w') as fh: fh.write('identifier,file\n') fh.write('nasa,foo/test.txt\n') # Default behaviour with IaRequestsMock() as rsps: rsps.add_metadata_mock('nasa') rsps.add(responses.PUT, f'{PROTOCOL}//s3.us.archive.org/nasa/test.txt', body='', content_type='text/plain') ia_call(['ia', '--log', 'upload', 'nasa', 'foo/test.txt']) assert f'uploaded test.txt to {PROTOCOL}//s3.us.archive.org/nasa/test.txt' in caplog.text caplog.clear() with IaRequestsMock() as rsps: rsps.add_metadata_mock('nasa') rsps.add(responses.PUT, f'{PROTOCOL}//s3.us.archive.org/nasa/test.txt', body='', content_type='text/plain') ia_call(['ia', '--log', 'upload', '--spreadsheet', 'test.csv']) assert f'uploaded test.txt to {PROTOCOL}//s3.us.archive.org/nasa/test.txt' in caplog.text caplog.clear() # With the option with IaRequestsMock() as rsps: rsps.add_metadata_mock('nasa') rsps.add(responses.PUT, f'{PROTOCOL}//s3.us.archive.org/nasa/foo/test.txt', body='', content_type='text/plain') ia_call([ 'ia', '--log', 'upload', 'nasa', 'foo/test.txt', '--keep-directories' ]) assert f'uploaded foo/test.txt to {PROTOCOL}//s3.us.archive.org/nasa/foo/test.txt' in caplog.text caplog.clear() with IaRequestsMock() as rsps: rsps.add_metadata_mock('nasa') rsps.add(responses.PUT, f'{PROTOCOL}//s3.us.archive.org/nasa/foo/test.txt', body='', content_type='text/plain') ia_call([ 'ia', '--log', 'upload', '--spreadsheet', 'test.csv', '--keep-directories' ]) assert f'uploaded foo/test.txt to {PROTOCOL}//s3.us.archive.org/nasa/foo/test.txt' in caplog.text
def test_download(tmpdir, nasa_item): tmpdir.chdir() with IaRequestsMock() as rsps: rsps.add(responses.GET, DOWNLOAD_URL_RE, body='test content') nasa_item.download(files='nasa_meta.xml') assert len(tmpdir.listdir()) == 1 with IaRequestsMock() as rsps: rsps.add(responses.GET, DOWNLOAD_URL_RE, body='new test content') nasa_item.download(files='nasa_meta.xml') with open('nasa/nasa_meta.xml', 'r') as fh: assert fh.read() == 'new test content'
def test_upload_delete(tmpdir, nasa_item): body = ( "<?xml version='1.0' encoding='UTF-8'?>" '<Error><Code>BadDigest</Code><Message>The Content-MD5 you specified did not ' 'match what we received.</Message><Resource>content-md5 submitted with PUT: ' 'foo != received data md5: 70871f9fce8dd23853d6e42417356b05also not equal to ' 'base64 version: cIcfn86N0jhT1uQkFzVrBQ==</Resource><RequestId>ec03fe7c-e123-' '4133-a207-3141d4d74096</RequestId></Error>') _expected_headers = deepcopy(EXPECTED_S3_HEADERS) del _expected_headers['x-archive-meta00-scanner'] tmpdir.chdir() test_file = os.path.join(str(tmpdir), 'test.txt') with open(test_file, 'w') as fh: fh.write('test delete') with IaRequestsMock(assert_all_requests_are_fired=False) as rsps: # Non-matching md5, should not delete. rsps.add(responses.PUT, S3_URL_RE, body=body, adding_headers=_expected_headers, status=400) with pytest.raises(HTTPError): nasa_item.upload(test_file, access_key='a', secret_key='b', delete=True, queue_derive=True) assert len(tmpdir.listdir()) == 1 _expected_headers = deepcopy(EXPECTED_S3_HEADERS) test_file = os.path.join(str(tmpdir), 'test.txt') with open(test_file, 'w') as fh: fh.write('test delete') # Matching md5, should delete. with IaRequestsMock(assert_all_requests_are_fired=False) as rsps: rsps.add(responses.PUT, S3_URL_RE, adding_headers=_expected_headers) resp = nasa_item.upload(test_file, access_key='a', secret_key='b', delete=True, queue_derive=True) for r in resp: headers = {k.lower(): str(v) for k, v in r.headers.items()} del headers['content-type'] assert headers == _expected_headers assert len(tmpdir.listdir()) == 0
def test_ia_list_columns(capsys): with IaRequestsMock() as rsps: rsps.add_metadata_mock('nasa') ia_list.main(['list', '--columns', 'name,md5', '--glob', '*meta.xml', 'nasa'], SESSION) out, err = capsys.readouterr() assert out == 'nasa_meta.xml\t0e339f4a29a8bc42303813cbec9243e5\n' with IaRequestsMock() as rsps: rsps.add_metadata_mock('nasa') ia_list.main(['list', '--columns', 'md5', '--glob', '*meta.xml', 'nasa'], SESSION) out, err = capsys.readouterr() assert out == '0e339f4a29a8bc42303813cbec9243e5\n'
def test_search_items_fts(session): with IaRequestsMock(assert_all_requests_are_fired=False) as rsps: rsps.add(responses.POST, '{0}//be-api.us.archive.org/ia-pub-fts-api'.format(PROTOCOL), body=TEST_SCRAPE_RESPONSE) rsps.add_metadata_mock('nasa') r = search_items('nina simone', full_text_search=True, archive_session=session) print(r.search_url) assert r.fts == True assert r.dsl_fts == False assert r.query == '!L nina simone' assert r.params == {'count': 10000, 'q': '!L nina simone'} r = search_items('nina simone', full_text_search=True, dsl_fts=True, archive_session=session) assert r.fts == True assert r.dsl_fts == True assert r.query == 'nina simone' assert r.params == {'count': 10000, 'q': 'nina simone'} r = search_items('nina simone', dsl_fts=True, archive_session=session) assert r.fts == True assert r.dsl_fts == True assert r.query == 'nina simone' assert r.params == {'count': 10000, 'q': 'nina simone'}
def test_upload_validate_identifier(): try: upload('føø', NASA_METADATA_PATH, access_key='test_access', secret_key='test_secret', validate_identifier=True) assert False except Exception as exc: assert isinstance(exc, InvalidIdentifierException) expected_s3_headers = { 'content-length': '7557', 'x-archive-queue-derive': '1', 'x-archive-meta00-scanner': 'uri(Internet%20Archive%20Python%20library', 'x-archive-size-hint': '7557', 'x-archive-auto-make-bucket': '1', 'authorization': 'LOW test_access:test_secret', } with IaRequestsMock(assert_all_requests_are_fired=False) as rsps: rsps.add(responses.PUT, re.compile(r'.*s3.us.archive.org/.*'), adding_headers=expected_s3_headers) rsps.add_metadata_mock('nasa') rsps.add(responses.GET, '{0}//archive.org/metadata/nasa'.format(PROTOCOL), body='{}') upload('nasa', NASA_METADATA_PATH, access_key='test_access', secret_key='test_secret', validate_identifier=True) assert True
def test_upload_dir(tmpdir, nasa_item): with IaRequestsMock(assert_all_requests_are_fired=False) as rsps: rsps.add(responses.PUT, S3_URL_RE, adding_headers=EXPECTED_S3_HEADERS) tmpdir.mkdir('dir_test') with open(os.path.join(str(tmpdir), 'dir_test', 'foo.txt'), 'w') as fh: fh.write('hi') with open(os.path.join(str(tmpdir), 'dir_test', 'foo2.txt'), 'w') as fh: fh.write('hi 2') # Test no-slash upload, dir is not in key name. _responses = nasa_item.upload(os.path.join(str(tmpdir), 'dir_test') + '/', access_key='a', secret_key='b') expected_eps = [ f'{S3_URL}nasa/foo.txt', f'{S3_URL}nasa/foo2.txt', ] for resp in _responses: assert resp.request.url in expected_eps # Test slash upload, dir is in key name. _responses = nasa_item.upload(os.path.join(str(tmpdir), 'dir_test'), access_key='a', secret_key='b') tmp_path = norm_filepath(str(tmpdir)) expected_eps = [ f'{S3_URL}nasa{tmp_path}/dir_test/foo.txt', f'{S3_URL}nasa{tmp_path}/dir_test/foo2.txt', ] for resp in _responses: assert resp.request.url in expected_eps
def test_upload_checksum(tmpdir, nasa_item): with IaRequestsMock() as rsps: rsps.add_metadata_mock('nasa') nasa_item = get_item('nasa') _expected_headers = deepcopy(EXPECTED_S3_HEADERS) del _expected_headers['x-archive-meta00-scanner'] test_file = os.path.join(str(tmpdir), 'checksum_test.txt') with open(test_file, 'wb') as fh: fh.write(b'test delete') # No skip. rsps.add(responses.PUT, S3_URL_RE, adding_headers=_expected_headers) resp = nasa_item.upload(test_file, access_key='a', secret_key='b', checksum=True) for r in resp: headers = dict((k.lower(), str(v)) for k, v in r.headers.items()) del headers['content-type'] assert headers == _expected_headers assert r.status_code == 200 # Skip. nasa_item.item_metadata['files'].append( dict(name='checksum_test.txt', md5='33213e7683c1e6d15b2a658f3c567717')) resp = nasa_item.upload(test_file, access_key='a', secret_key='b', checksum=True) for r in resp: headers = dict((k.lower(), str(v)) for k, v in r.headers.items()) assert r.status_code is None
def test_search_items(session): results_url = ( '{0}//archive.org/services/search/v1/scrape' '?q=identifier%3Anasa&count=10000&REQUIRE_AUTH=true'.format(PROTOCOL)) count_url = ('{0}//archive.org/services/search/v1/scrape' '?q=identifier%3Anasa&total_only=true&REQUIRE_AUTH=true' '&count=10000'.format(PROTOCOL)) with IaRequestsMock(assert_all_requests_are_fired=False) as rsps: rsps.add(responses.POST, results_url, body=TEST_SCRAPE_RESPONSE, match_querystring=True) rsps.add(responses.POST, count_url, body='{"items":[],"count":0,"total":1}', match_querystring=True, content_type='application/json; charset=UTF-8') r = search_items('identifier:nasa', archive_session=session) expected_results = [{'identifier': 'nasa'}] assert r.num_found == 1 assert iter(r).search == r assert len(iter(r)) == 1 assert len(r.iter_as_results()) == 1 assert list(r) == expected_results assert list(r.iter_as_results()) == expected_results
def test_download_checksum(tmpdir, caplog): tmpdir.chdir() # test overwrite based on checksum. with IaRequestsMock() as rsps: rsps.add_metadata_mock('nasa') rsps.add(responses.GET, DOWNLOAD_URL_RE, body='test content') rsps.add(responses.GET, DOWNLOAD_URL_RE, body='overwrite based on md5') nasa_item = get_item('nasa') nasa_item.download(files='nasa_meta.xml') nasa_item.download(files='nasa_meta.xml', checksum=True) assert load_file('nasa/nasa_meta.xml') == 'overwrite based on md5' # test no overwrite based on checksum. rsps.reset() rsps.add(responses.GET, DOWNLOAD_URL_RE, body=load_test_data_file('nasa_meta.xml')) nasa_item.download(files='nasa_meta.xml', checksum=True) nasa_item.download(files='nasa_meta.xml', checksum=True) assert 'skipping nasa' in caplog.text assert 'nasa_meta.xml, file already exists based on checksum.' in caplog.text
def test_upload(): expected_s3_headers = { 'content-length': '7557', 'x-archive-queue-derive': '1', 'x-archive-meta00-scanner': 'uri(Internet%20Archive%20Python%20library', 'x-archive-size-hint': '7557', 'content-md5': '6f1834f5c70c0eabf93dea675ccf90c4', 'x-archive-auto-make-bucket': '1', 'authorization': 'LOW test_access:test_secret', } with IaRequestsMock(assert_all_requests_are_fired=False) as rsps: rsps.add(responses.PUT, re.compile(r'.*s3.us.archive.org/.*'), adding_headers=expected_s3_headers) rsps.add_metadata_mock('nasa') rsps.add(responses.GET, '{0}//archive.org/metadata/nasa'.format(PROTOCOL), body='{}') _responses = upload('nasa', NASA_METADATA_PATH, access_key='test_access', secret_key='test_secret') for response in _responses: req = response.request headers = dict((k.lower(), str(v)) for k, v in req.headers.items()) scanner_header = '%20'.join( response.headers['x-archive-meta00-scanner'].split('%20')[:4]) headers['x-archive-meta00-scanner'] = scanner_header assert headers == expected_s3_headers assert req.url == '{0}//s3.us.archive.org/nasa/nasa.json'.format(PROTOCOL)
def test_upload_503(capsys, nasa_item): body = ( "<?xml version='1.0' encoding='UTF-8'?>" '<Error><Code>SlowDown</Code><Message>Please reduce your request rate.' '</Message><Resource>simulated error caused by x-(amz|archive)-simulate-error' ', try x-archive-simulate-error:help</Resource><RequestId>d36ec445-8d4a-4a64-' 'a110-f67af6ee2c2a</RequestId></Error>') with IaRequestsMock(assert_all_requests_are_fired=False) as rsps: _expected_headers = deepcopy(EXPECTED_S3_HEADERS) rsps.add(responses.GET, S3_URL_RE, body='{"over_limit": "1"}') rsps.add(responses.PUT, S3_URL_RE, body=body, adding_headers=_expected_headers, status=503) try: nasa_item.upload(NASA_METADATA_PATH, access_key='a', secret_key='b', retries=1, retries_sleep=.1, verbose=True) except Exception as exc: assert 'Please reduce your request rate' in str(exc) out, err = capsys.readouterr() assert 'warning: s3 is overloaded' in err
def test_download_io_error(tmpdir, nasa_item): tmpdir.chdir() with IaRequestsMock() as rsps: rsps.add(responses.GET, DOWNLOAD_URL_RE, body='test content') nasa_item.download(files='nasa_meta.xml') with pytest.raises(ConnectionError): nasa_item.download(files='nasa_meta.xml')
def test_upload_metadata(nasa_item): with IaRequestsMock(assert_all_requests_are_fired=False) as rsps: _expected_headers = deepcopy(EXPECTED_S3_HEADERS) del _expected_headers['x-archive-meta00-scanner'] _expected_headers['x-archive-meta00-foo'] = 'bar' _expected_headers['x-archive-meta00-subject'] = 'first' _expected_headers['x-archive-meta01-subject'] = 'second' _expected_headers['x-archive-meta00-baz'] = ( 'uri(%D0%9F%D0%BE%D1%87%D0%B5%D0%BC' '%D1%83%20%D0%B1%D1%8B%20%D0%B8%20%' 'D0%BD%D0%B5%D1%82...)') _expected_headers['x-archive-meta00-baz2'] = ( 'uri(%D0%9F%D0%BE%D1%87%D0%B5%D0%BC' '%D1%83%20%D0%B1%D1%8B%20%D0%B8%20%' 'D0%BD%D0%B5%D1%82...)') rsps.add(responses.PUT, S3_URL_RE, adding_headers=_expected_headers) md = dict( foo='bar', subject=['first', 'second'], baz='Почему бы и нет...', baz2=(u'\u041f\u043e\u0447\u0435\u043c\u0443 \u0431\u044b \u0438 ' u'\u043d\u0435\u0442...'), ) _responses = nasa_item.upload(NASA_METADATA_PATH, metadata=md, access_key='a', secret_key='b') for resp in _responses: request = resp.request del request.headers['x-archive-meta00-scanner'] headers = dict((k.lower(), str(v)) for k, v in request.headers.items()) assert 'user-agent' in headers del headers['user-agent'] assert headers == _expected_headers
def test_ia_upload_checksum(tmpdir_ch, caplog): with open('test.txt', 'w') as fh: fh.write('foo') # First upload, file not in metadata yet with IaRequestsMock() as rsps: rsps.add_metadata_mock('nasa') rsps.add(responses.PUT, f'{PROTOCOL}//s3.us.archive.org/nasa/test.txt', body='', content_type='text/plain') ia_call(['ia', '--log', 'upload', 'nasa', 'test.txt', '--checksum']) assert f'uploaded test.txt to {PROTOCOL}//s3.us.archive.org/nasa/test.txt' in caplog.text caplog.clear() # Second upload with file in metadata def insert_test_txt(body): body = json.loads(body) body['files'].append({ 'name': 'test.txt', 'md5': 'acbd18db4cc2f85cedef654fccc4a4d8' }) return json.dumps(body) with IaRequestsMock() as rsps: rsps.add_metadata_mock('nasa', transform_body=insert_test_txt) ia_call(['ia', '--log', 'upload', 'nasa', 'test.txt', '--checksum'], expected_exit_code=1) assert f'test.txt already exists: {PROTOCOL}//s3.us.archive.org/nasa/test.txt' in caplog.text caplog.clear() # Second upload with spreadsheet with open('test.csv', 'w') as fh: fh.write('identifier,file\n') fh.write('nasa,test.txt\n') with IaRequestsMock() as rsps: rsps.add_metadata_mock('nasa', transform_body=insert_test_txt) ia_call([ 'ia', '--log', 'upload', '--spreadsheet', 'test.csv', '--checksum' ], expected_exit_code=1) assert f'test.txt already exists: {PROTOCOL}//s3.us.archive.org/nasa/test.txt' in caplog.text
def test_download_no_directory(tmpdir, nasa_item): url_re = re.compile(f'{PROTOCOL}//archive.org/download/.*') tmpdir.chdir() with IaRequestsMock() as rsps: rsps.add(responses.GET, url_re, body='no dest dir') nasa_item.download(files='nasa_meta.xml', no_directory=True) with open(os.path.join(str(tmpdir), 'nasa_meta.xml'), 'r') as fh: assert fh.read() == 'no dest dir'
def test_download_clobber(tmpdir, nasa_item): tmpdir.chdir() with IaRequestsMock() as rsps: rsps.add(responses.GET, DOWNLOAD_URL_RE, body='test content') nasa_item.download(files='nasa_meta.xml') rsps.add(responses.GET, DOWNLOAD_URL_RE, body='new test content') nasa_item.download(files='nasa_meta.xml') load_file('nasa/nasa_meta.xml') == 'new test content'
def test_search_items_as_items(): with IaRequestsMock(assert_all_requests_are_fired=False) as rsps: rsps.add(responses.POST, '{0}//archive.org/services/search/v1/scrape'.format(PROTOCOL), body=TEST_SCRAPE_RESPONSE) rsps.add_metadata_mock('nasa') r = search_items('identifier:nasa') assert [x.identifier for x in r.iter_as_items()] == ['nasa'] assert r.iter_as_items().search == r
def test_download_destdir(tmpdir, nasa_item): tmpdir.chdir() with IaRequestsMock() as rsps: rsps.add(responses.GET, DOWNLOAD_URL_RE, body='new destdir') dest = os.path.join(str(tmpdir), 'new destdir') nasa_item.download(files='nasa_meta.xml', destdir=dest) assert 'nasa' in os.listdir(dest) with open(os.path.join(dest, 'nasa/nasa_meta.xml'), 'r') as fh: assert fh.read() == 'new destdir'
def test_download_ignore_existing(tmpdir, nasa_item): tmpdir.chdir() with IaRequestsMock(assert_all_requests_are_fired=False) as rsps: rsps.add(responses.GET, DOWNLOAD_URL_RE, body='test content') nasa_item.download(files='nasa_meta.xml', ignore_existing=True) rsps.add(responses.GET, DOWNLOAD_URL_RE, body='new test content') nasa_item.download(files='nasa_meta.xml', ignore_existing=True) with open('nasa/nasa_meta.xml', 'r') as fh: assert fh.read() == 'test content'
def test_ia_list_non_existing(capsys): with IaRequestsMock() as rsps: rsps.add_metadata_mock('nasa', body='{}') try: ia_list.main(['list', 'nasa'], SESSION) except SystemExit as exc: assert exc.code == 1 out, err = capsys.readouterr() assert out == ''
def test_upload_file_keys(nasa_item): with IaRequestsMock(assert_all_requests_are_fired=False) as rsps: rsps.add(responses.PUT, S3_URL_RE, adding_headers=EXPECTED_S3_HEADERS) files = {'new_key.txt': NASA_METADATA_PATH, '222': NASA_METADATA_PATH} _responses = nasa_item.upload(files, access_key='a', secret_key='b') expected_urls = [ f'{PROTOCOL}//s3.us.archive.org/nasa/new_key.txt', f'{PROTOCOL}//s3.us.archive.org/nasa/222', ] for resp in _responses: assert resp.request.url in expected_urls
def test_download_verbose(tmpdir, capsys, nasa_item): tmpdir.chdir() with IaRequestsMock(assert_all_requests_are_fired=False) as rsps: rsps.add(responses.GET, DOWNLOAD_URL_RE, body='no dest dir', adding_headers={'content-length': '100'}) nasa_item.download(files='nasa_meta.xml', verbose=True) out, err = capsys.readouterr() print(repr(err)) assert 'downloading nasa_meta.xml' in err
def test_ia_metadata_modify(capsys): md_rsp = ('{"success":true,"task_id":447613301,' '"log":"https://catalogd.archive.org/log/447613301"}') with IaRequestsMock() as rsps: rsps.add_metadata_mock('nasa') rsps.add_metadata_mock('nasa', body=md_rsp, method=responses.POST) rsps.add_metadata_mock('nasa') valid_key = f'foo-{int(time())}' ia_call(['ia', 'metadata', '--modify', f'{valid_key}:test_value', 'nasa']) out, err = capsys.readouterr() assert err == 'nasa - success: https://catalogd.archive.org/log/447613301\n'
def test_get_item_with_kwargs(): with IaRequestsMock(assert_all_requests_are_fired=False) as rsps: rsps.add_metadata_mock('nasa') item = get_item('nasa', http_adapter_kwargs={'max_retries': 13}) assert isinstance(item.session.adapters['{0}//'.format(PROTOCOL)].max_retries, urllib3.Retry) try: get_item('nasa', request_kwargs={'timeout': .0000000000001}) except Exception as exc: assert 'timed out' in str(exc)
def test_ia_metadata_exists(capsys): with IaRequestsMock() as rsps: rsps.add_metadata_mock('nasa') ia_call(['ia', 'metadata', '--exists', 'nasa']) out, err = capsys.readouterr() assert out == 'nasa exists\n' rsps.add_metadata_mock('nasa', '{}') sys.argv = ['ia', 'metadata', '--exists', 'nasa'] ia_call(['ia', 'metadata', '--exists', 'nasa'], expected_exit_code=1) out, err = capsys.readouterr() assert err == 'nasa does not exist\n'
def test_download(tmpdir): tmpdir.chdir() with IaRequestsMock() as rsps: rsps.add(responses.GET, '{0}//archive.org/download/nasa/nasa_meta.xml'.format(PROTOCOL), body='test content') rsps.add_metadata_mock('nasa') download('nasa', 'nasa_meta.xml') p = os.path.join(str(tmpdir), 'nasa') assert len(os.listdir(p)) == 1 assert load_file('nasa/nasa_meta.xml') == 'test content'
def test_download_dry_run(tmpdir, capsys, nasa_item): tmpdir.chdir() with IaRequestsMock(assert_all_requests_are_fired=False) as rsps: rsps.add(responses.GET, DOWNLOAD_URL_RE, body='no dest dir', adding_headers={'content-length': '100'}) nasa_item.download(formats='Metadata', dry_run=True) expected = set(['nasa_reviews.xml', 'nasa_meta.xml', 'nasa_files.xml']) out, err = capsys.readouterr() assert set([x.split('/')[-1] for x in out.split('\n') if x]) == expected
def test_upload_validate_identifier(session): item = session.get_item('føø') with IaRequestsMock(assert_all_requests_are_fired=False) as rsps: rsps.add(responses.PUT, S3_URL_RE, adding_headers=EXPECTED_S3_HEADERS) try: item.upload(NASA_METADATA_PATH, access_key='a', secret_key='b', validate_identifier=True) assert False except Exception as exc: assert isinstance(exc, InvalidIdentifierException) valid_item = session.get_item('foo') with IaRequestsMock(assert_all_requests_are_fired=False) as rsps: rsps.add(responses.PUT, S3_URL_RE, adding_headers=EXPECTED_S3_HEADERS) valid_item.upload(NASA_METADATA_PATH, access_key='a', secret_key='b', validate_identifier=True) assert True