Skip to content
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

Merged
merged 6 commits into from Feb 4, 2018
Merged

Conversation

timifasubaa
Copy link
Contributor

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

@xrmx
Copy link
Contributor

xrmx commented Jan 26, 2018

Would be nice to have tests to avoid regressions :)

flash(e, 'error')
return redirect('/tablemodelview/list/')
os.remove(os.path.join(config['UPLOAD_FOLDER'], csv_filename))
flash(str(e), 'error')
Copy link
Contributor

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

.filter_by(sqlalchemy_uri=form.data.get('con'))
.one()
)
db_name = table.database.database_name
message = _('CSV file "{0}" uploaded to table "{1}" in '
Copy link
Contributor

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@timifasubaa
Copy link
Contributor Author

timifasubaa commented Jan 26, 2018

@xrmx I already added tests in the earlier PR. I now updated the tests to work with the new form field type.

@timifasubaa timifasubaa changed the title Refactor imoprt csv Refactor import csv Jan 26, 2018
@timifasubaa timifasubaa force-pushed the refactor_imoprt_csv branch 2 times, most recently from 88013d8 to f7373f4 Compare January 26, 2018 17:38
@timifasubaa
Copy link
Contributor Author

PING


config = app.config


class CsvToDatabaseForm(DynamicForm):
# pylint: disable=E0211
def all_db_items():
from superset.models import core as models
Copy link
Member

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?

Copy link
Contributor Author

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

def upload_file(file):
"""Takes in the name of the file to be uploaded and uploads that file"""

from superset import app
Copy link
Member

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?

Copy link
Contributor Author

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.

Copy link
Contributor Author

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.

Copy link
Contributor

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

Copy link
Contributor Author

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.


from superset import app
config = app.config
if not file or not file.filename:
Copy link
Member

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.

Copy link
Contributor Author

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

Copy link
Contributor

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.

Copy link
Contributor Author

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.

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'])
Copy link
Member

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?

Copy link
Contributor Author

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.

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']):
Copy link
Contributor

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

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:
Copy link
Contributor

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good idea! Done.

@@ -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)\
Copy link
Contributor

@xrmx xrmx Jan 31, 2018

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

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']):
Copy link
Contributor

@xrmx xrmx Jan 31, 2018

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

Copy link
Contributor Author

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.

@timifasubaa timifasubaa force-pushed the refactor_imoprt_csv branch 7 times, most recently from c9b9c8c to 8e78608 Compare January 31, 2018 10:55
@mistercrunch mistercrunch merged commit 6d37d97 into apache:master Feb 4, 2018
graceguo-supercat pushed a commit to graceguo-supercat/superset that referenced this pull request Feb 5, 2018
* move helpers to utils

* make form use queryselector

* refactor exception throwing and handling

* update db_connection access point

* nits

(cherry picked from commit 6d37d97)
@timifasubaa timifasubaa mentioned this pull request Feb 5, 2018
michellethomas pushed a commit to michellethomas/panoramix that referenced this pull request May 24, 2018
* move helpers to utils

* make form use queryselector

* refactor exception throwing and handling

* update db_connection access point

* nits
wenchma pushed a commit to wenchma/incubator-superset that referenced this pull request Nov 16, 2018
* move helpers to utils

* make form use queryselector

* refactor exception throwing and handling

* update db_connection access point

* nits
@mistercrunch mistercrunch added 🏷️ bot A label used by `supersetbot` to keep track of which PR where auto-tagged with release labels 🚢 0.23.0 labels Feb 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🏷️ bot A label used by `supersetbot` to keep track of which PR where auto-tagged with release labels 🚢 0.23.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants