<chdorner> I can't find anything, but just wanted to check with you first
<robertknight> @chdorner: It is unused. It was removed by 0f747a04036bbc17e8a56037e993c7ad0887eab5
<chdorner> ah good. I'll remove it then (rather than renaming it to `signup`)
<robertknight> I'm currently working through remaining issues with the Orphans branch with Sheetal, then I'll get back to working on the logged-in navbar. Nick and me have a tech interview this afternoon as well.
<nick> @chdorner: ok, there's a PR open to change nginx config in stage for Sheetal's routing PR.
<nick> I'd suggest maybe we want to add a redirect for the `/reset_password` URLs, too?
<nick> I'm happy to do that on master after merge, tbh
<chdorner> the card only mentioned `/register` for a redirect, but yes, it's probably a good idea
<nick> yeah, it did
<chdorner> it'll be a bit more work to the redirect tween for supporting regex (`/reset_password/{code}`), so I think it'll be better to do it in the PR
<nick> that's my fault
<chdorner> I will do some pairing with @sheetaluk today and add that regex support
<nick> okdoke!
<nick> @chdorner: FWIW I'd suggest for that just append the (unmatched) suffix to the return value of `route_path` rather than actually trying to parse URL params.
<chdorner> I was thinking of just making the whole thing a regex? `^/profile$` and `^/reset_password/[a-zA-z0-9]+$`
<chdorner> or would that be too slow?
<chdorner> I guess the issue is that it'll be O(n) instead of O(1)
<chdorner> I don't understand what you mean with "just append the (unmatched suffix) to the return value of `route_path`"
<nick> so we have a list of redirected paths, right?
<nick> I mean treat them as prefix routes, so any request that starts with `/foo` or `/bar/baz` matches
<nick> and then for the redirect URL we simply append the unmatched part (the suffix) to the URL we were going to redirect them to
<nick> i.e. a request for `/foo/abc123` gets sent to `request.route_path('foo-new') + '/abc123'`
<seanh> I've got to go out to help Shannon buy a bike, back in a couple of hours. What I'm working on today, though, is this idea that we might be able to have some sort of generic view decorator or something that can be applied to any deform view and turn it into one that can handle both xhr and non-xhr requests appropriately. I think it might be doable, we'll see
<nick> @seanh: yep, I was wondering about that
<nick> I think it should be possible, at least for deform views that don't handle multiple forms
<nick> the only slight complication is supporting redirect-after-post for non-XHR requests in a nice way
<nick> I don't really want us blindly fixing bugs without really understanding what's going on, so we need to hash out exactly what's going on, why `r.start.nextSibling === null` can happen, and what the correct behaviour in that case is.
<nick> It would be useful if you could generate some minimal test case markup that reproduces the bug.
<nick> Given that you think the bug is in `range.coffee` it should be possible to reproduce with just HTML, not a PDF.
<nick> Thanks for catching that stupid error @chdorner. I'm not having a very successful day all round today.
<chdorner> no worries :slightly_smiling_face: it usually happens with commits directly on master ;)
<nick> So far I've broken a pint glass and invented about 20 nonexistent git commands
<nick> Indeed.
<chdorner> I did a commit to master yesterday and forgot to change the tests
mlncn joined the channel
mlncn has quit
<seanh> nick: I'd like to swing back to #61 later and produce a minimal example, want to keep working on this xhr forms thing now
<nick> :+1: ok w me
mlncn joined the channel
<seanh> nick: ^ The above diff is a bit messy, but I've been playing with Pyramid view wrappers and decorators (and also took a look at the docs for view derivers) and I think they're all a bit awkward to use for this HTTP -> XHR form pattern. It wouldn't be impossible to use one of these Pyramid options. But the problem is that a helper function for taking the full page response for a form and (if it's an XHR request)
order for such a helper function to work across all our different forms it requires a bunch of arguments and those args are only available at request time and not when `@view_config()`s are processed. So I think the view callable might have to put the args on the request object or something. It seems simpler and easier just to have a helper function that you can call as the last line of your view callable: "here is my
if necessary". Because then you can simply pass in whatever runtime-derived args you want
<seanh> (In the above code the form is being rendered twice when it's an XHR request, and also when it's an XHR request the full page is being rendered and then thrown away, but those could be fixed easily enough.)
<nick> @seanh: not sure I understand what you mean by "it requires a bunch of arguments and those args are only available at request time and not when `@view_config()`s are processed."
<nick> doesn't it just require a form object?
<nick> which is either returned from the view function or present in the raised exception in case of a validation failure?
<seanh> Hmm, yeah that's true. The way I had it originally, you wrote the XHR version of the view and then a helper would turn it into the full HTML version if necessary, that required several args. The above diff is the opposite way around and only requires the form as arg. The form is only available at request time though.
<nick> I think a view deriver is probably what we're looking for, but we can probably shortcut the need to upgrade to Pyramid 1.7 in order to get this done by just using a plain ol' decorator
<seanh> Can a decorate view function just return whatever it wants? i.e. not just a response object or whatever a view would normally return. That might work
<nick> (much like `h.paginator.paginate`)
<nick> So I think that's kind of the problem with view decorators
<seanh> Meh, I dunno if view derivers would give us much over view decorators
<nick> well, they do
<nick> because view decorators (as opposed to just a plain decorator over the view function) are passed a response object, iirc
<seanh> If the decorated view function can return a arbitrary objects, that would be a way for it to pass args to the view decorator dynamically
<seanh> A view decorator is passed the view callable that it decorates
<seanh> It's then up to the view decorator itself to call the decorated view callable
<nick> ok, but if the view callable uses a renderer, what is the return value?
<nick> the rendered view?
<seanh> Which now that I realise it, might actually work, as long as we're okay with saying something like "if you use this view decorator you have to return a (response, form) tuple"
<nick> or the return value of the view function
<seanh> Not sure
<nick> well, I'm pretty sure it's the rendered view
<nick> which makes it tricky
<seanh> Of course the view callable could return `render_to_response(...)`
<nick> I don't really know what you mean.
<nick> We don't *want* the rendered view
<seanh> Right right
<seanh> Sorry
<nick> we just want a plain decorator around the view function as defined
<nick> which *already* returns the form
<nick> `return {'form': form}`
<nick> usually
<seanh> If we're willing to say that your view function can't use a renderer, it would work
<nick> and then all you need to do is check `request.is_xhr`, and if so, set `request.response.overrider_renderer = 'text'` and return `response['form'].render()`
<nick> no, it can still use a renderer
<nick> that's what I'm trying to say
<nick> just don't use a Pyramid view decorator
<nick> instead use a plain decorator
<seanh> Right, that's effectively the same as calling a helper function
<nick> well, uh, yes
<nick> because that's what a decorator is
<seanh> So instead of `return xhr_helper(...)` we're gonna do `@xhr_decorator` instead, that's fine
<nick> c.f. `h.paginator.paginate`
<nick> as I mentioned earlier
<seanh> If think it might actually work with pyramid view decorators as well but it seems unnecessary to use them
<nick> how would it work with pyramid view decorators?
<nick> it would only work if the result of calling the view callable wasn't a response object
<nick> but was the bare return value of the view function
<nick> and I don't think it is
<seanh> It could be, though
<seanh> You could change the view callable to that it was
<seanh> Anyway, there's no point
<nick> by removing the renderer?
<seanh> For example, you could return the name of the template to be rendered in the dict that the view callable returns to the view decorator. The decorator can then render it or not, depending
<nick> not sure I really understand why you'd give this decorator that responsibility when you could also not
<seanh> Yeah I agree a plain decorator is better
<nick> and when we upgrade to Pyramid 1.7 then we can translate that into a view deriver
<nick> so that we don't have to fix the signature of the underlying function
<seanh> I see, so view derivers return the original dict (or whatever) that the view callable returned, and not the rendered response object
<nick> well, not really, no
<nick> how they interact with the underlying function depends on where they are in the stack
<nick> it's all in the docs
<seanh> Yes, I see it
<nick> if you define a view deriver that fits in low enough in that stack (i.e. under `rendered_view`) then yes, they have access to the bare return value
<seanh> So they _can_ receive the original thing before it gets rendered, anyway
<nick> yep
<seanh> That's kind of nice, but at the same time, I'm left thinking why not just keep using a normal Python decorate though? Simply because it's easier to activate a view deriver on any given view? (Just `support_xhr=True` or something in the `@view_config()`, no need to import and then use a decorator function.)