Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-ora2
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-ora2
Commits
f2d4e6cb
Commit
f2d4e6cb
authored
Aug 22, 2017
by
Eric Fischer
Committed by
GitHub
Aug 22, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1037 from edx/efischer/back_to_boto
Revert boto3 upgrade
parents
251005cf
00f9b975
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
97 additions
and
95 deletions
+97
-95
openassessment/fileupload/backends/s3.py
+20
-30
openassessment/fileupload/tests/test_api.py
+16
-11
openassessment/management/commands/upload_oa_data.py
+7
-14
openassessment/management/tests/test_upload_oa_data.py
+9
-6
openassessment/xblock/test/test_leaderboard.py
+13
-10
openassessment/xblock/test/test_submission.py
+14
-16
requirements/base.txt
+1
-1
requirements/test.txt
+1
-1
test/acceptance/pages.py
+15
-6
test/acceptance/tests.py
+1
-0
No files found.
openassessment/fileupload/backends/s3.py
View file @
f2d4e6cb
import
logging
import
logging
import
boto
3
import
boto
from
django.conf
import
settings
from
django.conf
import
settings
...
@@ -15,16 +15,15 @@ class Backend(BaseBackend):
...
@@ -15,16 +15,15 @@ class Backend(BaseBackend):
def
get_upload_url
(
self
,
key
,
content_type
):
def
get_upload_url
(
self
,
key
,
content_type
):
bucket_name
,
key_name
=
self
.
_retrieve_parameters
(
key
)
bucket_name
,
key_name
=
self
.
_retrieve_parameters
(
key
)
try
:
try
:
client
=
_connect_to_s3
()
conn
=
_connect_to_s3
()
return
client
.
generate_presigned_url
(
upload_url
=
conn
.
generate_url
(
ExpiresIn
=
self
.
UPLOAD_URL_TIMEOUT
,
expires_in
=
self
.
UPLOAD_URL_TIMEOUT
,
ClientMethod
=
'put_object'
,
method
=
'PUT'
,
Params
=
{
bucket
=
bucket_name
,
'Bucket'
:
bucket_name
,
key
=
key_name
,
'Key'
:
key_name
headers
=
{
'Content-Length'
:
'5242880'
,
'Content-Type'
:
content_type
}
},
HttpMethod
=
"PUT"
)
)
return
upload_url
except
Exception
as
ex
:
except
Exception
as
ex
:
logger
.
exception
(
logger
.
exception
(
u"An internal exception occurred while generating an upload URL."
u"An internal exception occurred while generating an upload URL."
...
@@ -34,16 +33,10 @@ class Backend(BaseBackend):
...
@@ -34,16 +33,10 @@ class Backend(BaseBackend):
def
get_download_url
(
self
,
key
):
def
get_download_url
(
self
,
key
):
bucket_name
,
key_name
=
self
.
_retrieve_parameters
(
key
)
bucket_name
,
key_name
=
self
.
_retrieve_parameters
(
key
)
try
:
try
:
client
=
_connect_to_s3
()
conn
=
_connect_to_s3
()
return
client
.
generate_presigned_url
(
bucket
=
conn
.
get_bucket
(
bucket_name
)
ExpiresIn
=
self
.
DOWNLOAD_URL_TIMEOUT
,
s3_key
=
bucket
.
get_key
(
key_name
)
ClientMethod
=
'get_object'
,
return
s3_key
.
generate_url
(
expires_in
=
self
.
DOWNLOAD_URL_TIMEOUT
)
if
s3_key
else
""
Params
=
{
'Bucket'
:
bucket_name
,
'Key'
:
key_name
},
HttpMethod
=
"GET"
)
except
Exception
as
ex
:
except
Exception
as
ex
:
logger
.
exception
(
logger
.
exception
(
u"An internal exception occurred while generating a download URL."
u"An internal exception occurred while generating a download URL."
...
@@ -52,15 +45,13 @@ class Backend(BaseBackend):
...
@@ -52,15 +45,13 @@ class Backend(BaseBackend):
def
remove_file
(
self
,
key
):
def
remove_file
(
self
,
key
):
bucket_name
,
key_name
=
self
.
_retrieve_parameters
(
key
)
bucket_name
,
key_name
=
self
.
_retrieve_parameters
(
key
)
client
=
_connect_to_s3
()
conn
=
_connect_to_s3
()
resp
=
client
.
delete_objects
(
bucket
=
conn
.
get_bucket
(
bucket_name
)
Bucket
=
bucket_name
,
s3_key
=
bucket
.
get_key
(
key_name
)
Delete
=
{
if
s3_key
:
'Objects'
:
[{
'Key'
:
key_name
}]
bucket
.
delete_key
(
s3_key
)
}
)
if
'Deleted'
in
resp
and
any
(
key_name
==
deleted_dict
[
'Key'
]
for
deleted_dict
in
resp
[
'Deleted'
]):
return
True
return
True
else
:
return
False
return
False
...
@@ -76,8 +67,7 @@ def _connect_to_s3():
...
@@ -76,8 +67,7 @@ def _connect_to_s3():
aws_access_key_id
=
getattr
(
settings
,
'AWS_ACCESS_KEY_ID'
,
None
)
aws_access_key_id
=
getattr
(
settings
,
'AWS_ACCESS_KEY_ID'
,
None
)
aws_secret_access_key
=
getattr
(
settings
,
'AWS_SECRET_ACCESS_KEY'
,
None
)
aws_secret_access_key
=
getattr
(
settings
,
'AWS_SECRET_ACCESS_KEY'
,
None
)
return
boto3
.
client
(
return
boto
.
connect_s3
(
's3'
,
aws_access_key_id
=
aws_access_key_id
,
aws_access_key_id
=
aws_access_key_id
,
aws_secret_access_key
=
aws_secret_access_key
aws_secret_access_key
=
aws_secret_access_key
)
)
openassessment/fileupload/tests/test_api.py
View file @
f2d4e6cb
...
@@ -7,7 +7,8 @@ import tempfile
...
@@ -7,7 +7,8 @@ import tempfile
import
urllib
import
urllib
from
urlparse
import
urlparse
from
urlparse
import
urlparse
import
boto3
import
boto
from
boto.s3.key
import
Key
import
ddt
import
ddt
from
mock
import
Mock
,
patch
from
mock
import
Mock
,
patch
from
moto
import
mock_s3
from
moto
import
mock_s3
...
@@ -35,8 +36,8 @@ class TestFileUploadService(TestCase):
...
@@ -35,8 +36,8 @@ class TestFileUploadService(TestCase):
FILE_UPLOAD_STORAGE_BUCKET_NAME
=
"mybucket"
FILE_UPLOAD_STORAGE_BUCKET_NAME
=
"mybucket"
)
)
def
test_get_upload_url
(
self
):
def
test_get_upload_url
(
self
):
s3
=
boto3
.
resource
(
's3'
)
conn
=
boto
.
connect_s3
(
)
s3
.
create_bucket
(
Bucket
=
'mybucket'
)
conn
.
create_bucket
(
'mybucket'
)
uploadUrl
=
api
.
get_upload_url
(
"foo"
,
"bar"
)
uploadUrl
=
api
.
get_upload_url
(
"foo"
,
"bar"
)
self
.
assertIn
(
"https://mybucket.s3.amazonaws.com/submissions_attachments/foo"
,
uploadUrl
)
self
.
assertIn
(
"https://mybucket.s3.amazonaws.com/submissions_attachments/foo"
,
uploadUrl
)
...
@@ -47,9 +48,11 @@ class TestFileUploadService(TestCase):
...
@@ -47,9 +48,11 @@ class TestFileUploadService(TestCase):
FILE_UPLOAD_STORAGE_BUCKET_NAME
=
"mybucket"
FILE_UPLOAD_STORAGE_BUCKET_NAME
=
"mybucket"
)
)
def
test_get_download_url
(
self
):
def
test_get_download_url
(
self
):
s3
=
boto3
.
resource
(
's3'
)
conn
=
boto
.
connect_s3
()
s3
.
create_bucket
(
Bucket
=
'mybucket'
)
bucket
=
conn
.
create_bucket
(
'mybucket'
)
s3
.
Object
(
'mybucket'
,
'submissions_attachments/foo'
)
.
put
(
Body
=
"How d'ya do?"
)
key
=
Key
(
bucket
)
key
.
key
=
"submissions_attachments/foo"
key
.
set_contents_from_string
(
"How d'ya do?"
)
downloadUrl
=
api
.
get_download_url
(
"foo"
)
downloadUrl
=
api
.
get_download_url
(
"foo"
)
self
.
assertIn
(
"https://mybucket.s3.amazonaws.com/submissions_attachments/foo"
,
downloadUrl
)
self
.
assertIn
(
"https://mybucket.s3.amazonaws.com/submissions_attachments/foo"
,
downloadUrl
)
...
@@ -60,9 +63,11 @@ class TestFileUploadService(TestCase):
...
@@ -60,9 +63,11 @@ class TestFileUploadService(TestCase):
FILE_UPLOAD_STORAGE_BUCKET_NAME
=
"mybucket"
FILE_UPLOAD_STORAGE_BUCKET_NAME
=
"mybucket"
)
)
def
test_remove_file
(
self
):
def
test_remove_file
(
self
):
s3
=
boto3
.
resource
(
's3'
)
conn
=
boto
.
connect_s3
()
s3
.
create_bucket
(
Bucket
=
'mybucket'
)
bucket
=
conn
.
create_bucket
(
'mybucket'
)
s3
.
Object
(
'mybucket'
,
'submissions_attachments/foo'
)
.
put
(
Body
=
"Test"
)
key
=
Key
(
bucket
)
key
.
key
=
"submissions_attachments/foo"
key
.
set_contents_from_string
(
"Test"
)
result
=
api
.
remove_file
(
"foo"
)
result
=
api
.
remove_file
(
"foo"
)
self
.
assertTrue
(
result
)
self
.
assertTrue
(
result
)
result
=
api
.
remove_file
(
"foo"
)
result
=
api
.
remove_file
(
"foo"
)
...
@@ -82,7 +87,7 @@ class TestFileUploadService(TestCase):
...
@@ -82,7 +87,7 @@ class TestFileUploadService(TestCase):
AWS_SECRET_ACCESS_KEY
=
'bizbaz'
,
AWS_SECRET_ACCESS_KEY
=
'bizbaz'
,
FILE_UPLOAD_STORAGE_BUCKET_NAME
=
"mybucket"
FILE_UPLOAD_STORAGE_BUCKET_NAME
=
"mybucket"
)
)
@patch.object
(
boto
3
,
'client
'
)
@patch.object
(
boto
,
'connect_s3
'
)
@raises
(
exceptions
.
FileUploadInternalError
)
@raises
(
exceptions
.
FileUploadInternalError
)
def
test_get_upload_url_error
(
self
,
mock_s3
):
def
test_get_upload_url_error
(
self
,
mock_s3
):
mock_s3
.
side_effect
=
Exception
(
"Oh noes"
)
mock_s3
.
side_effect
=
Exception
(
"Oh noes"
)
...
@@ -94,7 +99,7 @@ class TestFileUploadService(TestCase):
...
@@ -94,7 +99,7 @@ class TestFileUploadService(TestCase):
AWS_SECRET_ACCESS_KEY
=
'bizbaz'
,
AWS_SECRET_ACCESS_KEY
=
'bizbaz'
,
FILE_UPLOAD_STORAGE_BUCKET_NAME
=
"mybucket"
FILE_UPLOAD_STORAGE_BUCKET_NAME
=
"mybucket"
)
)
@patch.object
(
boto
3
,
'client
'
)
@patch.object
(
boto
,
'connect_s3
'
)
@raises
(
exceptions
.
FileUploadInternalError
,
mock_s3
)
@raises
(
exceptions
.
FileUploadInternalError
,
mock_s3
)
def
test_get_download_url_error
(
self
,
mock_s3
):
def
test_get_download_url_error
(
self
,
mock_s3
):
mock_s3
.
side_effect
=
Exception
(
"Oh noes"
)
mock_s3
.
side_effect
=
Exception
(
"Oh noes"
)
...
...
openassessment/management/commands/upload_oa_data.py
View file @
f2d4e6cb
...
@@ -9,7 +9,8 @@ import sys
...
@@ -9,7 +9,8 @@ import sys
import
tarfile
import
tarfile
import
tempfile
import
tempfile
import
boto3
import
boto
from
boto.s3.key
import
Key
from
django.conf
import
settings
from
django.conf
import
settings
from
django.core.management.base
import
BaseCommand
,
CommandError
from
django.core.management.base
import
BaseCommand
,
CommandError
...
@@ -137,24 +138,16 @@ class Command(BaseCommand):
...
@@ -137,24 +138,16 @@ class Command(BaseCommand):
# environment vars or configuration files instead.
# environment vars or configuration files instead.
aws_access_key_id
=
getattr
(
settings
,
'AWS_ACCESS_KEY_ID'
,
None
)
aws_access_key_id
=
getattr
(
settings
,
'AWS_ACCESS_KEY_ID'
,
None
)
aws_secret_access_key
=
getattr
(
settings
,
'AWS_SECRET_ACCESS_KEY'
,
None
)
aws_secret_access_key
=
getattr
(
settings
,
'AWS_SECRET_ACCESS_KEY'
,
None
)
client
=
boto3
.
client
(
conn
=
boto
.
connect_s3
(
's3'
,
aws_access_key_id
=
aws_access_key_id
,
aws_access_key_id
=
aws_access_key_id
,
aws_secret_access_key
=
aws_secret_access_key
aws_secret_access_key
=
aws_secret_access_key
)
)
bucket
=
client
.
create_bucket
(
Bucket
=
s3_bucket
)
bucket
=
conn
.
get_bucket
(
s3_bucket
)
key_name
=
os
.
path
.
join
(
course_id
,
os
.
path
.
split
(
file_path
)[
1
])
key_name
=
os
.
path
.
join
(
course_id
,
os
.
path
.
split
(
file_path
)[
1
])
client
.
put_object
(
Bucket
=
s3_bucket
,
Key
=
key_name
,
Body
=
open
(
file_path
,
'rb'
))
key
=
Key
(
bucket
=
bucket
,
name
=
key_name
)
url
=
client
.
generate_presigned_url
(
key
.
set_contents_from_filename
(
file_path
)
ExpiresIn
=
self
.
URL_EXPIRATION_HOURS
*
3600
,
url
=
key
.
generate_url
(
self
.
URL_EXPIRATION_HOURS
*
3600
)
ClientMethod
=
'get_object'
,
Params
=
{
'Bucket'
:
s3_bucket
,
'Key'
:
key_name
},
HttpMethod
=
"GET"
)
# Store the key and url in the history
# Store the key and url in the history
self
.
_history
.
append
({
'key'
:
key_name
,
'url'
:
url
})
self
.
_history
.
append
({
'key'
:
key_name
,
'url'
:
url
})
...
...
openassessment/management/tests/test_upload_oa_data.py
View file @
f2d4e6cb
...
@@ -2,9 +2,10 @@
...
@@ -2,9 +2,10 @@
"""
"""
Tests for management command that uploads submission/assessment data.
Tests for management command that uploads submission/assessment data.
"""
"""
from
StringIO
import
StringIO
import
tarfile
import
tarfile
import
boto
3
import
boto
import
moto
import
moto
from
openassessment.management.commands
import
upload_oa_data
from
openassessment.management.commands
import
upload_oa_data
...
@@ -30,8 +31,8 @@ class UploadDataTest(CacheResetTest):
...
@@ -30,8 +31,8 @@ class UploadDataTest(CacheResetTest):
@moto.mock_s3
@moto.mock_s3
def
test_upload
(
self
):
def
test_upload
(
self
):
# Create an S3 bucket using the fake S3 implementation
# Create an S3 bucket using the fake S3 implementation
s3
=
boto3
.
resource
(
's3'
)
conn
=
boto
.
connect_s3
(
)
s3
.
create_bucket
(
Bucket
=
self
.
BUCKET_NAME
)
conn
.
create_bucket
(
self
.
BUCKET_NAME
)
# Create some submissions to ensure that we cover
# Create some submissions to ensure that we cover
# the progress indicator code.
# the progress indicator code.
...
@@ -54,10 +55,12 @@ class UploadDataTest(CacheResetTest):
...
@@ -54,10 +55,12 @@ class UploadDataTest(CacheResetTest):
# Retrieve the uploaded file from the fake S3 implementation
# Retrieve the uploaded file from the fake S3 implementation
self
.
assertEqual
(
len
(
cmd
.
history
),
1
)
self
.
assertEqual
(
len
(
cmd
.
history
),
1
)
s3
.
Object
(
self
.
BUCKET_NAME
,
cmd
.
history
[
0
][
'key'
])
.
download_file
(
"tmp-test-file.tar.gz"
)
bucket
=
conn
.
get_all_buckets
()[
0
]
key
=
bucket
.
get_key
(
cmd
.
history
[
0
][
'key'
])
contents
=
StringIO
(
key
.
get_contents_as_string
())
# Expect that the contents contain all the expected CSV files
# Expect that the contents contain all the expected CSV files
with
tarfile
.
open
(
"tmp-test-file.tar.gz"
,
mode
=
"r:gz"
)
as
tar
:
with
tarfile
.
open
(
mode
=
"r:gz"
,
fileobj
=
contents
)
as
tar
:
file_sizes
=
{
file_sizes
=
{
member
.
name
:
member
.
size
member
.
name
:
member
.
size
for
member
in
tar
.
getmembers
()
for
member
in
tar
.
getmembers
()
...
@@ -68,4 +71,4 @@ class UploadDataTest(CacheResetTest):
...
@@ -68,4 +71,4 @@ class UploadDataTest(CacheResetTest):
# Expect that we generated a URL for the bucket
# Expect that we generated a URL for the bucket
url
=
cmd
.
history
[
0
][
'url'
]
url
=
cmd
.
history
[
0
][
'url'
]
self
.
assertIn
(
"https://
s3.amazonaws.com/
{}"
.
format
(
self
.
BUCKET_NAME
),
url
)
self
.
assertIn
(
"https://{}"
.
format
(
self
.
BUCKET_NAME
),
url
)
openassessment/xblock/test/test_leaderboard.py
View file @
f2d4e6cb
...
@@ -6,7 +6,8 @@ import json
...
@@ -6,7 +6,8 @@ import json
from
random
import
randint
from
random
import
randint
from
urlparse
import
urlparse
from
urlparse
import
urlparse
import
boto3
import
boto
from
boto.s3.key
import
Key
import
mock
import
mock
from
moto
import
mock_s3
from
moto
import
mock_s3
...
@@ -146,15 +147,15 @@ class TestLeaderboardRender(XBlockHandlerTransactionTestCase):
...
@@ -146,15 +147,15 @@ class TestLeaderboardRender(XBlockHandlerTransactionTestCase):
@scenario
(
'data/leaderboard_show.xml'
)
@scenario
(
'data/leaderboard_show.xml'
)
def
test_non_text_submission
(
self
,
xblock
):
def
test_non_text_submission
(
self
,
xblock
):
# Create a mock bucket
# Create a mock bucket
s3
=
boto3
.
resource
(
's3'
)
conn
=
boto
.
connect_s3
(
)
s3
.
create_bucket
(
Bucket
=
'mybucket'
)
bucket
=
conn
.
create_bucket
(
'mybucket'
)
# Create a non-text submission (the submission dict doesn't contain 'text')
# Create a non-text submission (the submission dict doesn't contain 'text')
file_download_url
=
api
.
get_download_url
(
's3key'
)
file_download_url
=
api
.
get_download_url
(
's3key'
)
self
.
_create_submissions_and_scores
(
xblock
,
[(
's3key'
,
1
)],
submission_key
=
'file_key'
)
self
.
_create_submissions_and_scores
(
xblock
,
[(
's3key'
,
1
)],
submission_key
=
'file_key'
)
# Expect that we default to an empty string for content
# Expect that we default to an empty string for content
self
.
_assert_scores
(
xblock
,
[
self
.
_assert_scores
(
xblock
,
[
{
'score'
:
1
,
'files'
:
[
(
file_download_url
,
''
)
],
'submission'
:
''
}
{
'score'
:
1
,
'files'
:
[],
'submission'
:
''
}
])
])
@mock_s3
@mock_s3
...
@@ -171,10 +172,11 @@ class TestLeaderboardRender(XBlockHandlerTransactionTestCase):
...
@@ -171,10 +172,11 @@ class TestLeaderboardRender(XBlockHandlerTransactionTestCase):
file_keys
=
[
'foo'
,
'bar'
]
file_keys
=
[
'foo'
,
'bar'
]
file_descriptions
=
[
'{}-description'
.
format
(
file_key
)
for
file_key
in
file_keys
]
file_descriptions
=
[
'{}-description'
.
format
(
file_key
)
for
file_key
in
file_keys
]
s3
=
boto3
.
resource
(
's3'
)
conn
=
boto
.
connect_s3
(
)
s3
.
create_bucket
(
Bucket
=
'mybucket'
)
bucket
=
conn
.
create_bucket
(
'mybucket'
)
for
file_key
in
file_keys
:
for
file_key
in
file_keys
:
s3
.
Object
(
'mybucket'
,
'submissions_attachments/{}'
.
format
(
file_key
))
.
put
(
Body
=
"How d'ya do?"
)
key
=
Key
(
bucket
,
'submissions_attachments/{}'
.
format
(
file_key
))
key
.
set_contents_from_string
(
"How d'ya do?"
)
files_url_and_description
=
[
files_url_and_description
=
[
(
api
.
get_download_url
(
file_key
),
file_descriptions
[
idx
])
(
api
.
get_download_url
(
file_key
),
file_descriptions
[
idx
])
for
idx
,
file_key
in
enumerate
(
file_keys
)
for
idx
,
file_key
in
enumerate
(
file_keys
)
...
@@ -210,9 +212,10 @@ class TestLeaderboardRender(XBlockHandlerTransactionTestCase):
...
@@ -210,9 +212,10 @@ class TestLeaderboardRender(XBlockHandlerTransactionTestCase):
Tests that text and image submission works as expected
Tests that text and image submission works as expected
"""
"""
# Create a file and get the download URL
# Create a file and get the download URL
s3
=
boto3
.
resource
(
's3'
)
conn
=
boto
.
connect_s3
()
s3
.
create_bucket
(
Bucket
=
'mybucket'
)
bucket
=
conn
.
create_bucket
(
'mybucket'
)
s3
.
Object
(
'mybucket'
,
'submissions_attachments/foo'
)
.
put
(
Body
=
"How d'ya do?"
)
key
=
Key
(
bucket
,
'submissions_attachments/foo'
)
key
.
set_contents_from_string
(
"How d'ya do?"
)
file_download_url
=
[(
api
.
get_download_url
(
'foo'
),
''
)]
file_download_url
=
[(
api
.
get_download_url
(
'foo'
),
''
)]
# Create a image and text submission
# Create a image and text submission
...
...
openassessment/xblock/test/test_submission.py
View file @
f2d4e6cb
...
@@ -6,7 +6,8 @@ Test submission to the OpenAssessment XBlock.
...
@@ -6,7 +6,8 @@ Test submission to the OpenAssessment XBlock.
import
datetime
as
dt
import
datetime
as
dt
import
json
import
json
import
boto3
import
boto
from
boto.s3.key
import
Key
from
mock
import
Mock
,
patch
from
mock
import
Mock
,
patch
from
moto
import
mock_s3
from
moto
import
mock_s3
import
pytz
import
pytz
...
@@ -157,14 +158,11 @@ class SubmissionTest(XBlockHandlerTestCase):
...
@@ -157,14 +158,11 @@ class SubmissionTest(XBlockHandlerTestCase):
@scenario
(
'data/file_upload_scenario.xml'
)
@scenario
(
'data/file_upload_scenario.xml'
)
def
test_download_url
(
self
,
xblock
):
def
test_download_url
(
self
,
xblock
):
""" Test generate correct download URL with existing file. should create a file and get the download URL """
""" Test generate correct download URL with existing file. should create a file and get the download URL """
s3
=
boto3
.
resource
(
's3'
)
conn
=
boto
.
connect_s3
()
s3
.
create_bucket
(
Bucket
=
'mybucket'
)
bucket
=
conn
.
create_bucket
(
'mybucket'
)
s3
.
Object
(
key
=
Key
(
bucket
)
'mybucket'
,
key
.
key
=
"submissions_attachments/test_student/test_course/"
+
xblock
.
scope_ids
.
usage_id
'submissions_attachments/test_student/test_course/'
+
xblock
.
scope_ids
.
usage_id
key
.
set_contents_from_string
(
"How d'ya do?"
)
)
.
put
(
Body
=
"How d'ya do?"
)
download_url
=
api
.
get_download_url
(
"test_student/test_course/"
+
xblock
.
scope_ids
.
usage_id
)
download_url
=
api
.
get_download_url
(
"test_student/test_course/"
+
xblock
.
scope_ids
.
usage_id
)
xblock
.
xmodule_runtime
=
Mock
(
xblock
.
xmodule_runtime
=
Mock
(
...
@@ -189,7 +187,7 @@ class SubmissionTest(XBlockHandlerTestCase):
...
@@ -189,7 +187,7 @@ class SubmissionTest(XBlockHandlerTestCase):
resp
=
self
.
request
(
xblock
,
'download_url'
,
json
.
dumps
(
dict
()),
response_format
=
'json'
)
resp
=
self
.
request
(
xblock
,
'download_url'
,
json
.
dumps
(
dict
()),
response_format
=
'json'
)
self
.
assertTrue
(
resp
[
'success'
])
self
.
assertTrue
(
resp
[
'success'
])
self
.
assert
In
(
u'https://mybucket.s3.amazonaws.com/submissions_attachments
'
,
resp
[
'url'
])
self
.
assert
Equal
(
u'
'
,
resp
[
'url'
])
@mock_s3
@mock_s3
@override_settings
(
@override_settings
(
...
@@ -200,11 +198,11 @@ class SubmissionTest(XBlockHandlerTestCase):
...
@@ -200,11 +198,11 @@ class SubmissionTest(XBlockHandlerTestCase):
@scenario
(
'data/file_upload_scenario.xml'
)
@scenario
(
'data/file_upload_scenario.xml'
)
def
test_remove_all_uploaded_files
(
self
,
xblock
):
def
test_remove_all_uploaded_files
(
self
,
xblock
):
""" Test remove all user files """
""" Test remove all user files """
s3
=
boto3
.
resource
(
's3'
)
conn
=
boto
.
connect_s3
(
)
s3
.
create_bucket
(
Bucket
=
'mybucket'
)
bucket
=
conn
.
create_bucket
(
'mybucket'
)
s3
.
Object
(
'mybucket'
,
'submissions_attachments/test_student/test_course/'
+
xblock
.
scope_ids
.
usage_id
)
.
put
(
key
=
Key
(
bucket
)
Body
=
"How d'ya do?"
key
.
key
=
"submissions_attachments/test_student/test_course/"
+
xblock
.
scope_ids
.
usage_id
)
key
.
set_contents_from_string
(
"How d'ya do?"
)
xblock
.
xmodule_runtime
=
Mock
(
xblock
.
xmodule_runtime
=
Mock
(
course_id
=
'test_course'
,
course_id
=
'test_course'
,
...
@@ -221,7 +219,7 @@ class SubmissionTest(XBlockHandlerTestCase):
...
@@ -221,7 +219,7 @@ class SubmissionTest(XBlockHandlerTestCase):
resp
=
self
.
request
(
xblock
,
'download_url'
,
json
.
dumps
(
dict
()),
response_format
=
'json'
)
resp
=
self
.
request
(
xblock
,
'download_url'
,
json
.
dumps
(
dict
()),
response_format
=
'json'
)
self
.
assertTrue
(
resp
[
'success'
])
self
.
assertTrue
(
resp
[
'success'
])
self
.
assert
In
(
u'https://mybucket.s3.amazonaws.com/submissions_attachments
'
,
resp
[
'url'
])
self
.
assert
Equal
(
u'
'
,
resp
[
'url'
])
@mock_s3
@mock_s3
@override_settings
(
@override_settings
(
...
...
requirements/base.txt
View file @
f2d4e6cb
...
@@ -5,7 +5,7 @@ git+https://github.com/edx/XBlock.git@xblock-1.0.1#egg=XBlock==1.0.1
...
@@ -5,7 +5,7 @@ git+https://github.com/edx/XBlock.git@xblock-1.0.1#egg=XBlock==1.0.1
git+https://github.com/edx/xblock-sdk.git@v0.1.4#egg=xblock-sdk==0.1.4
git+https://github.com/edx/xblock-sdk.git@v0.1.4#egg=xblock-sdk==0.1.4
# Third Party Requirements
# Third Party Requirements
boto
3>=1.4.4,<2
.0.0
boto
>=2.48.0,<3
.0.0
python-swiftclient>=3.1.0,<4.0.0
python-swiftclient>=3.1.0,<4.0.0
defusedxml>=0.4.1,<1.0.0
defusedxml>=0.4.1,<1.0.0
django-model-utils>=2.3.1
django-model-utils>=2.3.1
...
...
requirements/test.txt
View file @
f2d4e6cb
...
@@ -5,7 +5,7 @@ ddt==1.0.0
...
@@ -5,7 +5,7 @@ ddt==1.0.0
factory_boy==2.8.1
factory_boy==2.8.1
freezegun==0.3.9
freezegun==0.3.9
mock==2.0.0
mock==2.0.0
moto==
1.0.
1
moto==
0.4.3
1
nose==1.3.7
nose==1.3.7
tox==2.7.0
tox==2.7.0
...
...
test/acceptance/pages.py
View file @
f2d4e6cb
...
@@ -93,7 +93,7 @@ class OpenAssessmentPage(BaseAssessmentPage):
...
@@ -93,7 +93,7 @@ class OpenAssessmentPage(BaseAssessmentPage):
"""
"""
submit_button_selector
=
self
.
_bounded_selector
(
button_css
)
submit_button_selector
=
self
.
_bounded_selector
(
button_css
)
EmptyPromise
(
EmptyPromise
(
lambda
:
False
==
any
(
self
.
q
(
css
=
submit_button_selector
)
.
attrs
(
'disabled'
)),
lambda
:
not
any
(
self
.
q
(
css
=
submit_button_selector
)
.
attrs
(
'disabled'
)),
"Submit button is enabled."
"Submit button is enabled."
)
.
fulfill
()
)
.
fulfill
()
...
@@ -286,7 +286,7 @@ class AssessmentMixin(object):
...
@@ -286,7 +286,7 @@ class AssessmentMixin(object):
attempts
=
0
attempts
=
0
while
not
criterion_selected
()
and
attempts
<
5
:
while
not
criterion_selected
()
and
attempts
<
5
:
select_criterion
()
select_criterion
()
attempts
+=
1
attempts
+=
1
self
.
submit_assessment
()
self
.
submit_assessment
()
return
self
return
self
...
@@ -695,14 +695,20 @@ class StaffAreaPage(OpenAssessmentPage, AssessmentMixin):
...
@@ -695,14 +695,20 @@ class StaffAreaPage(OpenAssessmentPage, AssessmentMixin):
self
.
q
(
css
=
student_input_css
)
.
fill
(
username
)
self
.
q
(
css
=
student_input_css
)
.
fill
(
username
)
submit_button
=
self
.
q
(
css
=
self
.
_bounded_selector
(
".action--submit-username"
))
submit_button
=
self
.
q
(
css
=
self
.
_bounded_selector
(
".action--submit-username"
))
submit_button
.
first
.
click
()
submit_button
.
first
.
click
()
self
.
wait_for_element_visibility
(
self
.
_bounded_selector
(
".staff-info__student__report"
),
"Student report is present"
)
self
.
wait_for_element_visibility
(
self
.
_bounded_selector
(
".staff-info__student__report"
),
"Student report is present"
)
def
expand_staff_grading_section
(
self
):
def
expand_staff_grading_section
(
self
):
"""
"""
Clicks the staff grade control to expand staff grading section for use in staff required workflows.
Clicks the staff grade control to expand staff grading section for use in staff required workflows.
"""
"""
self
.
q
(
css
=
self
.
_bounded_selector
(
".staff__grade__show-form"
))
.
first
.
click
()
self
.
q
(
css
=
self
.
_bounded_selector
(
".staff__grade__show-form"
))
.
first
.
click
()
self
.
wait_for_element_visibility
(
".staff-full-grade__assessment__rubric__question--0"
,
"staff grading is present"
)
self
.
wait_for_element_visibility
(
".staff-full-grade__assessment__rubric__question--0"
,
"staff grading is present"
)
@property
@property
def
available_checked_out_numbers
(
self
):
def
available_checked_out_numbers
(
self
):
...
@@ -718,7 +724,8 @@ class StaffAreaPage(OpenAssessmentPage, AssessmentMixin):
...
@@ -718,7 +724,8 @@ class StaffAreaPage(OpenAssessmentPage, AssessmentMixin):
def
verify_available_checked_out_numbers
(
self
,
expected_value
):
def
verify_available_checked_out_numbers
(
self
,
expected_value
):
"""
"""
Waits until the expected value for available and checked out numbers appears. If it does not appear, fails the test.
Waits until the expected value for available and checked out numbers appears. If it does not appear, fails the
test.
expected_value should be a tuple as described in the available_checked_out_numbers property above.
expected_value should be a tuple as described in the available_checked_out_numbers property above.
"""
"""
...
@@ -863,7 +870,9 @@ class StaffAreaPage(OpenAssessmentPage, AssessmentMixin):
...
@@ -863,7 +870,9 @@ class StaffAreaPage(OpenAssessmentPage, AssessmentMixin):
Returns: the text present in "Overall Feedback"
Returns: the text present in "Overall Feedback"
"""
"""
return
self
.
q
(
css
=
self
.
_bounded_selector
(
".staff-info__{} .student__answer__display__content"
.
format
(
section
)))
.
text
[
0
]
return
self
.
q
(
css
=
self
.
_bounded_selector
(
".staff-info__{} .student__answer__display__content"
.
format
(
section
))
)
.
text
[
0
]
def
_get_table_text
(
self
,
selector
):
def
_get_table_text
(
self
,
selector
):
"""
"""
...
...
test/acceptance/tests.py
View file @
f2d4e6cb
...
@@ -20,6 +20,7 @@ from acceptance.pages import AssessmentPage, GradePage, StaffAreaPage, Submissio
...
@@ -20,6 +20,7 @@ from acceptance.pages import AssessmentPage, GradePage, StaffAreaPage, Submissio
# This value is generally used in jenkins, but not locally
# This value is generally used in jenkins, but not locally
PROFILING_ENABLED
=
os
.
environ
.
get
(
'ORA_PROFILING_ENABLED'
,
False
)
PROFILING_ENABLED
=
os
.
environ
.
get
(
'ORA_PROFILING_ENABLED'
,
False
)
def
retry
(
tries
=
2
,
delay
=
4
,
backoff
=
2
):
def
retry
(
tries
=
2
,
delay
=
4
,
backoff
=
2
):
"""
"""
Retry decorator with exponential backoff.
Retry decorator with exponential backoff.
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment