Fast HTML/XML template engine for Python

Overview

Overview

Chameleon is an HTML/XML template engine for Python. It uses the page templates language.

You can use it in any Python web application with just about any version of Python (2.7 and up, including 3.4+ and pypy).

Visit the documentation for more information.

License and Copyright

This software is made available as-is under a BSD-like license [1] (see included copyright notice).

Notes

[1] This software is licensed under the Repoze license.
Comments
  • Add support to repeat items with no new line inserted

    Add support to repeat items with no new line inserted

    tal:repeat always inserts a new line inbetween repeating elements. Whitespace is sometimes important in HTML and unnecessary whitespace can cause styling problems in some older browsers.

    It would be great if Chameleon could support repeating elements, or text, all on the same line.

    The equivalent bug in zope.tal project is https://bugs.launchpad.net/zope3/+bug/229931

    It seems tricky to do this in a backwards compatible way. A rule that would make sense to me would be that if the repeating element is the first non white space element on its line then add a new line otherwise don't.

    e.g.

        <ul><li tal:repeat="item items" tal:content="item"></li></ul>
    

    would result in

        <ul><li>item 1</li><li>item 2</li><li>item 3</li></ul>
    

    but

        <ul>
            <li tal:repeat="item items" tal:content="item"></li>
        </ul>
    

    would result in

        <ul>
            <li>item 1</li>
            <li>item 2</li>
            <li>item 3</li>
        </ul>
    
    feature 
    opened by anthonygerrard 23
  • Windowsfix

    Windowsfix

    Hi

    I made some changes to Chameleon to get it working correctly on Windows. The problems are related to the way Windows handles temporary files. It should fix Launchpad Bug #731803.

    I also changed the unit tests because they suffer from the same problem. However I'm not sure if everything gets clean up and I think there will be some temp files that are not deleted after the test is run.

    opened by bachp 20
  • No such file or directory error with Plone image_view_fullscreen

    No such file or directory error with Plone image_view_fullscreen

    Traceback

    Traceback (innermost last):
      Module ZPublisher.Publish, line 126, in publish
      Module ZPublisher.mapply, line 77, in mapply
      Module ZPublisher.Publish, line 46, in call_object
      Module Shared.DC.Scripts.Bindings, line 322, in __call__
      Module Shared.DC.Scripts.Bindings, line 359, in _bindAndExec
      Module Products.CMFCore.FSPageTemplate, line 204, in _exec
      Module Products.CMFCore.FSObject, line 183, in _updateFromFS
      Module Products.CMFCore.FSPageTemplate, line 146, in _readFile
      Module zope.pagetemplate.pagetemplate, line 143, in write
      Module five.pt.patches, line 83, in cook
      Module z3c.pt.pagetemplate, line 209, in __init__
      Module chameleon.zpt.template, line 66, in __init__
      Module chameleon.template, line 252, in __init__
    OSError: [Errno 2] No such file or directory: '/usr/local/plone/buildout-cache/eggs/five.pt-2.1.3-py2.6.egg/five/pt/leadImage-1.jpg'
    

    Steps to reproduce

    • Start with a Plone 4.1 instance using Chameleon
    • Create new site
    • Add a News Item to the News folder, including an image
    • View the News Item
    • Click on the image in the news item view, which takes you to the image_view_fullscreen view. This gives the error above.

    Notes

    I verified this only happens with Chameleon enabled, and not with the default Plone 4.1

    And, 22% increase in pages/second when tested with ab. Awesome!

    five.pt 
    opened by tsimkins 16
  • Do not silently ignore unclosed tags

    Do not silently ignore unclosed tags

    Fixes #327

    @d-maurer This is a draft as food for discussion on a fix for #327. The code change will flag up any unclosed tag - but is that really desirable? As the failing test shows it will also flag up simple tags that few people close, like <br>. But it feels a fix shouldn't introduce code to introspect the unclosed tag to see if it's OK to ignore it.

    opened by dataflake 15
  • Bug in rendering tal:attributes in case of boolean values?

    Bug in rendering tal:attributes in case of boolean values?

    We discovered a changement in rendering of boolean attributes in the option tag since release 3.8.0 (using python 3.8). Example: <select> <option value="" tal:attributes="selected True">Selected</option> <option value="a" tal:attributes="selected False">Not selected</option> <option value="ok" tal:attributes="selected None">OK</option> </select> will render to: <select> <option value="" selected="True">Selected</option> <option value="a" selected="False">Not selected</option> <option value="ok">OK</option> </select> Can somebody confirm this? The workaround for now would be to pin down the version to 3.7.4.

    opened by DadaDaMotha 15
  • fix chameleon `default` handling

    fix chameleon `default` handling

    Use the default_marker integration parameter rather than a locally defined marker("default") as representation of the TALES default object.

    This fix would resolve "https://github.com/zopefoundation/Zope/pull/853".

    opened by d-maurer 13
  • PageTemplate digest cannot be computed for TTW template

    PageTemplate digest cannot be computed for TTW template

    chameleon.template.BaseTemplate.digest() prepends the pathname (minus extension) to the digest under this condition:

            if self.filename is not BaseTemplate.filename:
                digest = os.path.splitext(self.filename)[0] + '-' + digest
    

    However, when self is <PageTempate None> this throws the following error:

    *** AttributeError: 'NoneType' object has no attribute 'rfind'
    

    This happens in the following scenario:

    1. Install a clean Plone 4.3.15 buildout
    2. Add Products.PloneFormGen 1.7.23 to the buildout
    3. Add five.pt to the buildout
    4. Create a new Plone site, activate PloneFormGen
    5. Create a FormFolder
    6. Go to the mailer Mail Adapter which is added by default to a new Form Folder
    7. Edit the mailer
    8. Save it without making any changes

    Result: You will not be able to save. The following validation error for the textarea containing the default mail template is displayed:

    Compilation Failed
    
    exceptions.AttributeError: 'NoneType' object has no attribute 'rfind'
    

    I'm not sure if there is something that PloneFormGen needs to do differently, but I do know that changing the condition to this fixed the problem:

            if self.filename and self.filename is not BaseTemplate.filename:
    

    Is self = <PageTemplate None> because we are being called from __init__()? Either way, this is a TTW template, so it should not have a filename.

    This is the tail of the stack where the error happens:

     /usr/local/plone-4.3/buildout-cache/eggs/Products.CMFFormController-3.0.8-py2.7.egg/Products/CMFFormController/FSControllerValidator.py(58)__call__()
    -> result = FSControllerValidator.inheritedAttribute('__call__')(self, *args, **kwargs)
      /usr/local/plone-4.3/buildout-cache/eggs/Products.CMFFormController-3.0.8-py2.7.egg/Products/CMFFormController/Script.py(145)__call__()
    -> return BaseFSPythonScript.__call__(self, *args, **kw)
      /usr/local/plone-4.3/buildout-cache/eggs/Products.CMFCore-2.2.10-py2.7.egg/Products/CMFCore/FSPythonScript.py(127)__call__()
    -> return Script.__call__(self, *args, **kw)
      /usr/local/plone-4.3/buildout-cache/eggs/Zope2-2.13.26-py2.7.egg/Shared/DC/Scripts/Bindings.py(322)__call__()
    -> return self._bindAndExec(args, kw, None)
      /usr/local/plone-4.3/buildout-cache/eggs/Zope2-2.13.26-py2.7.egg/Shared/DC/Scripts/Bindings.py(359)_bindAndExec()
    -> return self._exec(bound_data, args, kw)
      /usr/local/plone-4.3/buildout-cache/eggs/Products.PythonScripts-2.13.2-py2.7.egg/Products/PythonScripts/PythonScript.py(344)_exec()
    -> result = f(*args, **kw)
      /usr/local/plone-4.3/zeoserver/Script (Python)(6)validate_base()
      /usr/local/plone-4.3/buildout-cache/eggs/Products.Archetypes-1.9.17-py2.7.egg/Products/Archetypes/BaseObject.py(487)validate()
    -> errors=errors, data=data, metadata=metadata)
      /usr/local/plone-4.3/buildout-cache/eggs/Products.Archetypes-1.9.17-py2.7.egg/Products/Archetypes/Schema/__init__.py(606)validate()
    -> REQUEST=REQUEST)
      /usr/local/plone-4.3/buildout-cache/eggs/Products.Archetypes-1.9.17-py2.7.egg/Products/Archetypes/Field.py(345)validate()
    -> res = self.validate_validators(value, instance, errors, **kwargs)
      /usr/local/plone-4.3/buildout-cache/eggs/Products.Archetypes-1.9.17-py2.7.egg/Products/Archetypes/Field.py(358)validate_validators()
    -> field=self, **kwargs)
      /usr/local/plone-4.3/buildout-cache/eggs/Products.validation-2.0.2-py2.7.egg/Products/validation/chain.py(136)__call__()
    -> result = validator(value, *args, **kwargs)
      /usr/local/plone-4.3/buildout-cache/eggs/Products.TemplateFields-1.2.5-py2.7.egg/Products/TemplateFields/validators.py(98)__call__()
    -> pt.write(value)
      /usr/local/plone-4.3/buildout-cache/eggs/zope.pagetemplate-3.6.3-py2.7.egg/zope/pagetemplate/pagetemplate.py(162)write()
    -> self._cook()
      /usr/local/plone-4.3/buildout-cache/eggs/zope.pagetemplate-3.6.3-py2.7.egg/zope/pagetemplate/pagetemplate.py(209)_cook()
    -> source_file, self._text, pt_engine, self.content_type)
      /usr/local/plone-4.3/buildout-cache/eggs/five.pt-2.2.4-py2.7.egg/five/pt/engine.py(132)cook()
    -> encoding='utf-8', extra_builtins=cls.extra_builtins,
      /usr/local/plone-4.3/buildout-cache/eggs/Chameleon-3.1-py2.7.egg/chameleon/zpt/template.py(185)__init__()
    -> super(PageTemplate, self).__init__(body, **config)
      /usr/local/plone-4.3/buildout-cache/eggs/Chameleon-3.1-py2.7.egg/chameleon/template.py(116)__init__()
    -> self.write(body)
      /usr/local/plone-4.3/buildout-cache/eggs/Chameleon-3.1-py2.7.egg/chameleon/template.py(209)write()
    -> self.cook(body)
      /usr/local/plone-4.3/buildout-cache/eggs/Chameleon-3.1-py2.7.egg/chameleon/template.py(145)cook()
    -> digest = self.digest(body, names)
      /usr/local/plone-4.3/buildout-cache/eggs/Chameleon-3.1-py2.7.egg/chameleon/zpt/template.py(297)digest()
    -> hex = super(PageTemplate, self).digest(body, names)
    > /usr/local/plone-4.3/buildout-cache/eggs/Chameleon-3.1-py2.7.egg/chameleon/template.py(247)digest()
    -> digest = os.path.splitext(self.filename)[0] + '-' + digest
    (Pdb) self
    <PageTemplate None>
    (Pdb) self.filename
    (Pdb) os.path.splitext(self.filename)
    *** AttributeError: 'NoneType' object has no attribute 'rfind'
    

    See https://community.plone.org/t/cant-save-pfg-mailer-adapter-compilation-failed-exceptions-attributeerror-nonetype-object-has-no-attribute-rfind/5088?u=fulv

    opened by fulv 12
  • Tag value need to be translated

    Tag value need to be translated

    How can I translate tag value in chameleon template?

    Something like this

    <meta name="keywords" content="need to be translated"/>
    

    or this

    <input type="submit" value="need to be translated"/>
    

    I use meta as slot

    <meta metal:fill-slot="description" name="description" content="need to be translated"/>
    

    Thanks!

    opened by maxvi 12
  • Python 3.9: Creating invalid Python code

    Python 3.9: Creating invalid Python code

    This following snipped of generated Chameleon code is taken from the Zope tests which fail on Python 3.9 because of generated invalid syntax:

    
                # <Substitution "y/z | python:'||'[:0]" (15:27)> -> __attr_name
                __token = 486
                try:
                    __attr_name = _static_4444020112(getitem('y'), econtext, True, ('z', ))
                except (AttributeError, LookupError, NameError, TypeError, ValueError, _NotFound, _Unauthorized, _LocationError, ):
                    __token = 492
                    __attr_name = _guarded_getitem('||', :0)
    

    The error is in the last line in :0.

    In Python 3.8 the generated code is valid and looks like the following:

                # <Substitution "y/z | python:'||'[:0]" (15:27)> -> __attr_name
                __token = 486
                try:
                    __attr_name = _static_4561636800(getitem('y'), econtext, True, ('z', ))
                except (AttributeError, LookupError, NameError, TypeError, ValueError, _NotFound, _Unauthorized, _LocationError, ):
                    __token = 492
                    __attr_name = _guarded_getitem('||', get('slice', slice)(None, 0, None))
    

    I was using 3.9.0b3 on MacOS but the error is also on TravisCI, see https://travis-ci.org/github/zopefoundation/Zope/jobs/703426836

    core 
    opened by icemac 11
  • Add i18n:language attribute

    Add i18n:language attribute

    I have a situation where I need to force translation to a specific language in a template. Would it be possible to support that with a i18n:language attribute? Usage would look like this:

    <button i18n:translate="" lang="en" i18n:target="en">Continue</button>
    <button i18n:translate="" lang="nl" i18n:target="nl">Continue</button>
    <button i18n:translate="" lang="de" i18n:target="de">Continue</button>
    

    Which would result in:

    <button lang="en">Continue</button>
    <button lang="nl">Verder</button>
    <button lang="de">Weiter</button>
    
    opened by wichert 11
  • does the load expression reuse the loader cache?

    does the load expression reuse the loader cache?

    I am not sure this is an issue -- I'm just trying to understand the code. Here goes:

    The load expression uses __loader, which is initialized as _loader in the init of PageTemplateFile. This is always created as an instance of the loader_class.

    The loader in chameleon.loader keeps a cache of templates in self.registry through a decorator.

    If I create a page template loader and load a page template file, and then load it again, it'll come from the cache. But that page template file creates its own loader again, so that when the load expression fires it will set it up in a new cache. This means that if page template a loads up m, and page template b then loads up m again, b won't benefit from the cache of a -- it'll load m again.

    I run into all this because I'm trying to create a custom loader, which I'd like to propagate into the templates it loads, so that any load expression in that template also uses that loader. But custom loaders don't propagate to load expressions, do they? Instead I have to initialize it with its own class as a keyword argument, I think.

    Again, I may get this all wrong -- I'm trying to read the code and I may be misunderstanding something. But I thought it was worth reporting.

    opened by faassen 11
  • VS Code extension

    VS Code extension

    Hi there,

    Is there anyway that we can have any VS code extension for Chameleon as the templating language? I see that a similar feature exists in PyCharm professional.

    Thanks, Sam

    tooling 
    opened by samiit 2
  • Replace pkg_resources

    Replace pkg_resources

    Just importing pkg_resources becomes slower and slower the more packages are installed. Even on fast machines with SSDs this can add a second or more to the startup time.

    opened by fschulze 1
  • str() of Chameleon Exception throws UnicodeDecodeError

    str() of Chameleon Exception throws UnicodeDecodeError

    In Zope PageTemplates there is a handy method called "find_bad_templates", which does the obvious: traverse through all PageTemplates in a Folder and listing those, where the "_cook" method fails.

    However, we encountered a PageTemplate where the traversing stops with a "UnicodeDecodeError". The reason is that described method catches the Chameleon Exceptions and saves them as a string. Schematically:

    def _cook(self):
        ...
        try:
            ..._cook()
        except:
            etype, e = sys.exc_info()[:2]
            self._v_errors = [
                "Compilation failed",
                "%s.%s: %s" % (etype.__module__, etype.__name__, e)
        #               ^^                                       ^
                ]
    

    If an exception occurs, it is converted to a string. And that can fail, if the token contains a non-ascii char. We can reproduce it with Python2 like this:

    from chameleon import exc, tokenize
    body = u'<p>ein text mit uumlaut\xfc</p>'
    string = body[3:-4]
    token = tokenize.Token(string, 3, body)
    e = exc.LanguageError('Invalid define syntax', token)
    str(e)
    

    The last line throws an exception:

    Traceback (most recent call last):
      File ...
        str(e)
      File ".../chameleon/src/chameleon/exc.py", line 192, in __str__
        text += "\n" + line
    UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 47:
      ordinal not in range(128)
    

    I will make a pull request to fix this...

    opened by wlang42 0
  • Cannot access repeat variable when iterating over dict items

    Cannot access repeat variable when iterating over dict items

    To iterate over a list, you can access the repeat variable by referencing the iteration item variable name:

    <div tal:repeat="item range(10)">
      <p tal:condition="repeat.item.even">Even</p>
      <p tal:condition="repeat.item.odd">Odd</p>
    </div>
    

    However it doesn't seem possible to access the repeat variable when iterating over dict items:

    <div tal:repeat="(key, value) my_dict.items()">
      <p tal:condition="repeat.key.even">Even</p>
      <p tal:condition="repeat.key.odd">Odd</p>
    </div>
    

    Essence of the traceback:

    ...
    KeyError: 'end'
    
    During handling of the above exception, another exception occurred:
    
    ...
    AttributeError: end
    
    During handling of the above exception, another exception occurred:
    
    ...
    AttributeError: end
    
    feature 
    opened by bennuttall 1
  • 3.9.1: pytest is failing

    3.9.1: pytest is failing

    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 --no-isolation
    • because I'm calling build with --no-isolation I'm using during all processes only locally installed modules
    • install .whl file in </install/prefix>
    • run pytest with PYTHONPATH pointing to sitearch and sitelib inside </install/prefix>

    Here is pytest output:

    + PYTHONPATH=/home/tkloczko/rpmbuild/BUILDROOT/python-chameleon-3.9.1-5.fc35.x86_64/usr/lib64/python3.8/site-packages:/home/tkloczko/rpmbuild/BUILDROOT/python-chameleon-3.9.1-5.fc35.x86_64/usr/lib/python3.8/site-packages
    + /usr/bin/pytest -ra
    =========================================================================== 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/chameleon-3.9.1
    collected 71 items
    
    src/chameleon/tests/test_astutil.py .                                                                                                                                [  1%]
    src/chameleon/tests/test_doctests.py EEEEE                                                                                                                           [  8%]
    src/chameleon/tests/test_exc.py .                                                                                                                                    [  9%]
    src/chameleon/tests/test_loader.py ........                                                                                                                          [ 21%]
    src/chameleon/tests/test_parser.py ..                                                                                                                                [ 23%]
    src/chameleon/tests/test_sniffing.py ....                                                                                                                            [ 29%]
    src/chameleon/tests/test_templates.py ................................................                                                                               [ 97%]
    src/chameleon/tests/test_tokenizer.py ..                                                                                                                             [100%]
    
    ================================================================================== ERRORS ==================================================================================
    _______________________________________________________________ ERROR at setup of DoctestCase.test_compiler ________________________________________________________________
    
    cls = <class '_pytest.runner.CallInfo'>, func = <function call_runtest_hook.<locals>.<lambda> at 0x7ff580f1e3a0>, when = 'setup'
    reraise = (<class '_pytest.outcomes.Exit'>, <class 'KeyboardInterrupt'>)
    
        @classmethod
        def from_call(
            cls,
            func: "Callable[[], TResult]",
            when: "Literal['collect', 'setup', 'call', 'teardown']",
            reraise: Optional[
                Union[Type[BaseException], Tuple[Type[BaseException], ...]]
            ] = None,
        ) -> "CallInfo[TResult]":
            excinfo = None
            start = timing.time()
            precise_start = timing.perf_counter()
            try:
    >           result: Optional[TResult] = func()
    
    /usr/lib/python3.8/site-packages/_pytest/runner.py:311:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    /usr/lib/python3.8/site-packages/_pytest/runner.py:255: in <lambda>
        lambda: ihook(item=item, **kwds), when=when, reraise=reraise
    /usr/lib/python3.8/site-packages/pluggy/_hooks.py:265: in __call__
        return self._hookexec(self.name, self.get_hookimpls(), kwargs, firstresult)
    /usr/lib/python3.8/site-packages/pluggy/_manager.py:80: in _hookexec
        return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
    /usr/lib/python3.8/site-packages/_pytest/runner.py:150: in pytest_runtest_setup
        item.session._setupstate.prepare(item)
    /usr/lib/python3.8/site-packages/_pytest/runner.py:452: in prepare
        raise e
    /usr/lib/python3.8/site-packages/_pytest/runner.py:449: in prepare
        col.setup()
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    self = <TestCaseFunction test_compiler>
    
        def setup(self) -> None:
            # A bound method to be called during teardown() if set (see 'runtest()').
            self._explicit_tearDown: Optional[Callable[[], None]] = None
            assert self.parent is not None
            self._testcase = self.parent.obj(self.name)  # type: ignore[attr-defined]
    >       self._obj = getattr(self._testcase, self.name)
    E       AttributeError: '_DocTestSuite' object has no attribute 'test_compiler'
    
    /usr/lib/python3.8/site-packages/_pytest/unittest.py:195: AttributeError
    __________________________________________________________________ ERROR at setup of DoctestCase.test_exc __________________________________________________________________
    
    cls = <class '_pytest.runner.CallInfo'>, func = <function call_runtest_hook.<locals>.<lambda> at 0x7ff580313af0>, when = 'setup'
    reraise = (<class '_pytest.outcomes.Exit'>, <class 'KeyboardInterrupt'>)
    
        @classmethod
        def from_call(
            cls,
            func: "Callable[[], TResult]",
            when: "Literal['collect', 'setup', 'call', 'teardown']",
            reraise: Optional[
                Union[Type[BaseException], Tuple[Type[BaseException], ...]]
            ] = None,
        ) -> "CallInfo[TResult]":
            excinfo = None
            start = timing.time()
            precise_start = timing.perf_counter()
            try:
    >           result: Optional[TResult] = func()
    
    /usr/lib/python3.8/site-packages/_pytest/runner.py:311:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    /usr/lib/python3.8/site-packages/_pytest/runner.py:255: in <lambda>
        lambda: ihook(item=item, **kwds), when=when, reraise=reraise
    /usr/lib/python3.8/site-packages/pluggy/_hooks.py:265: in __call__
        return self._hookexec(self.name, self.get_hookimpls(), kwargs, firstresult)
    /usr/lib/python3.8/site-packages/pluggy/_manager.py:80: in _hookexec
        return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
    /usr/lib/python3.8/site-packages/_pytest/runner.py:150: in pytest_runtest_setup
        item.session._setupstate.prepare(item)
    /usr/lib/python3.8/site-packages/_pytest/runner.py:452: in prepare
        raise e
    /usr/lib/python3.8/site-packages/_pytest/runner.py:449: in prepare
        col.setup()
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    self = <TestCaseFunction test_exc>
    
        def setup(self) -> None:
            # A bound method to be called during teardown() if set (see 'runtest()').
            self._explicit_tearDown: Optional[Callable[[], None]] = None
            assert self.parent is not None
            self._testcase = self.parent.obj(self.name)  # type: ignore[attr-defined]
    >       self._obj = getattr(self._testcase, self.name)
    E       AttributeError: '_DocTestSuite' object has no attribute 'test_exc'
    
    /usr/lib/python3.8/site-packages/_pytest/unittest.py:195: AttributeError
    __________________________________________________________________ ERROR at setup of DoctestCase.test_tal __________________________________________________________________
    
    cls = <class '_pytest.runner.CallInfo'>, func = <function call_runtest_hook.<locals>.<lambda> at 0x7ff5801ebd30>, when = 'setup'
    reraise = (<class '_pytest.outcomes.Exit'>, <class 'KeyboardInterrupt'>)
    
        @classmethod
        def from_call(
            cls,
            func: "Callable[[], TResult]",
            when: "Literal['collect', 'setup', 'call', 'teardown']",
            reraise: Optional[
                Union[Type[BaseException], Tuple[Type[BaseException], ...]]
            ] = None,
        ) -> "CallInfo[TResult]":
            excinfo = None
            start = timing.time()
            precise_start = timing.perf_counter()
            try:
    >           result: Optional[TResult] = func()
    
    /usr/lib/python3.8/site-packages/_pytest/runner.py:311:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    /usr/lib/python3.8/site-packages/_pytest/runner.py:255: in <lambda>
        lambda: ihook(item=item, **kwds), when=when, reraise=reraise
    /usr/lib/python3.8/site-packages/pluggy/_hooks.py:265: in __call__
        return self._hookexec(self.name, self.get_hookimpls(), kwargs, firstresult)
    /usr/lib/python3.8/site-packages/pluggy/_manager.py:80: in _hookexec
        return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
    /usr/lib/python3.8/site-packages/_pytest/runner.py:150: in pytest_runtest_setup
        item.session._setupstate.prepare(item)
    /usr/lib/python3.8/site-packages/_pytest/runner.py:452: in prepare
        raise e
    /usr/lib/python3.8/site-packages/_pytest/runner.py:449: in prepare
        col.setup()
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    self = <TestCaseFunction test_tal>
    
        def setup(self) -> None:
            # A bound method to be called during teardown() if set (see 'runtest()').
            self._explicit_tearDown: Optional[Callable[[], None]] = None
            assert self.parent is not None
            self._testcase = self.parent.obj(self.name)  # type: ignore[attr-defined]
    >       self._obj = getattr(self._testcase, self.name)
    E       AttributeError: '_DocTestSuite' object has no attribute 'test_tal'
    
    /usr/lib/python3.8/site-packages/_pytest/unittest.py:195: AttributeError
    _________________________________________________________________ ERROR at setup of DoctestCase.test_tales _________________________________________________________________
    
    cls = <class '_pytest.runner.CallInfo'>, func = <function call_runtest_hook.<locals>.<lambda> at 0x7ff580fd3790>, when = 'setup'
    reraise = (<class '_pytest.outcomes.Exit'>, <class 'KeyboardInterrupt'>)
    
        @classmethod
        def from_call(
            cls,
            func: "Callable[[], TResult]",
            when: "Literal['collect', 'setup', 'call', 'teardown']",
            reraise: Optional[
                Union[Type[BaseException], Tuple[Type[BaseException], ...]]
            ] = None,
        ) -> "CallInfo[TResult]":
            excinfo = None
            start = timing.time()
            precise_start = timing.perf_counter()
            try:
    >           result: Optional[TResult] = func()
    
    /usr/lib/python3.8/site-packages/_pytest/runner.py:311:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    /usr/lib/python3.8/site-packages/_pytest/runner.py:255: in <lambda>
        lambda: ihook(item=item, **kwds), when=when, reraise=reraise
    /usr/lib/python3.8/site-packages/pluggy/_hooks.py:265: in __call__
        return self._hookexec(self.name, self.get_hookimpls(), kwargs, firstresult)
    /usr/lib/python3.8/site-packages/pluggy/_manager.py:80: in _hookexec
        return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
    /usr/lib/python3.8/site-packages/_pytest/runner.py:150: in pytest_runtest_setup
        item.session._setupstate.prepare(item)
    /usr/lib/python3.8/site-packages/_pytest/runner.py:452: in prepare
        raise e
    /usr/lib/python3.8/site-packages/_pytest/runner.py:449: in prepare
        col.setup()
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    self = <TestCaseFunction test_tales>
    
        def setup(self) -> None:
            # A bound method to be called during teardown() if set (see 'runtest()').
            self._explicit_tearDown: Optional[Callable[[], None]] = None
            assert self.parent is not None
            self._testcase = self.parent.obj(self.name)  # type: ignore[attr-defined]
    >       self._obj = getattr(self._testcase, self.name)
    E       AttributeError: '_DocTestSuite' object has no attribute 'test_tales'
    
    /usr/lib/python3.8/site-packages/_pytest/unittest.py:195: AttributeError
    _________________________________________________________________ ERROR at setup of DoctestCase.test_utils _________________________________________________________________
    
    cls = <class '_pytest.runner.CallInfo'>, func = <function call_runtest_hook.<locals>.<lambda> at 0x7ff58038ef70>, when = 'setup'
    reraise = (<class '_pytest.outcomes.Exit'>, <class 'KeyboardInterrupt'>)
    
        @classmethod
        def from_call(
            cls,
            func: "Callable[[], TResult]",
            when: "Literal['collect', 'setup', 'call', 'teardown']",
            reraise: Optional[
                Union[Type[BaseException], Tuple[Type[BaseException], ...]]
            ] = None,
        ) -> "CallInfo[TResult]":
            excinfo = None
            start = timing.time()
            precise_start = timing.perf_counter()
            try:
    >           result: Optional[TResult] = func()
    
    /usr/lib/python3.8/site-packages/_pytest/runner.py:311:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    /usr/lib/python3.8/site-packages/_pytest/runner.py:255: in <lambda>
        lambda: ihook(item=item, **kwds), when=when, reraise=reraise
    /usr/lib/python3.8/site-packages/pluggy/_hooks.py:265: in __call__
        return self._hookexec(self.name, self.get_hookimpls(), kwargs, firstresult)
    /usr/lib/python3.8/site-packages/pluggy/_manager.py:80: in _hookexec
        return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
    /usr/lib/python3.8/site-packages/_pytest/runner.py:150: in pytest_runtest_setup
        item.session._setupstate.prepare(item)
    /usr/lib/python3.8/site-packages/_pytest/runner.py:452: in prepare
        raise e
    /usr/lib/python3.8/site-packages/_pytest/runner.py:449: in prepare
        col.setup()
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    
    self = <TestCaseFunction test_utils>
    
        def setup(self) -> None:
            # A bound method to be called during teardown() if set (see 'runtest()').
            self._explicit_tearDown: Optional[Callable[[], None]] = None
            assert self.parent is not None
            self._testcase = self.parent.obj(self.name)  # type: ignore[attr-defined]
    >       self._obj = getattr(self._testcase, self.name)
    E       AttributeError: '_DocTestSuite' object has no attribute 'test_utils'
    
    /usr/lib/python3.8/site-packages/_pytest/unittest.py:195: AttributeError
    ========================================================================= short test summary info ==========================================================================
    ERROR src/chameleon/tests/test_doctests.py::DoctestCase::test_compiler - AttributeError: '_DocTestSuite' object has no attribute 'test_compiler'
    ERROR src/chameleon/tests/test_doctests.py::DoctestCase::test_exc - AttributeError: '_DocTestSuite' object has no attribute 'test_exc'
    ERROR src/chameleon/tests/test_doctests.py::DoctestCase::test_tal - AttributeError: '_DocTestSuite' object has no attribute 'test_tal'
    ERROR src/chameleon/tests/test_doctests.py::DoctestCase::test_tales - AttributeError: '_DocTestSuite' object has no attribute 'test_tales'
    ERROR src/chameleon/tests/test_doctests.py::DoctestCase::test_utils - AttributeError: '_DocTestSuite' object has no attribute 'test_utils'
    ======================================================================= 66 passed, 5 errors in 2.97s =======================================================================
    
    opened by kloczek 3
  • python complains about BaseException being unsafe

    python complains about BaseException being unsafe

      File "../lib/python3.8/site-packages/chameleon/exc.py", line 321, in __call__
        exc = create_formatted_exception(exc, type(exc), exc._original__str__)
      File "../lib/python3.8/site-packages/chameleon/utils.py", line 227, in create_formatted_exception
        inst = cls.__new__(new)
    TypeError: BaseException.__new__(SyntaxError) is not safe, use SyntaxError.__new__()
    
            try:
                inst = BaseException.__new__(new)
            except TypeError:
                inst = cls.__new__(new)     # line 227
    
            BaseException.__init__(inst, *exc.args)
            inst.__dict__ = exc.__dict__
    
    opened by yogo1212 1
HTML Template Linter and Formatter. Use with Django, Jinja, Nunjucks and Handlebars templates.

Find common formatting issues and reformat HTML templates. Django · Jinja · Nunjucks · Handlebars · Mustache · GoLang Ps, --check it out on other temp

Riverside Healthcare Analytics 263 Jan 1, 2023
A simple, elegant Python based web templating engine (part of web.py).

Templator Simple, elegant Python based web templating (part of web.py). If you are familiar with Python, there is no new syntax to learn. This is a st

Dan 1 Dec 13, 2021
Use a docx as a jinja2 template

Use a docx as a jinja2 template

Eric Lapouyade 1.4k Jan 2, 2023
A general purpose template driven code generator

?? Shit Mountain Generator A general purpose template driven code generator Contribute shits to your company's shit mountain more efficiently! Quick S

Kelly 14 Mar 9, 2022
A string template language hosted by Python3 runtime

A string template language hosted by Python3 runtime. Conventionally, the source code of this language is written in plain text with utf-8 encoding and stored in a file with extension ".meme".

null 6 Nov 2, 2022
A Python command-line utility for validating that the outputs of a given Declarative Form Azure Portal UI JSON template map to the input parameters of a given ARM Deployment Template JSON template

A Python command-line utility for validating that the outputs of a given Declarative Form Azure Portal UI JSON template map to the input parameters of a given ARM Deployment Template JSON template

Glenn Musa 1 Feb 3, 2022
Safely add untrusted strings to HTML/XML markup.

MarkupSafe MarkupSafe implements a text object that escapes characters so it is safe to use in HTML and XML. Characters that have special meanings are

The Pallets Projects 514 Dec 31, 2022
Parsel lets you extract data from XML/HTML documents using XPath or CSS selectors

Parsel Parsel is a BSD-licensed Python library to extract and remove data from HTML and XML using XPath and CSS selectors, optionally combined with re

Scrapy project 859 Dec 29, 2022
Use minify-html, the extremely fast HTML + JS + CSS minifier, with Django.

django-minify-html Use minify-html, the extremely fast HTML + JS + CSS minifier, with Django. Requirements Python 3.8 to 3.10 supported. Django 2.2 to

Adam Johnson 60 Dec 28, 2022
A HTML-code compiler-thing that lets you reuse HTML code.

RHTML RHTML stands for Reusable-Hyper-Text-Markup-Language, and is pronounced "Rech-tee-em-el" despite how its abbreviation is. As the name stands, RH

Duckie 4 Nov 15, 2021
That project takes as input special TXT File, divides its content into lsit of HTML objects and then creates HTML file from them.

That project takes as input special TXT File, divides its content into lsit of HTML objects and then creates HTML file from them.

null 1 Jan 10, 2022
Lektor-html-pretify - Lektor plugin to pretify the HTML DOM using Beautiful Soup

html-pretify Lektor plugin to pretify the HTML DOM using Beautiful Soup. How doe

Chaos Bodensee 2 Nov 8, 2022
Django-Text-to-HTML-converter - The simple Text to HTML Converter using Django framework

Django-Text-to-HTML-converter This is the simple Text to HTML Converter using Dj

Nikit Singh Kanyal 6 Oct 9, 2022
Simple reuse of partial HTML page templates in the Jinja template language for Python web frameworks.

Jinja Partials Simple reuse of partial HTML page templates in the Jinja template language for Python web frameworks. (There is also a Pyramid/Chameleo

Michael Kennedy 106 Dec 28, 2022
HTML Template Linter and Formatter. Use with Django, Jinja, Nunjucks and Handlebars templates.

Find common formatting issues and reformat HTML templates. Django · Jinja · Nunjucks · Handlebars · Mustache · GoLang Ps, --check it out on other temp

Riverside Healthcare Analytics 263 Jan 1, 2023
Template for a Dataflow Flex Template in Python

Dataflow Flex Template in Python This repository contains a template for a Dataflow Flex Template written in Python that can easily be used to build D

STOIX 5 Apr 28, 2022
Discord.py-Bot-Template - Discord Bot Template with Python 3.x

Discord Bot Template with Python 3.x This is a template for creating a custom Di

Keagan Landfried 3 Jul 17, 2022
Fastapi-ml-template - Fastapi ml template with python

FastAPI ML Template Run Web API Local $ sh run.sh # poetry run uvicorn app.mai

Yuki Okuda 29 Nov 20, 2022
Flask Project Template A full feature Flask project template.

Flask Project Template A full feature Flask project template. See also Python-Project-Template for a lean, low dependency Python app. HOW TO USE THIS

Bruno Rocha 96 Dec 23, 2022