Skip to content

Commit 40483bd

Browse files
committed
lang: add kivy.lib.debug that is a modified version of jinja2.debug for outputing better traceback when we are using kvlang files. Now callback defined in the kvlang are properly showed if we are using a file.
1 parent 0196026 commit 40483bd

File tree

2 files changed

+335
-16
lines changed

2 files changed

+335
-16
lines changed

kivy/lang.py

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,9 @@
453453
from kivy.logger import Logger
454454
from kivy.utils import OrderedDict, QueryDict
455455
from kivy.cache import Cache
456-
from kivy import kivy_data_dir
456+
from kivy import kivy_data_dir, require
457+
from kivy.lib.debug import make_traceback
458+
457459

458460
trace = Logger.trace
459461
global_idmap = {}
@@ -467,7 +469,7 @@
467469
lang_keyvalue = re.compile('([a-zA-Z_][a-zA-Z0-9_.]*\.[a-zA-Z0-9_.]+)')
468470

469471

470-
def precompile_value(name, value):
472+
def precompile_value(name, value, line=1, parser=None):
471473
# if it's an id, we don't need to compile, the value is the id.
472474
if name == 'id':
473475
return value
@@ -480,18 +482,18 @@ def precompile_value(name, value):
480482
# if we don't detect any string/key in it, we can eval and give the
481483
# result
482484
if re.search(lang_key, tmp) is None:
483-
return (None, eval(value), value)
485+
return (None, eval(value), value, line + 1, parser)
484486

485487
# ok, we can compile.
486-
code = compile(value, '<string>', mode)
488+
code = compile(value, parser.filename or '<string>', mode)
487489

488490
# now, detect obj.prop
489491
# first, remove all the string from the value
490492
tmp = re.sub(lang_str, '', value)
491493
# detect key.value inside value
492494
kw = re.findall(lang_keyvalue, tmp)
493495

494-
return (kw, code, value)
496+
return (kw, code, value, line + 1, parser)
495497

496498

497499
class ParserError(Exception):
@@ -529,13 +531,10 @@ def __init__(self, **kwargs):
529531
self.sourcecode = []
530532
self.objects = []
531533
self.directives = []
534+
self.filename = kwargs.get('filename', None)
532535
content = kwargs.get('content', None)
533-
self.filename = filename = kwargs.get('filename', None)
534-
if filename:
535-
content = self.load_resource(filename)
536536
if content is None:
537-
raise ValueError('No content passed. Use filename or '
538-
'content attribute.')
537+
raise ValueError('No content passed')
539538
self.parse(content)
540539

541540
def execute_directives(self):
@@ -633,7 +632,7 @@ def precompile_objects(self, objects):
633632
'canvas.after'):
634633
self.precompile_objects(value[0])
635634
continue
636-
value[0] = precompile_value(key, value[0])
635+
value[0] = precompile_value(key, value[0], value[1], value[2])
637636

638637
def parse_version(self, line):
639638
'''Parse the version line.
@@ -648,9 +647,9 @@ def parse_version(self, line):
648647
'#:kivy <version>')
649648

650649
version = content[6:].strip()
651-
if version != '1.0':
652-
raise ParserError(self, ln, 'Only Kivy language 1.0 is supported'
653-
' (<%s> found)' % version)
650+
if len(version.split('.')) == 2:
651+
version += '.0'
652+
require(version)
654653
if __debug__:
655654
trace('Parser: Kivy version is %s' % version)
656655

@@ -792,9 +791,16 @@ def _eval_center(boxsize, center):
792791

793792
def custom_callback(*largs, **kwargs):
794793
element, key, value, idmap = largs[0]
794+
__kvlang__ = value
795795
locals().update(idmap)
796796
args = largs[1:]
797-
exec value[1]
797+
try:
798+
exec value[1]
799+
except:
800+
exc_info = sys.exc_info()
801+
traceback = make_traceback(exc_info)
802+
exc_type, exc_value, tb = traceback.standard_exc_info
803+
raise exc_type, exc_value, tb
798804

799805

800806
def create_handler(element, key, vd, idmap):
@@ -960,7 +966,8 @@ def load_string(self, string, **kwargs):
960966
kwargs.setdefault('rulesonly', False)
961967
self._current_filename = kwargs.get('filename', None)
962968
try:
963-
parser = Parser(content=string)
969+
parser = Parser(content=string, filename=kwargs.get(
970+
'filename', None))
964971
root = self.build(parser.objects)
965972
if kwargs['rulesonly'] and root:
966973
filename = kwargs.get('rulesonly', '<string>')

0 commit comments

Comments
 (0)