jackrosenthal / kajiki Goto Github PK
View Code? Open in Web Editor NEWPython XML-based template engine with Genshi-like syntax and Jinja-style blocks
License: Other
Python XML-based template engine with Genshi-like syntax and Jinja-style blocks
License: Other
Python2 counter is ticking, but kajiki still needs python-nine to run on python3. Looks like there is no release of nine after year 2016. Do you think, that kajiki still needs python-nine?
Currently build of kajiki in Fedora 32 (development) is broken due to problems with python-nine. I suggest to release a new version of kajiki, which will not rely on python-nine.
Unfortunately, Kajiki doesn't handle CDATA sections correctly. This causes problems with non-HTML XML documents. At the moment the CDATA markers are omitted and valid content may get translated to HTML entity references:
>>> import kajiki
>>> kajiki.XMLTemplate(u'''<myxml><data><![CDATA[>ð $foo]]></data></myxml>''')(dict(foo='bar')).render()
u'<myxml><data>&gt;&#240; bar</data></myxml>'
To avoid unexpected behavior Kajiki should preserve CDATA markers and the content of CDATA sections shouldn't be modified, except for the expansion of variables.
Many HTML entities i.e. … cause KeyError:
Try:
kajiki.XMLTemplate(u'<div>© …</div>')
Result:
Traceback (most recent call last): File "<input>", line 1, in <module> Template = kajiki.XMLTemplate(u'<div>© …</div>') File "/usr/lib/python2.7/dist-packages/kajiki/xml_template.py", line 52, in XMLTemplate doc = _Parser(filename, source).parse() File "/usr/lib/python2.7/dist-packages/kajiki/xml_template.py", line 629, in parse parser.parse(source) File "/usr/lib/python2.7/xml/sax/expatreader.py", line 110, in parse xmlreader.IncrementalParser.parse(self, source) File "/usr/lib/python2.7/xml/sax/xmlreader.py", line 123, in parse self.feed(buffer) File "/usr/lib/python2.7/xml/sax/expatreader.py", line 213, in feed self._parser.Parse(data, isFinal) File "/usr/lib/python2.7/xml/sax/expatreader.py", line 416, in skipped_entity_handler self._cont_handler.skippedEntity(name) File "/usr/lib/python2.7/dist-packages/kajiki/xml_template.py", line 675, in skippedEntity return self.characters(html5[name]) KeyError: u'hellip'
When I extract translatable strings from templates, Kajiki splits text blocks into individual lines (destroying paragraph context). Take a template containing a paragraph like this one:
...
<p>
A cookie is a small text file that a website saves on your computer or
mobile device when you visit the site. It enables the website to remember
your actions and preferences (such as login, language, font size and
other display preferences) over a period of time, so you don’t have to
keep re-entering them whenever you come back to the site or browse from
one page to another.
</p>
...
Here's what python setup.py extract_messages
produces with Genshi:
...
#: project/templates/cookies.html:19
msgid ""
"A cookie is a small text file that a website saves on your computer or\n"
" mobile device when you visit the site. It enables the website to "
"remember\n"
" your actions and preferences (such as login, language, font size and\n"
" other display preferences) over a period of time, so you don’t have to\n"
" keep re-entering them whenever you come back to the site or browse from\n"
" one page to another."
msgstr ""
...
The whitespace and newlines aren't that pretty, but it's one continuous string. Here's what Kajiki makes of it:
...
#: project/templates/cookies.xhtml:18
msgid " A cookie is a small text file that a website saves on your computer or"
msgstr ""
#: project/templates/cookies.xhtml:19
msgid " mobile device when you visit the site. It enables the website to remember"
msgstr ""
#: project/templates/cookies.xhtml:20
msgid " your actions and preferences (such as login, language, font size and"
msgstr ""
#: project/templates/cookies.xhtml:21
msgid " other display preferences) over a period of time, so you don’t have to"
msgstr ""
#: project/templates/cookies.xhtml:22
msgid " keep re-entering them whenever you come back to the site or browse from"
msgstr ""
#: project/templates/cookies.xhtml:23
msgid " one page to another."
msgstr ""
...
Tools like poedit don't honor the order in which msgids are in a PO file. That really makes it unusable for me. :(
A few issues were added today by @jackrosenthal which are pretty essential for the health of the Kajiki project. I am not coming back as a maintainer of Kajiki, but I know it deserves to be well maintained. Essentially I wish to responsibly remove myself. Are you interested in a transfer of ownership to you, or should we open this up for takers?
hello friends,
a module imported at the level of <html> or <body>
is not accessible within a <py:def> function,
even if defined in the same level
hello friends,
i'm using kajiki templates as mixed direct and dotted filenames.
the reload functionality had to be fixed, so i united it
under the smaller common denominator: the resolved filename.
please review my included patch:
alex
kajiki.diff.txt
hello friends,
and many thanks for providing kajiki.
with genshi, i was using transformation filters,
that allowed me to give a last touch to some tags' attributes.
how could i hook a callback in kajiki template _render_attrs?
how could _render_attrs know the tag name it was called for?
should such callback be hooked somewhere else?
thanks in advance,
alex
nose v1 hasn't seen any new updates since 2016, and compatibility appears to be broken in Python 3.10.
pytest is the hot thing these days, and appears to already find and run the tests just fine...
switch the test runner from nose to pytest?
Adding XML comment using <!-- comment -->
outside the root node seems to cause an unnecessary and confusing exception in py:else handling.
d="""
<!-- stuff -->
<a>
<py:switch test="val">
<py:case value="1">2</py:case>
<py:else>1</py:else>
</py:switch>
</a>
"""
>>> dd=kajiki.XMLTemplate(d)
...
kajiki.xml_template.XMLTemplateCompileError: [<string>:6] py:else directive must be inside a py:switch or directly after py:if without text or spaces in between
Without py:else this works fine:
>>> e="""
<!-- stuff -->
<a>
<py:switch test="val">
<py:case value="1">2</py:case>
</py:switch>
</a>
"""
>>> ee=kajiki.XMLTemplate(e)
>>> print(ee(dict(val=1)).render())
<a>
2
</a>
>>>
With py:else and without XML comment also works fine
>>> f="""
<a>
<py:switch test="val">
<py:case value="1">2</py:case>
<py:else>1</py:else>
</py:switch>
</a>"""
>>> ff=kajiki.XMLTemplate(f)
>>> print(ff(dict(val=1)).render())
<a>
2
</a>
>>> print(ff(dict(val=7)).render())
<a>
1
</a>
Hi,
I've run into a problem with the py:switch code. If I define a py:switch with more than two py:case and then a py:else, the content of the py:else is always output, except if the final py:case is True.
txt = u'''<div>
<py:switch test="category">
<py:case value="'a'">A</py:case>
<py:case value="'b'">B</py:case>
<py:else>O</py:else>
</py:switch>
</div>'''
tmpl = XMLTemplate(txt)
With that base code
tmpl({'category': 'a'}).render()
should output "
tmpl({'category': 'b'}).render()
correctly outputs "
There's considerable cleanup that could be done if we stop supporting these versions of Python.
These days they are probably mostly antiques... any oppositions to dropping them?
The CI system appears to have a scary banner on it that it may be shutting down in a few days:
Hi! It seems there are still plenty of builds running. We're pushing back the shutdown date to June 15th. Please consider migrating to travis-ci.com.
Does something need done by the repo admins here to move it to travis-ci.com?
is there ext for supporting kajiki template ?
I wrote a test in TestFunction in test_xml.py
def test_function_call_double_parenthesis(self):
perform('''<div py:strip="True"
><py:def function="echo(x)">$x</py:def
>${echo('hello'))}</div>''', 'hello')
it fails in this way:
FAIL: test_function_double_parenthesis (kajiki.tests.test_xml.TestFunction)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/castix/axant/kajiki/kajiki/tests/test_xml.py", line 375, in test_function_double_parenthesis
>${echo('hello'))}</div>''', 'hello')
File "/home/castix/axant/kajiki/kajiki/tests/test_xml.py", line 78, in perform
assert rsp == expected_output, (rsp, expected_output)
AssertionError: (u'hello}', u'hello')
-------------------- >> begin captured stdout << ---------------------
class template:
@kajiki.expose
def __main__():
if not (True): yield u'<div>'
yield self.__kj__.escape(echo('hello'))
yield local.__kj__.gettext(u'}')
if not (True): yield u'</div>'
@kajiki.expose
def echo(x):
yield self.__kj__.escape(x)
template = kajiki.Template(template)
as the call is ${echo('hello'))}
i would expect a KajikiSyntaxError to be raised instead of have that extra }
Thanks :)
I've been using Kajiki on two projects recently and found it really nice to use. However, at the moment there is a significant lack of code documentation, which makes it a lot harder to contribute to the project, particularly when I run into bugs. It would be nice if some time could be spent on the documentation, then I could provide pull-requests with fixes rather than just bug-reports.
Unable to use kajiki on python3.10b2 (b1 works, b2 don't).
Here is an example:
import kajiki
tpl = kajiki.TextTemplate('''%def quote(caller, speaker)
%for i in range(2)
Quoth $speaker, "${caller(i)}."
%end
%end
%call(n) quote(%caller ,'the raven')
Nevermore $n\\
%end''')
Raises an exception:
Traceback (most recent call last):
File "/root/Kajiki-0.8.2/kajiki/template.py", line 323, in from_ir
exec(py_text, dct)
File "<string>", line 17
yield caller(i)}.
^
SyntaxError: unmatched '}'
Looks like problem is in kajiki/text.py:
compile(self.source[self.pos:], '', 'eval')
,
and python3.10 better error handling. I don't know, how to fix this, compile raises error from end of string instead of from start.
Short python example:
Python 3.10.0b1 (default, May 4 2021, 00:00:00) [GCC 11.1.1 20210428 (Red Hat 11.1.1-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> compile('caller(i)}."', '', 'eval')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "", line 1
caller(i)}."
^
SyntaxError: unmatched '}'
Python 3.10.0b2 (default, Jun 1 2021, 00:00:00) [GCC 11.1.1 20210531 (Red Hat 11.1.1-3)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> compile('caller(i)}."', '', 'eval')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "", line 1
caller(i)}."
^
SyntaxError: unterminated string literal (detected at line 1)
>>>
Any volunteer, who can fix this? Fedora's kajiki build is broken. :-(
This is a feature request. I'm willing to work on this feature and submit a PR if the maintainers would find this valuable.
Essentially, it seems that on occasion it's convenient to use Kajiki from a bash
script (or something similar) and would be convenient to have an entry point for this. For example, it could be used to format emails from mutt
.
I was thinking of some sort of interface like this:
kajiki [--xml] [input_file] [output_file]
input_file
and output_file
could default to stdin
and stdout
respectively.
Is this in the maintainers' interest?
During my evaluation of Kajiki benefits (compared to Genshi) I have found following problem:
>>> Template = kajiki.XMLTemplate(u'<html><py:def function="attrtest()">Some value</py:def><img src="${attrtest()}"/></html>')
>>> print(Template().render())
<html><img src="<kajiki.util.flattener object at 0xf82a50>"/></html>
>>> Expected result was:
<html><img src="Some value"/></html>
Kajiki apparently tried to evaluate attrtest()
function, but it didn't went well...
My env.: Python 2.6.6, Kajiki==0.5.5
It looks like the File loader broke during the porting process.
https://github.com/nandoflorestan/kajiki/blob/master/kajiki/loader.py#L92 opens the file in binary mode, this leads to a "str" type being returned on Python2.
Then the resulting object gets passed to the XMLTemplate initialization function which builds _Parser with the given source.
The _Parser init method checks for the source being an instance of str at https://github.com/nandoflorestan/kajiki/blob/master/kajiki/xml_template.py#L395
but at https://github.com/nandoflorestan/kajiki/blob/master/kajiki/xml_template.py#L9 str has been patched to actually mean "unicode" so the check fails.
This has been found due to the TurboGears2 test suite failing with Kajiki 0.4 https://travis-ci.org/TurboGears/tg2/jobs/9749531#L813
File "/home/travis/virtualenv/python3.8-dev/lib/python3.8/site-packages/kajiki/loader.py", line 78, in import_
return super(FileLoader, self).import_(name, *args, **kwargs)
File "/home/travis/virtualenv/python3.8-dev/lib/python3.8/site-packages/kajiki/loader.py", line 21, in import_
mod = self._load(name, *args, **kwargs)
File "/home/travis/virtualenv/python3.8-dev/lib/python3.8/site-packages/kajiki/loader.py", line 97, in _load
return XMLTemplate(filename=filename,
File "/home/travis/virtualenv/python3.8-dev/lib/python3.8/site-packages/kajiki/xml_template.py", line 56, in XMLTemplate
t = template.from_ir(ir_, base_globals=base_globals)
File "/home/travis/virtualenv/python3.8-dev/lib/python3.8/site-packages/kajiki/template.py", line 323, in from_ir
tpl.annotate_lnotab(py_linenos)
File "/home/travis/virtualenv/python3.8-dev/lib/python3.8/site-packages/kajiki/template.py", line 257, in annotate_lnotab
meth.annotate_lnotab(cls.filename, py_to_tpl, dict(py_to_tpl))
File "/home/travis/virtualenv/python3.8-dev/lib/python3.8/site-packages/kajiki/template.py", line 389, in annotate_lnotab
new_code = patch_code_file_lines(
File "/home/travis/virtualenv/python3.8-dev/lib/python3.8/site-packages/kajiki/template.py", line 413, in patch_code_file_lines
return types.CodeType(code.co_argcount,
TypeError: an integer is required (got type bytes)
Hi,
after searching for a while I found the solution my self. However, I believe this should make it to the docs.
I was struggling with implementing a py:if
comparison like x < 2
. The naive way
Template = kajiki.XMLTemplate('''
<html><body>
<div py:if="x < 2">$title</div>
</body></html>''')
yields an XMLTemplateParseError
. This is perfectly correct since the <
is a reserves letter in XML. Realizing that, the solution is as simple as replacing <
with <
.
In doing so I get:
print(Template(dict(title='Kajiki is teh awesome!', x=1)).render())
<html><body>
<div>Kajiki is teh awesome!</div>
</body></html>
I don't understand inhertence in kajiki template enginge, I learned and used inhertinence in jinja2 template engine I try the example in demo but I don't understand, I create this repo https://github.com/elycheikhsmail/kajiki-demo as demo for kajiki but I don't include inheritence (in official way)
Got
#: ticketslist/templates/master.xhtml:12
msgid " .project-navbar {"
msgstr ""
#: ticketslist/templates/master.xhtml:13
msgid " background-color: #323A45;"
msgstr ""
#: ticketslist/templates/master.xhtml:14 ticketslist/templates/master.xhtml:18
#: ticketslist/templates/master.xhtml:22
msgid " color: white;"
msgstr ""
#: ticketslist/templates/master.xhtml:15
msgid " border-bottom: 4px solid #D72749;"
msgstr ""
#: ticketslist/templates/master.xhtml:16 ticketslist/templates/master.xhtml:20
#: ticketslist/templates/master.xhtml:23
#: ticketslist/templates/ticketlist/fill.xhtml:68
msgid " }"
msgstr ""
when running on a master.xhtml containing
<style>
.project-navbar {
background-color: #323A45;
color: white;
border-bottom: 4px solid #D72749;
}
</style>
A commonly used template feature is filters in the form somevalue | filter | filter(option)
to transform the value in various ways. Usually to format it properly for rendering.
In Jinja this is provided through a specific piece of parser and compiler that parse |
to a filter.
The same seems to me can be achieved by not parsing filters at all and forcing them to subclass a common base class that relies on __ror__
like::
class TemplateFilter(object):
"""Base Class for all filters"""
def apply(self, value, *args, **kwargs):
raise NotImplementedError('Filters must implement this')
def __init__(self, *args, **kwargs):
self.args, self.kwargs = args, kwargs
def __call__(self, *args, **kwargs):
return self.__class__(*args, **kwargs)
def __ror__(self, input):
return self.apply(input, *self.args, **self.kwargs)
class WrapWithFilter(TemplateFilter):
"""Wraps the whole content in a given tag"""
def apply(self, value, tag):
return '<{tag}>{value}</{tag}>'.format(tag=tag, value=value)
Than "something" | WrapWithFilter('strong')
will render to <strong>something</strong>
@nandoflorestan @rick446 do you think there is any use case we can only achieve by implementing filters at parser/compiler level? Because I see the implementation based on operator overloading far easier to achieve and maintain.
In [1]: from genshi.template import MarkupTemplate
In [2]: from kajiki import XMLTemplate
In [3]: MarkupTemplate('<!-- whatever --><x>${1+1}</x>').generate().render()
Out[3]: '<!-- whatever --><x>2</x>'
In [4]: XMLTemplate('<!-- whatever --><x>${1+1}</x>')().render()
Out[4]: '<!-- whatever -->'
I use xmllint --format
to automatically format XML files (much like black
for Python code, csscomb
for CSS, etc).
That autoformatter always inserts <?xml version="1.0"?>
at the beginning of the XML file, which as far as I know is perfectly valid thing to do and is called the XML declaration:
<?xml version="1.0"?>
<html>
<head>
...
The issue is that some internal manipulation of the XML by Kajiki inserts a custom DOCTYPE before that XML-Declaration, rather than after it, making the XML invalid:
kajiki.xml_template.XMLTemplateParseError: [resources/templates/home.xml:1] XML or text declaration not at start of entity
--> <!DOCTYPE kajiki SYSTEM "kajiki.dtd"><?xml version="1.0"?>
<html>
<head>
If the result of the manipulation was instead:
<?xml version="1.0"?><!DOCTYPE kajiki SYSTEM "kajiki.dtd">
...
or:
<?xml version="1.0"?>
<!DOCTYPE kajiki SYSTEM "kajiki.dtd">
...
...then presumably the XML would still be valid and the template parsing would succeed.
Kajiki fails to build with python 3.11 in Fedora rawhide. Fails with this error:
TypeError: code expected at least 18 arguments, got 16
More information in redhat bugzilla:
https://bugzilla.redhat.com/show_bug.cgi?id=2057885
I'm trying to package your module as an rpm package. So I'm using the typical PEP517 based build, install and test cycle used on building packages from non-root account.
python3 -sBm build -w
I have alredy packaged almost 800 python modules ane to be honest I see first time such errors. Liooks like something is wrong with importing modules.
May I ask for some help?
Here is pytest output:
+ PYTHONPATH=/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/usr/lib64/python3.8/site-packages:/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/usr/lib/python3.8/site-packages
+ /usr/bin/pytest -ra --import-mode=importlib
=========================================================================== test session starts ============================================================================
platform linux -- Python 3.8.12, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: /home/tkloczko/rpmbuild/BUILD/kajiki-0.9.0, configfile: pytest.ini
collected 158 items / 20 errors / 138 selected
================================================================================== ERRORS ==================================================================================
___________________________________________________________________ ERROR collecting kajiki/__main__.py ____________________________________________________________________
/usr/lib/python3.8/site-packages/_pytest/runner.py:311: in from_call
result: Optional[TResult] = func()
/usr/lib/python3.8/site-packages/_pytest/runner.py:341: in <lambda>
call = CallInfo.from_call(lambda: list(collector.collect()), "collect")
/usr/lib/python3.8/site-packages/_pytest/doctest.py:532: in collect
module = import_path(self.fspath)
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:544: in import_path
raise ImportPathMismatchError(module_name, module_file, path)
E _pytest.pathlib.ImportPathMismatchError: ('kajiki.__main__', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/usr/lib/python3.8/site-packages/kajiki/__main__.py', PosixPath('/home/tkloczko/rpmbuild/BUILD/kajiki-0.9.0/kajiki/__main__.py'))
____________________________________________________________________ ERROR collecting kajiki/doctype.py ____________________________________________________________________
/usr/lib/python3.8/site-packages/_pytest/runner.py:311: in from_call
result: Optional[TResult] = func()
/usr/lib/python3.8/site-packages/_pytest/runner.py:341: in <lambda>
call = CallInfo.from_call(lambda: list(collector.collect()), "collect")
/usr/lib/python3.8/site-packages/_pytest/doctest.py:532: in collect
module = import_path(self.fspath)
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:544: in import_path
raise ImportPathMismatchError(module_name, module_file, path)
E _pytest.pathlib.ImportPathMismatchError: ('kajiki.doctype', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/usr/lib/python3.8/site-packages/kajiki/doctype.py', PosixPath('/home/tkloczko/rpmbuild/BUILD/kajiki-0.9.0/kajiki/doctype.py'))
__________________________________________________________________ ERROR collecting kajiki/html_utils.py ___________________________________________________________________
/usr/lib/python3.8/site-packages/_pytest/runner.py:311: in from_call
result: Optional[TResult] = func()
/usr/lib/python3.8/site-packages/_pytest/runner.py:341: in <lambda>
call = CallInfo.from_call(lambda: list(collector.collect()), "collect")
/usr/lib/python3.8/site-packages/_pytest/doctest.py:532: in collect
module = import_path(self.fspath)
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:544: in import_path
raise ImportPathMismatchError(module_name, module_file, path)
E _pytest.pathlib.ImportPathMismatchError: ('kajiki.html_utils', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/usr/lib/python3.8/site-packages/kajiki/html_utils.py', PosixPath('/home/tkloczko/rpmbuild/BUILD/kajiki-0.9.0/kajiki/html_utils.py'))
_____________________________________________________________________ ERROR collecting kajiki/i18n.py ______________________________________________________________________
/usr/lib/python3.8/site-packages/_pytest/runner.py:311: in from_call
result: Optional[TResult] = func()
/usr/lib/python3.8/site-packages/_pytest/runner.py:341: in <lambda>
call = CallInfo.from_call(lambda: list(collector.collect()), "collect")
/usr/lib/python3.8/site-packages/_pytest/doctest.py:532: in collect
module = import_path(self.fspath)
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:544: in import_path
raise ImportPathMismatchError(module_name, module_file, path)
E _pytest.pathlib.ImportPathMismatchError: ('kajiki.i18n', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/usr/lib/python3.8/site-packages/kajiki/i18n.py', PosixPath('/home/tkloczko/rpmbuild/BUILD/kajiki-0.9.0/kajiki/i18n.py'))
______________________________________________________________________ ERROR collecting kajiki/ir.py _______________________________________________________________________
/usr/lib/python3.8/site-packages/_pytest/runner.py:311: in from_call
result: Optional[TResult] = func()
/usr/lib/python3.8/site-packages/_pytest/runner.py:341: in <lambda>
call = CallInfo.from_call(lambda: list(collector.collect()), "collect")
/usr/lib/python3.8/site-packages/_pytest/doctest.py:532: in collect
module = import_path(self.fspath)
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:544: in import_path
raise ImportPathMismatchError(module_name, module_file, path)
E _pytest.pathlib.ImportPathMismatchError: ('kajiki.ir', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/usr/lib/python3.8/site-packages/kajiki/ir.py', PosixPath('/home/tkloczko/rpmbuild/BUILD/kajiki-0.9.0/kajiki/ir.py'))
____________________________________________________________________ ERROR collecting kajiki/lnotab.py _____________________________________________________________________
/usr/lib/python3.8/site-packages/_pytest/runner.py:311: in from_call
result: Optional[TResult] = func()
/usr/lib/python3.8/site-packages/_pytest/runner.py:341: in <lambda>
call = CallInfo.from_call(lambda: list(collector.collect()), "collect")
/usr/lib/python3.8/site-packages/_pytest/doctest.py:532: in collect
module = import_path(self.fspath)
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:544: in import_path
raise ImportPathMismatchError(module_name, module_file, path)
E _pytest.pathlib.ImportPathMismatchError: ('kajiki.lnotab', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/usr/lib/python3.8/site-packages/kajiki/lnotab.py', PosixPath('/home/tkloczko/rpmbuild/BUILD/kajiki-0.9.0/kajiki/lnotab.py'))
____________________________________________________________________ ERROR collecting kajiki/loader.py _____________________________________________________________________
/usr/lib/python3.8/site-packages/_pytest/runner.py:311: in from_call
result: Optional[TResult] = func()
/usr/lib/python3.8/site-packages/_pytest/runner.py:341: in <lambda>
call = CallInfo.from_call(lambda: list(collector.collect()), "collect")
/usr/lib/python3.8/site-packages/_pytest/doctest.py:532: in collect
module = import_path(self.fspath)
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:544: in import_path
raise ImportPathMismatchError(module_name, module_file, path)
E _pytest.pathlib.ImportPathMismatchError: ('kajiki.loader', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/usr/lib/python3.8/site-packages/kajiki/loader.py', PosixPath('/home/tkloczko/rpmbuild/BUILD/kajiki-0.9.0/kajiki/loader.py'))
________________________________________________________________ ERROR collecting kajiki/markup_template.py ________________________________________________________________
/usr/lib/python3.8/site-packages/_pytest/runner.py:311: in from_call
result: Optional[TResult] = func()
/usr/lib/python3.8/site-packages/_pytest/runner.py:341: in <lambda>
call = CallInfo.from_call(lambda: list(collector.collect()), "collect")
/usr/lib/python3.8/site-packages/_pytest/doctest.py:532: in collect
module = import_path(self.fspath)
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:544: in import_path
raise ImportPathMismatchError(module_name, module_file, path)
E _pytest.pathlib.ImportPathMismatchError: ('kajiki.markup_template', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/usr/lib/python3.8/site-packages/kajiki/markup_template.py', PosixPath('/home/tkloczko/rpmbuild/BUILD/kajiki-0.9.0/kajiki/markup_template.py'))
___________________________________________________________________ ERROR collecting kajiki/template.py ____________________________________________________________________
/usr/lib/python3.8/site-packages/_pytest/runner.py:311: in from_call
result: Optional[TResult] = func()
/usr/lib/python3.8/site-packages/_pytest/runner.py:341: in <lambda>
call = CallInfo.from_call(lambda: list(collector.collect()), "collect")
/usr/lib/python3.8/site-packages/_pytest/doctest.py:532: in collect
module = import_path(self.fspath)
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:544: in import_path
raise ImportPathMismatchError(module_name, module_file, path)
E _pytest.pathlib.ImportPathMismatchError: ('kajiki.template', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/usr/lib/python3.8/site-packages/kajiki/template.py', PosixPath('/home/tkloczko/rpmbuild/BUILD/kajiki-0.9.0/kajiki/template.py'))
_____________________________________________________________________ ERROR collecting kajiki/text.py ______________________________________________________________________
/usr/lib/python3.8/site-packages/_pytest/runner.py:311: in from_call
result: Optional[TResult] = func()
/usr/lib/python3.8/site-packages/_pytest/runner.py:341: in <lambda>
call = CallInfo.from_call(lambda: list(collector.collect()), "collect")
/usr/lib/python3.8/site-packages/_pytest/doctest.py:532: in collect
module = import_path(self.fspath)
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:544: in import_path
raise ImportPathMismatchError(module_name, module_file, path)
E _pytest.pathlib.ImportPathMismatchError: ('kajiki.text', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/usr/lib/python3.8/site-packages/kajiki/text.py', PosixPath('/home/tkloczko/rpmbuild/BUILD/kajiki-0.9.0/kajiki/text.py'))
_____________________________________________________________________ ERROR collecting kajiki/util.py ______________________________________________________________________
/usr/lib/python3.8/site-packages/_pytest/runner.py:311: in from_call
result: Optional[TResult] = func()
/usr/lib/python3.8/site-packages/_pytest/runner.py:341: in <lambda>
call = CallInfo.from_call(lambda: list(collector.collect()), "collect")
/usr/lib/python3.8/site-packages/_pytest/doctest.py:532: in collect
module = import_path(self.fspath)
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:544: in import_path
raise ImportPathMismatchError(module_name, module_file, path)
E _pytest.pathlib.ImportPathMismatchError: ('kajiki.util', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/usr/lib/python3.8/site-packages/kajiki/util.py', PosixPath('/home/tkloczko/rpmbuild/BUILD/kajiki-0.9.0/kajiki/util.py'))
____________________________________________________________________ ERROR collecting kajiki/version.py ____________________________________________________________________
/usr/lib/python3.8/site-packages/_pytest/runner.py:311: in from_call
result: Optional[TResult] = func()
/usr/lib/python3.8/site-packages/_pytest/runner.py:341: in <lambda>
call = CallInfo.from_call(lambda: list(collector.collect()), "collect")
/usr/lib/python3.8/site-packages/_pytest/doctest.py:532: in collect
module = import_path(self.fspath)
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:544: in import_path
raise ImportPathMismatchError(module_name, module_file, path)
E _pytest.pathlib.ImportPathMismatchError: ('kajiki.version', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/usr/lib/python3.8/site-packages/kajiki/version.py', PosixPath('/home/tkloczko/rpmbuild/BUILD/kajiki-0.9.0/kajiki/version.py'))
_________________________________________________________________ ERROR collecting kajiki/xml_template.py __________________________________________________________________
/usr/lib/python3.8/site-packages/_pytest/runner.py:311: in from_call
result: Optional[TResult] = func()
/usr/lib/python3.8/site-packages/_pytest/runner.py:341: in <lambda>
call = CallInfo.from_call(lambda: list(collector.collect()), "collect")
/usr/lib/python3.8/site-packages/_pytest/doctest.py:532: in collect
module = import_path(self.fspath)
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:544: in import_path
raise ImportPathMismatchError(module_name, module_file, path)
E _pytest.pathlib.ImportPathMismatchError: ('kajiki.xml_template', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/usr/lib/python3.8/site-packages/kajiki/xml_template.py', PosixPath('/home/tkloczko/rpmbuild/BUILD/kajiki-0.9.0/kajiki/xml_template.py'))
________________________________________________________________ ERROR collecting kajiki/tests/test_cli.py _________________________________________________________________
/usr/lib/python3.8/site-packages/_pytest/runner.py:311: in from_call
result: Optional[TResult] = func()
/usr/lib/python3.8/site-packages/_pytest/runner.py:341: in <lambda>
call = CallInfo.from_call(lambda: list(collector.collect()), "collect")
/usr/lib/python3.8/site-packages/_pytest/doctest.py:532: in collect
module = import_path(self.fspath)
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:544: in import_path
raise ImportPathMismatchError(module_name, module_file, path)
E _pytest.pathlib.ImportPathMismatchError: ('kajiki.tests.test_cli', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/usr/lib/python3.8/site-packages/kajiki/tests/test_cli.py', PosixPath('/home/tkloczko/rpmbuild/BUILD/kajiki-0.9.0/kajiki/tests/test_cli.py'))
______________________________________________________________ ERROR collecting kajiki/tests/test_doctype.py _______________________________________________________________
/usr/lib/python3.8/site-packages/_pytest/runner.py:311: in from_call
result: Optional[TResult] = func()
/usr/lib/python3.8/site-packages/_pytest/runner.py:341: in <lambda>
call = CallInfo.from_call(lambda: list(collector.collect()), "collect")
/usr/lib/python3.8/site-packages/_pytest/doctest.py:532: in collect
module = import_path(self.fspath)
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:544: in import_path
raise ImportPathMismatchError(module_name, module_file, path)
E _pytest.pathlib.ImportPathMismatchError: ('kajiki.tests.test_doctype', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/usr/lib/python3.8/site-packages/kajiki/tests/test_doctype.py', PosixPath('/home/tkloczko/rpmbuild/BUILD/kajiki-0.9.0/kajiki/tests/test_doctype.py'))
________________________________________________________________ ERROR collecting kajiki/tests/test_e2e.py _________________________________________________________________
/usr/lib/python3.8/site-packages/_pytest/runner.py:311: in from_call
result: Optional[TResult] = func()
/usr/lib/python3.8/site-packages/_pytest/runner.py:341: in <lambda>
call = CallInfo.from_call(lambda: list(collector.collect()), "collect")
/usr/lib/python3.8/site-packages/_pytest/doctest.py:532: in collect
module = import_path(self.fspath)
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:544: in import_path
raise ImportPathMismatchError(module_name, module_file, path)
E _pytest.pathlib.ImportPathMismatchError: ('kajiki.tests.test_e2e', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/usr/lib/python3.8/site-packages/kajiki/tests/test_e2e.py', PosixPath('/home/tkloczko/rpmbuild/BUILD/kajiki-0.9.0/kajiki/tests/test_e2e.py'))
_________________________________________________________________ ERROR collecting kajiki/tests/test_ir.py _________________________________________________________________
/usr/lib/python3.8/site-packages/_pytest/runner.py:311: in from_call
result: Optional[TResult] = func()
/usr/lib/python3.8/site-packages/_pytest/runner.py:341: in <lambda>
call = CallInfo.from_call(lambda: list(collector.collect()), "collect")
/usr/lib/python3.8/site-packages/_pytest/doctest.py:532: in collect
module = import_path(self.fspath)
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:544: in import_path
raise ImportPathMismatchError(module_name, module_file, path)
E _pytest.pathlib.ImportPathMismatchError: ('kajiki.tests.test_ir', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/usr/lib/python3.8/site-packages/kajiki/tests/test_ir.py', PosixPath('/home/tkloczko/rpmbuild/BUILD/kajiki-0.9.0/kajiki/tests/test_ir.py'))
______________________________________________________________ ERROR collecting kajiki/tests/test_runtime.py _______________________________________________________________
/usr/lib/python3.8/site-packages/_pytest/runner.py:311: in from_call
result: Optional[TResult] = func()
/usr/lib/python3.8/site-packages/_pytest/runner.py:341: in <lambda>
call = CallInfo.from_call(lambda: list(collector.collect()), "collect")
/usr/lib/python3.8/site-packages/_pytest/doctest.py:532: in collect
module = import_path(self.fspath)
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:544: in import_path
raise ImportPathMismatchError(module_name, module_file, path)
E _pytest.pathlib.ImportPathMismatchError: ('kajiki.tests.test_runtime', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/usr/lib/python3.8/site-packages/kajiki/tests/test_runtime.py', PosixPath('/home/tkloczko/rpmbuild/BUILD/kajiki-0.9.0/kajiki/tests/test_runtime.py'))
________________________________________________________________ ERROR collecting kajiki/tests/test_text.py ________________________________________________________________
/usr/lib/python3.8/site-packages/_pytest/runner.py:311: in from_call
result: Optional[TResult] = func()
/usr/lib/python3.8/site-packages/_pytest/runner.py:341: in <lambda>
call = CallInfo.from_call(lambda: list(collector.collect()), "collect")
/usr/lib/python3.8/site-packages/_pytest/doctest.py:532: in collect
module = import_path(self.fspath)
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:544: in import_path
raise ImportPathMismatchError(module_name, module_file, path)
E _pytest.pathlib.ImportPathMismatchError: ('kajiki.tests.test_text', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/usr/lib/python3.8/site-packages/kajiki/tests/test_text.py', PosixPath('/home/tkloczko/rpmbuild/BUILD/kajiki-0.9.0/kajiki/tests/test_text.py'))
________________________________________________________________ ERROR collecting kajiki/tests/test_xml.py _________________________________________________________________
/usr/lib/python3.8/site-packages/_pytest/runner.py:311: in from_call
result: Optional[TResult] = func()
/usr/lib/python3.8/site-packages/_pytest/runner.py:341: in <lambda>
call = CallInfo.from_call(lambda: list(collector.collect()), "collect")
/usr/lib/python3.8/site-packages/_pytest/doctest.py:532: in collect
module = import_path(self.fspath)
/usr/lib/python3.8/site-packages/_pytest/pathlib.py:544: in import_path
raise ImportPathMismatchError(module_name, module_file, path)
E _pytest.pathlib.ImportPathMismatchError: ('kajiki.tests.test_xml', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/usr/lib/python3.8/site-packages/kajiki/tests/test_xml.py', PosixPath('/home/tkloczko/rpmbuild/BUILD/kajiki-0.9.0/kajiki/tests/test_xml.py'))
========================================================================= short test summary info ==========================================================================
ERROR kajiki/__main__.py - _pytest.pathlib.ImportPathMismatchError: ('kajiki.__main__', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/usr/lib/pyth...
ERROR kajiki/doctype.py - _pytest.pathlib.ImportPathMismatchError: ('kajiki.doctype', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/usr/lib/python...
ERROR kajiki/html_utils.py - _pytest.pathlib.ImportPathMismatchError: ('kajiki.html_utils', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/usr/lib/...
ERROR kajiki/i18n.py - _pytest.pathlib.ImportPathMismatchError: ('kajiki.i18n', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/usr/lib/python3.8/si...
ERROR kajiki/ir.py - _pytest.pathlib.ImportPathMismatchError: ('kajiki.ir', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/usr/lib/python3.8/site-p...
ERROR kajiki/lnotab.py - _pytest.pathlib.ImportPathMismatchError: ('kajiki.lnotab', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/usr/lib/python3....
ERROR kajiki/loader.py - _pytest.pathlib.ImportPathMismatchError: ('kajiki.loader', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/usr/lib/python3....
ERROR kajiki/markup_template.py - _pytest.pathlib.ImportPathMismatchError: ('kajiki.markup_template', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_6...
ERROR kajiki/template.py - _pytest.pathlib.ImportPathMismatchError: ('kajiki.template', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/usr/lib/pyth...
ERROR kajiki/text.py - _pytest.pathlib.ImportPathMismatchError: ('kajiki.text', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/usr/lib/python3.8/si...
ERROR kajiki/util.py - _pytest.pathlib.ImportPathMismatchError: ('kajiki.util', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/usr/lib/python3.8/si...
ERROR kajiki/version.py - _pytest.pathlib.ImportPathMismatchError: ('kajiki.version', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/usr/lib/python...
ERROR kajiki/xml_template.py - _pytest.pathlib.ImportPathMismatchError: ('kajiki.xml_template', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/usr/...
ERROR kajiki/tests/test_cli.py - _pytest.pathlib.ImportPathMismatchError: ('kajiki.tests.test_cli', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/...
ERROR kajiki/tests/test_doctype.py - _pytest.pathlib.ImportPathMismatchError: ('kajiki.tests.test_doctype', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35...
ERROR kajiki/tests/test_e2e.py - _pytest.pathlib.ImportPathMismatchError: ('kajiki.tests.test_e2e', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/...
ERROR kajiki/tests/test_ir.py - _pytest.pathlib.ImportPathMismatchError: ('kajiki.tests.test_ir', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/us...
ERROR kajiki/tests/test_runtime.py - _pytest.pathlib.ImportPathMismatchError: ('kajiki.tests.test_runtime', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35...
ERROR kajiki/tests/test_text.py - _pytest.pathlib.ImportPathMismatchError: ('kajiki.tests.test_text', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_6...
ERROR kajiki/tests/test_xml.py - _pytest.pathlib.ImportPathMismatchError: ('kajiki.tests.test_xml', '/home/tkloczko/rpmbuild/BUILDROOT/python-kajiki-0.9.0-5.fc35.x86_64/...
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 20 errors during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
============================================================================ 20 errors in 1.75s ===========================================================================
In [1]: foo = dict(bar = 'baz')
In [2]: from genshi.template import NewTextTemplate
In [3]: NewTextTemplate('${foo.bar}').generate(foo=foo).render()
Out[3]: 'baz'
In [4]: from kajiki import TextTemplate
In [5]: TextTemplate('${foo.bar}')(dict(foo=foo)).render()
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-5-b774b6cc6e8e> in <module>()
----> 1 TextTemplate('${foo.bar}')(dict(foo=foo)).render()
…/venv/lib/python3.6/site-packages/kajiki/template.py in render(self)
103 def render(self):
104 """Render the template to a string."""
--> 105 return ''.join(self)
106
107 def _gettext(self, s):
…/venv/lib/python3.6/site-packages/kajiki/template.py in __iter__(self)
98 Here, ``chunk`` can be the computed expression result.
99 """
--> 100 for chunk in self.__main__():
101 yield str(chunk)
102
…/venv/lib/python3.6/site-packages/kajiki/util.py in __iter__(self)
75
76 def __iter__(self):
---> 77 for x in self.iterator:
78 if type(x) == flattener:
79 for xx in x:
<string> in __main__()
AttributeError: 'dict' object has no attribute 'bar'
_func.xhtml
<py:def function="abc()">
<p>Hello</p>
</py:def>
master.xhtml
<py:include href='phb.templates.masters._func' />
${abc()}
I have tried the most simple example... as described in the docs, and it's just not working:
>>> import kajiki
>>> Template = kajiki.XMLTemplate('index.html', mode='html5')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python3.8/site-packages/kajiki/xml_template.py", line 52, in XMLTemplate
doc = _Parser(filename, source).parse()
File "/usr/local/lib/python3.8/site-packages/kajiki/xml_template.py", line 695, in parse
raise exc
kajiki.xml_template.XMLTemplateParseError: [<string>:1] syntax error
--> <!DOCTYPE kajiki SYSTEM "kajiki.dtd">index.html
My HTML file:
<!DOCTYPE html>
<html>
<head><!-- Some stuff here --></head>
<body>
<form>
<input checked type="checkbox">
<select>
<option selected>One</option>
<option>Two</option>
<option>Three</option>
</select>
</form>
</body>
</html>
This is on FreeBSD, Python 3.8, latest kajiki installed via pip.
I'd love to try this template engine... any ideas what's wrong?
In specific, loader.py doesn't have FileLoader
mentioned at all, nor do the docs spell out the accepted filename extensions for PackageLoader
.
Also, the online docs seem to be from v0.4.
Are there any initiatives to improve the situation?
You might want to get in touch with the ToscaWidgets2 team which recently removed support for Kajiki in toscawidgets/tw2.core@ea14b79 due to some issues with it.
It looks like it is broken on Py3.3 and has issues with CDATA
There is no code.co_endlinetable and code.co_columntable in python3.11. Upgrading python to 3.11 causes to trash tgext debugbar with exception:
File "/home/ondrejj/.local/lib/python3.11/site-packages/kajiki/template.py", line 419, in patch_code_file_lines
code.co_endlinetable if version_info >= (3, 11) else "REMOVE",
AttributeError: 'code' object has no attribute 'co_endlinetable'
Looks that these attributes are missing in python 3.11.
Python 3.11.0 (main, Oct 24 2022, 00:00:00) [GCC 12.2.1 20220819 (Red Hat 12.2.1-2)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import code
>>> o = code.compile_command("a=1")
>>> o.co_
o.co_argcount o.co_flags o.co_names
o.co_cellvars o.co_freevars o.co_nlocals
o.co_code o.co_kwonlyargcount o.co_positions(
o.co_consts o.co_lines( o.co_posonlyargcount
o.co_exceptiontable o.co_linetable o.co_qualname
o.co_filename o.co_lnotab o.co_stacksize
o.co_firstlineno o.co_name o.co_varnames
>>> o.co_
I can't seem to use <py:import>
within a template that is called via <py:extends>
Here's a test case to show what I'm talking about:
def test_extends_with_import(self):
loader = MockLoader({
'parent.html': XMLTemplate(
'<div>'
'<py:import href="lib.html" alias="lib"/>'
'${lib.foo()}'
'</div>'),
'lib.html': XMLTemplate(
'<div>'
'<py:def function="foo()"><b>foo</b></py:def>'
'</div>'),
'child.html': XMLTemplate('<py:extends href="parent.html"/>')})
child = loader.import_('child.html')
r = child().render()
assert r == '<div><b>foo</b></div>'
This fails with the error NameError: name 'lib' is not defined
.
I can fix it easily enough with this patch:
diff --git a/kajiki/ir.py b/kajiki/ir.py
--- a/kajiki/ir.py
+++ b/kajiki/ir.py
@@ -96,10 +96,13 @@
self.alias = alias
def py(self):
- yield self.line(
- 'local.__kj__.import_(%r, %r, self.__globals__)' % (
- self.tpl_name, self.alias))
+ s = 'local.__kj__.import_(%r, %r, self.__globals__)' % (
+ self.tpl_name, self.alias)
+ if self.alias:
+ yield self.line('%s = %s' % (self.alias, s))
+ else:
+ yield self.line(s)
class IncludeNode(Node):
def __init__(self, tpl_name):
diff --git a/kajiki/tests/test_xml.py b/kajiki/tests/test_xml.py
--- a/kajiki/tests/test_xml.py
+++ b/kajiki/tests/test_xml.py
@@ -542,6 +542,23 @@
</html>''', rsp
But I'm not really happy with this. I don't completely understand what the role of self.__globals__
is here. I'm sure there must be a better fix than this!
It's unable to run kajiki 0.9.2 on python lower than 3.11. There is an requirement on linetable, which requires python3.11. Please, update dependencies and make linetable optional to fix older python compatibility.
Kajiki's HTML modes default to produce "dirty" HTML, e.g. unclosed
# make kajiki render nicer HTML
from kajiki import html_utils
html_utils.HTML_OPTIONAL_END_TAGS.clear()
You can say many things about Genshi, but the (X)HTML it renders is beautiful. I realize that Kajiki uses a totally different way to create the templates which might make "staying close to the original template" difficult, but it should at least preserve closed and shortened end tags.
There's not even basic things covered, like “replace NewTextTemplate, MarkupTemplate, TemplateLoader
with TextTemplate, XMLTemplate, FileLoader
” or “substitude template.generate(foo=bar)
for template(dict(foo=bar))
”.
By the way, is there any plan to bring current Kajiki APIs closer to Genshi ones? And should I report things like missing doctype
and serializer
options for Template.render(…)
as separate issues here?
Within an element body:
In [1]: from genshi.template import MarkupTemplate
In [2]: from kajiki import XMLTemplate
In [3]: MarkupTemplate('<x>${ 1+1 }</x>').generate().render()
Out[3]: '<x>2</x>'
In [4]: XMLTemplate('<x>${ 1+1 }</x>')().render()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-4-70ec8b1a4b9a> in <module>()
----> 1 XMLTemplate('<x>${ 1+1 }</x>')().render()
…/venv/lib/python3.6/site-packages/kajiki/template.py in render(self)
103 def render(self):
104 """Render the template to a string."""
--> 105 return ''.join(self)
106
107 def _gettext(self, s):
…/venv/lib/python3.6/site-packages/kajiki/template.py in __iter__(self)
98 Here, ``chunk`` can be the computed expression result.
99 """
--> 100 for chunk in self.__main__():
101 yield str(chunk)
102
…/venv/lib/python3.6/site-packages/kajiki/util.py in __iter__(self)
75
76 def __iter__(self):
---> 77 for x in self.iterator:
78 if type(x) == flattener:
79 for xx in x:
<string> in __main__()
TypeError: _escape() missing 1 required positional argument: 'value'
Within an attribute:
In [9]: MarkupTemplate("<x y=\"${ 1+1 }\" />").generate().render()
Out[9]: '<x y="2"/>'
In [10]: XMLTemplate("<x y=\"${ 1+1 }\" />")().render()
Out[10]: '<x y="1+1 }"/>'
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.