Skip to content

Conversation

@peterkle
Copy link

@peterkle peterkle commented Oct 1, 2025

RDISCROWD-8392

  • Upgrade to boto3, preserving backwards compatibility
  • Remove boto from dependencies

@peterkle peterkle requested a review from dchhabda October 1, 2025 19:55
@coveralls
Copy link

coveralls commented Oct 2, 2025

Pull Request Test Coverage Report for Build 19114618549

Details

  • 214 of 223 (95.96%) changed or added relevant lines in 7 files are covered.
  • 152 unchanged lines in 8 files lost coverage.
  • Overall coverage increased (+0.03%) to 94.093%

Changes Missing Coverage Covered Lines Changed/Added Lines %
pybossa/cloud_store_api/base_s3_client.py 53 57 92.98%
pybossa/task_creator_helper.py 30 35 85.71%
Files with Coverage Reduction New Missed Lines %
pybossa/view/attachment.py 1 93.88%
pybossa/view/fileproxy.py 1 97.04%
pybossa/cache/users.py 3 97.83%
pybossa/task_creator_helper.py 3 94.05%
pybossa/view/account.py 3 96.23%
pybossa/redis_lock.py 4 97.59%
pybossa/jobs.py 6 98.03%
pybossa/view/projects.py 131 91.38%
Totals Coverage Status
Change from base Build 18789800363: 0.03%
Covered Lines: 17920
Relevant Lines: 19045

💛 - Coveralls

Copy link

@dchhabda dchhabda left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines 166 to 182
def get_path(self, path='/', **kwargs):
"""
Get the full path by prepending host_suffix if it exists.
This method provides compatibility with the legacy boto2-style interface.
"""
host_suffix = getattr(self, 'host_suffix', '')
if host_suffix:
if not host_suffix.startswith('/'):
host_suffix = '/' + host_suffix
if not host_suffix.endswith('/') and path.startswith('/'):
return host_suffix + path
elif host_suffix.endswith('/') and path.startswith('/'):
return host_suffix + path[1:]
else:
return host_suffix + path
return path

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be removed as it seems this method is not used anywhere except under tests.

Comment on lines 156 to 175
def get_object(self, bucket: str, key: str, **kwargs):
return self.client.get_object(Bucket=bucket, Key=key, **kwargs)

def put_object(self, bucket: str, key: str, body, **kwargs):
return self.client.put_object(Bucket=bucket, Key=key, Body=body, **kwargs)

def list_objects(self, bucket: str, prefix: str = "", **kwargs):
return self.client.list_objects_v2(Bucket=bucket, Prefix=prefix, **kwargs)

def upload_file(self, filename: str, bucket: str, key: str, **kwargs):
# Uses s3transfer under the hood (built-in retries/backoff)
return self.client.upload_file(filename, bucket, key, ExtraArgs=kwargs or {})

def raw(self):
"""Access the underlying boto3 client if you need operations not wrapped here."""
return self.client

def get_bucket(self, bucket_name, validate=False, **kwargs):
"""Return a bucket adapter for boto2-style interface compatibility."""
return ProxiedBucketAdapter(self, bucket_name)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar function definitions exists at multiple places. Please have them defined in base class. Any customization can be done in derived classes. This will make codebase easier to evolve and reduce inconsistencies over time. Thanks

Comment on lines -238 to -271
def test_proxy_s3_error(self, create_connection):
admin, owner = UserFactory.create_batch(2)
project = ProjectFactory.create(owner=owner)
url = '/fileproxy/encrypted/s3/test/%s/file.pdf' % project.id
task = TaskFactory.create(project=project, info={
'url': url
})

signature = signer.dumps({'task_id': task.id})
req_url = '%s?api_key=%s&task-signature=%s' % (url, admin.api_key, signature)

key = self.get_key(create_connection)
key.get_contents_as_string.side_effect = S3ResponseError(403, 'Forbidden')

res = self.app.get(req_url, follow_redirects=True)
assert res.status_code == 500, f"Expected 500 Internal Server Error, got {res.status_code}"

@with_context
@patch('pybossa.cloud_store_api.s3.create_connection')
def test_proxy_key_not_found(self, create_connection):
admin, owner = UserFactory.create_batch(2)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would be the new approach to test these cases?

Copy link

@dchhabda dchhabda left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a big PR with auto formatting at multiple places that is unrelated to the changes specific to this PR. Please remove the auto formatting so that PR only contains necessary changes. Also, fix coverage and failing tests to make all checks green. Thanks.

@peterkle
Copy link
Author

It's a big PR with auto formatting at multiple places that is unrelated to the changes specific to this PR. Please remove the auto formatting so that PR only contains necessary changes. Also, fix coverage and failing tests to make all checks green. Thanks.

I’ll fix the test, but I’ll keep the auto-formatting changes. While they aren’t directly related to the main changes, they improve code readability and consistency.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants