I am trying to handle the exceptions/errors generated by Python Snowflake connector.
connection = snowflake.connector.connect(
user='user',
password=''password,
account='account',
role='ACCOUNTADMIN'
)
If the connection is successful then it will return a snowflake object or else I would want to handle all the possible exception and print a custom message.
What are the possible exception snowflake.connector.connect method would generate.
How to handle all of those exceptions. (link to the documentation or an example would be really helpful)
If you have a look at the snowflake.connector.errors file you can see a list of all errors that can be returned by the snowflake connector. It doesn't say anywhere about the specific errors that can be returned by snowflake.connector.connect. Here is a list of the error types that I suspect can get returned:
class InterfaceError(Error)
class DatabaseError(Error)
class InternalError(DatabaseError)
class OperationalError(DatabaseError)
class InternalServerError(Error)
class ServiceUnavailableError(Error)
class GatewayTimeoutError(Error)
class ForbiddenError(Error)
class RequestTimeoutError(Error)
class BadRequest(Error)
class BadGatewayError(Error)
class MethodNotAllowed(Error)
class OtherHTTPRetryableError(Error)
class MissingDependencyError(Error)
Rather than trying to handle every error, you should only handle the errors that you know what to do with. For example, you wouldn't handle an InternalServerError unless you knew what to do to fix it. Instead, log it and let it fail.
Here is an example of how you would catch a bad username/password. You could then ask the user to re-enter their details:
import os
import snowflake.connector
from snowflake.connector.errors import DatabaseError, ProgrammingError
snowflake_account = os.environ['SNOWFLAKE_ACCOUNT']
if __name__ == '__main__':
try:
con = snowflake.connector.connect(
user='bad username', # <-------- Bad user
password='bad password', # <-------- Bad pass
account=snowflake_account # <-------- This is correct
)
except DatabaseError as db_ex:
if db_ex.errno == 250001:
print(f"Invalid username/password, please re-enter username and password...")
# code for user to re-enter username & pass
else:
raise
except Exception as ex:
# Log this
print(f"Some error you don't know how to handle {ex}")
raise
else:
try:
results = con.cursor().execute("select * from db.schema.table").fetchall()
print(results)
except ProgrammingError as db_ex:
print(f"Programming error: {db_ex}")
raise
finally:
con.close()
I've also put in an example of catching a ProgrammingError which can be raised when you enter some invalid SQL.
You can use try.. catch method in python
try:
self.mainsfconnection = sf.connect(
user=config.user,
password=config.password,
account=config.account,
warehouse=config.warehouse,
role=config.role,
database=config.database,
schema=config.schema)
# -- Snowflake : Default Session parameters
self.mainsfconnection.cursor().execute("USE ROLE {0}".format(config.role))
self.mainsfconnection.cursor().execute("USE WAREHOUSE {0}".format(config.warehouse))
self.mainsfconnection.cursor().execute("USE SCHEMA {0}.{1}".format(config.database, config.schema))
# -- Exception clause : snowflake
except sf.errors.ProgrammingError as e:
print('SQL Execu tion Error: {0}'.format(e.msg))
print('Snowflake Query Id: {0}'.format(e.sfqid))
print('Error Number: {0}'.format(e.errno))
print('SQL State: {0}'.format(e.sqlstate))
Here's a really good example from the docs, note there is no reason not to move the cur = and the connection = to below the try command (with proper indentation of course):
https://docs.snowflake.com/en/user-guide/python-connector-example.html#handling-errors
# Catching the syntax error
cur = con.cursor()
try:
cur.execute("SELECT * FROM testtable")
except snowflake.connector.errors.ProgrammingError as e:
# default error message
print(e)
# customer error message
print('Error {0} ({1}): {2} ({3})'.format(e.errno, e.sqlstate, e.msg, e.sfqid))
finally:
cur.close()
Related
I'm working through a full-stack project using Rails on the back end and React on the front end. I have a Sign Up form designed to accept a new user's information and avatar and pass it to the Users controller on the back end. For whatever reason though, if the form is empty or incomplete, it throws a 500 Internal Server Error instead of a more informative 400 error.
User Controller is :
``
class UsersController < ApplicationController
rescue_from ActiveRecord::RecordInvalid, with: :render_unprocessable_entity_response
def index
users = User.all
render json: users
end
def create
user = User.create(user_params)
session[:user_id] = user.id
render json: user, status: :created
end
private
def user_params
params.require(:user).permit(:first_name, :last_name, :email, :birthday, :username, :password, :password_confirmation, :avatar)
end
def render_unprocessable_entity_response(invalid)
render json: { errors: invalid.record.errors.full_messages }, status: :unprocessable_entity
end
end
Sign Up Form in React (specifically, my Submit function)
function handleSubmit(event) {
event.preventDefault();
const data = new FormData();
data.append("[user][first_name]", firstName);
data.append("[user][last_name]", lastName);
data.append("[user][email]", email);
data.append("[user][username]", username);
data.append("[user][password]", password);
data.append("[user][password_confirmation]", passwordConfirmation);
data.append("[user][avatar]", avatar);
fetch("/signup", {
method: "POST",
body: data
})
.then((response) => {
if (response.ok) {
response.json().then((user) => onLogin(user));
} else {
response.json().then((errorData) => contextData.setErrors(errorData.errors));
}
})
};
Response I'm getting in the console when I submit an empty form:
Parameters: {"user"=>{"first_name"=>"", "last_name"=>"", "email"=>"", "username"=>"", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]", "avatar"=>""}}
Completed 500 Internal Server Error in 97ms (ActiveRecord: 49.6ms | Allocations: 9234)
When I remove the "params.require(:user)" portion, it gives me the validation errors I was expecting, but then I'm unable to create a new user due to have ActiveStorage works and requires data.
There is a lot wrong in the premise of this question so please bear with me.
First lets look at the docs for ActionController::Parameters#require:
Ensures that a parameter is present. If it's present, returns the
parameter at the given key, otherwise raises an
ActionController::ParameterMissing error.
Rails will rescue this error on the framework level but you can rescue it on a per controller level with rescue_from 'ActionController::ParameterMissing'. But remember that the purpose of require isn't validation. Its just to bail early if the request is missing the correct structure and should not be processed anyways - because classical Rails applications nest their parameters in a key with the same name as the resource by default.
In an API application you don't even have to follow that pattern - you could just as well use "flat parameters" or standards like JSONAPI.org.
Then there is the use of:
rescue_from ActiveRecord::RecordInvalid, with: :render_unprocessable_entity_response
This pops up from time to time as a "clever" way to DRY out API's. In your case it won't even work because User.create does not raise - User.create! does.
It's also not a good use of exceptions. Exceptions should be used for exceptional events that should cause an immediate halt of the execution. A user passing invalid input is not exceptional in any way - in fact its completely mundane.
If you want to DRY your API in a good way instead do it the way that the Responders gem does:
class UsersController < ApplicationController
def create
user = User.create(user_params)
session[:user_id] = user.id
respond_with(user)
end
end
class ApplicationController
# ...
private
def respond_with(resource)
if resource.valid?
resource.new_record? ? render_created_response(resource) : render_updated_response(resource)
else
render_unprocessable_entity_response(resource)
end
end
def render_created_response(resource)
render json: resource, status: :created
end
def render_updated_response(resource)
render json: resource, status: :ok
end
end
This creates an explicit flow of methods that can be overridden in subclasses. Instead of an implicit flow created by what is actually a callback.
class UsersController < ApplicationController
private
def render_updated_response
# do something wild and craazy
end
end
Reserve the use of create! for contexts where creating the record should not be expected to fail (like in a seed file or non-interactive contexts) or to cause rollbacks inside of a transaction.
I'm adding BaseX to an existing web application and currently writing code to import data into it. The documentation is crystal-clear that
An existing database will be overwritten.
Finding this behavior mindboggingly dangerous, I tried it with the hope that the documentation was wrong but unfortunately my test confirmed it. For instance, using basexclient I can do this:
> create db test
Database 'test' created in 12.03 ms.
> create db test
Database 'test' created in 32.43 ms.
>
I can also replicate this behavior with the Python client, which is I what I'm actually using for my application. Reducing my code to the essentials:
session = BaseXClient.Session("127.0.0.1", 1984, "admin", "admin")
session.create("test", "")
It does not matter whether test exists or not, the whole thing is overwritten if it exists.
How can I work around this dangerous default behavior? I'd would like to prevent the possibility of missteps in production.
You can issue a list command before you create your database. For instance with the command line client if the database does not exist:
> list foo
Database 'foo' was not found.
Whereas if the database exists:
> list test
Input Path Type Content-Type Size
------------------------------------
This is a database that is empty so it does not show any contents but at least you do not get the error message. When you use a client you have to check whether it errors out or not. With the Python client you could do:
def exists(session, db):
try:
session.execute("list " + db)
except IOError as ex:
if ex.message == "Database '{0}' was not found.".format(db):
return False
raise
return True
The client raises IOError if the server raises an error, which is a very generic way to report a problem. So you have to test the error message to figure out what is going on. We reraise if it happens that the error message is not the one which pertains to our test. This way we don't swallow exceptions caused by unrelated issues.
With that function you could do:
session = BaseXClient.Session("127.0.0.1", 1984, "admin", "admin")
if exists(session, "test"):
raise SomeRelevantException("Oi! You are about to overwrite your database!")
session.create("test", "")
I would like to control and embed my send() calls in a try/except, but I'm not sure of what errors it can produce.
Looking around the SDK, it seems like MailServiceError is the one, but not sure since I don't know how to test an error like that.
Can anyone confirm this?
Here are the exceptions that can be thrown by a call to send(): https://developers.google.com/appengine/docs/python/mail/exceptions
Here's an example of how you could catch these:
from google3.apphosting.api import mail
# other code to create 'message' here
try:
message.send()
except mail.InvalidSender, e:
# Do something special for an invalid sender error
pass
except mail.Error, e:
# This will catch all the other exceptions in the doc above.
pass
I have a CakePHP 2.0 application with a MySQL database. Two database tables are connected with a 1:n relation and a foreign key constraint.
So if I want to delete an entry which is connected in the other database table, I get the error:
Error: SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a forein key constraint fails (...)
SQL Query: DELETE 'Test' FROM 'tests' AS 'Test' WHERE 'Test'.'id' = 10
Notice: If you want to customize this error message, create app/View/Errors/pdo_error.ctp
But what I want to do is to handle the error message! I read something about 'onError' but putting it into the 'AppModel' it seems not to be called (maybe it works only with CakePHP 1.3?):
class Test extends AppModel {
function onError() {
echo "TESTTESTTEST";
$db = ConnectionManager::getDataSource('default');
$err = $db->lastError();
$this->log($err);
$this->log($this->data);
}
}
So what can I do? I want to remain on this page, and I want to show only an error message (not a stack trace and this kind of stuff).
Anyone an idea?
What about using the .ctp?
If you want to customize this error message, create app/View/Errors/pdo_error.ctp
The one that's being used is in the Cake directory, you could just copy that to your app/View/Errors directory and remove the stack trace from that if you like.
There's also the beforeDelete() Model callback function you could use to set a flashMessage.
Data base error normally give 500 error so cakephp handle 500 exception by using
View/Errors/error500.ctp or app/View/Errors/pdo_error.ctp only and customize this page
and add this function bellow in AppController.php
function beforeRender() {
if($this->name == 'CakeError') {
$this->set('title','Internal error occurs');
$this->layout = 'frontend';
}
}
I have a Django app that gets it's data completely from an external source (queried via HTTP). That is, I don't have the option for a local database. Session data is stored in the cache (on my development server I use a SQLite database, so that is no error source). I'm using bleeding edge Django 1.1svn.
Enter the problem: I want to use Django's own authentication system for the users.
It seems quite simple to write my own Authentication Backend, but always just under the condition that you have a local database where to save the users. Without database my main problem is persistence.
I tried it with the following (assume that datasource.get() is a function that returns some kind of dict):
class ModelBackend (object):
"""Login backend."""
def authenticate (self, username=None, password=None):
"""Check, if a given user/password combination is valid"""
data = datasource.get ('login', username, password)
if data and data['ok']:
return MyUser (username=username)
else:
raise TypeError
return None
def get_user (self, username):
"""get data about a specific user"""
try:
data = datasource.get ('userdata', username)
if data and data['ok']:
return data.user
except:
pass
return None
class MyUser (User):
"""Django user who isn't saved in DB"""
def save (self):
return None
But the intentionally missing save() method on MyUser seems to break the session storage of a login.
How should MyUser look like without a local database?
OK, it's much more complicated than I thought. First, start with http://docs.djangoproject.com/en/dev/howto/auth-remote-user/, but you'll need to extend it with your own backend and user.
from django.contrib.auth.backends import RemoteUserBackend
class MyRemoteUserBackend (RemoteUserBackend):
# Create a User object if not already in the database?
create_unknown_user = False
def get_user (self, user_id):
user = somehow_create_an_instance_of (MyUser, user_id)
return user
def authenticate (self, **credentials):
check_credentials ()
user = somehow_create_an_instance_of (MyUser, credentials)
return user
Then the user:
from django.contrib.auth.models import User
class MyUser (User):
def save (self):
"""saving to DB disabled"""
pass
objects = None # we cannot really use this w/o local DB
username = "" # and all the other properties likewise.
# They're defined as model.CharField or similar,
# and we can't allow that
def get_group_permissions (self):
"""If you don't make your own permissions module,
the default also will use the DB. Throw it away"""
return [] # likewise with the other permission defs
def get_and_delete_messages (self):
"""Messages are stored in the DB. Darn!"""
return []
Phew! Django really isn't designed for usage without a database...
Rather than overwriting the save method, you may also disconnect the signal that invokes it. This is what I do in some apps which have read-only access to the user database.
# models.py (for instance)
from django.contrib.auth.models import update_last_login, user_logged_in
user_logged_in.disconnect(update_last_login)
grepping the source showed, that the only place user.save() is actually called (except for user creation and password management code, which you don't need to use at all) is django.contrib.auth.login(), to update user.last_login value.
# TODO: It would be nice to support different login methods, like signed cookies.
user.last_login = datetime.datetime.now()
user.save()
If you don't want user data to rest in DB, try adding dummy save() method. If I'm right, it should work.
def save(self, *args, **kwargs):
pass
Of course, because you have no persistence at all, you should consider caching datasource.get results, otherwise in worst case you may end up querying data again and again on every single logged in user's hit.