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

AssertionError #133

Closed
nadermx opened this issue Jul 3, 2015 · 2 comments
Closed

AssertionError #133

nadermx opened this issue Jul 3, 2015 · 2 comments
Assignees
Labels
Milestone

Comments

@nadermx
Copy link

nadermx commented Jul 3, 2015

I am trying to do what I thought was a simple user sign in. Here is my route, models, and the error it is spitting out when I'm trying to log in as the user.

@app.route('/login', methods=['GET', 'POST'])
@pny.db_session
def login():
    form = LoginForm(request.form)
    print request.environ['REMOTE_ADDR']
    if request.method == 'POST' and form.validate():
        username = form.username.data
        password = form.password.data
        user = User.get(username=username)
        if not user or not user.verify_password(password):
            return "Wrong username or password"
        remote_address = request.environ['REMOTE_ADDR']
        ip_address = IP_Address.get(address=remote_address)
        if ip_address is None:
            ip_address = IP_Address(address=remote_address)
        user.ips.create(ip_address=ip_address, date_used=datetime.now())
        return 'loged in'
    return render_template('login.html', form=form)

Here is the models

from datetime import datetime
from pony.orm import *
from app import app, db
from passlib.apps import custom_app_context as pwd_context

class User(db.Entity):
    username = Required(unicode, 20, unique=True)
    email = Required(unicode, 255, unique=True)
    password_hash = Optional(unicode, 255)
    main = Optional("User", reverse="alts")
    alts = Set("User", reverse="main")
    roles = Set("Role")
    permissions = Set("Permission")
    profile = Optional("UserProfile")
    is_confirmed = Required(bool, default=0)
    is_active = Required(bool, default=0)
    is_main = Required(bool, default=0)
    confirmed_at = Required(datetime, default=lambda: datetime.now())
    last_login = Required(datetime, default=lambda: datetime.now())
    current_login = Required(datetime, default=lambda: datetime.now())
    ips = Set("User_IP")
    favorites = Optional("Favorite")
    upvotes = Optional("Game_Upvotes")

    def hash_password(self, password):
        self.password_hash = pwd_context.encrypt(password)

    def verify_password(self, password):
        return pwd_context.verify(password, self.password_hash)

    def is_authenticated(self):
        return True

    def is_active(self):
        return True

    def is_anonymous(self):
        return False

    def get_id(self):
        try:
            return unicode(self.id)  # python 2
        except NameError:
            return str(self.id)  # python 3

    def __repr__(self):
        return '<User %r>' % (self.username)

class Game(db.Entity):
    game_name = Required(unicode, 255)
    game_swf = Required(unicode, 255)
    game_thumb = Required(unicode, 255)
    game_category = Required(unicode, 255)
    game_name_es = Required(unicode, 255)
    game_name_pt = Required(unicode, 255)
    game_name_fr = Required(unicode, 255)
    favorites = Optional("Favorite")
    votes = Optional(int, default=1)
    votes_up = Optional("Game_Upvotes")

class Favorite(db.Entity):
    game = Required(Game)
    user = Required(User)
    date_favorited = Required(datetime)
    PrimaryKey(user, game)

class Game_Upvotes(db.Entity):
    game = Required(Game)
    user = Required(User)
    PrimaryKey(game, user)

class Role(db.Entity):
    id = PrimaryKey(int)
    name = Required(unicode, 60, unique=True, lazy=False)
    description = Required(unicode, 255)
    users = Set(User)


class IP_Address(db.Entity):
    address = Required(unicode, 45, default='127.0.0.1')
    users = Set("User_IP")


class Permission(db.Entity):
    name = Required(unicode, 60, unique=True)
    applies_to = Required(unicode, 60)
    description = Required(unicode, 255)
    users = Set(User)


class User_IP(db.Entity):
    user = Required(User)
    ip_address = Required(IP_Address)
    date_used = Required(datetime)
    PrimaryKey(user, ip_address)


class UserProfile(db.Entity):
    user = Required(User)
    age = Optional(int)
    gender = Optional(int, default=0)
    bio = Optional(LongUnicode)



sql_debug(True)
db.generate_mapping(create_tables=True)

And lastly here is the error I get spit out

    File "/home/john/.virtualenvs/juegoapi/lib/python2.7/site-packages/flask/app.py", line 1836, in __call__

    return self.wsgi_app(environ, start_response)

    File "/home/john/.virtualenvs/juegoapi/lib/python2.7/site-packages/flask/app.py", line 1820, in wsgi_app

    response = self.make_response(self.handle_exception(e))

    File "/home/john/.virtualenvs/juegoapi/lib/python2.7/site-packages/flask/app.py", line 1403, in handle_exception

    reraise(exc_type, exc_value, tb)

    File "/home/john/.virtualenvs/juegoapi/lib/python2.7/site-packages/flask/app.py", line 1817, in wsgi_app

    response = self.full_dispatch_request()

    File "/home/john/.virtualenvs/juegoapi/lib/python2.7/site-packages/flask/app.py", line 1477, in full_dispatch_request

    rv = self.handle_user_exception(e)

    File "/home/john/.virtualenvs/juegoapi/lib/python2.7/site-packages/flask/app.py", line 1381, in handle_user_exception

    reraise(exc_type, exc_value, tb)

    File "/home/john/.virtualenvs/juegoapi/lib/python2.7/site-packages/flask/app.py", line 1475, in full_dispatch_request

    rv = self.dispatch_request()

    File "/home/john/.virtualenvs/juegoapi/lib/python2.7/site-packages/flask/app.py", line 1461, in dispatch_request

    return self.view_functions[rule.endpoint](**req.view_args)

    File "<auto generated wrapper of login() function>", line 2, in login

    File "/home/john/.virtualenvs/juegoapi/lib/python2.7/site-packages/pony/orm/core.py", line 347, in new_func

    try: return func(*args, **kwargs)

    File "/home/john/Scripts/Python/games/views.py", line 76, in login

    user.ips.create(ip_address=ip_address, date_used=datetime.now())

    File "<auto generated wrapper of create() function>", line 2, in create

    File "/home/john/.virtualenvs/juegoapi/lib/python2.7/site-packages/pony/utils.py", line 88, in cut_traceback

    return func(*args, **kwargs)

    File "/home/john/.virtualenvs/juegoapi/lib/python2.7/site-packages/pony/orm/core.py", line 2431, in create

    wrapper.add(item)

    File "<auto generated wrapper of add() function>", line 2, in add

    File "/home/john/.virtualenvs/juegoapi/lib/python2.7/site-packages/pony/utils.py", line 88, in cut_traceback

    return func(*args, **kwargs)

    File "/home/john/.virtualenvs/juegoapi/lib/python2.7/site-packages/pony/orm/core.py", line 2449, in add

    setdata = attr.load(obj, new_items)

    File "/home/john/.virtualenvs/juegoapi/lib/python2.7/site-packages/pony/orm/core.py", line 1948, in load

    items = rentity._fetch_objects(cursor, attr_offsets)

    File "/home/john/.virtualenvs/juegoapi/lib/python2.7/site-packages/pony/orm/core.py", line 3231, in _fetch_objects

    obj._db_set_(avdict)

    File "/home/john/.virtualenvs/juegoapi/lib/python2.7/site-packages/pony/orm/core.py", line 3713, in _db_set_

    assert obj._status_ not in created_or_deleted_statuses

    AssertionError

@kozlovsky
Copy link
Member

Thanks for the reporting! We need to fix it.
Instead of AssertionError Pony should raise IntegrityError "the instance of User_IP with specified values of User and IP_Address already exists"

In order to fix the error you need to replace the line

        user.ips.create(ip_address=ip_address, date_used=datetime.now())

to the following code:

        user_ip = User_IP.get(user=user, ip_address=ip_address)
        if user_ip is None:
            user_ip = User_IP(user=user, ip_address=ip_address, date_used=datetime.now())
            user.ips.add(user_ip)
        else:
            user_ip.date_used = datetime.now()

This version of code assumes that you want to keep only the last date_used value for each pair of (user, ip_adress). If want to keep all dates when the user visited the specific ip address, then you need to change primary key of User_IP object. Just remove the PrimaryKey description from the entity definition, and Pony will use autogenerated integer primary key attribute with the name id. In that case your previous line user.ips.create(...) should work fine, because each time you will create new User_IP instance.

Probably we need to add create_or_update method for simplifying the code in situations where an object may already exist.

@nadermx
Copy link
Author

nadermx commented Jul 5, 2015

Thanks, worked.

@nadermx nadermx closed this as completed Jul 5, 2015
@p-hash p-hash mentioned this issue Feb 21, 2017
kozlovsky added a commit that referenced this issue Mar 24, 2017
…tead of AssertionError if obj.collection.create(**kwargs) creates duplicate object
@kozlovsky kozlovsky added the bug label Jul 17, 2017
@kozlovsky kozlovsky added this to the 0.7.2 milestone Jul 17, 2017
@kozlovsky kozlovsky self-assigned this Jul 17, 2017
kozlovsky added a commit that referenced this issue Jul 17, 2017
# New features

* All arguments of db.bind() can be specified as keyword arguments. Previously Pony required the first positional argument which specified the database provider. Now you can pass all the database parameters using the dict: db.bind(**db_params). See https://docs.ponyorm.com/api_reference.html#Database.bind
* The `optimistic` attribute option is added https://docs.ponyorm.com/api_reference.html#cmdoption-arg-optimistic

# Bugfixes

* Fixes #219: when a database driver raises an error, sometimes this error was masked by the 'RollbackException: InterfaceError: connection already closed' exception. This happened because on error, Pony tried to rollback transaction, but the connection to the database was already closed and it masked the initial error. Now Pony displays the original error which helps to understand the cause of the problem.
* Fixes #276: Memory leak
* Fixes the __all__ declaration. Previously IDEs, such as PyCharm, could not understand what is going to be imported by 'from pony.orm import *'. Now it works fine.
* Fixes #232: negate check for numeric expressions now checks if value is zero or NULL
* Fixes #238, fixes #133: raise TransactionIntegrityError exception instead of AssertionError if obj.collection.create(**kwargs) creates a duplicate object
* Fixes #221: issue with unicode json path keys
* Fixes bug when discriminator column is used as a part of a primary key
* Handle situation when SQLite blob column contains non-binary value
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants