Is there a way to add tempate string which contains error to mako`s error trace?
I don't think you're likely to find such a thing. Like all the other fast python template engines, Mako achieves its speed by compiling your template into python code and then executing it. An exception will divert execution out of your template's code, so by the time one is raised, that template will have no way of displaying it (or doing anything else for that matter).
As an alternative, I suggest putting your template rendering code inside a try block, and rendering any caught exceptions with a separate template used specifically for that purpose.
I was looking for another error I have and found this. I though it would be nice if you still ever need this, you can achieve it by setting mako.strict_undefined = True. I am using mako-0.6.2 so it may not been possible in the version back in 2010.
Related
So, I'm new to programming and my question is:
Is it considered a bad practice to use an exception handler to override error-message-behaviour of default methods of a programming language with custom functionality? I mean, is it ethically correct to use something like this (Python):
def index(p, val):
try:
return p.index(val)
except ValueError:
return -1
Maybe I wasn't precise enough. What I meant is: is it a normal or not-recommended practice to consider thrown exceptions (well, I guess it's not applicable everywhere) as legit and valid case-statements?
Like, the idea of the example given above is not to make a custom error message, but to suppress possible errors happening without warning neither users nor other program modules, that something is going wrong.
I think that doing something like this is OK as long as you use function names which make it clear that the user isn't using a built-in. If the user thinks they're using a builtin and all of a sudden index returns -1, imagine the bugs that could happen ... They do:
a[index(a,'foo')]
and all of a sudden they get the last element in the list (which isn't foo).
As a very important rule though, Only handle exceptions that you know what to do with. Your example above does this nicely. Kudos.
This is perfectly fine but depends on what kind of condition you are checking. It is the developers responsibility to check for these conditions. Some exceptions are fatal for the program and some may not. All depends on the context of the method.
With a language like python, I would argue it is much better to give a custom error message for the function than the generic ValueError exception.
However, for your own applications, having this functionality inside your methods can make code easier to read and maintain.
For other languages, the same is true, but you should try and make sure that you don't mimick another function with a different behaviour, whilst hiding the Exceptions.
If you know where exactly your errors will occur and the cause of error too, then there is nothing wrong with such kind of handling. Becaues you are just taking appropriate action for something wrong happening, that you know can happen .
So, For E.g: - If you are trying to divide two numbers, and you know that if the denominator is 0, then you can't divide, then in that case you can use a custom message to denote the problem.
I don't have an easy access to the code, I'm working only with a Mako template, and I would like to know all the values that were made available to the template, which I can use.
Is there a way to add something in the template, so that the output result would contain all the variables (recursively)?
You're looking for the context object. After a minute or two of play:
${context.keys()} # list of direct variable names
${context.__dict__} # probably more along what you're looking for.
The entire section on the Mako Runtime environment is probably worth reading, especially the part 'All the built in names.' You may find the other post I just made relevant:
Mako how to check if variable exists or not.
Lets try this I think this must help:
${globals()}
I am trying to override the default implementation of the raw/endraw block tag in jinja2. I am familiar with how to write custom tag extensions, but in this case my extension is not firing (the default implementation of the raw tag is still being called).
Can this even be done? If not, can someone point me to where in the source the raw tag is implemented so I can patch it to fit my needs.
Thanks.
It looks like overriding the raw/endraw tags is not supported.
The code for dealing with the raw/endraw tags is directly in the lexer, and the handling is hard coded.
So you would probably have to patch the code. Luckily, the code is hosted on github, so it would be easy to have your own shallow fork of jinja2, but still keep up to date with future improvements from the main distribution.
One of my favorite features about python is that you can write configuration files in python that are very simple to read and understand. If you put a few boundaries on yourself, you can be pretty confident that non-pythonistas will know exactly what you mean and will be perfectly capable of reconfiguring your program.
My question is, what exactly are those boundaries? My own personal heuristic was
Avoid flow control. No functions, loops, or conditionals. Those wouldn't be in a text config file and people aren't expecting to have understand them. In general, it probably shouldn't matter the order in which your statements execute.
Stick to literal assignments. Methods and functions called on objects are harder to think through. Anything implicit is going to be a mess. If there's something complicated that has to happen with your parameters, change how they're interpreted.
Language keywords and error handling are right out.
I guess I ask this because I came across a situation with my Django config file where it seems to be useful to break these rules. I happen to like it, but I feel a little guilty. Basically, my project is deployed through svn checkouts to a couple different servers that won't all be configured the same (some will share a database, some won't, for example). So, I throw a hook at the end:
try:
from settings_overrides import *
LOCALIZED = True
except ImportError:
LOCALIZED = False
where settings_overrides is on the python path but outside the working copy. What do you think, either about this example, or about python config boundaries in general?
There is a Django wiki page, which addresses exactly the thing you're asking.
http://code.djangoproject.com/wiki/SplitSettings
Do not reinvent the wheel. Use configparser and INI files. Python files are to easy to break by someone, who doesn't know Python.
Your heuristics are good. Rules are made so that boundaries are set and only broken when it's obviously a vastly better solution than the alternate.
Still, I can't help but wonder that the site checking code should be in the parser, and an additional configuration item added that selects which option should be taken.
I don't think that in this case the alternative is so bad that breaking the rules makes sense...
-Adam
I think it's a pain vs pleasure argument.
It's not wrong to put code in a Python config file because it's all valid Python, but it does mean you could confuse a user who comes in to reconfigure an app. If you're that worried about it, rope it off with comments explaining roughly what it does and that the user shouldn't edit it, rather edit the settings_overrides.py file.
As for your example, that's nigh on essential for developers to test then deploy their apps. Definitely more pleasure than pain. But you should really do this instead:
LOCALIZED = False
try:
from settings_overrides import *
except ImportError:
pass
And in your settings_overrides.py file:
LOCALIZED = True
... If nothing but to make it clear what that file does.. What you're doing there splits overrides into two places.
As a general practice, see the other answers on the page; it all depends. Specifically for Django, however, I see nothing fundamentally wrong with writing code in the settings.py file... after all, the settings file IS code :-)
The Django docs on settings themselves say:
A settings file is just a Python module with module-level variables.
And give the example:
assign settings dynamically using normal Python syntax. For example:
MY_SETTING = [str(i) for i in range(30)]
Settings as code is also a security risk. You import your "config", but in reality you are executing whatever code is in that file. Put config in files that you parse first and you can reject nonsensical or malicious values, even if it is more work for you. I blogged about this in December 2008.
I'm trying to do the following in my Django template:
{% for embed in embeds %}
{% embed2 = embed.replace("<", "<") %}
{{embed2}}<br />
{% endfor %}
However, I always get an invalid block or some syntax error when I do anything like that (by that I mean {% %} code inside a loop). Python doesn't have {} to signify "scope" so I think this might be my problem? Am I formatting my code wrong?
Edit: the exact error is: Invalid block tag: 'embed2'
Edit2: Since someone said what I'm doing is not supported by Django templates, I rewrote the code, putting the logic in the view. I now have:
embed_list = []
for embed in embeds:
embed_list[len(embed_list):] = [embed.replace("<", "<")] #this is line 35
return render_to_response("scanvideos.html", {
"embed_list" :embed_list
})
However, I now get an error: 'NoneType' object is not callable" on line 35.
I am quite sure that Django templates does not support that.
For your replace operation I would look into different filters.
You really should try to keep as much logic as you can in your views and not in the templates.
Django's template language is deliberately hobbled. When used by non-programming designers, this is definitely a Good Thing, but there are times when you need to do a little programming. (No, I don't want to argue about that. This has come up several times on django-users and django-dev.)
Two ways to accomplish what you were trying:
Use a different template engine. See Jinja2 for a good example that is fully explained for integrating with Django.
Use a template tag that permits you to do Python expressions. See limodou's Expr tag.
I have used the expr tag in several places and it has made life much easier. My next major Django site will use jinja2.
I don't see why you'd get "NoneType object is not callable". That should mean that somewhere on the line is an expression like "foo(...)", and it means foo is None.
BTW: You are trying to extend the embed_list, and it's easier to do it like this:
embed_list = []
for embed in embeds:
embed_list.append(embed.replace("<", "<")) #this is line 35
return render_to_response("scanvideos.html", {"embed_list":embed_list})
and even easier to use a list comprehension:
embed_list = [embed.replace("<", "<") for embed in embeds]
Instead of using a slice assignment to grow a list
embed_list[len(embed_list):] = [foo]
you should probably just do
embed_list.append(foo)
But really you should try unescaping html with a library function rather than doing it yourself.
That NoneType error sounds like embed.replace is None at some point, which only makes sense if your list is not a list of strings - you might want to double-check that with some asserts or something similar.
Django templates use their own syntax, not like Kid or Genshi.
You have to roll your own Custom Template Tag.
I guess the main reason is enforcing good practice. In my case, I've already a hard time explaining those special templates tags to the designer on our team. If it was plain Python I'm pretty sure we wouldn't have chosen Django at all. I think there's also a performance issue, Django templates benchmarks are fast, while last time I checked genshi was much slower. I don't know if it's due to freely embedded Python, though.
You either need to review your approach and write your own custom templates (more or less synonyms to "helpers" in Ruby on Rails), or try another template engine.
For your edit, there's a better syntax in Python:
embed_list.append(embed.replace("<", "<"))
I don't know if it'll fix your error, but at least it's less JavaScriptesque ;-)
Edit 2: Django automatically escapes all variables. You can enforce raw HTML with |safe filter : {{embed|safe}}.
You'd better take some time reading the documentation, which is really great and useful.