Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
0815db5
Add httpx to optional requirements
TheLazzziest Aug 21, 2021
1beeee1
Replace requests with httpx
TheLazzziest Aug 22, 2021
2336821
Replace requests with httpx for mocked s3 server
TheLazzziest Aug 22, 2021
51e6319
Add a standalone S3 server
TheLazzziest Aug 22, 2021
9426a26
Replace the value for base url
TheLazzziest Aug 22, 2021
d8416d0
Change the value for base_url property in setup step
TheLazzziest Aug 22, 2021
4b159ff
Change the value for base_url property in setup step
TheLazzziest Aug 22, 2021
56c53a7
Change the value for expected links in tests for image
TheLazzziest Aug 22, 2021
9ff9a5a
Reffactor tests for s3 integration
TheLazzziest Aug 22, 2021
02e70c9
Change the value for base_url property for ssh test cases
TheLazzziest Aug 22, 2021
d0bfc86
Fix the test in ImageTestCase by adding parameterization to the alche…
TheLazzziest Aug 22, 2021
cabc33f
Replace pypi with git source for requests-aws4auth
TheLazzziest Sep 5, 2021
d1ab4ed
Move config constants to a separate module
TheLazzziest Sep 5, 2021
9fb54ea
Add create_s3_store to s3 helpers
TheLazzziest Sep 5, 2021
1ce17d1
Add S3TestCase. Replace options with keyword arguments
TheLazzziest Sep 5, 2021
604739f
Move S3TestCase to s3 helpers
TheLazzziest Sep 5, 2021
d9bb8b7
Add S3TestCase to s3 helpers
TheLazzziest Sep 5, 2021
f9bfc74
Add imports from config and s3 helpers
TheLazzziest Sep 5, 2021
828603e
Reffactor tests for s3 storage
TheLazzziest Sep 5, 2021
5b125db
Remove docker-compose config
TheLazzziest Sep 5, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions requirements-optional.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
requests
Werkzeug
requests-aws4auth >= 0.9
requests-aliyun >= 0.2.5
httpx
paramiko
git+https://github.com/tedder/requests-aws4auth.git@master
requests-aliyun >= 0.2.5
Werkzeug
20 changes: 10 additions & 10 deletions sqlalchemy_media/stores/s3.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

# Importing optional stuff required by http based store
try:
import requests
import httpx
except ImportError: # pragma: no cover
requests = None
httpx = None


# Importing optional stuff required by S3 store
Expand Down Expand Up @@ -38,7 +38,7 @@ class S3Store(Store):
def __init__(self, bucket: str, access_key: str, secret_key: str,
region: str, max_age: int = DEFAULT_MAX_AGE,
prefix: str = None, base_url: str = None,
cdn_url: str = None, cdn_prefix_ignore: bool = False,
cdn_url: str = None, cdn_prefix_ignore: bool = False,
acl: str = 'private'):
self.bucket = bucket
self.access_key = access_key
Expand Down Expand Up @@ -68,7 +68,7 @@ def __init__(self, bucket: str, access_key: str, secret_key: str,
def _get_s3_url(self, filename: str):
return '{0}/{1}'.format(self.base_url, filename)

def _upload_file(self, url: str, data: str, content_type: str,
def _upload_file(self, url: str, content: str, content_type: str,
rrs: bool = False):
ensure_aws4auth()

Expand All @@ -84,31 +84,31 @@ def _upload_file(self, url: str, data: str, content_type: str,
}
if content_type:
headers['Content-Type'] = content_type
res = requests.put(url, auth=auth, data=data, headers=headers)
res = httpx.put(url, auth=auth, content=content, headers=headers)
if not 200 <= res.status_code < 300:
raise S3Error(res.text)

def put(self, filename: str, stream: FileLike):
url = self._get_s3_url(filename)
data = stream.read()
content = stream.read()
content_type = getattr(stream, 'content_type', None)
rrs = getattr(stream, 'reproducible', False)
self._upload_file(url, data, content_type, rrs=rrs)
return len(data)
self._upload_file(url, content, content_type, rrs=rrs)
return len(content)

def delete(self, filename: str):
ensure_aws4auth()
url = self._get_s3_url(filename)
auth = AWS4Auth(self.access_key, self.secret_key, self.region, 's3')
res = requests.delete(url, auth=auth)
res = httpx.delete(url, auth=auth)
if not 200 <= res.status_code < 300:
raise S3Error(res.text)

def open(self, filename: str, mode: str = 'rb') -> FileLike:
ensure_aws4auth()
url = self._get_s3_url(filename)
auth = AWS4Auth(self.access_key, self.secret_key, self.region, 's3')
res = requests.get(url, auth=auth)
res = httpx.get(url, auth=auth)
if not 200 <= res.status_code < 300:
raise S3Error(res.text)
return BytesIO(res.content)
Expand Down
4 changes: 2 additions & 2 deletions sqlalchemy_media/tests/helpers/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

from .config import TEST_ACCESS_KEY, TEST_BUCKET, TEST_REGION, TEST_SECRET_KEY
from .http import simple_http_server, encode_multipart_data
from .os2 import mockup_os2_server
from .s3 import mockup_s3_server
from .s3 import mockup_s3_server, create_s3_store, S3TestCase
from .ssh import MockupSSHServer, MockupSSHTestCase
from .ftp import MockFTP
from .static import mockup_http_static_server
Expand Down
7 changes: 7 additions & 0 deletions sqlalchemy_media/tests/helpers/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

# Settings for S3 storage

TEST_BUCKET = 'test-bucket'
TEST_ACCESS_KEY = 'test_access_key'
TEST_SECRET_KEY = 'test_secret_key'
TEST_REGION = 'ap-northeast-2'
36 changes: 32 additions & 4 deletions sqlalchemy_media/tests/helpers/s3.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import unittest
import contextlib
from wsgiref.simple_server import WSGIRequestHandler, WSGIServer

import requests
import httpx

from sqlalchemy_media.stores import S3Store

from .config import TEST_ACCESS_KEY, TEST_BUCKET, TEST_REGION, TEST_SECRET_KEY
from .http import simple_http_server


Expand All @@ -13,13 +17,37 @@ def mockup_s3_server(bucket, **kwargs):
mock_app.debug = False
with simple_http_server(
WSGIRequestHandler,
server_class=WSGIServer,
app=mock_app,
server_class=WSGIServer,
app=mock_app,
**kwargs
) as server:
url = 'http://localhost:%s' % server.server_address[1]
# Create the bucket
bucket_uri = '%s/%s' % (url, bucket)
res = requests.put(bucket_uri)
res = httpx.put(bucket_uri)
assert res.status_code == 200
yield server, bucket_uri


def create_s3_store(bucket=TEST_BUCKET, **kwargs):
return S3Store(
bucket,
TEST_ACCESS_KEY,
TEST_SECRET_KEY,
TEST_REGION,
**kwargs
)


class S3TestCase(unittest.TestCase):
"""Mixin for runnning the S3 server"""

def run(self, result):
with mockup_s3_server(bucket=TEST_BUCKET) as (server, bucket_uri):
self.storage = create_s3_store(
bucket=TEST_BUCKET, base_url=bucket_uri
)
self.bucket_name = TEST_BUCKET
self.server = server
self.base_url = bucket_uri
super(S3TestCase, self).run(result)
13 changes: 10 additions & 3 deletions sqlalchemy_media/tests/helpers/testcases.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@

from sqlalchemy_media import StoreManager, FileSystemStore

from .config import TEST_BUCKET
from .s3 import mockup_s3_server, create_s3_store


class SqlAlchemyTestCase(unittest.TestCase):
@classmethod
Expand All @@ -20,13 +23,17 @@ def setUp(self):
self.Base = declarative_base()
self.engine = create_engine(self.db_uri, echo=False)

def create_all_and_get_session(self):
def create_all_and_get_session(self, expire_on_commit: bool = False):
"""
A factory method for making a SQLAlchemy session factory object.
:param expire_on_commit: @see: https://docs.sqlalchemy.org/en/14/orm/session_api.html?highlight=expire_on_commit#sqlalchemy.orm.Session.params.expire_on_commit
"""
self.Base.metadata.create_all(self.engine, checkfirst=True)
self.session_factory = sessionmaker(
bind=self.engine,
autoflush=False,
autocommit=False,
expire_on_commit=True,
expire_on_commit=expire_on_commit,
twophase=False
)
return self.session_factory()
Expand Down Expand Up @@ -54,7 +61,7 @@ def setUp(self):
self.__class__.__name__,
self._testMethodName
)
self.base_url = 'http://static1.example.orm'
self.base_url = 'http://localhost:9000'

# Remove previous files, if any! to make a clean temp directory:
if exists(self.temp_path): # pragma: no cover
Expand Down
4 changes: 2 additions & 2 deletions sqlalchemy_media/tests/test_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,11 +243,11 @@ class Person(self.Base):
person1 = session.query(Person).filter(Person.id == person1.id).one()
with StoreManager(session):
self.assertTrue(person1.image.locate().startswith(
'http://static1.example.orm/images/image-'
'http://localhost:9000/images/image-'
))
thumbnail = person1.image.get_thumbnail(width=100)
self.assertTrue(thumbnail.locate().startswith(
'http://static1.example.orm/thumbnails/thumbnail-'
'http://localhost:9000/thumbnails/thumbnail-'
))

def test_image_list(self):
Expand Down
Loading