/kai/model/traceback.py

https://bitbucket.org/bbangert/kai/ · Python · 130 lines · 108 code · 18 blank · 4 comment · 20 complexity · f70a73e0d3fe21785a8b6c5122e0601a MD5 · raw file

  1. from datetime import datetime
  2. import pylons
  3. from couchdb.schema import DateTimeField, DictField, Document, TextField, \
  4. ListField, FloatField, Schema, IntegerField, BooleanField, View
  5. from kai.model.generics import Comment
  6. class Traceback(Document):
  7. type = TextField(default='Traceback')
  8. human_id = TextField()
  9. displayname = TextField()
  10. email = TextField()
  11. uuid = TextField()
  12. session_id = TextField()
  13. created = DateTimeField(default=datetime.utcnow)
  14. description = TextField()
  15. # Meta
  16. language = TextField()
  17. version = TextField()
  18. full_version = TextField()
  19. platform = TextField()
  20. libraries = ListField(DictField(Schema.build(
  21. name = TextField(),
  22. version = TextField()
  23. )))
  24. # Traceback stack / Exception
  25. frames = ListField(DictField(Schema.build(
  26. module = TextField(),
  27. line = IntegerField(),
  28. function = TextField(),
  29. operation = TextField()
  30. )))
  31. exception_type = TextField()
  32. exception_value = TextField()
  33. by_uuid = View('traceback', '''
  34. function(doc) {
  35. if (doc.type == 'Traceback' && doc.uuid) {
  36. emit(doc.uuid, null);
  37. }
  38. }''', include_docs=True)
  39. by_time = View('traceback', '''
  40. function(doc) {
  41. if (doc.type == 'Traceback') {
  42. emit(doc.created, null);
  43. }
  44. }''', include_docs=True)
  45. by_session_id = View('traceback', '''
  46. function(doc) {
  47. if (doc.type == 'Traceback' && doc.session_id) {
  48. emit(doc.session_id, null);
  49. }
  50. }''', include_docs=True)
  51. @classmethod
  52. def from_xml(cls, content):
  53. try:
  54. from lxml import objectify
  55. except ImportError:
  56. return False
  57. data = objectify.fromstring(content)
  58. tb = cls()
  59. # Add the session id if available, otherwise force a new session
  60. if not pylons.session.id:
  61. pylons.session.save()
  62. tb.session_id = pylons.session.id
  63. exc = data.exception
  64. tb.exception_type = exc.type.text
  65. tb.exception_value = exc.value.text
  66. # Add the meta data
  67. sysinfo = data.sysinfo
  68. tb.language = sysinfo.language.text
  69. tb.version = sysinfo.language.get('version')
  70. tb.full_version = sysinfo.language.get('full_version')
  71. tb.libraries = []
  72. for lib in sysinfo.libraries.iterchildren(tag='library'):
  73. tb.libraries.append(dict(name=lib.get('name'),
  74. version=lib.get('version')))
  75. tb.frames = []
  76. for frame in data.stack.iterchildren(tag='frame'):
  77. fd = dict(module=frame.module.text, line=int(frame.line.text),
  78. function=frame.function.text)
  79. if hasattr(frame, 'operation'):
  80. fd['operation'] = frame.operation.text
  81. else:
  82. fd['operation'] = 'No operation context'
  83. tb.frames.append(fd)
  84. return tb
  85. def is_owner(self, user, check_session=False):
  86. if user and self.human_id and user.id == self.human_id:
  87. return True
  88. else:
  89. if check_session:
  90. if pylons.session.id and self.session_id and pylons.session.id == self.session_id:
  91. return True
  92. return False
  93. def comment_count(self):
  94. comments = Comment.comment_count(pylons.tmpl_context.db)[self.id]
  95. if not comments:
  96. return 0
  97. else:
  98. return comments[0]
  99. @classmethod
  100. def associate_tracebacks(cls, user):
  101. db = pylons.tmpl_context.db
  102. tracebacks = list(cls.by_session_id(db)[pylons.session.id])
  103. if tracebacks:
  104. for tb in tracebacks:
  105. try:
  106. tb.session_id = None
  107. tb.human_id = user.id
  108. tb.displayname = user.displayname
  109. tb.email = user.email
  110. tb.store(db)
  111. except:
  112. pass