-
Notifications
You must be signed in to change notification settings - Fork 38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
implement aspen.simplate.context #30
Comments
I am torn.
This is also really complicated to write due to the nine engines we support (can only use thread locals for some of them). I say to heck with aspen.context. Instead: better docs on the available objects. |
I started using PyFlakes, which is rubbing my face in this. And now I've thought of a simple way to implement this: pre-process the first simplate page to look for:
The import target list would be stored, and only those objects requested would be placed in the execution context for pages 2 ff. This would work regardless of the backend, since we wouldn't be using threading locals or async library equivalent.
What about Waddya think, @kennethreitz? Also interested in @dcrosta's opinion. |
Do the same for configure-aspen.py, I serpose. |
Hrm, this is a little trickier than it sounds. How does this behave? from aspen.context import request
^L
from aspen.context import website
^L There is no request object for page one, so importing it should be an ImportError. Or this? def foo(request):
from aspen.context import response
raise response
^L
from aspen.context import request
foo(request)
^L Python import statements can appear anywhere and the names are defined in scope. The response object shouldn't be added to the global page one context, it should only be available inside foo. We could do like future and require that it be the first line of the page (unless the first line is a future import? Do those work in exec?) I suppose we would then keep track of available names for each of the first two pages and raise ImportError if the requested name isn't among them. We could relax a little bit and allow "from aspen.context import ..." on lines other than the first as long as there's nothing before it except docstrings, comments and import statements. That's probably a good compromise. |
I have some code which I believe correctly handles the most common types of imports using |
Heh. After writing that I went looking for that very code but got side-tracked w/ travis-ci.org integration (noticed you have keystone on there). Travis all set up, going to check out some AST madness. !m @dcrosta |
AST traversal >> source code scanning of any sort. You could probably do something more sophisticated than I am in Keystone with visitors (that would be able to more easily look inside of class or function definitions, for instance) |
Do we know why compiler went away in 3.0? Is there a replacement? |
Looks like you can use ast.parse and end up with something similar. Didn't even realize compiler was gone in Py3k. |
Another idea: can I vary sys.modules for each execution context? |
What type of thing is |
It's not strictly the context.py module, though the overload is intentional so that if anyone goes looking for aspen.context they can find doc in the context.py module. It's supposed to be a "virtual module" that is magically available inside simplates. So instead of having magical names request, response, website, headers, qs, etc., you have a magical module that you import stuff from and it looks "normal," and if you dig into it you find docs really quickly. |
Down to the wire on 1.0. One "punt" option here: implement a stupid re-based hack where we only match:
And probably only as the first line of each logic page. That's low-hanging fruit, and syntax-wise it's a limiting case of the more robust AST-manipulation approach, so that we can implement the robust approach later on without breaking backwards compatibility. We haven't even floated yet the idea of importing from aspen.context inside of a module (as opposed to a simplate). That would almost certainly require threadlocals or equivalent, which would cover us here as well and may in the end not be more complicated than AST manipulation. |
If I implement this for @kennethreitz, will he appreciate it? |
This may just be my opinion, but having Why not make the "request" context simply fail to work when used at module-scope in the first page? It will have to be some sort of object which proxies to a thread-local (or something similar) in order to work in the first page anyway, but, as you suggest, there's a valid use case to define functions in the first page which are not used until the second page. |
For the record, the reason this is important with PyFlakes is that it breaks the habituation of "oh crap it's red something is wrong." When so many red names are false positives, it re-trains you not to care about red. Before you know it Michael Fagan is sitting on the edge of your bed slugging Famous Grouse. |
Can you not just allow the request to be imported but have it be None? |
There's precedent in the future module for implementing some functionality outside of the usual interpreter mechanisms, while maintaining "a real module" that is simply for documentation and way-finding purposes. |
see https://gist.github.com/pjz/5558820 for how to make a virtual module for exec'd code. |
@pjz Okay, but that's still process-global. Request and response objects need to be local to each simplate request context. For thread-based network engines this would mean thread-locals. Not even sure what it would look like for an evented engine. |
While writing the debug helper for algorithm.py, I thought of a way to implement this ticket:
This has the advantage of reducing the variance from the behavior of the import statement to a minimum: both result in a
from __future__ import print_function
import dis
def as_import():
import string
__aspen_context = {'string': object}
def as_dict():
string = __aspen_context['string']
print("as import:")
dis.dis(as_import)
print
print("as dict:")
dis.dis(as_dict) |
+2 from @thomasboyt and @simon-weber in IRC. |
I removed the |
Revisited this on #496, still interested in it. |
Though with #481 it attaches to simplates, not to aspen. |
@pjz points out that importing request in the first page may not behave as expected in the second page. |
Closing per AspenWeb/aspen.py#38 (comment). |
Want to explicitly import objects from aspen.context into simplates instead of placing them there magically.
The text was updated successfully, but these errors were encountered: