def _upload_file_to_s3(
        self, filepath, upload_details, import_record_id, source_type
    ):
        """
        Implements uploading a data file to S3 directly.
        This is a 3-step process:
        1. SEED instance signs the upload request.
        2. File is uploaded to S3 with signature included.
        3. Client notifies SEED instance when upload completed.
        @TODO: Currently can only upload to s3.amazonaws.com, though there are
            other S3-compatible services that could be drop-in replacements.

        Args:
            filepath: full path to file
            upload_details: Results from 'get_upload_details' endpoint;
                contains details about where to send file and how.
            import_record_id: What ImportRecord to associate file with.
            source_type: Type of data in file (Assessed Raw, Portfolio Raw)

        Returns:
            {"import_file_id": 54,
             "success": true,
             "filename": "DataforSEED_dos15.csv"}
        """
        filename = os.path.basename(filepath)
        #step 1: get the request signed
        sig_uri = upload_details['signature']

        payload = {}
        now = datetime.utcnow()
        expires = now + timedelta(hours=1)
        now_ts = timegm(now.timetuple())
        key = 'data_imports/%s.%s' % (filename, now_ts)

        payload['expiration'] = expires.isoformat() + 'Z'
        payload['conditions'] = [
            {'bucket': upload_details['aws_bucket_name']},
            {'Content-Type': 'text/csv'},
            {'acl': 'private'},
            {'success_action_status': '200'},
            {'key': key}
        ]

        sig = self._request(sig_uri, payload=payload)

        #step2: upload the file to S3
        upload_url = "http://%s.s3.amazonaws.com/" % (
            upload_details['aws_bucket_name']
        )

        #s3 expects multipart form encoding with files at the end, so this
        #payload needs to be a list of tuples; the requests library will encode
        #it property if sent as the 'files' parameter.
        s3_payload = [
            ('key', key),
            ('AWSAccessKeyId', upload_details['aws_client_key']),
            ('Content-Type', 'text/csv'),
            ('success_action_status', '200'),
            ('acl', 'private'),
            ('policy', sig['policy']),
            ('signature', sig['signature']),
            ('file', open(filepath, 'rb'))
        ]

        res = requests.post(upload_url, files=s3_payload)

        if res.status_code != 200:
            msg = "Something went wrong with the S3 upload: %s" % res.content
            raise RuntimeError(msg)

        #Step 3: Notify SEED about the upload
        completion_uri = upload_details['upload_complete']
        completion_payload = {
            'import_record': import_record_id,
            'key': key,
            'source_type': source_type
        }
        return self._request(completion_uri,
                             params=completion_payload,
                             method='get')
dataset/ETHPy150Open buildingenergy/buildingenergy-platform/seed/utils/api_client.py/APIClient._upload_file_to_s3/original