Backblaze / b2-sdk-python

Python library to access B2 cloud storage.
Other
186 stars 61 forks source link

b2sdk.v2.SqliteAccountInfo does not raise an error when it fails to locate an account file #457

Closed titus8 closed 11 months ago

titus8 commented 11 months ago

When b2sdk.v2.SqliteAccountInfo fails to locate an account file, it does not raise an error, and it creates the file "None" in the current working directory, which naturally contains no credentials. As a result, b2sdk.v2.B2Folder fails loudly later on.

A partial application workaround is to check the b2sdk.v2.SqliteAccountInfo instance variable filename for the value "None" immediately after calling b2sdk.v2.SqliteAccountInfo. However, "None" has already been created.

b2sdk.v2.SqliteAccountInfo should raise an error when it fails to locate a file, and it should not create the file "None".

vbaltrusaitis-reef commented 11 months ago

Could you share the following:

  1. b2sdk version you are using
  2. operating system you are using
  3. filename and profile arguments you're using to create b2sdk.v2.SqliteAccountInfo
  4. what (if any) B2_ACCOUNT_INFO environment variable is set
titus8 commented 11 months ago

Sorry for providing incomplete information.

  1. b2sdk-1.29.0
  2. macOS Sonoma 14.2, Python 3.12.1
  3. calling b2sdk.v2.SqliteAccountInfo(<file_name>), see below
  4. B2_ACCOUNT_INFO not set

If I call b2sdk.v2.SqliteAccountInfo() with the name of a nonexistent file, then a file with that name is created. Please disregard my earlier comment about "None", it was the result of a Path conversion.

Was I wrong to expect an error to be raised? If, by design, b2sdk.v2.SqliteAccountInfo creates a file when its complex logic fails to find one, then an option to raise an error instead would be most useful.

titus8 commented 11 months ago

I see inb2sdk.v2.SQliteAccountInfo._validate_database:

# If there is no file there, that's fine.  It will get created when
# we connect.
if not os.path.exists(self.filename):
    self._create_database(last_upgrade_to_run)
    return

OK, perhaps the docstring for b2sdk.v2.SQliteAccountInfo could be more explicit about this.

To quote the docs:

The exact algorithm used to determine the location of the database file is not API in any sense.

Given this, if an app expects to use existing B2 credentials, it should have the option to askb2sdk.v2.SQliteAccountInfo to raise an error.

ppolewicz commented 11 months ago

I think in such case the app wouldn't just need the file to exist, but it'd expect the SQliteAccountInfo to be already configured with an authorize_account call, right? Would an empty (not fully authorized due to a bug / unexpected hardware restart or after clear_account() was ran) SQliteAccountInfo be useful?

I think if you need to know if it's fresh or good, you might need to query the SQliteAccountInfo object to determine its state and then decide how to proceed in the logic of your application.

titus8 commented 11 months ago

OK, thanks for the useful insight. I'll look that, and then close this issue if I have no more questions.

titus8 commented 11 months ago

IMHO, it's regrettable that b2sdk.v2.SQliteAccountInfo(None) creates ~/.b2_account_info when no file is found. I can work around this by requiring that the b2 account file be explicitly specified. Also, per your recommendation, I can call get_application_key() to check the result of b2sdk.v2.SQliteAccountInfo(filename) during app initialization, well before any attempt to call b2sdk.v2.B2Folder.

Thanks for your help.