-
Notifications
You must be signed in to change notification settings - Fork 13.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor import csv #4298
Refactor import csv #4298
Conversation
bb1615c
to
4e2f47c
Compare
Would be nice to have tests to avoid regressions :) |
superset/views/core.py
Outdated
flash(e, 'error') | ||
return redirect('/tablemodelview/list/') | ||
os.remove(os.path.join(config['UPLOAD_FOLDER'], csv_filename)) | ||
flash(str(e), 'error') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't use str but six.text_type
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
superset/views/core.py
Outdated
.filter_by(sqlalchemy_uri=form.data.get('con')) | ||
.one() | ||
) | ||
db_name = table.database.database_name | ||
message = _('CSV file "{0}" uploaded to table "{1}" in ' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
while you are at it could you please make it a unicode string with u?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
4e2f47c
to
13f9b94
Compare
13f9b94
to
6c43b4c
Compare
@xrmx I already added tests in the earlier PR. I now updated the tests to work with the new form field type. |
c52ca34
to
78b94d5
Compare
88013d8
to
f7373f4
Compare
PING |
superset/forms.py
Outdated
|
||
config = app.config | ||
|
||
|
||
class CsvToDatabaseForm(DynamicForm): | ||
# pylint: disable=E0211 | ||
def all_db_items(): | ||
from superset.models import core as models |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are these imports not global?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wrongly assumed it would cause cyclical imports. I moved it to be global
superset/utils.py
Outdated
def upload_file(file): | ||
"""Takes in the name of the file to be uploaded and uploads that file""" | ||
|
||
from superset import app |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are these imports not global?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because there will be cyclical imports if they are global.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because it will cause cyclical import.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be cleaner to pass the upload_folder from the caller then
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True. After removing the extra lines, I decided it was best to just call file.save directly as opposed to calling a function with just . one line.
superset/utils.py
Outdated
|
||
from superset import app | ||
config = app.config | ||
if not file or not file.filename: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens when this Exception
gets raised? Note in the previous version this check doesn't exist.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It gets caught in the try block in views/core.py and the error message gets shown at the top of the form
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this happen in practice? You have one caller of this function so you can be pretty sure that a proper file is passed down.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True. I'll take it out.
superset/utils.py
Outdated
if not file or not file.filename: | ||
raise Exception | ||
file.save(os.path.join(config['UPLOAD_FOLDER'], file.filename)) | ||
assert file.filename in os.listdir(config['UPLOAD_FOLDER']) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similarly what happens if an AssertionError
is raised?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed the assertion in favor of exceptions which are handled by surfacing the exception message at the top of the form.
f7373f4
to
36f01a1
Compare
superset/views/core.py
Outdated
os.remove(os.path.join(config['UPLOAD_FOLDER'], csv_file.filename)) | ||
flash(e, 'error') | ||
return redirect('/tablemodelview/list/') | ||
if csv_filename in os.listdir(config['UPLOAD_FOLDER']): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
try:
os.remove(os.path.join(config['UPLOAD_FOLDER'], csv_filename))
except OSError:
pass
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
superset/views/core.py
Outdated
table.database = form.data.get('con') | ||
table.database_id = table.database.id | ||
table.database.db_engine_spec.create_table_from_csv(form, table) | ||
except IntegrityError: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can probably unify these and the generic exception and just change the flash message if the exception is an instance of IntegrityError
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea! Done.
tests/core_tests.py
Outdated
@@ -804,15 +804,15 @@ def test_import_csv(self): | |||
test_file.write('paul,2\n') | |||
test_file.close() | |||
main_db_uri = db.session.query( | |||
models.Database.sqlalchemy_uri)\ | |||
models.Database)\ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you move the closing parens on the line below you can avoid the backslash
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
superset/utils.py
Outdated
if not file or not file.filename: | ||
raise Exception("No file chosen for upload") | ||
file.save(os.path.join(config['UPLOAD_FOLDER'], file.filename)) | ||
if file.filename not in os.listdir(config['UPLOAD_FOLDER']): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this happen in practice? i assume file.save will return or raise something in case of error
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True. Taken it out and left it to the exception that will be raised if something goes wrong.
c9b9c8c
to
8e78608
Compare
8e78608
to
dcaa5a9
Compare
dcaa5a9
to
5f90554
Compare
* move helpers to utils * make form use queryselector * refactor exception throwing and handling * update db_connection access point * nits (cherry picked from commit 6d37d97)
* move helpers to utils * make form use queryselector * refactor exception throwing and handling * update db_connection access point * nits
* move helpers to utils * make form use queryselector * refactor exception throwing and handling * update db_connection access point * nits
This PR addresses issues #4285 , #4287 and #4289 . It also refactors the import csv code to make it more robust to errors
@john-bodley @mistercrunch @xrmx