Problem writing bool converter in ponyorm - python

My database stores bool values as CHAR(1), T=True, F=False. I'm trying to write a converter so that I can use bool values in my python code and have pony handle the conversion to the database.
Here's what I have:
from pony import orm
from pony.orm.dbapiprovider import BoolConverter
class DALBoolConverter(BoolConverter):
def validate(self, val, obj=None):
print 'VALIDATOR', val, obj
return val
def py2sql(self, val):
print 'py2sql', val
return 'T' if val else 'F'
def sql2py(self, val):
print 'sql2py', val
return True if val == 'T' else False
def sql_type(self):
print 'sql_type'
return 'CHAR(1)'
db.provider.converter_classes.append((bool, DALBoolConverter))
class AuthUser(db.Entity):
_table_ = 'auth_user'
first_name = orm.Required(str)
last_name = orm.Required(str)
email = orm.Optional(str)
password = orm.Optional(str)
registration_key = orm.Optional(str)
reset_password_key = orm.Optional(str)
registration_id = orm.Optional(str)
active = orm.Required(bool)
if __name__ == '__main__':
with db_session:
a = AuthUser[1]
print a.active # returns True
a.active = False
You can see I have some print statements in there but they are never executed. I'm getting the following traceback:
Traceback (most recent call last):
File "/home/jim/dev/qlf/qlf/pony_model.py", line 720, in <module>
"""
File "/home/jim/.local/lib/python2.7/site-packages/pony/orm/core.py", line 476, in __exit__
db_session._commit_or_rollback(exc_type, exc, tb)
File "/home/jim/.local/lib/python2.7/site-packages/pony/orm/core.py", line 490, in _commit_or_rollback
commit()
File "/home/jim/.local/lib/python2.7/site-packages/pony/orm/core.py", line 381, in commit
rollback_and_reraise(sys.exc_info())
File "/home/jim/.local/lib/python2.7/site-packages/pony/orm/core.py", line 370, in rollback_and_reraise
reraise(*exc_info)
File "/home/jim/.local/lib/python2.7/site-packages/pony/orm/core.py", line 379, in commit
cache.flush()
File "/home/jim/.local/lib/python2.7/site-packages/pony/orm/core.py", line 1888, in flush
if obj is not None: obj._save_()
File "/home/jim/.local/lib/python2.7/site-packages/pony/orm/core.py", line 5363, in _save_
elif status == 'modified': obj._save_updated_()
File "/home/jim/.local/lib/python2.7/site-packages/pony/orm/core.py", line 5272, in _save_updated_
cursor = database._exec_sql(sql, arguments, start_transaction=True)
File "/home/jim/.local/lib/python2.7/site-packages/pony/orm/core.py", line 945, in _exec_sql
connection = cache.reconnect(e)
File "/home/jim/.local/lib/python2.7/site-packages/pony/orm/core.py", line 1776, in reconnect
if not provider.should_reconnect(exc): reraise(*sys.exc_info())
File "/home/jim/.local/lib/python2.7/site-packages/pony/orm/core.py", line 943, in _exec_sql
try: new_id = provider.execute(cursor, sql, arguments, returning_id)
File "<auto generated wrapper of execute() function>", line 2, in execute
File "/home/jim/.local/lib/python2.7/site-packages/pony/orm/dbapiprovider.py", line 61, in wrap_dbapi_exceptions
raise OperationalError(e)
pony.orm.dbapiprovider.OperationalError: (1292, "Truncated incorrect DOUBLE value: 'T '")
...which probably makes sense because I don't think my DALBoolConverter is ever getting called.
Any pointers?

Easiest way to achieve your goal is to use hybrid methods.
So you do
class AuthUser(db.Entity):
_table_ = 'auth_user'
first_name = orm.Required(str)
last_name = orm.Required(str)
email = orm.Optional(str)
password = orm.Optional(str)
registration_key = orm.Optional(str)
reset_password_key = orm.Optional(str)
registration_id = orm.Optional(str)
active = orm.Required(str) # use str here
#property
def is_active(self):
return self.active == 'T'
Then you might use
with db_session:
a = AuthUser[1]
print a.is_active

Related

Error when indexing data using elasticsearch dsl

I have two models which are as follows:
class PostUser(models.Model):
user_id = models.CharField(max_length=1000,blank=True,null=True)
reputation = models.CharField(max_length = 1000 , blank = True , null = True)
def __unicode__(self):
return self.user_id
def indexing(self):
obj = PostUserIndex(
meta = {'id': self.id},
user_id = self.user_id,
reputation = self.reputation,
)
obj.save(index = 'post-user-index')
return obj.to_dict(include_meta=True)
class Posts(models.Model):
user_post_id = models.CharField(max_length = 1000 , blank = True , null = True)
score = models.CharField(max_length = 1000 , blank = True , null = True)
owner_user_id = models.ForeignKey(PostUser,default="-100")
def __unicode__(self):
return self.user_post_id
def indexing(self):
obj = PostsIndex(
meta = {'id': self.id},
user_post_id = self.user_post_id,
score = self.score,
owner_user_id = self.owner_user_id,
)
obj.save(index = 'newuserposts-index')
return obj.to_dict(include_meta=True)
The way I am trying to index my data is as follows:
class PostUserIndex(DocType):
user_id = Text()
reputation = Text()
class PostsIndex(DocType):
user_post_id = Text()
score = Text()
owner_user_id = Nested(PostUserIndex)
Then i try to run the following method to index data:
def posts_indexing():
PostsIndex.init(index='newuserposts-index')
es = Elasticsearch()
bulk(client=es, actions=(b.indexing() for b in models.Posts.objects.all().iterator()))
I have tried different approaches by manually entering the nested properties and also changing from doctype to inner doc of PostUser but still I am getting the weird error.
ERROR:
AttributeError: 'PostUser' object has no attribute 'copy'
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/Users/ammarkhan/Desktop/danny/src/dataquerying/datatoindex.py", line 74, in new_user_posts_indexing
bulk(client=es, actions=(b.indexing() for b in models.Posts.objects.all().iterator()))
File "/Users/ammarkhan/Desktop/danny/lib/python2.7/site-packages/elasticsearch/helpers/__init__.py", line 257, in bulk
for ok, item in streaming_bulk(client, actions, **kwargs):
File "/Users/ammarkhan/Desktop/danny/lib/python2.7/site-packages/elasticsearch/helpers/__init__.py", line 180, in streaming_bulk
client.transport.serializer):
File "/Users/ammarkhan/Desktop/danny/lib/python2.7/site-packages/elasticsearch/helpers/__init__.py", line 58, in _chunk_actions
for action, data in actions:
File "/Users/ammarkhan/Desktop/danny/src/dataquerying/datatoindex.py", line 74, in <genexpr>
bulk(client=es, actions=(b.indexing() for b in models.Posts.objects.all().iterator()))
File "/Users/ammarkhan/Desktop/danny/src/dataquerying/models.py", line 167, in indexing
obj.save(index = 'newuserposts-index')
File "/Users/ammarkhan/Desktop/danny/lib/python2.7/site-packages/elasticsearch_dsl/document.py", line 405, in save
self.full_clean()
File "/Users/ammarkhan/Desktop/danny/lib/python2.7/site-packages/elasticsearch_dsl/utils.py", line 417, in full_clean
self.clean_fields()
File "/Users/ammarkhan/Desktop/danny/lib/python2.7/site-packages/elasticsearch_dsl/utils.py", line 403, in clean_fields
data = field.clean(data)
File "/Users/ammarkhan/Desktop/danny/lib/python2.7/site-packages/elasticsearch_dsl/field.py", line 179, in clean
data = super(Object, self).clean(data)
File "/Users/ammarkhan/Desktop/danny/lib/python2.7/site-packages/elasticsearch_dsl/field.py", line 90, in clean
data = self.deserialize(data)
File "/Users/ammarkhan/Desktop/danny/lib/python2.7/site-packages/elasticsearch_dsl/field.py", line 86, in deserialize
return self._deserialize(data)
File "/Users/ammarkhan/Desktop/danny/lib/python2.7/site-packages/elasticsearch_dsl/field.py", line 166, in _deserialize
return self._wrap(data)
File "/Users/ammarkhan/Desktop/danny/lib/python2.7/site-packages/elasticsearch_dsl/field.py", line 142, in _wrap
return self._doc_class.from_es(data)
File "/Users/ammarkhan/Desktop/danny/lib/python2.7/site-packages/elasticsearch_dsl/utils.py", line 342, in from_es
meta = hit.copy()
AttributeError: ‘PostUser' object has no attribute 'copy'
You are calling .save in your indexing methods which will save the document to elasticsearch and then you are also passing it to bulk to accomplish the same, the save is extra.
You are also assigning an instance of PostUser to owner_user_id instead of properly serializing it by calling the indexing method on it (without the save inside):
def indexing(self):
obj = PostsIndex(
meta = {'id': self.id, 'index': 'newuserposts-index'},
user_post_id = self.user_post_id,
score = self.score,
owner_user_id = self.owner_user_id.indexing(),
)
return obj.to_dict(include_meta=True)

I got this "ValueError: invalid literal for int() with base 10" in my Django project [duplicate]

This question already has answers here:
ValueError: invalid literal for int() with base 10: ''
(15 answers)
Closed 5 years ago.
model in my application:
from __future__ import unicode_literals
from django.db import models
class Category(models.Model):
name = models.CharField(max_length = 128, unique = True)
def __unicode__(self):
return self.name
class ModelName(models.Model):
name = models.CharField(max_length = 128, unique = True)
def __unicode__(self):
return self.name
class CarStorage(models.Model):
category = models.ForeignKey(Category)
CarID = models.CharField(max_length = 10, unique = True, null = False)
model = models.ForeignKey(ModelName)
storage = models.IntegerField(default = 0)
perchasedYear = models.IntegerField(default = 0)
def __unicode__(self):
return self.CarID
Population code:
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE','TKTrading.settings')
import django
django.setup()
from APP.models import Category, ModelName, CarStorage
def populate():
BASE_DIR = '/Users/apple/WebWorkshop/TKTrading/'
DATA_DIR = os.path.join(BASE_DIR, 'APP/Data')
CATEGORY = open(os.path.join(DATA_DIR, 'CATEGORY.txt'),'r')
global CategoryList
CategoryList = []
for line in CATEGORY:
newC = Add_Category(line)
CategoryList.append(newC)
CATEGORY.close
MODELNAME = open(os.path.join(DATA_DIR, 'Model.txt'), 'r')
global ModelList
ModelList = []
for line2 in MODELNAME:
newM = Add_ModelName(line2)
ModelList.append(newM)
MODELNAME.close
CARSTORAGE = open(os.path.join(DATA_DIR, 'CARSTORAGE.txt'), 'r')
for line3 in CARSTORAGE:
print(line3)
c = line3.split(',')
ID = str(c[0])
category = str(c[1])
model = str(c[2])
storage = int(c[3])
year = int(c[4])
Add_CarStorage(ID, category, model, storage, year)
CARSTORAGE.close
def Add_Category(name):
c = Category.objects.get_or_create(name = name)[0]
c.save()
return c
def Add_ModelName(name):
m = ModelName.objects.get_or_create(name = name)[0]
m.save()
return m
def Add_CarStorage(ID, category, model, storage, year):
for CATEGORY in CategoryList:
if CATEGORY.name == category:
category = CATEGORY
for MODEL in ModelList:
if MODEL.name == model:
model = MODEL
car = CarStorage.objects.get_or_create(CarID = ID,
category = category,
model = model,)[0]
car.storage = storage
car.perchasedYear = year
car.save()
return car
if __name__ =='__main__':
print('Starting population...')
populate()
For the population code, I have try two way but got the same message.
One is put all the category and model in a list as object, the other one is using string to create new object directly.
In the end this is the whole message feedback:
Traceback (most recent call last):
File "DBPopulation.py", line 77, in <module>
populate()
File "DBPopulation.py", line 45, in populate
Add_CarStorage(ID, category, model, storage, year)
File "DBPopulation.py", line 69, in Add_CarStorage
model = model,)[0]
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/query.py", line 471, in get_or_create
return self.get(**lookup), False
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/query.py", line 376, in get
clone = self.filter(*args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/query.py", line 794, in filter
return self._filter_or_exclude(False, *args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/query.py", line 812, in _filter_or_exclude
clone.query.add_q(Q(*args, **kwargs))
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1227, in add_q
clause, _ = self._add_q(q_object, self.used_aliases)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1253, in _add_q
allow_joins=allow_joins, split_subq=split_subq,
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1183, in build_filter
condition = lookup_class(lhs, value)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/lookups.py", line 19, in __init__
self.rhs = self.get_prep_lookup()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/fields/related_lookups.py", line 100, in get_prep_lookup
self.rhs = target_field.get_prep_value(self.rhs)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 946, in get_prep_value
return int(value)
ValueError: invalid literal for int() with base 10: 'Wing'
TXT file:
2512-305,Wing,Nissan UD,10,2003
2010-41,Wing,Hino,4,1997
2607-312,Cargo Drop Side,Isuzu,6,2012
2411-341,Cargo Drop Side,Nissan UD,7,2000
2406-326,Tractor,Nissan UD,12,1996
2211-101,Other,Komatsu,1,0
I understand there might have problems like putting string or nothing in the integer field, but I have reread many time and still not figure out.
The problem is with your Add_CarStorage function.
when
if MODEL.name == model:
is true you are replacing string model with MODEL which is a ModelName instance but when the condition is false you are not updating the variable model with anything. A quick fix would be to use get_or_create call only when the condition is true.

Cannot pass the form data to a method in order to validate form

I'm trying to create a custom validator for one field in the AddSongForm. I used the inline validator and it uses two methods from my Songs class. When I try running the code, I get the following trace back:
form = AddSongForm()
[2017-05-16 13:44:11,547] ERROR in app: Exception on /addsong [POST]
Traceback (most recent call last):
File "C:\Python36-32\lib\site-packages\flask\app.py", line 1982, in wsgi_app
response = self.full_dispatch_request()
File "C:\Python36-32\lib\site-packages\flask\app.py", line 1614, in full_dispatch_request
rv = self.handle_user_exception(e)
File "C:\Python36-32\lib\site-packages\flask\app.py", line 1517, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "C:\Python36-32\lib\site-packages\flask\_compat.py", line 33, in reraise
raise value
File "C:\Python36-32\lib\site-packages\flask\app.py", line 1612, in full_dispatch_request
rv = self.dispatch_request()
File "C:\Python36-32\lib\site-packages\flask\app.py", line 1598, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "C:\Python36-32\lib\site-packages\flask_login\utils.py", line 228, in decorated_view
return func(*args, **kwargs)
File "C:/Users/Pellissari/Desktop/files/projects/Musical 9gag/view.py", line 40, in addsong
if form.validate_on_submit():
File "C:\Python36-32\lib\site-packages\flask_wtf\form.py", line 101, in validate_on_submit
return self.is_submitted() and self.validate()
File "C:\Python36-32\lib\site-packages\wtforms\form.py", line 310, in validate
return super(Form, self).validate(extra)
File "C:\Python36-32\lib\site-packages\wtforms\form.py", line 152, in validate
if not field.validate(self, extra):
File "C:\Python36-32\lib\site-packages\wtforms\fields\core.py", line 204, in validate
stop_validation = self._run_validation_chain(form, chain)
File "C:\Python36-32\lib\site-packages\wtforms\fields\core.py", line 224, in _run_validation_chain
validator(form, self)
File "C:\Users\Pellissari\Desktop\files\projects\app\forms.py", line 20, in validate_song_link
if Songs.get_provider(url) in valid_providers:
TypeError: get_provider() missing 1 required positional argument: 'url'
127.0.0.1 - - [16/May/2017 13:44:11] "POST /addsong HTTP/1.1" 500 -
This is my form class
class AddSongForm(Form):
song_title = StringField('song_title', validators=[DataRequired()])
song_artist = StringField('song_artist', validators=[DataRequired()])
song_genre = StringField('song_genre')
song_link = StringField('song_link', validators=[DataRequired()])
def validate_song_link(form, song_link):
valid_providers = ['youtube.com', 'www.youtube.com', 'soundcloud.com', 'www.soundcloud.com']
url = song_link.data
if Songs.get_provider(url) in valid_providers:
if Songs.get_embed_code(url) is not False:
return True
else:
print("couldn't get your content")
return False
else:
print("unsupported provider")
return False
And here is the class I used the methods
class Songs(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
title = db.Column(db.String(50))
artist = db.Column(db.String(30))
genre = db.Column(db.String(40))
author = db.Column(db.String(40))
timestamp = db.Column(db.DateTime)
likes_num = db.Column(db.Integer)
song_link = db.Column(db.String(120))
def get_provider(self, url):
return urllib.parse.urlsplit(url)[1]
def get_embed_code(self, url):
code = None
vars = {'url': url, 'format': 'json', 'iframe': 'true', 'maxwidth': '450', 'show_comments': 'false'}
provider = self.get_provider(url)
endpoint = "http://"+provider+"/oembed?"
source = endpoint+urllib.parse.urlencode(vars)
try:
request = urlopen(source)
code = json.load(request)['html']
return code
except:
print("impossible to get your content. Check the link")
return False
I'm quite new with Python and this is my first time writing OO code, so I have no idea what could be happening here. Besides the problem, I would be happy if you also could give me some feedback on the code and if there are room to improve in some sense.
I'm not convinced these should be methods on Songs. They don't refer to anything to do with the Song class.
However if you want to keep them as methods, but still want to call them from the class, they need to be classmethods, not instance methods.
#classmethod
def get_provider(cls, url):
return urllib.parse.urlsplit(url)[1]
#classmethod
def get_embed_code(cls, url):
...
provider = cls.get_provider(url)
First of all correct the indentation for the method validate_song_link. It should be like this:
def validate_song_link(form, song_link):
valid_providers = ['youtube.com', 'www.youtube.com', 'soundcloud.com', 'www.soundcloud.com']
url = song_link.data
if Songs.get_provider(url) in valid_providers:
if Songs.get_embed_code(url) is not False:
return True
else:
print("couldn't get your content")
return False
else:
print("unsupported provider")
return False
To solve your problem you can try to change the get_provider method to a class method like this:
#classmethod
def get_provider(cls, url):
return urllib.parse.urlsplit(url)[1]
And then you can call this way:
songs = Songs()
if Songs.get_provider(songs, url) in valid_providers:
if Songs.get_embed_code(url) is not False:
return True

ValueError: Attribute Users.request is required

I need help again. Can anybody tell my why I get this error? I use Flask and pony orm and python 3.4. I have few files.
users.py
from app import models
from pony.orm import *
class UsersAPI:
#staticmethod
#db_session
def is_registered(e_mail):
"""
This method for checking registered user or not
:param e_mail:
:return:
"""
user = select(o for o in models.Users if o.email == e_mail)[:]
print(user)
UsersAPI.is_registered("evgenusov96#yandex.ru")
File models.py
from pony.orm import *
import config
db = Database()
class Users(db.Entity):
id = PrimaryKey(int, auto=True)
email = Required(str, 100)
password = Required(str, 32)
name = Required(str, 15)
surname = Required(str, 20)
city = Required(City, nullable=True)
sex = Required(int)
request = Required(str, 250, nullable=True)
hobby = Required(str, 250, nullable=True)
about = Required(str, 250, nullable=True)
status_message = Required(str, 100, nullable=True)
user1 = Set("Friends", reverse="user1")
user2 = Set("Friends", reverse="user2")
author = Set("Messages", reverse="author")
addressee = Set("Messages", reverse="addressee")
This error I got:
C:\Python34\python.exe C:/Users/Евгений/PycharmProjects/langunet/run.py
Traceback (most recent call last):
File "C:/Users/Евгений/PycharmProjects/langunet/run.py", line 2, in <module>
from app import app
File "C:\Users\Евгений\PycharmProjects\langunet\app\__init__.py", line 4, in <module>
from app import routes
File "C:\Users\Евгений\PycharmProjects\langunet\app\routes.py", line 2, in <module>
from app.users import *
File "C:\Users\Евгений\PycharmProjects\langunet\app\users.py", line 21, in <module>
UsersAPI.is_registered("evgenusov96#yandex.ru")
File "<string>", line 2, in is_registered
File "C:\Python34\lib\site-packages\pony\orm\core.py", line 347, in new_func
try: return func(*args, **kwargs)
File "C:\Users\Евгений\PycharmProjects\langunet\app\users.py", line 18, in is_registered
user = get(o for o in models.Users if o.email == e_mail)
File "<string>", line 2, in get
File "C:\Python34\lib\site-packages\pony\utils.py", line 88, in cut_traceback
return func(*args, **kwargs)
File "C:\Python34\lib\site-packages\pony\orm\core.py", line 4260, in get
return make_query(args, frame_depth=3).get()
File "<string>", line 2, in get
File "C:\Python34\lib\site-packages\pony\utils.py", line 88, in cut_traceback
return func(*args, **kwargs)
File "C:\Python34\lib\site-packages\pony\orm\core.py", line 4531, in get
objects = query[:2]
File "<string>", line 2, in __getitem__
File "C:\Python34\lib\site-packages\pony\utils.py", line 88, in cut_traceback
return func(*args, **kwargs)
File "C:\Python34\lib\site-packages\pony\orm\core.py", line 4721, in __getitem__
return query._fetch(range=(start, stop))
File "C:\Python34\lib\site-packages\pony\orm\core.py", line 4426, in _fetch
used_attrs=translator.get_used_attrs())
File "C:\Python34\lib\site-packages\pony\orm\core.py", line 3228, in _fetch_objects
real_entity_subclass, pkval, avdict = entity._parse_row_(row, attr_offsets)
File "C:\Python34\lib\site-packages\pony\orm\core.py", line 3258, in _parse_row_
avdict[attr] = attr.parse_value(row, offsets)
File "C:\Python34\lib\site-packages\pony\orm\core.py", line 1329, in parse_value
val = attr.validate(row[offset], None, attr.entity, from_db=True)
File "C:\Python34\lib\site-packages\pony\orm\core.py", line 1611, in validate
if obj is None: throw(ValueError, 'Attribute %s is required' % attr)
File "C:\Python34\lib\site-packages\pony\utils.py", line 126, in throw
raise exc
ValueError: Attribute Users.request is required
How this may to fix? Thank you!
This error can happen if you defined User.request attribute as Required, but in the table the corresponding column is actually optional (that is, nullable). During loading of an object, Pony checks if the object's internal state is consistent. Since the value of a required attribute is missed, Pony generates an exception.
I think that we need to improve Pony behavior in one of two ways here:
Even if an attribute is required, Pony should allow loading of null values for this attribute from the database.
Another alternative is to make error message more clear.

Getting results from query with alchimia library

Im trying to use alchimia for get asynchronous API for DB. Trying to make a simple request to DB, like that:
def authorization(self, data):
"""
Checking user with DB
"""
def __gotResult(user):
yield engine.execute(sqlalchemy.select([Users]).where(Users.name == user))
result = __gotResult(data['user'])
log.msg("[AUTH] User=%s trying to auth..." % data['user'])
data, result_msg = commands.AUTH(result, data)
log.msg(result_msg)
return data
And cant understand - what i doing wrong? Maybe issue in option for engine (where reactor=[])?
Source code:
import sys
from json import dumps, loads
import sqlalchemy
from twisted.internet import reactor, ssl
from twisted.python import log, logfile
from twisted.web.server import Site
from twisted.web.static import File
from autobahn.twisted.websocket import WebSocketServerFactory, WebSocketServerProtocol, listenWS
import commands
from db.tables import Users
from alchimia import TWISTED_STRATEGY
log_file = logfile.LogFile("service.log", ".")
log.startLogging(log_file)
engine = sqlalchemy.create_engine('postgresql://test:test#localhost/testdb', pool_size=20, max_overflow=0,strategy=TWISTED_STRATEGY, reactor=[])
class DFSServerProtocol(WebSocketServerProtocol):
commands = commands.commands_user
def __init__(self):
self.commands_handlers = self.__initHandlersUser()
def __initHandlersUser(self):
handlers = commands.commands_handlers_server
handlers['AUTH'] = self.authorization
handlers['READ'] = None
handlers['WRTE'] = None
handlers['DELT'] = None
handlers['RNME'] = None
handlers['SYNC'] = None
handlers['LIST'] = None
return handlers
def authorization(self, data):
"""
Checking user with DB
"""
def __gotResult(user):
yield engine.execute(sqlalchemy.select([Users]).where(Users.name == data['user']))
result = __gotResult(data['user'])
log.msg("[AUTH] User=%s trying to auth..." % data['user'])
data, result_msg = commands.AUTH(result, data)
log.msg(result_msg)
return data
def onMessage(self, payload, isBinary):
json_data = loads(payload)
json_auth = json_data['auth']
json_cmd = json_data['cmd']
if json_auth == False:
if json_cmd == 'AUTH':
json_data = self.commands_handlers['AUTH'](json_data)
# for authorized users
else:
if json_cmd in commands.commands_user.keys():
if self.commands_handlers[json_cmd] is not None:
json_data = self.commands_handlers[json_cmd](json_data)
else:
json_data['error'] = '%s command is not already realized...' % json_cmd
else:
json_data['auth'] = False
json_data['error'] = 'This command is not supported on server...'
response = dumps(json_data)
self.sendMessage(str(response))
if __name__ == '__main__':
if len(sys.argv) > 1 and sys.argv[1] == 'debug':
log.startLogging(sys.stdout)
debug = True
else:
debug = False
contextFactory = ssl.DefaultOpenSSLContextFactory('keys/server.key', 'keys/server.crt')
factory = WebSocketServerFactory("wss://localhost:9000", debug = debug, debugCodePaths = debug)
factory.protocol = DFSServerProtocol
factory.setProtocolOptions(allowHixie76 = True)
listenWS(factory, contextFactory)
webdir = File("./web/")
webdir.contentTypes['.crt'] = 'application/x-x509-ca-cert'
web = Site(webdir)
reactor.listenSSL(8080, web, contextFactory)
#reactor.listenTCP(8080, web)
reactor.run()
Traceback:
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/twisted/python/log.py", line 88, in callWithLogger
return callWithContext({"system": lp}, func, *args, **kw)
File "/usr/local/lib/python2.7/dist-packages/twisted/python/log.py", line 73, in callWithContext
return context.call({ILogContext: newCtx}, func, *args, **kw)
File "/usr/local/lib/python2.7/dist-packages/twisted/python/context.py", line 118, in callWithContext
return self.currentContext().callWithContext(ctx, func, *args, **kw)
File "/usr/local/lib/python2.7/dist-packages/twisted/python/context.py", line 81, in callWithContext
return func(*args,**kw)
--- <exception caught here> ---
File "/usr/local/lib/python2.7/dist-packages/twisted/internet/posixbase.py", line 614, in _doReadOrWrite
why = selectable.doRead()
File "/usr/local/lib/python2.7/dist-packages/twisted/internet/tcp.py", line 215, in doRead
return self._dataReceived(data)
File "/usr/local/lib/python2.7/dist-packages/twisted/internet/tcp.py", line 221, in _dataReceived
rval = self.protocol.dataReceived(data)
File "/usr/local/lib/python2.7/dist-packages/twisted/protocols/tls.py", line 419, in dataReceived
self._flushReceiveBIO()
File "/usr/local/lib/python2.7/dist-packages/twisted/protocols/tls.py", line 389, in _flushReceiveBIO
ProtocolWrapper.dataReceived(self, bytes)
File "/usr/local/lib/python2.7/dist-packages/twisted/protocols/policies.py", line 120, in dataReceived
self.wrappedProtocol.dataReceived(data)
File "/usr/local/lib/python2.7/dist-packages/autobahn/twisted/websocket.py", line 78, in dataReceived
self._dataReceived(data)
File "/usr/local/lib/python2.7/dist-packages/autobahn/websocket/protocol.py", line 1270, in _dataReceived
self.consumeData()
File "/usr/local/lib/python2.7/dist-packages/autobahn/websocket/protocol.py", line 1286, in consumeData
while self.processData() and self.state != WebSocketProtocol.STATE_CLOSED:
File "/usr/local/lib/python2.7/dist-packages/autobahn/websocket/protocol.py", line 1445, in processData
return self.processDataHybi()
File "/usr/local/lib/python2.7/dist-packages/autobahn/websocket/protocol.py", line 1758, in processDataHybi
fr = self.onFrameEnd()
File "/usr/local/lib/python2.7/dist-packages/autobahn/websocket/protocol.py", line 1887, in onFrameEnd
self._onMessageEnd()
File "/usr/local/lib/python2.7/dist-packages/autobahn/twisted/websocket.py", line 107, in _onMessageEnd
self.onMessageEnd()
File "/usr/local/lib/python2.7/dist-packages/autobahn/websocket/protocol.py", line 734, in onMessageEnd
self._onMessage(payload, self.message_is_binary)
File "/usr/local/lib/python2.7/dist-packages/autobahn/twisted/websocket.py", line 110, in _onMessage
self.onMessage(payload, isBinary)
File "server.py", line 84, in onMessage
json_data = self.commands_handlers['AUTH'](json_data)
File "server.py", line 68, in authorization
data, result_msg = commands.AUTH(result, data)
File "/home/relrin/code/Helenae/helenae/commands.py", line 68, in AUTH
if result['name'] == data['user']:
exceptions.TypeError: 'generator' object has no attribute '__getitem__'
I think you are missing an #inlineCallbacks around __gotResult() That might not help you quite enough, though; since a single statement generator wrapped with inlineCallbacks is sort of pointless. You should get used to working with explicit deferred handling anyway. Lets pull this apart:
def authorization(self, data):
"""
Checking user with DB
"""
# engine.execute already gives us a deferred, will grab on to that.
user = data['user']
result_d = engine.execute(sqlalchemy.select([Users]).where(Users.name == user))
# we don't have the result in authorization,
# we need to wrap any code that works with its result int a callback.
def result_cb(result):
data, result_msg = commands.AUTH(result, data)
return data
result_d.addCallback(result_cb)
# we want to pass the (asynchronous) result out, it's hiding in our deferred;
# so we return *that* instead; callers need to add more callbacks to it.
return result_d
If you insist; we can squish this down into an inline callbacks form:
from twisted.internet.defer import inlineCallbacks, returnValue
#inlineCallbacks
def authorization(self, data):
user = data['user']
result = yield engine.execute(sqlalchemy.select([Users]).where(Users.name == user))
data, result_msg = commands.AUTH(result, data)
yield returnValue(data)
as before, though, authorization() is asynchronous; and must be since engine.execute is async. to use it, you must attach a callback to the deferred it returns (although the caller may also yield it if it is also wrapped in inlineCallbacks

Categories

Resources