Re: Proposal to format Django using black

2019-04-19 Thread Luke Plant

  
  
Hi Tim,
I didn't mean to imply the original decisions were foolish, in
  their context. Reading it again, my language in the email was too
  strong - it was directed at myself as much as anyone else, because
  I'm also the kind of person who loves getting everything
  consistent, often too much, and that wasn't clear. What I meant to
  say was that if it turns out that our guidelines are becoming a
  problem, we should drop them, or change how we regard them (e.g.
  as guidelines for those who want to go the extra mile, not as
  rules that will frustrate contributors).

Your work on the Django code base has been tireless and
  fantastic, and along with the other fellows I don't know what we'd
  do without you, sorry for not making that clear with my comments.

Thanks,
 Luke


On 19/04/2019 15:51, Tim Graham wrote:


  
  I'm sorry for establishing some (foolish?)
guidelines that discouraged some people from contributing. I
didn't establish those guidelines merely to be pedantic, but
perhaps I'm too much of a perfectionist at times.

After GitHub allowed mergers to amend pull requests, I often
made cosmetic adjustments myself to eliminate the trivial back
and forth that some have lamented. I never blocked a merge
merely for trivial cosmetic reasons.

On Friday, April 19, 2019 at 3:25:24 AM UTC-4, Luke Plant wrote:

  
Hi all,
An alternative solution to the problem of nit-picky,
  formatting related PR reviews is simple: let's not do
that. 

We already have an automated code formatting enforcer,
  flake8. Let's simply drop the requirement on fixing
  anything that flake8 doesn't pick up. A committer can fix
  up style issues if they want to, but shouldn't make anyone
  else do it. This would mean most of the stuff on our coding style page
  should just be delete, or at least not enforced - by which
  I mean almost anything that can't be enforced by a tool
  (such as isort, flake8, editors via .editorconfig etc.),
  and has no non-local effects. (So consistent naming of
  classes/functions *should* be enforced, because that
  affects other people's ability to use the code).  Large
  parts of that page are just duplicating of flake8/isort
  rules anyway. Honestly, does it kill us if someone writes
  "we" in a code comment? And black couldn't help with some
  of these things anyway. Let's just stop being code review
  jerks.

I'm kind of ambivalent on black itself. Certainly there
  are cases where it makes code less readable (a significant
  sin in my book) e.g. lists that are better displayed
  vertically, as mentioned already, and there are cases
  where it makes your diff larger than it needs to be (e.g.
  when it decides a list is now too long and needs to be
  re-formatted vertically). If we adopt black we'd have to
  live with those annoyances. Alternatively, we can live
  with the annoyance that code formatting is not perfectly
  consistent and we accept less than 'perfect' PR. But we
  should just live with those things:


    A foolish consistency
  is the hobgoblin
of little minds


And if our consistency requirements are causing problems
  for people attempting to contribute, they are foolish and
  should be dropped.
My 2 ¢.
Luke


On 18/04/2019 16:03, Jani Tiainen wrote:


  Well let me add my two cents here since I
was also in the group in DCEU that talked about the
usage of black.


Personally I don't like to contribute to Django.
  And this is why:


Day one: I'll make the fix/patch and create PR
Day two (or four or five depending how busy
  reviewers are): I missed a comma or some minor indent
  is wrong
Day three: I fix styles
Day four: PR is accepted.


So whole round trip took about a five days (give a
  take few usually depending how busy reviewers are).


That gives me a feeling that I'm really wasting my
  time and since I can

Re: Proposal to format Django using black

2019-04-19 Thread Luke Plant

  
  
Hi all,
An alternative solution to the problem of nit-picky, formatting
  related PR reviews is simple: let's not do that. 

We already have an automated code formatting enforcer, flake8.
  Let's simply drop the requirement on fixing anything that flake8
  doesn't pick up. A committer can fix up style issues if they want
  to, but shouldn't make anyone else do it. This would mean most of
  the stuff on our coding
style page should just be delete, or at least not enforced -
  by which I mean almost anything that can't be enforced by a tool
  (such as isort, flake8, editors via .editorconfig etc.), and has
  no non-local effects. (So consistent naming of classes/functions
  *should* be enforced, because that affects other people's ability
  to use the code).  Large parts of that page are just duplicating
  of flake8/isort rules anyway. Honestly, does it kill us if someone
  writes "we" in a code comment? And black couldn't help with some
  of these things anyway. Let's just stop being code review jerks.

I'm kind of ambivalent on black itself. Certainly there are cases
  where it makes code less readable (a significant sin in my book)
  e.g. lists that are better displayed vertically, as mentioned
  already, and there are cases where it makes your diff larger than
  it needs to be (e.g. when it decides a list is now too long and
  needs to be re-formatted vertically). If we adopt black we'd have
  to live with those annoyances. Alternatively, we can live with the
  annoyance that code formatting is not perfectly consistent and we
  accept less than 'perfect' PR. But we should just live with those
  things:


    A foolish consistency
  is the hobgoblin of
little minds


And if our consistency requirements are causing problems for
  people attempting to contribute, they are foolish and should be
  dropped.
My 2 ¢.
Luke


On 18/04/2019 16:03, Jani Tiainen
  wrote:


  
  Well let me add my two cents here since I was also
in the group in DCEU that talked about the usage of black.


Personally I don't like to contribute to Django. And this
  is why:


Day one: I'll make the fix/patch and create PR
Day two (or four or five depending how busy reviewers are):
  I missed a comma or some minor indent is wrong
Day three: I fix styles
Day four: PR is accepted.


So whole round trip took about a five days (give a take few
  usually depending how busy reviewers are).


That gives me a feeling that I'm really wasting my time and
  since I can't get all the small bits and pieces exactly as
  Django wants in correct place.


And that's because we have slightly different rules at the
  work. And some other projects do have different rules.


So it would be great if some of this pain could be relieved
  with a tool. In my short experience with black (I've been
  using it for work projects) it does a pretty decent job.


Like others have said black does some decisions I don't
  agree with. But I don't have to. Black does it for a "greater
  good". And after a while black actually vanishes from the
  flow. 
  
  
  
On Sat, Apr 13, 2019 at 6:35
  PM Herman S 
  wrote:

Hi.
  
  I propose that Django starts using 'black' [0] to auto-format
  all Python code.
  For those unfamiliar with 'black' I recommend reading the the
  projects README.
  The short version: it aims to reduce bike-shedding and non
  value-adding
  discussions; saving time reviewing code; and making the
  barrier to entry lower
  by taking some uncompromissing choices with regards to
  formatting.  This is
  similar to tools such as 'gofmt' for Go and 'prettier' for
  _javascript_.
  
  Personally I first got involved contributing to Django couple
  of weeks back,
  and from anecdotal experience I can testify to how 'formatting
  of code' creates
  a huge barrier for entry. My PR at the time went multiple
  times back and forth
  tweaking formatting. Before this, I had to research the style
  used by exploring
  the docs at length and reading at least 10-20 different source
  – and even those
  were not always consistent. At the end of the day I felt like
  almost 50% of the
  time I used on the patch was not used on actually solving the
  issue at hand.
  Thinking 

Re: Development story for CBV FormViews using GET

2019-03-14 Thread Luke Plant

  
  
Hi Kyle,
My take would be this: What does the code look like if you don't
  use FormView but just write a function view? How does that compare
  to using a CBV? This may be the simpler method you are missing -
  if you are finding you are fighting with inherited functionality,
  just don't inherit it.
Luke


On 09/03/2019 03:55, Kye Russell wrote:


  
  

  
Hi,


Sometimes it is appropriate to for a HTML form to use
  the GET method for submission (usually search / filter
  forms).


My impression has always been that in order to build a
  FormView-based view that acts on GET data, you have to
  override a few methods on your class (which involves
  understanding how FormView works). Even as someone with a
  fairly good understanding of these classes, I sometimes
  have to reference a previously-written example to make
  sure I've got it right.


I am aware of the existence of django-filter[0] which
  takes care of this for you, however at times I find it
  hard to justify adding it to a project just to deal with
  this.



I have the following questions:


* Is my understanding of the current process correct,
  or is there an easier way that I've missed?
* Is this documented anywhere? I looked at the Django
  'working with forms' documentation[1], and whilst it
  discusses the different scenarios in which you'd use GET
  vs POST, it does not seem to discuss implementations in a
  CBV context.

* Is there enough of a generic use-case where FormView
  / FormMixin / ProcessFormView could be altered to support
  this? Or are there subtleties / nuances in each
  implementation that make a generic solution hard to
  develop?


Sorry if this is the wrong avenue to discuss this. I am
  approaching it from the position of wanting to alter
  Django to better support this use case, but I'm aware that
  I may have just missed a Blessed method in the docs.


Kye



[0]: https://github.com/carltongibson/django-filter

[1]: https://docs.djangoproject.com/en/2.1/topics/forms/





  

  
  -- 
  You received this message because you are subscribed to the Google
  Groups "Django developers (Contributions to Django itself)" group.
  To unsubscribe from this group and stop receiving emails from it,
  send an email to django-developers+unsubscr...@googlegroups.com.
  To post to this group, send email to django-developers@googlegroups.com.
  Visit this group at https://groups.google.com/group/django-developers.
  To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/CANK-ykkMtxezA9cHN8jQ_czLn6OYtdDn6JYbjNgASyyqHH-aAw%40mail.gmail.com.
  For more options, visit https://groups.google.com/d/optout.

  




-- 
You received this message because you are subscribed to the Google Groups "Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/668e083b-d3c1-8a5b-989e-03a0a85d895a%40cantab.net.
For more options, visit https://groups.google.com/d/optout.


Re: Support for unittest -k option

2019-03-14 Thread Luke Plant

  
  
I use `--keepdb` a lot, I never knew there was a shorthand and
  even know I do know wouldn't use it. For things like this I
  usually find it easy to remember the long option. So I'm +1 on
  changing it too, without a new shorthand for `--keepdb`. In the
  keyword usage `-k` must be followed by a keyword, so for people
  who did use it the shorthand, the old usage will break loudly
  which is good.

Luke


On 11/03/2019 15:13, François Freitag
  wrote:


  Hi Django Devs,

https://code.djangoproject.com/ticket/30245 suggests supporting Python
unittest `-k` option, to selectively run tests matching a keyword.

Currently, `-k` is the shorthand for `--keepdb` in Django.
A `--filter` flag was suggested to preserve backward compatibility.
Carlton suggested removing the `-k` option from `--keepdb` and reusing
it for unittest `-k`. That would follow unittest more closely, reduce
user confusion and ease maintenance.

What do you think is best? Do you see other options?

If re-taking the `-k` option for unittest `-k`, should a new shorthand
be introduced for `--keepdb`?

Thanks for your time,
François



  




-- 
You received this message because you are subscribed to the Google Groups "Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/ffdefe87-33f9-05c6-ee61-30087deee517%40cantab.net.
For more options, visit https://groups.google.com/d/optout.


Re: Post mortem on today's packaging error.

2019-02-12 Thread Luke Plant

Hi Carlton,

I have had problems in the past with `setup.py sdist` and friends 
actually depending on existing artefacts in build directories from 
previous runs. A quick google turns up this bug report - 
https://github.com/pypa/setuptools/issues/436 - originally filed by  
oh, me :-)  and it is still open. It seems that `git clean -dfx` does 
clean out these files, so adding that to the release Makefile should fix 
the issue if this was the root problem. The release process document 
needs to be adjusted to mention that wanted build artefacts need to be 
moved somewhere else before preparing the next release, otherwise they 
are going to get deleted before they are uploaded.


Luke

On 11/02/2019 19:28, Carlton Gibson wrote:

Hi all.

This morning I released four versions of Django. Three of which, for 
2.1, 2.0 and 1.11. (i.e. all the actually supported versions) were 
broken.
In the package were additional files from `master`/2.2 which shouldn't 
have been there.


This afternoon I have released follow-ups to correct this issue.

First of all, sorry about that, and for any inconvenience caused.


Then, these are process issues so, how can we do better next time?

I'm not 100% sure what occurred.

* The history in Git is correct.
* I must have had the right commits checked out, because the package 
metadata is correct. (Filenames, version numbers and so on.)


My best guess is that I've failed to `git clean` correctly before 
building each release.
I'm not certain here because switching between branches doesn't leave 
the repos in an unclean state, and I'm pretty sure it was clean, but 
this seems the most likely error.



Q: is there a nice git command to "assert I'm at exactly this tag"?


Steps I've taken:

* Moved the `git clean` step into the helper script used to build the 
packages. No chance of then missing it.
* Added a `diff`-step after building just to make sure what's in the 
`django` module matches the checkout.
The second of these, whilst just a visual check, would have worked 
with what ended up in the package vs what was in my working tree when 
I checked later, but I'm not sure it would have caught the issue when 
the package was created (because presumably my working tree was wrong 
at that point).


A similar issue affects the checksums, which check that nothing 
changed since it was packaged, but not that the right things were 
packaged...

(Similarly, pip install worked without error.)

On the new 1.11 package, I created a virtualenv with Python 2 and ran 
the test suite. This worked so it should be good. But it would be good 
to automate this.
(I'll look into it.) We don't ship the tests in the wheel, so we have 
to use the src-dist for this. (We could then diff the two django 
modules to make sure they were the same.)


On the other packages I visually looked for incorrect files, but, 
beyond specific migrations (etc) that were known bad from the previous 
release, this doesn't generalise.


"zaytsev" on IRC suggested running `makemigrations --check`, so having 
a test project to install against might also be worth it.

(I'd guess running the test suite would be sufficient...)


Any other thoughts very welcome.


Kind Regards,

Carlton

--
You received this message because you are subscribed to the Google 
Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send 
an email to django-developers+unsubscr...@googlegroups.com 
.
To post to this group, send email to 
django-developers@googlegroups.com 
.

Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/90c531fc-3d5b-4d9e-a55f-b88f2e04bb54%40googlegroups.com 
.

For more options, visit https://groups.google.com/d/optout.


--
You received this message because you are subscribed to the Google Groups "Django 
developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/c795f471-9f0b-8794-8899-ed3bbec821aa%40cantab.net.
For more options, visit https://groups.google.com/d/optout.


Re: Request to reconsider ticket #27910: using an Enum class in model Field choices

2019-01-11 Thread Luke Plant
I've also tried to come up with something better than Django's current 
default, using Enums, and found them lacking when it comes to the 
caption, especially when you need translations.


I would be happy with re-opening the ticket, but in terms of committing 
a solution I would be -1 unless we can find something which is 
definitely significantly better than the status quo, which the majority 
of people would want to use, rather than just an alternative - something 
that we would be happy to be become the recommended default and present 
in the docs as such. Otherwise we just have 2 ways to do it.


I quite like Tom's suggestion here:

https://code.djangoproject.com/ticket/27910#comment:6

It's not perfect but seems a reasonable compromise given the constraints.

Luke


On 11/01/2019 14:55, Shai Berger wrote:

On Mon, 31 Dec 2018 23:40:53 +
Tom Forbes  wrote:

We currently have a -1 and a +1, does anyone else have any input on
this?


So, the tally is +3, -1, and the -1 seems to be based on a technical
argument which I believe I refuted; and more than a week has passed
with no further comment.

Looks to me like at least a rough consensus of "eh, ok, if you really
want it..."



--
You received this message because you are subscribed to the Google Groups "Django 
developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/f0677170-65d9-d1bb-9b3f-da7c494acb6d%40cantab.net.
For more options, visit https://groups.google.com/d/optout.


Re: CSRF Middlware and usage of request attributes (META, csrf_cookie_needs_reset)

2019-01-01 Thread Luke Plant

Hi Florian,

My own instincts would be steer away from writing to request.META for 
most things, because request.META also contains things from the 
environment and indeed from the user request. You really don't want an 
attacker to be able to set an HTTP header and bypass security controls 
or directly influence anything which is supposed to be from 
application/framework code.


Of course, all arbitrary HTTP request headers are mapped to 
`request.META['HTTP_ …`, while some specific ones have special 
mappings,  but I'd rather not have to think about that kind of thing 
when doing security audits. With attributes it is always very clear 
where they have come from.


In addition, looking at the docs for request.META 
 it is 
confusing to users if there are things in there that have not originated 
directly from the request.


As the original author of the CSRF stuff, I have no idea now why I used 
request.META for some things, if indeed it was me who did it that way — 
attributes seems much better for those usages.


Luke


On 29/12/2018 14:47, Florian Apolloner wrote:

Hi there,

I am considering rewriting and (hopefully) simplifying the CSRF 
middleware. While looking through the code I realized that we put 
stuff into request.META as well as attributes on the request object 
itself (csrf_cookie_needs_reset) for instance. Is there any reason why 
we do not stick to one format?


Or more generally put: When should middlewares write into META as 
opposed to a attribute.


Cheers,
Florian
--
You received this message because you are subscribed to the Google 
Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send 
an email to django-developers+unsubscr...@googlegroups.com 
.
To post to this group, send email to 
django-developers@googlegroups.com 
.

Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/43f6d8da-c66c-4100-a6d6-e85d4cef3684%40googlegroups.com 
.

For more options, visit https://groups.google.com/d/optout.


--
You received this message because you are subscribed to the Google Groups "Django 
developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/9fb674dc-df9a-0c86-8e93-3465b8a596bb%40cantab.net.
For more options, visit https://groups.google.com/d/optout.


Re: New Feature: Allow password reset token to expire in under a day

2017-09-23 Thread Luke Plant

Hi Zach,

To be clear, I'm not totally opposed to the change. There could 
certainly be advantages to updating the code, especially if we move to 
TimestampSigner.


However, from a quick look, I'm not sure if TimestampSigner will be 
possible - we want the hashed value to incorporate some internal data, 
but don't want that internal data to be part of the signed message that 
Signer produces (for various reasons, including the fact that we want to 
keep the URL as short as possible for maximum compatibility). I think we 
should also be careful not to change the public interface of 
PasswordResetTokenGenerator, since people may have subclassed it, which 
limits the amount of cleanup you can do here.


I imagine that changing the timestamp to support better precision will 
also create work for people upgrading (the setting change, plus URLconf 
changes).


What I am suggesting is that we should seriously consider whether all 
this is worth it given the extremely marginal security benefits.


Regards,

Luke


On 23/09/17 04:33, Zhiqiang Liu wrote:

Luke,

thanks for the long explanation. I see your points here. I actually 
saw the make token function and was thinking about it what is the best 
way to do with that. I think most people here feel there's need to at 
least allow some flexibility for the time out since there will be 
cases under a day is needed.
I will keep this discussion for a couple of more days to see if we can 
get consensus and how we should implemented if needed.


Zach

On Friday, September 22, 2017 at 3:04:01 PM UTC-4, Luke Plant wrote:

I would be +1 to what Adam wrote from me i.e. just allow the value
to accept floats.

However, I don't think it will work due to the way that we round
the precision of timestamps to days

<https://github.com/django/django/blob/master/django/contrib/auth/tokens.py#L21>.
This was done partly to reduce the number of characters needed to
express the timestamp, to keep URLs as short as possible. We would
have to change the mechanism to store more precision into the
timestamp. This would result in an upgrade 'bump' for users (i.e.
links generated before the upgrade would become invalid after
upgrade).

However, I really question whether we need any change here, and
whether it would be a good idea.

Having a short expiration time (less than 1 hour) could cause
major problems for some people - plenty of systems introduce 5 or
10 minute delays in mail delivery, and with some people's internet
connection it can take several minutes to open a web page. This
also means that some people end up finishing the process of
whatever they were doing the next day (I know I've done this
several times on various sites), so a timeout of at least 1 or 2
days is a good default. If you want to come back after the weekend
and carry on, 3 days makes more sense as a minimum.

In terms of security, I don't think there is really any need for
anyone to reduce below the default at all (see below). So I'm very
unconvinced about the need for changing to PASSWORD_RESET_TIMEOUT
- it is just unnecessary upgrade work for some existing projects
(this is the biggest consideration for me), and it could encourage
people to set the value to something low that would decrease
usability.

*Security:*

The security of the password reset feature is almost entirely
independent of the value of the timeout setting. There are 3
attack vectors I can see:

1) Someone's email account is compromised, and they then do a
password reset on a Django site.

We simply can't protect against this AFAICS.

2) Someone's email account is compromised, and they find/use a
password reset email in the person's inbox.

This is the only scenario for which having a shorter timeout makes
a difference. It is somewhat unlikely, because in 99% of cases the
attacker would be able to generate a password reset email
themselves after compromising the account. For this narrow case
where the attacker is unwilling/unable to trigger/receive a new
password reset email, it is worth having some protection against
them being able to use old tokens, but 3 days seems plenty short
enough for this situation, especially given the fact that a *used*
password reset token immediately becomes invalid due to the way we
hash on internal state of the user record.

3) A brute force attack.

To do this, the attacker has to:

1. Supply a user ID (let's assume this is easy)

2. ***Choose*** a timestamp (very easy, just choose the current time)

3. Create a 20 character hexadecimal hmac that matches both the
timestamp and the internal state of the user (see
https://github.com/django/django/blob/master/django/contrib/auth/tokens.py
<https://github.com/django/django/blob/master/django/contrib/auth/tokens.py>
).

Since 

Re: New Feature: Allow password reset token to expire in under a day

2017-09-22 Thread Luke Plant
I would be +1 to what Adam wrote from me i.e. just allow the value to 
accept floats.


However, I don't think it will work due to the way that we round the 
precision of timestamps to days 
. 
This was done partly to reduce the number of characters needed to 
express the timestamp, to keep URLs as short as possible. We would  have 
to change the mechanism to store more precision into the timestamp. This 
would result in an upgrade 'bump' for users (i.e. links generated before 
the upgrade would become invalid after upgrade).


However, I really question whether we need any change here, and whether 
it would be a good idea.


Having a short expiration time (less than 1 hour) could cause major 
problems for some people - plenty of systems introduce 5 or 10 minute 
delays in mail delivery, and with some people's internet connection it 
can take several minutes to open a web page. This also means that some 
people end up finishing the process of whatever they were doing the next 
day (I know I've done this several times on various sites), so a timeout 
of at least 1 or 2 days is a good default. If you want to come back 
after the weekend and carry on, 3 days makes more sense as a minimum.


In terms of security, I don't think there is really any need for anyone 
to reduce below the default at all (see below). So I'm very unconvinced 
about the need for changing to PASSWORD_RESET_TIMEOUT - it is just 
unnecessary upgrade work for some existing projects (this is the biggest 
consideration for me), and it could encourage people to set the value to 
something low that would decrease usability.


*Security:*

The security of the password reset feature is almost entirely 
independent of the value of the timeout setting. There are 3 attack 
vectors I can see:


1) Someone's email account is compromised, and they then do a password 
reset on a Django site.


We simply can't protect against this AFAICS.

2) Someone's email account is compromised, and they find/use a password 
reset email in the person's inbox.


This is the only scenario for which having a shorter timeout makes a 
difference. It is somewhat unlikely, because in 99% of cases the 
attacker would be able to generate a password reset email themselves 
after compromising the account. For this narrow case where the attacker 
is unwilling/unable to trigger/receive a new password reset email, it is 
worth having some protection against them being able to use old tokens, 
but 3 days seems plenty short enough for this situation, especially 
given the fact that a *used* password reset token immediately becomes 
invalid due to the way we hash on internal state of the user record.


3) A brute force attack.

To do this, the attacker has to:

1. Supply a user ID (let's assume this is easy)

2. ***Choose*** a timestamp (very easy, just choose the current time)

3. Create a 20 character hexadecimal hmac that matches both the 
timestamp and the internal state of the user (see 
https://github.com/django/django/blob/master/django/contrib/auth/tokens.py 
).


Since the attacker can choose the timestamp, the probability of guessing 
correctly depends **only** on:


1. The number of bits in the hash (20*4 = 80)

2. The number of attempts (or, the number of requests per second 
possible and the time available)


It does **not** depend on the value of the reset timeout **at all**.

If we assume they can make 100 req/s, and they try continuously for 10 
years, they've got a chance of around 1 in 10^13.


In other words, I reject the premise of the ticket, which is that to 
improve security some people need to reduce the timeout. It makes 
virtually no difference to the security of this feature, and in fact you 
would be protected against almost all realistic attacks if there was no 
timeout. I imagine that the requirement of "meeting security 
requirements" mentioned on the ticket is due to people who think this 
works like a short, 6 digit OTP, for which 3 days would be far too long 
( see https://sakurity.com/blog/2015/07/18/2fa.html ). We could put a 
note in the docs about this, I don't know how to do that in a succinct 
way apart from to link to a copy of this email or something.


However, if we really do 'need' this change, we should at least keep the 
default to what it is now, and put a notice in the docs saying that 
reducing it hurts usability and makes no practical difference to 
security. Since we would be causing an upgrade bump and breaking 
existing links, we may as well also switch to TimestampSigner (the 
password reset code was originally written before that existed), which 
would also mean changing urlconfs I imagine. This would also require a 
significant section in the upgrade notes. (In my book, this is a further 
argument against doing this change at all).



Regards,

Luke
On 21/09/17 12:25, Adam Johnson wrote:
Why not just keep PASSWORD_RESET_TIMEOUT_DAYSand allow 

Re: Automatic prefetching in querysets

2017-08-19 Thread Luke Plant
This could work something like the way that ForeignKey `on_delete` works 
- you have options that are enumerated as constants, but in reality they 
are classes that embody the strategy to be used. We could have something 
similar - `on_missing_relation=FETCH | WARN | ERROR | IGNORE ... `


Luke

On 18/08/17 14:01, Shai Berger wrote:

On Friday 18 August 2017 09:08:11 Anssi Kääriäinen wrote:

Maybe we should just add the queryset method. This is the smallest atomic
task that can be done. Even if there's only the queryset method available,
it's possible to enable prefetches per model by using a Manager.


I disagree on both counts: I don't think it's the smallest atomic task, and
I'm not so sure it's the right thing to do.

The smallest atomic task, the way I see it, is building the infrastructure
that would allow adding the queryset method -- but would also allow different
APIs to be set around it.

And since there is as yet no consensus on the correct API for "end" users, I
would rather not define one immediately.

Shai.



--
You received this message because you are subscribed to the Google Groups "Django 
developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/ba0ddd74-5240-757f-e6ea-3300f2ba3a61%40cantab.net.
For more options, visit https://groups.google.com/d/optout.


Re: Automatic prefetching in querysets

2017-08-16 Thread Luke Plant
 to ask is:

- How many people have had their day/site ruined because we think 
auto-prefetching is too magical?
- How many people would have their day/site ruined because we think 
auto-prefetching is the better default?


Answer - we could guess, but we don't know, and we still have problems 
both way, of different frequencies and size. In this case, I think 
"explicit is better than implicit" is the wisdom to fall back on. We 
should also fall back to the experience we've had with this in the past. 
We did have more magical performance fixes in the past, such as the 
`depth` argument to `select_related`, removed in 1.7. You now have to 
explicitly name the things you want to be selected, instead of the 
'easy' option which did the wrong thing in some cases.




If we were introducing a new ORM, I think the above answer would be 
obvious given what we know of Django use today.


What I'd propose:

1. (optional) A global setting to disable autoprefetching


This would almost surely interact very badly with 3rd party libraries 
and apps who will all want you to set it differently.



2. An opt out per queryset
3. (optional) An opt out per Meta?
4. Logging any autoprefetches - perhaps as a warning?


Logging of possible improvements or auto-prefetches could be really 
helpful. We should be careful to namespace the logging so that it can be 
silenced easily. The biggest issue with logs/warnings is that the 
unhelpful reports drown out the helpful ones, and then the whole feature 
becomes useless or worse.


Regards,

Luke

More experienced Django users that do not want this behaviour are 
going to know about a global setting and can opt in to the old 
behaviour rather easily. Newer users that do not know about 
select/prefetch_related or these settings will fall into the new 
behaviour by default.


It's unreasonable to expect every user of django learn the ins and 
outs of all queryset methods. I'm probably considered a django orm 
expert, and I still sometimes write queries that are non-optimal or 
*become* non-optimal after changes in unrelated areas. At an absolute 
minimum we should be screaming and shouting when this happens. But we 
can also fix the issue while complaining, and help guide users into 
correct behaviour.



On Wednesday, 16 August 2017 08:41:31 UTC+10, Anthony King wrote:

Automatically prefetching is something I feel should be avoided.

A common gripe I have with ORMs is they hide what's actually
happening with the database, resulting in
beginners-going-on-intermediates building libraries/systems that
don't scale well.

We have several views in a dashboard, where a relation may be
accessed once or twice while iterating over a large python
filtered queryset.
Prefetching this relation based on the original queryset has the
potential to add around 5 seconds to the response time (probably
more, that table has doubled in size since I last measured it).

I feel it would be better to optimise for your usecase, as apposed
to try to prevent uncalled-for behaviour.



On Aug 15, 2017 23:15, "Luke Plant" <l.pla...@cantab.net
> wrote:

I agree with Marc here that the proposed optimizations are
'magical'. I think when it comes to optimizations like these
you simply cannot know in advance whether doing extra queries
is going to a be an optimization or a pessimization. If I can
come up with a single example where it would significantly
decrease performance (either memory usage or speed) compared
to the default (and I'm sure I can), then I would be strongly
opposed to it ever being default behaviour.

Concerning implementing it as an additional QuerySet method
like `auto_prefetch()` - I'm not sure what I think, I feel
like it could get icky (i.e. increase our technical debt), due
to the way it couples things together. I can't imagine ever
wanting to use it, though, I would always prefer the manual
option.

Luke



On 15/08/17 21:02, Marc Tamlyn wrote:

Hi Gordon,

Thanks for the suggestion.

I'm not a fan of adding a layer that tries to be this clever.
How would possible prefetches be identified? What happens
when an initial loop in a view requires one prefetch, but a
subsequent loop in a template requires some other prefetch?
What about nested loops resulting in nested prefetches? Code
like this is almost guaranteed to break unexpectedly in
multiple ways. Personally, I would argue that correctly
setting up and maintaining appropriate prefetches and selects
is a necessary part of working with an ORM.

Do you know of any other ORMs which attempt similar magical
optimisations? How do they go about identifying the cases
where it is necessary?

On 15 August 2017 at 10:44, Gor

Re: Automatic prefetching in querysets

2017-08-15 Thread Luke Plant
I agree with Marc here that the proposed optimizations are 'magical'. I 
think when it comes to optimizations like these you simply cannot know 
in advance whether doing extra queries is going to a be an optimization 
or a pessimization. If I can come up with a single example where it 
would significantly decrease performance (either memory usage or speed) 
compared to the default (and I'm sure I can), then I would be strongly 
opposed to it ever being default behaviour.


Concerning implementing it as an additional  QuerySet method like 
`auto_prefetch()` - I'm not sure what I think, I feel like it could get 
icky (i.e. increase our technical debt), due to the way it couples 
things together. I can't imagine ever wanting to use it, though, I would 
always prefer the manual option.


Luke



On 15/08/17 21:02, Marc Tamlyn wrote:

Hi Gordon,

Thanks for the suggestion.

I'm not a fan of adding a layer that tries to be this clever. How 
would possible prefetches be identified? What happens when an initial 
loop in a view requires one prefetch, but a subsequent loop in a 
template requires some other prefetch? What about nested loops 
resulting in nested prefetches? Code like this is almost guaranteed to 
break unexpectedly in multiple ways. Personally, I would argue that 
correctly setting up and maintaining appropriate prefetches and 
selects is a necessary part of working with an ORM.


Do you know of any other ORMs which attempt similar magical 
optimisations? How do they go about identifying the cases where it is 
necessary?


On 15 August 2017 at 10:44, Gordon Wrigley > wrote:


I'd like to discuss automatic prefetching in querysets.
Specifically automatically doing prefetch_related where needed
without the user having to request it.

For context consider these three snippets using the Question &
Choice models from the tutorial
 
when
there are 100 questions each with 5 choices for a total of 500
choices.

Default
|
forchoice inChoice.objects.all():
print(choice.question.question_text,':',choice.choice_text)
|
501 db queries, fetches 500 choice rows and 500 question rows from
the DB

Prefetch_related
|
forchoice inChoice.objects.prefetch_related('question'):
print(choice.question.question_text,':',choice.choice_text)
|
2 db queries, fetches 500 choice rows and 100 question rows from
the DB

Select_related
|
forchoice inChoice.objects.select_related('question'):
print(choice.question.question_text,':',choice.choice_text)
|
1 db query, fetches 500 choice rows and 500 question rows from the DB

I've included select_related for completeness, I'm not going to
propose changing anything about it's use. There are places where
it is the best choice and in those places it will still be up to
the user to request it. I will note that anywhere select_related
is optimal prefetch_related is still better than the default and
leave it at that.

The 'Default' example above is a classic example of the N+1 query
problem, a problem that is widespread in Django apps.
This pattern of queries is what new users produce because they
don't know enough about the database and / or ORM to do otherwise.
Experieced users will also often produce this because it's not
always obvious what fields will and won't be used and subsequently
what should be prefetched.
Additionally that list will change over time. A small change to a
template to display an extra field can result in a denial of
service on your DB due to a missing prefetch.
Identifying missing prefetches is fiddly, time consuming and error
prone. Tools like django-perf-rec
 (which I was involved
in creating) and nplusone 
exist in part to flag missing prefetches introduced by changed code.
Finally libraries like Django Rest Framework and the Admin will
also produce queries like this because it's very difficult for
them to know what needs prefetching without being explicitly told
by an experienced user.

As hinted at the top I'd like to propose changing Django so the
default code behaves like the prefetch_related code.
Longer term I think this should be the default behaviour but
obviously it needs to be proved first so for now I'd suggest a new
queryset function that enables this behaviour.

I have a proof of concept of this mechanism that I've used
successfully in production. I'm not posting it yet because I'd
like to focus on desired behavior rather than implementation
details. But in summary, what it does is when accessing a missing
field on a model, rather than fetching it just for that instance,
it runs a 

Re: Are there use cases for storing null bytes in CharField/TextField?

2017-05-15 Thread Luke Plant
I agree with Adam, we should never silently change submitted data at the 
model layer. My preference would be c), a form-level validation error 
that prevents saving.


Luke


On 15/05/17 19:11, Adam Johnson wrote:
The problem with (a) - data with null bytes in strings from other 
databases can't be loaded into PG as per #28117 .


The problem with (b) - data currently in databases in the wild will be 
modified upon save 


(b) is incredibly destructive and could break an unknown number of 
applications whilst (a) doesn't affect anyone until they try to 
migrate null-byte-strings into PG. I vote for (a), or (c) add 
form-level validation to (Char/Text)Field that null bytes aren't in 
the submitted string (for all databases) and error when trying to save 
them on PG.



On 15 May 2017 at 16:54, Tim Graham > wrote:


Does anyone know of a use case for using null bytes in
CharField/TextField?

psycopg2 2.7+ raises ValueError("A string literal cannot contain
NUL (0x00) characters.") when trying to save null bytes [0] and
this exception is unhandled in Django which allow malicious form
submissions to crash [1]. With psycopg2 < 2.7, there is no
exception and null bytes are silently truncated by PostgreSQL.
Other databases that I tested (SQLite, MySQL, Oracle) allow saving
null bytes. This creates possible cross-database compatibility
problems when moving data from those databases to PostgreSQL, e.g.[2].

I propose to have CharField and TextField strip null bytes from
the value either a) only on PostgreSQL or b) on all databases.
Please indicate your preference or suggest another solution.

[0] https://github.com/psycopg/psycopg2/issues/420

[1] https://code.djangoproject.com/ticket/28201
 - Saving a
Char/TextField with psycopg2 2.7+ raises ValueError: A string
literal cannot contain NUL (0x00) characters is unhandled
[2] https://code.djangoproject.com/ticket/28117
 - loaddata raises
ValueError with psycopg2 backend when data contains null bytes
-- 
You received this message because you are subscribed to the Google

Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it,
send an email to django-developers+unsubscr...@googlegroups.com
.
To post to this group, send email to
django-developers@googlegroups.com
.
Visit this group at
https://groups.google.com/group/django-developers
.
To view this discussion on the web visit

https://groups.google.com/d/msgid/django-developers/9897126d-b6ef-48f1-9f19-96ed98ce10e5%40googlegroups.com

.
For more options, visit https://groups.google.com/d/optout
.




--
Adam
--
You received this message because you are subscribed to the Google 
Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send 
an email to django-developers+unsubscr...@googlegroups.com 
.
To post to this group, send email to 
django-developers@googlegroups.com 
.

Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/CAMyDDM1qVc3ovXb9PhzKY3jd__FURYX6Fy9r1WFrBpcpMy%2Bz%2BA%40mail.gmail.com 
.

For more options, visit https://groups.google.com/d/optout.


--
You received this message because you are subscribed to the Google Groups "Django 
developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/1fbe9f18-f935-93eb-dd90-ffa754ad9c2b%40cantab.net.
For more options, visit https://groups.google.com/d/optout.


Re: DJANGO_SETTINGS_FILE

2017-04-09 Thread Luke Plant



On 09/04/17 16:16, Josh Smeaton wrote:


So I think there are a few questions to go over.

1. What are the more successful strategies that work in the wild? 
(files in /etc/, PYTHONPATH, env vars, local_settings.py)

2. Are any of the above clearly superior?
3. Is this a serious problem that people are having?
4. If yes, does it need to be solved in core?


To put a word in on number 2 regarding environment variables, we should 
take into account articles like:


 
https://diogomonica.com/2017/03/27/why-you-shouldnt-use-env-variables-for-secret-data/


The argument for solving in core would be if there are security issues 
we can genuinely fix by putting something in core rather than allowing 
custom mechanisms, and if that mechanism will really work in most cases. 
We also need to consider shared hosting where /etc/ is not an option.


Luke

--
You received this message because you are subscribed to the Google Groups "Django 
developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/a10c2ac8-b71c-0382-82c3-6a0c2bd0efa4%40cantab.net.
For more options, visit https://groups.google.com/d/optout.


Re: To keep or not to keep: logging of undefined template variables

2017-03-21 Thread Luke Plant
My general policy is that warnings should only be logged if there is a 
good way to silence them. A good way means:


1) fix the bug which is causing them (only applies if there is genuinely 
a bug or bad practice that should be fixed)


2) disable the warning in a fine tuned way i.e. you can indicate, 
without much work or hackiness, *this* instance generating the warning 
is actually fine.


Otherwise, these warnings are useless or worse - people often:

* just turn off all warnings of this type because they are too noisy (so 
they become useless)


* or end up turning off even more than necessary (hurting the project)

* or miss genuine issues because of the noise.

It sounds like these warnings are of the unhelpful kind.


For implementing option 2, the only thing I could think of is extending 
the template syntax with something that indicates you are expecting the 
value to be missing e.g.:


   {% if foo? %}

   {{ foo? }}

This would clearly be a big change though.


Luke


On 16/03/17 22:03, Tim Graham wrote:
Ticket #18773 [0] added logging of undefined template variables in 
Django 1.9 [1], however, I've seen several reports of users finding 
this logging more confusing than helpful. For example, admin templates 
log errors about missing is_popup variables [2] which is how the 
template are designed (is_popup is only in the contexts of pop ups) 
and the TECHNICAL_404_TEMPLATE also logs errors without any obvious 
solution about how to prevent that [3].


I'm thinking it might be better to remove this noisy, generally 
unhelpful logging. What do you think?


[0] https://code.djangoproject.com/ticket/18773
[1] 
https://github.com/django/django/commit/dc5b01ad05e50ccde688c73c2ed3334a956076b0

[2] https://groups.google.com/d/topic/django-users/6Ve9dcv23sI/discussion
[3] https://code.djangoproject.com/ticket/26886
--
You received this message because you are subscribed to the Google 
Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send 
an email to django-developers+unsubscr...@googlegroups.com 
.
To post to this group, send email to 
django-developers@googlegroups.com 
.

Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/a428f373-ef0c-4575-8a84-69a4beda154c%40googlegroups.com 
.

For more options, visit https://groups.google.com/d/optout.


--
You received this message because you are subscribed to the Google Groups "Django 
developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/56aa2380-64a0-aa39-d9ec-5d6124f4ebde%40cantab.net.
For more options, visit https://groups.google.com/d/optout.


Re: NEW Feature: Collect static order of directories searched. Possible upgrade inside FileSystemFinder.

2017-03-11 Thread Luke Plant
Like Tim, I'm surprised if there is non-determinism in the order here - 
a quick look at the code shows the search is in the order specified in  
STATICFILES_DIRS. Is it possible you are encountering browser caching 
effects, perhaps triggered by accessing both sites on 'localhost' locally?



Luke

On 10/03/17 16:35, Tim Graham wrote:
Hi, I'm surprised if the search behavior is nondeterministic rather 
than searching STATICFILES_DIRS in order. If that's really the case, 
it seems like a bug. Can you point to the code that causes the 
nondeterminism?


On Friday, March 10, 2017 at 7:35:25 AM UTC-5, Radosław Orłowski wrote:

Right now I'm working with Django 1.8.17 and What I'm trying to
acomplish is simple override of static files.

STATICFILES_DIRS = (
str(os.path.abspath(os.path.join(SITE_ROOT, 'static_new'))),
str(os.path.abspath(os.path.join(SITE_ROOT, 'static'))),
)

STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
)

my thinking:
I have to sites that need different logo file.

Both directories static and static_new have images/logo.png, but
this file is different.

I need to add logo from static_new and load rest of content from
static (js, css. etc)
This would allow me to create folders with statics -- per site
without changing urls and templates, just collect static would
take images from another dir, other changes are made with 
django.contrib.sites.models.get_current_site

Collect static works with *first found* but I have no way to
define 'seach here first behavior'. Also development static and
collectstatic don't seem to search for those files with same order
(also I find them both unstable as once in a while logo is loaded
from static_new and mostly from static)


Expected behavior:
when adding new folder to STATICFILES_FINDERS, I can somehow
define order of folders static file finder will go through
searching for this item either as alphabetic order or by explicit
order. ('static',2),('static_new',1)
second behavior is similar to list_display and fieldsets in admin
views, I would love to introduce here something like that.


Discussion open.

--
You received this message because you are subscribed to the Google 
Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send 
an email to django-developers+unsubscr...@googlegroups.com 
.
To post to this group, send email to 
django-developers@googlegroups.com 
.

Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/86d68df8-38e0-4dad-ab93-6d12e1d2eeba%40googlegroups.com 
.

For more options, visit https://groups.google.com/d/optout.


--
You received this message because you are subscribed to the Google Groups "Django 
developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/213566d4-3cf8-2e7e-e16d-4d48c82837f5%40cantab.net.
For more options, visit https://groups.google.com/d/optout.


Re: Template handling of undefined variables

2017-03-01 Thread Luke Plant



On 01/03/17 01:53, Tim Martin wrote:


On Tuesday, 28 February 2017 13:39:21 UTC, Luke Plant wrote:


On 28/02/17 15:24, Marten Kenbeek wrote:

What about adding a filter |definedthat returns True if a
variable is defined, False otherwise? It may not solve any
problems when it's left implicit, but at least it allows users
the explicitly define the behaviour for non-existing template
variables, and it makes the intention of the template code
crystal clear. And of course it's fully backwards compatible. The
drawback is perhaps the resulting verbosity of if statements:

{% if user.role|defined and roles.staff|defined and user.role
== roles.staff %}
[sensitive information here]
{% endif %}



The only way to do it would be to hard code this filter into the
template engine, because otherwise the 'defined' filter runs too
late to know whether the variable is defined.  This is really
hacky and magic.



Is that true? In my patch, the undefined variable gets expanded into 
an UndefinedVariable sentinel object, which can be detected by the 
defined modifier, and can compare == to None (or not, if you wish). 
Other than the result of the 'is' operator, I think you can make this 
fully backward compatible if you choose. Whether or not this is 
desirable is another question, of course.


I was talking about with the current behaviour of template engine i.e. 
without changing how undefined variables are handled. For this to work 
as you proposed, you would have to be passing the UndefinedVariable 
object into these filters. Having checked out your branch, I can see 
that is what you are doing.


This is a really big backwards incompatibility, as far as I can see. It 
means that any filter may now get passed `UndefinedVariable` instead of 
being passed `None` or string_if_invalid. So for example, the following 
template behaves oppositely with your patch, if variable 'missing' is 
undefined:


{% if missing|yesno == "maybe" %}true{% else %}false{% endif %}

There are likely many other filters that will behave differently e.g.:

{{ missing|add:"x" }}

Without the patch, if 'missing' is undefined this returns "x", but with 
the patch it returns "". It's not just builtin filters I'm thinking 
about, it's everyone else's that would also have to be made aware of 
this new false-y value that it will start receiving. This is a really 
big backwards incompatible change, I don't see how we could justify 
this. If we were starting from scratch it would be another matter.


Luke

--
You received this message because you are subscribed to the Google Groups "Django 
developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/fb53a533-9e83-476c-a20d-6bc7953b928c%40cantab.net.
For more options, visit https://groups.google.com/d/optout.


Re: Template handling of undefined variables

2017-03-01 Thread Luke Plant



In the context of template variable interpolation i.e. `{{ }}`
syntax, it is defined that `x` in this case will get converted to
the empty string (or your 'string_if_invalid' setting) -

https://docs.djangoproject.com/en/dev/ref/templates/api/#how-invalid-variables-are-handled


- unlike the case for `if` tags.

When this value (the empty string) is passed to `default_if_none`,
the value is not changed, since it is not None. See

https://docs.djangoproject.com/en/1.10/ref/templates/builtins/#default-if-none




The missing piece of information for me (and even reading the docs 
it's far from obvious) is that undefined variables mean two different 
things in the different contexts.


The value *is* changed in the second case, because it *is* None. 
Undefined values are '' in {{ }} context but are None in {% %} 
context. Maybe that's obvious to you, but it's not to me. In fact, 
after a few minutes searching I still can't find where this is 
mentioned in the documentation. Only the vague statement that invalid 
variables are "generally" replaced with string_if_invalid.


I meant above that in the {{ }} context 'default_if_none' doesn't return 
the default value, but just returns the empty string input value.


I also had to read the docs to understand the behaviour - it is 
mentioned in the 3rd paragraph down in the docs linked above, "How 
invalid variables are handled" - the `if`, `for` and `regroup` tags are 
specifically mentioned.  I think the docs could be clearly about how 
things work with variables passed to template tags etc. "In general" as 
you say is rather vague. Definitely room for improvement here!



Luke

--
You received this message because you are subscribed to the Google Groups "Django 
developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/49c674a7-ab69-cfd6-0fdc-9ba444fd1ffa%40cantab.net.
For more options, visit https://groups.google.com/d/optout.


Re: Template handling of undefined variables

2017-02-28 Thread Luke Plant



On 28/02/17 15:24, Marten Kenbeek wrote:
What about adding a filter |definedthat returns True if a variable is 
defined, False otherwise? It may not solve any problems when it's left 
implicit, but at least it allows users the explicitly define the 
behaviour for non-existing template variables, and it makes the 
intention of the template code crystal clear. And of course it's fully 
backwards compatible. The drawback is perhaps the resulting verbosity 
of if statements:


{% if user.role|defined and roles.staff|defined and user.role == 
roles.staff %}

[sensitive information here]
{% endif %}



The only way to do it would be to hard code this filter into the 
template engine, because otherwise the 'defined' filter runs too late to 
know whether the variable is defined.  This is really hacky and magic.


The alternative would be for this filter to take a string e.g.:


{% if "user.role"|defined and "roles.staff"|defined and user.role 
== roles.staff %}

[sensitive information here]
{% endif %}

As an analogy, in Python you can't write:

if hasattr(foo.bar)

you have to write:

if hasattr(foo, 'bar')

Another alternative would be to have some special syntax that could 
check for defined variables e.g.


   {% if user.role? and roles.staff? and user.role == roles.staff %}

My own preference, if I had a time machine, would be to have missing 
data/attributes just raise NameError/KeyError/AttributeError, and then 
have special syntax for replacing missing values with None - like 
https://msdn.microsoft.com/en-us/library/dn986595(v=vs.140).aspx .


However, I think that any option involving special syntax here has 
already got way too complex for the design philosophy of Django 
templates - to be simpler than normal Python code, and more designer 
friendly - this would take us in the opposite direction.


Luke

--
You received this message because you are subscribed to the Google Groups "Django 
developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/c1bada04-9852-e49a-e651-b12c68dcb284%40cantab.net.
For more options, visit https://groups.google.com/d/optout.


Re: Template handling of undefined variables

2017-02-27 Thread Luke Plant



On 05/01/17 02:39, Tim Martin wrote:

2) There appears to be an inconsistency in the default_if_none
   modifier. If I have a template with

   x|default_if_none:y = {{x|default_if_none:y}}
   {% if x|default_if_none:y %}
   x|default_if_none:y is apparently True
   {% endif %}

   with y defined to True and x undefined, then it produces:

   x|default_if_none:y =
   x|default_if_none:y is apparently True

   IOW it appears that the default_if_none doesn't cause y's value to
   be used in the case where the variable is being printed, even
   though it causes the expression to have y's value when evaluated in
   an if. I think this is something to do with the fact that the two
   ways of handling failures (ignore_failures and string_if_invalid)
   do different things.

   I don't see a way to make backward compatible code here.

   I think this is just a bug, does anyone think otherwise?


This seems to be working exactly as it should.

In the context of template variable interpolation i.e. `{{ }}` syntax, 
it is defined that `x` in this case will get converted to the empty 
string (or your 'string_if_invalid' setting) - 
https://docs.djangoproject.com/en/dev/ref/templates/api/#how-invalid-variables-are-handled 
- unlike the case for `if` tags.


When this value (the empty string) is passed to `default_if_none`, the 
value is not changed, since it is not None. See 
https://docs.djangoproject.com/en/1.10/ref/templates/builtins/#default-if-none


The behaviour here follows 100% logically from the documented behaviour 
of the two components.


Regards,

Luke




Sorry for the lengthy email. Thanks for any input.

Tim
--
You received this message because you are subscribed to the Google 
Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send 
an email to django-developers+unsubscr...@googlegroups.com 
.
To post to this group, send email to 
django-developers@googlegroups.com 
.

Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/b9d7b557-5826-4c7e-a064-5f8b59312faa%40googlegroups.com 
.

For more options, visit https://groups.google.com/d/optout.


--
You received this message because you are subscribed to the Google Groups "Django 
developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/a7dc3b9e-195f-e4e4-2692-4b07de68c0cd%40cantab.net.
For more options, visit https://groups.google.com/d/optout.


Re: Template handling of undefined variables

2017-02-27 Thread Luke Plant


On 26/02/17 00:44, Karen Tracey wrote:
On Sat, Feb 25, 2017 at 2:10 PM, Tim Graham > wrote:


I think any use of undefined template variables should raise an
exception. In the long run, keeping a setting to allow some other
behavior seems confusing and, considering the case of templates
that might be reused in different projects with different
settings, even dangerous.


I think I'm confused...Django templates have allowed use of undefined 
variables and documented their use as evaluating to the empty string 
for as long as I recall. Wouldn't a change to instead raise exceptions 
be a major backwards-incompatibility?


https://docs.djangoproject.com/en/1.7/topics/templates/#variables said 
"If you use a variable that doesn’t exist, the template system will 
insert the value of the TEMPLATE_STRING_IF_INVALID setting, which is 
set to '' (the empty string) by default."


This behaviour applies only to what happens when the variable is 
rendered. In the context of `if` tags, undefined variables get converted 
to `None`. This behaviour is documented - 
https://docs.djangoproject.com/en/dev/ref/templates/api/#how-invalid-variables-are-handled 
but perhaps not in as much detail as necessary.


The question is about changing this, especially due to templates like this:

{% if user.role == roles.staff %}
[sensitive information here]
{% endif %}

If:
1) you forget to provide both user and role to template context or
2) 'role' or 'staff' are invalid attributes, or
3) 'role' returns None but 'staff' is an invalid attribute, for example,
4) various combinations of these

then this results in the sensitive info being shown, because `None == 
None`. The proposal is to introduce a value that doesn't not compare 
equal to itself and avoid this kind of issue.


Having thought about it more, I've realised that this really isn't going 
to work at all.


First attempt:

class Undefined1(object):
def __eq__(self, other):
return False

If we use this, then consider the following template code:

{% if user.role != roles.staff %}
This info is private, sorry
{% else %}
[sensitive information here]
{% endif %}


The default implementation of != means we will again get the sensitive 
data shown for some of the error situations given above (e.g. 1 and 2). 
Second attempt:


class Undefined2(object):
def __eq__(self, other):
return False
def __new__(self, other):
return False

This object is neither equals nor not-equals to itself or anything else. 
But consider this template:



{% if user.role == roles.customer %}
This info is private, sorry
{% else %}
[sensitive information here]
{% endif %}

With `Undefined2` being used for invalid attributes, we again get the 
sensitive information being shown in the case of developer error and 
missing attributes. Plus, we now have the situation that `{% if a != b 
%}` is not the same as `{% if not a == b %}`, which is very confusing 
behaviour for most people.


In other words, we are getting into the territory of needing a value 
that behaves like NULL in SQL. Even if there were no implementation 
issues (and there will be lots, because operators like 'or' 'and' etc. 
would need to cope with this, not to mention 3rd party code), and there 
were no backwards compatibility issues (there are lots), this would be 
extremely dubious to me, because ternary logic is extremely tricky.


The only sensible alternative to current behaviour is to raise 
exceptions, but huge backwards incompatibility issues I think rule this 
out. If I were to start again, I think I would make the template system 
not silence any errors you would normally get in Python, but just have 
some special syntax for converting non-existent data or attributes into 
None. But I don't have that time machine.


Regards,

Luke

--
You received this message because you are subscribed to the Google Groups "Django 
developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/4b0a8ec9-c588-de8d-76ba-0d3b55b8fe20%40cantab.net.
For more options, visit https://groups.google.com/d/optout.


Re: Template handling of undefined variables

2017-02-20 Thread Luke Plant

On 19/02/17 12:55, Adam Johnson wrote:
+1 for more obvious errors, silently changing the behaviour could 
indeed lead to unconsidered security holes like


{% if user is None %}
non-sensitive information
{% else %}
sensitive information
{% endif %}

...which doesn't seem like an unrealistic template snippet. We all 
know variables can go missing in refactorings.


Another option, perhaps not feasible to implement, would be 
deprecating the old behaviour, similar to the previous change in 
url with something like:


{% load undefined_vars from future %}


I agree there are a lot of potential security/correctness issues with 
this, it is potentially quite a big change (though very helpful IMO).


A different approach to introducing it might be a setting, possibly an 
option to the Django template engine instead - 
https://docs.djangoproject.com/en/1.10/ref/settings/#std:setting-TEMPLATES-OPTIONS 
. I think this would be more appropriate for something that is more of a 
global behaviour issue, more practical than having to add hundreds of 
'load from future' tags, plus it would then parallel other similar 
settings like 'string_if_invalid'. In the next version of Django the 
option would default to False (i.e. old behaviour), but raise a 
deprecation warning, in future versions it would simply be True, and 
raise an error if someone tries to pass False (but allow True, for the 
sake of apps that are spanning multiple Django versions).


This would allow people to test their site with the new mechanism and 
have time to fix issues, which can be especially important for 3rd party 
Django apps.


Ideally there would be some way to instrument code and see if the output 
would be different with the new behaviour, but I can't think of an easy 
way to do this.


Luke

--
You received this message because you are subscribed to the Google Groups "Django 
developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/496fa4a8-b902-657a-92c2-9766bfff8a26%40cantab.net.
For more options, visit https://groups.google.com/d/optout.


Re: Consider reverting or adding guidelines on how to use class based views for security sensitive features

2016-11-22 Thread Luke Plant

Hi all,

First, I want to say that complex things fail in complex ways, so there 
it's probably a fallacy to look for a single root cause. I agree with 
various other points about mistakes that were made, but not others. 
Particularly:


On 22/11/16 12:41, Florian Apolloner wrote:

Hi,

On Monday, November 21, 2016 at 11:56:56 PM UTC+1, Tim Graham wrote:

… that the existing tests would catch this type of obviously
incorrect issue.


I think that is the main issue here. I was also really surprised to 
discover that the tests were missing cases like this -- then again, 
writing good tests is hard and I know that I am personally one not to 
write good tests usually. Either way, I think the way forward is to 
improve the testsuite in this case.


I disagree with this, there was no issue with the existing test suite 
for the FBV version. *Tests are never close to exhaustive and we should 
never think they are or can be.* Tests are spot checks of correctness in 
an infinite universe of possible input values. When trying to work out 
what you should test in this vast space, there are a few sensible ways:


1. Look at the requirements, and pick spots that match each requirement. 
In this case:


 * If a request has the required token, it should be allowed through
 * If a request does not have the required token, it should not be
   allowed through

2. Make some guesses about well known edge cases and test them (e.g the 
empty string case etc.). However this could be a complete waste of time


3. Look at the implementation at work out where it might go wrong. This 
one is really important in reality.


And this is what the existing tests did. Out of the infinite number of 
HTTP requests to test under point 1, they happened to pick a GET 
request, which was perfectly sensible. In the case of FBVs, the control 
flow is so clear that all of the following are equally silly tests to add:


 * Check that requests with query string parameter 'xyz' doesn't
   introduce a back door
 * Check that on leap years tokens are checked
 * Check that the security is correct for requests that are
   specifically GET, POST, HEAD, OPTIONS, DELETE


The conclusion is this: in CBVs control flow is much, much less clear. 
In the FBV the mistake would have been immediately obvious, the CBV base 
classes obfuscated things to the point where it wasn't at all clear. To 
write adequate tests for the CBV version, under point 3 above, you have 
*much, much more work* to do.


I disagree that forcing people to write their own auth views is 
*necessarily* worse than providing a CBV that people can customise. 
Given this demonstration of how CBVs obfuscate control flow, it's quite 
possible that writing an FBV from scratch will be less error prone than 
using a CBV and subclassing, especially when we have encapsulated things 
like the token checking. Personally I would be massively happier 
auditing a custom FBV than a subclassed CBV, especially when you 
consider that the CBV subclass is inheriting from a stack of classes 
that could change in later versions of Django in some subtle way that 
breaks the code. Subclassing is not necessarily safer, it just feels 
safer ("I'm only changing this one little method"), and *that feeling of 
greater safety is itself a huge danger*.


Going forward, I think we need to:

1. Recognise that CBVs are much harder to reason about, and therefore 
require much more care.

2. Avoid using CBVs unless you really need them.
3. Recognise that tests for FBVs are inadequate against the CBV translation.
4. Not deprecate the FBVs. At the very least, they provide a sensible 
and easy to understand starting point for people that want to copy the 
logic to create their own, and do so in a way that they actually 
understand and can audit.


I'd be +0 on reverting to an FBV only, but it's part of a much bigger 
discussion


Regards,

Luke

--
You received this message because you are subscribed to the Google Groups "Django 
developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/e160c9a0-0af0-7767-4b35-cb02a92d6a4d%40cantab.net.
For more options, visit https://groups.google.com/d/optout.


Re: Making max_length argument optional

2016-02-28 Thread Luke Plant
Regarding custom sentinels for values vs custom sentinels for missing values:

The added complication in this case is migrations, and migrations that support 
multiple Django versions, as is common in 3rd party apps. I haven't thought 
through the implications, but it is vital to do so, because getting it wrong 
can seriously hurt the adoption of a feature, and even the adoption of a new 
version of Django.

It may not be an option to say "for compatibility generate migrations using the 
lowest supported Django versions", because sometimes old Django versions have 
bugs that prevent migration generation. 

We also need to consider the potential need for several different sentinel 
values e.g. "unlimited" vs "database defined max length". 

Luke 

On 28 February 2016 14:38:40 GMT+00:00, "Loïc Bistuer"  
wrote:
>There is a precedent to this (although it seems to happen at startup
>time rather than save time), we loop through all the connections and
>check that max_length has a value supported by their backend:
>https://github.com/django/django/blob/master/django/db/backends/mysql/validation.py.
>
>I don’t think we need to create a new sentinel value to mean
>“unlimited” when `max_length=None` works well semantically, if we want
>to keep the `max_length` value explicit we can just use `NOT_PROVIDED`
>as the kwarg default value. It is backwards compatible since
>`max_length=None` currently issues an error.
>
>Regarding the switch to a default value of 120 or so, I don’t have a
>strong opinion against it, but I think it’s an orthogonal problem to
>supporting unlimited varchar on backends that can handle it.
>
>> On Feb 28, 2016, at 6:50 PM, Florian Apolloner
> wrote:
>> 
>> I do not see how blowing up on save is a good idea (especially not if
>we ran model validation before). We do not do that for MySQL (at least
>not if your project is configured properly, leaving issues with utf8mb4
>out for now) since our model form validation is able to use the
>supplied max_length to inform the user that the data is invalid
>__before__ save.
>
>-- 
>You received this message because you are subscribed to the Google
>Groups "Django developers  (Contributions to Django itself)" group.
>To unsubscribe from this group and stop receiving emails from it, send
>an email to django-developers+unsubscr...@googlegroups.com.
>To post to this group, send email to
>django-developers@googlegroups.com.
>Visit this group at https://groups.google.com/group/django-developers.
>To view this discussion on the web visit
>https://groups.google.com/d/msgid/django-developers/663F6FA1-1D09-4A21-928A-836157386253%40gmail.com.
>For more options, visit https://groups.google.com/d/optout.

-- 
Sent from my phone 

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/F5159BD5-23CD-46EF-92A7-EF10BCCE7890%40cantab.net.
For more options, visit https://groups.google.com/d/optout.


Re: Making max_length argument optional

2016-02-28 Thread Luke Plant
Replying to this and the other emails in the thread:

Django should not be settling low arbitrary limits for the sake of a database 
I'm not even using, that's just crazy. Limits as high as 120 are not "big 
enough for anyone", and will cause problems. (I can give lots of examples). 
Maximum field length is a critical value that must not be left to some default, 
because as soon as you come to interoperate with other systems, it *does* 
matter. 


So, this needs to be explicit. 

We also need to cover the case of unlimited length Charfield for the databases 
that support it. This can be covered with a simple sentinel value 
UNLIMITED_LENGTH or similar. This is a 4th option not listed below. 

We could also potentially add another sentinel like DB_MAX_UNICODE_SAFE_LENGTH 
that works as you expect and is clearly documented, for the sake of 3rd party 
apps, and comes with the caveat that it produces different behaviour on 
different databases. 

Explicit is better than implicit etc., and in this case there is simply no 
sensible default behaviour that will cover all our use cases. 

Luke 






On 27 February 2016 12:55:23 GMT+00:00, Wim Feijen  wrote:
>Hi guys,
>
>I'd like to reach consensus about 
>https://code.djangoproject.com/ticket/14094
>
>In the discussion, I saw three options:
>
>1. Adding a default max_length = None, which may in practice differ per
>
>database backend.
>2. Adding a default max_length of a value which can be used across 
>databases. Lengths which have been mentioned are: 100, 128, 191 and 255
>
>characters and 4000 bytes.
>3. Keep everything as is, being as explicit as possible.
>
>Option 1 does not allow for apps and data to be reused across several
>apps 
>and several core developers do not support this idea.
>
>I'm in favour of option 2, because it makes for shorter code and more 
>importantly, it helps programmers choose a value which actually can be 
>reused across multiple databases (I didn't know about the possible
>limit of 
>191 characters on mysql! Did you?).
>
>I dislike how it is now (option 3), and I don't think it is beneficial
>here 
>to force people to be explicit, because people are now using arbitrary 
>values anyway. 255 is commonly used, the poll app of the Django
>tutorial 
>uses 200. Actually I believe it is a big mess in practice, I see
>defaults 
>of 100, 200, 255, 300, 1000 seemingly randomly used. For example, try 
>searching for CharField in your favourite apps or CMSes.
>
>In addition, adding a default for max_length still allows to be
>explicit 
>when it matters. And it makes life simple when it doesn't matter, and 
>simple is better than complex.
>
>What would be a good default then? I am in favour of making it as big
>as 
>possible while still working on all databases, which would either be
>191 of 
>255 in order to support mysql.
>
>Wim
>
>
>
>On Wednesday, 23 September 2015 19:02:20 UTC+2, Tom Christie wrote:
>>
>> I'm with Tom here.
>> Forcing `max_length` to always be set on CharField feels like the
>right 
>> decision. Having a default there seems unnecessary obscure, and more
>likely 
>> to lead to untested/unnoticed failure cases.
>> It *could* be that we'd allow `max_length=None` to explicitly turn
>off the 
>> validation, but I'm not sure if that's better than forcing developers
>who 
>> want unvalidated lengths to use TextField.
>>
>
>-- 
>You received this message because you are subscribed to the Google
>Groups "Django developers  (Contributions to Django itself)" group.
>To unsubscribe from this group and stop receiving emails from it, send
>an email to django-developers+unsubscr...@googlegroups.com.
>To post to this group, send email to
>django-developers@googlegroups.com.
>Visit this group at https://groups.google.com/group/django-developers.
>To view this discussion on the web visit
>https://groups.google.com/d/msgid/django-developers/a2cfad14-4384-4118-bc28-d89099433ca5%40googlegroups.com.
>For more options, visit https://groups.google.com/d/optout.

-- 
Sent from my phone 

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/EBD26DDE-B91E-4CB6-950F-8E67B98AB97E%40cantab.net.
For more options, visit https://groups.google.com/d/optout.


Re: Django Admin - ModelAdmin exclude

2015-09-12 Thread Luke Plant
-developers>.
To view this discussion on the web visit

https://groups.google.com/d/msgid/django-developers/c1e8762d-1c9f-47e9-8fe7-e9761c27e057%40googlegroups.com

<https://groups.google.com/d/msgid/django-developers/c1e8762d-1c9f-47e9-8fe7-e9761c27e057%40googlegroups.com>.
For more options, visit https://groups.google.com/d/optout
<https://groups.google.com/d/optout>.


--
You received this message because you are subscribed to the Google 
Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send 
an email to django-developers+unsubscr...@googlegroups.com 
<mailto:django-developers+unsubscr...@googlegroups.com>.
To post to this group, send email to 
django-developers@googlegroups.com 
<mailto:django-developers@googlegroups.com>.

Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/ee4e1491-78cb-4e3a-8419-5a054ca079f1%40googlegroups.com 
<https://groups.google.com/d/msgid/django-developers/ee4e1491-78cb-4e3a-8419-5a054ca079f1%40googlegroups.com?utm_medium=email_source=footer>.

For more options, visit https://groups.google.com/d/optout.


--
Clothes make the man. Naked people have little or no influence on
society.
   -- Mark Twain

Luke Plant || http://lukeplant.me.uk/

--
You received this message because you are subscribed to the Google Groups "Django 
developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/55F45302.8010200%40cantab.net.
For more options, visit https://groups.google.com/d/optout.


Re: CSRF_FAILURE_VIEW should not be used when DEBUG is False

2015-08-10 Thread Luke Plant
When users see a CSRF failure, it is almost always because of mistake 
made by the developer, and it is more useful under those circumstances 
for the users to see a more specific error message that will help 
developers rectify the problem. A generic 403 template is very unlikely 
to be helpful for this case. I haven't looked into it much, but probably 
it would be hard to pass the 'reason' to a generic template, without 
which developers will have a hard time debugging the problem.


Regards,

Luke

On 07/08/15 14:02, Tim Graham wrote:
I guess we might have to wait for Luke to reply to explain the 
reasoning for the original decision.


On Friday, August 7, 2015 at 8:47:23 AM UTC-4, Žan Anderle wrote:

That's true. But it still seems a bit off, that all other 4xx will
be handled diffrently with DEBUG=False. Shouldn't the default
behavior for csrf failure be the same? So while it's not a bug, I
still don't get it why I should update the view for CSRF failure,
while I only need to create 4xx.html template for other 4xx and
5xx statuses. Because the default CSRF failure template is not
very user friendly.

Dne petek, 07. avgust 2015 14.41.21 UTC+2 je oseba Tim Graham
napisala:

It doesn't seem to be a bug to me as there's nothing in the
documentation that says the view should only be used when
DEBUG=True. The default template also includes logic to vary
the content based on DEBUG.

On Saturday, August 1, 2015 at 11:28:57 AM UTC-4, Žan Anderle
wrote:

Hey everyone!

I noticed today that CSRF_FAILURE_VIEW is used even when
DEBUG=False. I'm not sure why this is so and I think it
would make much more sense to use default 403 handling
when DEBUG=False.

I checked the ticket where this was initially added, to
see if there was a particular reason for it.

https://code.djangoproject.com/ticket/9977
<https://code.djangoproject.com/ticket/9977>

I could only find one comment related to this. And
although it says 'Helpful 403 page if DEBUG is True'
that's not really the case.

I wanted to check here if there is a reason for this
behaviour before opening a ticket for it.

Have a great weekend :)
Žan

--
You received this message because you are subscribed to the Google 
Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send 
an email to django-developers+unsubscr...@googlegroups.com 
<mailto:django-developers+unsubscr...@googlegroups.com>.
To post to this group, send email to 
django-developers@googlegroups.com 
<mailto:django-developers@googlegroups.com>.

Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/14115f91-7967-48b6-9843-586252fad624%40googlegroups.com 
<https://groups.google.com/d/msgid/django-developers/14115f91-7967-48b6-9843-586252fad624%40googlegroups.com?utm_medium=email_source=footer>.

For more options, visit https://groups.google.com/d/optout.


--
OSBORN'S LAW
Variables won't, constants aren't.

Luke Plant || http://lukeplant.me.uk/

--
You received this message because you are subscribed to the Google Groups "Django 
developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/55C8F37B.9010209%40cantab.net.
For more options, visit https://groups.google.com/d/optout.


Re: Support for UNLOGGED tables in PostgreSQL

2015-07-19 Thread Luke Plant
I agree with Federico on this - as long as we slap a big warning on it — 
"This is dangerous - it could make your database more likely to lose 
data or become corrupted, only use on a development machine where you 
can restore the entire contents of all databases in the cluster easily" 
— I don't see a problem in this being in our docs.


If people refuse to read a clear warning, they shouldn't be doing web 
development. They are just as likely to find similar instructions on the 
internet, but without warnings, and having it in our docs with the 
warning will be helpful.


Having a fast test suite is such an important part of development that 
it shouldn't be held back by  attempting to protect the world from 
people who cannot be helped.


Luke

On 16/07/15 16:49, Christophe Pettus wrote:

On Jul 16, 2015, at 1:16 AM, Federico Capoano <federico.capo...@gmail.com> 
wrote:


I also don't like the idea of believing django users are too stupid to
understand that this advice si valid for development only. Generally
python and django users are intelligent enough to properly read the
docs and understand what's written on it.

It's not a matter of being "intelligent" or not.  Developers are busy and can 
simply google things, see a particular line, and drop it in without fully understanding 
exactly what is going on.  (Simply read this group for a while if you don't believe this 
to be the case!)  People already turn off fsync, in production, after having read the 
PostgreSQL documentation, without actually realizing that they've put their database in 
danger.

Among other things, developers often have local data in their PostgreSQL 
instance that is valuable, and advising them to do a setting that runs the risk 
of them losing that data seems like a bad idea.

The Django documentation is not the place to go into the ramifications of fsync 
(or even synchronous_commit, although that's significantly less risky).

--
-- Christophe Pettus
x...@thebuild.com



--
"I was sad because I had no shoes, until I met a man who had no
feet. So I said, "Got any shoes you're not using?"  (Steven Wright)

Luke Plant || http://lukeplant.me.uk/

--
You received this message because you are subscribed to the Google Groups "Django 
developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/55ABDF21.9060106%40cantab.net.
For more options, visit https://groups.google.com/d/optout.


Re: Django Admin - ModelAdmin exclude

2015-06-19 Thread Luke Plant
I agree with Marc on this one  - I remember doing the work to change 
"ModelForm.fields" so that you needed "__all__" to indicate everything, 
instead of defaulting to all. This was a nightmare precisely because of 
the different number of ways of defining the fields. This is partly the 
result of retrofitting ModelAdmin to use ModelForms, which it didn't 
originally.


Just implementing ModelAdmin.get_exclude() might prove to be extremely 
difficult to do, especially when you need to document how it interacts 
with all the other ones.


I think the problems with the false negatives for the admin checks may 
need to be solved another way - namely by removing them. That's 
unfortunate, but I found them tricky in the past - they may prevent 
common errors, but they also prevent more advanced ways that you might 
want to use the admin.


Luke

On 06/06/15 14:42, Marc Tamlyn wrote:
I don't think we should add this. Exclude is passed to the form, and 
we already have a way of changing the form based on the request. I'd 
rather see changes made to reduce some of the many many ways to select 
fields in the admin. By my count at present we have:


ModelAdmin.fields
ModelAdmin.get_fields()
ModelAdmin.exclude
ModelAdmin.fieldsets
ModelAdmin.get_fieldsets()
ModelAdmin.readonly_fields
ModelAdmin.get_readonly_fields()
ModelAdmin.form concrete fields
ModelAdmin.form.Meta.fields
ModelAdmin.form.Meta.exclude
ModelAdmin.get_form()

There's an argument the only one missing here is get_exclude(), but I 
think the current API is silly. Personally, I'd like to see us moving 
towards us encouraging doing more work in the form (and defining the 
form) rather than doing so much in the ModelAdmin class. This may well 
require better support for fieldsets in django.forms.


Marc

On 6 June 2015 at 05:06, Peter Farrell <p...@maestropublishing.com 
<mailto:p...@maestropublishing.com>> wrote:


We are writing a custom admin for CleanerVersion that subclasses
ModelAdmin. Just about every attribute has a hook method which
makes extension easier. For example, list_display has
get_list_display(). However, exclude doesn't have one implemented
and it seems like an oversight. I'm proposing we add one.

Our current work seeking is to write a property descriptor for
exclude but then the admin check fails with it not being a tuple
or list. Then you have to create a custom admin checks class to
suppress the exclude check error because it's not a tuple or list
(but really a descriptor).

If this is ok, I'Ill write a PR.

--
You received this message because you are subscribed to the Google
Groups "Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it,
send an email to django-developers+unsubscr...@googlegroups.com
<mailto:django-developers%2bunsubscr...@googlegroups.com>.
To post to this group, send email to
django-developers@googlegroups.com
<mailto:django-developers@googlegroups.com>.
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit

https://groups.google.com/d/msgid/django-developers/c1e8762d-1c9f-47e9-8fe7-e9761c27e057%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


--
You received this message because you are subscribed to the Google 
Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send 
an email to django-developers+unsubscr...@googlegroups.com 
<mailto:django-developers+unsubscr...@googlegroups.com>.
To post to this group, send email to 
django-developers@googlegroups.com 
<mailto:django-developers@googlegroups.com>.

Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/CAMwjO1HKDr6T9BKf-%2B4rNm6775S7akyHfC%2BNEk4sqSDw8cOb%2Bg%40mail.gmail.com 
<https://groups.google.com/d/msgid/django-developers/CAMwjO1HKDr6T9BKf-%2B4rNm6775S7akyHfC%2BNEk4sqSDw8cOb%2Bg%40mail.gmail.com?utm_medium=email_source=footer>.

For more options, visit https://groups.google.com/d/optout.


--
"He knows the way I take: when he has tried me, I shall come forth
as gold" (Job 23:10).

Luke Plant || http://lukeplant.me.uk/

--
You received this message because you are subscribed to the Google Groups "Django 
developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/55843AC1.4040707%40cantab.net.
For more options, visit https://groups.google.com/d/optout.


Re: does django-admin need a man page?

2015-06-19 Thread Luke Plant
Another argument for removing it (or trimming it down to minimum) is 
that it's actually extensible 
(https://docs.djangoproject.com/en/1.8/howto/custom-management-commands/ 
), and some packages (at least in the past) have actually changed the 
behaviour of built in commands (e.g. 
http://south.readthedocs.org/en/latest/commands.html#syncdb ).


So, the man page is doomed to be both incomplete and possibly incorrect. 
Surely it makes more sense for a man page to just point to the "--help" 
tag and official docs online?


Luke

On 03/03/15 15:42, Tim Graham wrote:
Is anyone interested in updating Django's man page? It's a bit 
embarrassing that the one that ships with 1.7 includes commands that 
no longer exist (cleanup, install (never heard of that one before), 
etc.). The fact that it is so outdated and that we've gotten no 
complaints about it is why I thought we could consider it for removal).


Any recommendations for a program to edit/preview manpage sources 
that's more human friendly?


On Wednesday, November 26, 2014 at 8:21:31 AM UTC-5, Markus Holtermann 
wrote:


On Wednesday, November 26, 2014 7:46:16 AM UTC+1, Aymeric Augustin
wrote:

Le 26 nov. 2014 à 01:51, Nick Phillips <nick.p...@otago.ac.nz>
a écrit :
>
> I'd suggest considering implementing
> something to generate a man page from whatever you wish the
"canonical"
> source of the information to be.

The canonical source of information is:
https://docs.djangoproject.com/en/dev/ref/django-admin/
<https://docs.djangoproject.com/en/dev/ref/django-admin/>

Does a rst-->man conversion tool exist?


Yes, rst2man.py is part of docutils. And Sphinx even has a man
builder. Inside the docs directory run "make man". The generated
man page is 4MB though, and contains the _entire_ documentation,
not only the django-admin.py command. But there should be some way
to work around that.
/Markus

--
You received this message because you are subscribed to the Google 
Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send 
an email to django-developers+unsubscr...@googlegroups.com 
<mailto:django-developers+unsubscr...@googlegroups.com>.
To post to this group, send email to 
django-developers@googlegroups.com 
<mailto:django-developers@googlegroups.com>.

Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/1ecfaac4-b31a-4675-bd62-95e76369a6e5%40googlegroups.com 
<https://groups.google.com/d/msgid/django-developers/1ecfaac4-b31a-4675-bd62-95e76369a6e5%40googlegroups.com?utm_medium=email_source=footer>.

For more options, visit https://groups.google.com/d/optout.


--
"He knows the way I take: when he has tried me, I shall come forth
as gold" (Job 23:10).

Luke Plant || http://lukeplant.me.uk/

--
You received this message because you are subscribed to the Google Groups "Django 
developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/55842D5F.8010409%40cantab.net.
For more options, visit https://groups.google.com/d/optout.


Re: Multiple template engines for Django - week 8

2014-11-30 Thread Luke Plant
Hi Aymeric,

Just some quick feedback - I think it's perfectly reasonable not to be
writing any docs or tests at this point. It seems like the nitty-gritty
details are likely to be affecting various API decisions that you have
to make, and there is no point writing either docs or tests when API is
in flux. Some of your work - the default path - is going to be well
tested by virtue of Django's existing test suite.

Luke

On 30/11/14 09:37, Aymeric Augustin wrote:
> Hello,
> 
> Here’s my eight update — this is getting repetitive :-)
> https://myks.org/en/multiple-template-engines-for-django/#2014-11-30
> 


-- 
"Whom have I in heaven but You?
And there is none upon earth that I desire besides You." Psalm 73:25

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/547C11D0.8080704%40cantab.net.
For more options, visit https://groups.google.com/d/optout.


Re: Infinite loop in migration code

2014-11-27 Thread Luke Plant
Hi Markus,


It was basically this:

== app camps ==

class Camp:

  invited_officers = M2M(auth.User, through='officers.Invitation')


== app officers ==

class Invitation:
  timestamp = models.DateTimeField(default=datetime.now)
  camp = FK(camps.Camp)
  user = FK(auth.User)


=

I ran makemigrations for 'camps', then 'officers', and the generated
migrations ended up depending on each other.

Hopefully that's enough, let me know if that doesn't reproduce it.
Sorry, don't have time to put it together more formally.

Thanks,

Luke


On 26/11/14 13:08, Markus Holtermann wrote:
> Can you open a ticket with your models so the issue doesn't get lost.
> I'm happy to work on it.
> 
> Although it's somewhat uncommon, people normally have the through model
> in the app that has the m2m field (why don't you define it on the other
> model?) this is still something that shouldn't happen.
> 
> /Markus
> 
> On Wednesday, November 26, 2014 8:54:55 AM UTC+1, Luke Plant wrote:
> 
> On 25/11/14 16:23, Markus Holtermann wrote:
> > Hey Luke,
> >
> > It would be interesting to see why A.1 and B.1 depend on each
> other. If
> > there are e.g. FK constraints pointing to models in the other app the
> > autodetector should end up with e.g. A.1 <-- B.1 <-- B.2 <-- A.2 (or
> > optimized A.1 <-- B.1 <-- A.2), in which case you wouldn't end up
> with a
> > cycle. C.1 would then depend on B.2 (B.1 respectively in the
> optimized
> > graph).
> 
> I didn't realise the autodetector could handle that. Looking more
> closely, it looks like I have more of an edge case:
> 
> App B has a model with a FK to a model in app A
> 
> App A has a model with a ManyToMany field 'through' a model in app B.
> (It's actually added that way for the sake of the admin for the models
> in app A).
> 
> So it isn't the straight-forward A has FK to B. It might not be worth
> fixing the autodetector for this, as fixing the migrations is
> relatively
> easy. But I think fixing the infinite loop is another matter, and I'll
> go ahead and backport that.
> 
> Thanks for the input,
> 
>     Luke
> 
> 
> -- 
> "We may not return the affection of those who like us, but we
> always respect their good judgement." -- Libbie Fudim
> 
> Luke Plant || http://lukeplant.me.uk/
> 
> -- 
> You received this message because you are subscribed to the Google
> Groups "Django developers (Contributions to Django itself)" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to django-developers+unsubscr...@googlegroups.com
> <mailto:django-developers+unsubscr...@googlegroups.com>.
> To post to this group, send email to django-developers@googlegroups.com
> <mailto:django-developers@googlegroups.com>.
> Visit this group at http://groups.google.com/group/django-developers.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/django-developers/f2924e77-7604-4632-a7c1-1920a3bfb4d0%40googlegroups.com
> <https://groups.google.com/d/msgid/django-developers/f2924e77-7604-4632-a7c1-1920a3bfb4d0%40googlegroups.com?utm_medium=email_source=footer>.
> For more options, visit https://groups.google.com/d/optout.


-- 
"In your presence there is fullness of joy; at your right hand are
pleasures forevermore" Psalm 16:11

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/54774F2E.2020306%40cantab.net.
For more options, visit https://groups.google.com/d/optout.


Re: Infinite loop in migration code

2014-11-25 Thread Luke Plant
On 25/11/14 16:23, Markus Holtermann wrote:
> Hey Luke,
> 
> It would be interesting to see why A.1 and B.1 depend on each other. If
> there are e.g. FK constraints pointing to models in the other app the
> autodetector should end up with e.g. A.1 <-- B.1 <-- B.2 <-- A.2 (or
> optimized A.1 <-- B.1 <-- A.2), in which case you wouldn't end up with a
> cycle. C.1 would then depend on B.2 (B.1 respectively in the optimized
> graph).

I didn't realise the autodetector could handle that. Looking more
closely, it looks like I have more of an edge case:

App B has a model with a FK to a model in app A

App A has a model with a ManyToMany field 'through' a model in app B.
(It's actually added that way for the sake of the admin for the models
in app A).

So it isn't the straight-forward A has FK to B. It might not be worth
fixing the autodetector for this, as fixing the migrations is relatively
easy. But I think fixing the infinite loop is another matter, and I'll
go ahead and backport that.

Thanks for the input,

Luke


-- 
"We may not return the affection of those who like us, but we
always respect their good judgement." -- Libbie Fudim

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/5475873E.3010805%40cantab.net.
For more options, visit https://groups.google.com/d/optout.


Infinite loop in migration code

2014-11-25 Thread Luke Plant

I came across a bug with an infinite loop in migration dependency
searching code. This is fixed here:

https://github.com/django/django/commit/ff3d746e8d8e8fbe6de287bd0f4c3a9fa23c18dc

(another person reviewing it would be good, though I think it is correct).

My question is, should we backport this to 1.7.x? For me, the bug
manifested itself with migrations that were automatically created by
Django itself, in a project with apps A, B, and C:

App B depends on app A
App A depends on app B (it didn't initially, but does now)
App C depends on one/both of them.

After doing makemigrations for A and B, makemigrations for C then went
into an infinite loop.

So this is not a really obscure case, and could affect a fair number of
people attempting to upgrade to Django 1.7, as I was.

Regards,

Luke


-- 
"We may not return the affection of those who like us, but we
always respect their good judgement." -- Libbie Fudim

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/5474A4F1.20208%40cantab.net.
For more options, visit https://groups.google.com/d/optout.


Re: sys.exit(1) from makemigrations if no changes found

2014-10-31 Thread Luke Plant
My preference for this would be option 3., on the grounds that:

* I'd rule out 1 because of the slight backwards incompatibility (which
can affect people - I remember a deploy script failing because of a
changed exit code for a Mercurial command). In particular, currently
there are other conditions when you get a non-zero exit code - for the
case of some crash due to incorrect setup or other runtime error. This
is a distinct case from  "this command errored because there were no
migrations to make".

* I'd rule out 2 because it really makes --dry-run behave differently
from normal, which breaks expectations

Basically, having a flag like "--exit" is nice and explicit.

Luke

On 29/10/14 01:22, Tim Heap wrote:
> Hi all,
> 
> I have created a ticket for this
> (https://code.djangoproject.com/ticket/23728) but I would like some
> input before I work on it. I will copy the content of the ticket below
> for ease of reading:
> 
> It would be very useful for continuous deployment, testing, commit
> hooks, and other applications if django-admin makemigrations signaled
> via an exit code if any migrations were found. Commits in projects could
> be rejected if migrations were outstanding, continuous deployment
> systems could fail the build on outstanding migrations, and potentially
> other uses. No more would hasty commits break things when developers
> forgot to make migrations!
> 
> Changes to the code to make this happen are easy enough, but I am unsure
> how the command should behave. The grep unix utility is a example to
> copy. Under normal operation, grep always exits 0 unless an error
> happens, regardless of whether it found any matches. Invoking grep with
> the -q/--quiet flag causes grep to be silent, not printing anything, as
> well as exiting 0 if matches are found and 1 if nothing is found.
> 
> I am proposing django-admin makemigrations should exit with 1 (or
> anything non-zero) if no migrations to make were found, or exit 0 if
> migrations to make were found. As the command is instructed to make
> migrations, not making any is the error case.
> 
> I am unsure how this new functionality should be selected by the user
> when invoking makemigrations. The options I see are:
> 
>  1. Enable this always. This is very simple to implement and easy to
> understand. Good unixy tools use error codes extensively to signal
> errors. This may be surprising behaviour when compared to grep
> though, and breaks backwards compatibility in a minor way.
>  2. Enable this when the --dry-run flag is enabled. Now this flag can be
> used to check for migrations that need to be created both visually
> via the printed text, and composed in shell commands.
>  3. Add a new flag -e/--exit (or similar). The sole purpose of this flag
> would be to exit with 1 when no migrations were found. This could be
> combined with --dry-run to just check for migrations that need to be
> made.
>  4. Add a new flag -q/--quiet that copies the behaviour of greps
> -q/--quiet flag: silences output and exits with 1 when no migrations
> were found. This duplicates functionality though, as logging can be
> silenced using -v0 already.
> 
> My personal preference is for option 2. I was surprised when enabling
> --dry-run did not signal its result via the exit code. 3 would be the
> cleanest and most composable option, as 4 could be emulated using -ev0.
> 
> I will implement this change using 2, unless other people have opinions
> on the matter.
> 
> Regards,
> Tim
> 
> -- 
> You received this message because you are subscribed to the Google
> Groups "Django developers (Contributions to Django itself)" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to django-developers+unsubscr...@googlegroups.com
> <mailto:django-developers+unsubscr...@googlegroups.com>.
> To post to this group, send email to django-developers@googlegroups.com
> <mailto:django-developers@googlegroups.com>.
> Visit this group at http://groups.google.com/group/django-developers.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/django-developers/92203dcb-a775-4c17-a831-97d01ce8af3c%40googlegroups.com
> <https://groups.google.com/d/msgid/django-developers/92203dcb-a775-4c17-a831-97d01ce8af3c%40googlegroups.com?utm_medium=email_source=footer>.
> For more options, visit https://groups.google.com/d/optout.


-- 
"I was sad because I had no shoes, until I met a man who had no
feet. So I said, "Got any shoes you're not using?"  (Steven Wright)

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Dja

Re: Please don't kill the ecosystem

2014-10-02 Thread Luke Plant
Hi Pkl,

Sorry for slow reply, but I thought this was worth it:

On 03/09/14 20:45, Pkl wrote:

> Concerning the "rules of open source", I've yet to find a satisfying way
> to apply them regarding these "micro breaks". Imagine that project
> "myvideoplugin" is unmaintained (not handling PR) : unable to patch the
> original Repo, I'd have to fork it ; and unable to push results to the
> original pypi name, I'd have to create a separate myvideoplugin-pkl
> package on Pypi... that's quite some hassle for (often) a 10-lines patch.

There is no need to create a new pypi package and release - you can
install straight from github like this:

pip install git+git://github.com/foo/bar.git@abcde12345

You can put this straight into your requirements.txt as well. I have
dozens of instances of this in my requirements.txt files.

The trick then is to get your changes merged upstream. That is not
always very easy - you have to be willing to genuinely contribute
upstream i.e. contributions that make the maintainer's life easier, not
harder. That means writing unit tests, or bootstrapping use of tox so
that the test suite can be easily run against multiple versions. It
might even mean starting a test suite because upstream didn't have one -
in which case you also should reassess the process by which you choose
dependencies...

However, I've generally found that with effort and *genuinely helpful*
upstream contributions, my PRs are accepted, and I can go back to using
a PyPI release after some time. When I can't, it's because the upstream
dependency wasn't solid, and it kind of serves me right for not being
more careful and adding something to my project that wasn't reliable. In
some cases I might have to take over being maintainer of the project -
which is a burden, but part of the price you pay for being a part of the
open source world and getting tons of amazing quality software for free.

I do agree that we should be more careful about finding and documenting
ways of doing deprecations so that libraries can support both old and
new versions without generating deprecation warnings. I've just added
one fix to 1.6 release notes on this front.

Regards,

Luke


-- 
"Cross country skiing is great if you live in a small country."
(Steven Wright)

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/542D3182.3050201%40cantab.net.
For more options, visit https://groups.google.com/d/optout.


Re: Please don't kill the ecosystem

2014-10-02 Thread Luke Plant
On 03/09/14 14:21, Anssi Kääriäinen wrote:

> For example, lets consider the get_query_set() -> get_queryset() naming
> change done in 1.6. If 3rd party library writers change the method name
> to get_queryset() for 1.6, then their code won't work in 1.5. If they
> don't do the change, then all users trying to run with -Wall will get a
> bunch of deprecation warnings they can't do much about. This will
> effectively ruin the "run with -Wall" advice.
> 
> The usual way to solve these kinds of problems in code that needs to
> work in multiple Django versions is to write code which is conditional
> on Django's version. It looks a bit ugly to define methods
> conditionally, but in practice this works extremely well.
> 
> So, when adding a new deprecation to Django, we should document how 3rd
> party library writers can write code that works *silently* both before
> and after the feature deprecation is added. If there is no easy way to
> achieve that, then we should reconsider the deprecation.

Regarding get_queryset, it's possible to do it without warnings I think,
and the RenameMethodsBase class helps, but it's not entirely
straightforward.

I've added a paragraph to the docs that documents how to do it correctly
for the get_queryset renamings, and I agree that we should make this
kind of thing a standard practice. It might bloat the release notes a
bit, but I think that in general people appreciate the detail.

Luke


-- 
"Cross country skiing is great if you live in a small country."
(Steven Wright)

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/542D305C.2010206%40cantab.net.
For more options, visit https://groups.google.com/d/optout.


Re: Why is the CSRF template context processor hardcoded?

2014-10-02 Thread Luke Plant
Hi Aymeric,

I agree there is no security vulnerability, because the middleware
defaults to safe. That comment should be fixed.

The hard-coding was put there basically to make it easier to use, first
for the case of simple migration instructions when this CSRF protection
was introduced/changed, and secondly for the ongoing case - anything we
could do to streamline the instructions and minimise things that go
wrong was considered a good thing, so that we avoid the whole "just
disable the CSRF middleware" temptation.

Luke

On 20/09/14 22:16, Aymeric Augustin wrote:
> Hello,
> 
> I'm wondering why django.template.context defines:
> 
> # We need the CSRF processor no matter what the user has in their settings,
> # because otherwise it is a security vulnerability, and we can't afford to 
> leave
> # this to human error or failure to read migration instructions.
> _builtin_context_processors = ('django.core.context_processors.csrf',)
> 
> and then forcibly prepends it to settings.TEMPLATE_CONTEXT_PROCESSORS.
> 
> If the template context processor was missing, {% csrf_token %} wouldn't 
> output anything in templates. Then it would be impossible to submit forms, 
> but that would be a bug.
> 
> The CSRF context processor even has a branch that returns NOTPROVIDED. {% 
> csrf_token %} specifically tests for this case and doesn't output anything 
> when it happens.
> 
> So I fail to find the security vulnerability the comment talks about. I 
> didn't find the answer in:
> - 
> https://github.com/django/django/commit/8e70cef9b67433edd70935dcc30c621d1e7fc0a0
> - https://code.djangoproject.com/ticket/9977
> - https://code.djangoproject.com/wiki/CsrfProtection
> 
> Does anyone remembers the reasoning?
> 
> Thanks,
> 


-- 
"Cross country skiing is great if you live in a small country."
(Steven Wright)

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/542D1670.1010306%40cantab.net.
For more options, visit https://groups.google.com/d/optout.


Re: Callable LazyObject?

2014-03-06 Thread Luke Plant
On 05/03/14 23:05, Jeremy Dunck wrote:

> if ...
> elif isinstance(value, LazyObject):
>   pass
> elif callable(value):
>   ...

My gut instinct is that if Django's template code has to be patched and
special cased to accommodate this change, there will be lots of other
code that needs to be patched too.

LazyObject is already pretty hairy without trying to get it to support
more things.

Also, it seems that normally there should be other solutions. In many
cases, instead of:

  User = SimpleLazyObject(lambda: get_user_model())

you could use:

  User = lambda **kwargs: get_user_model()(**kwargs)

...assuming that the only thing you need 'User' to do is to produce User
instances when you call it. (If you need it to be an actual class for
some reason, then this won't work - but in most cases I'd suggest that
the consuming code shouldn't need an actual class).

Regards,

Luke


-- 
"God demonstrates his love towards us in this, that while we were
still sinners, Christ died for us." (Romans 5:8)

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/53189E5F.7010306%40cantab.net.
For more options, visit https://groups.google.com/groups/opt_out.


Re: BCrypt and PBKDF2 Password Hash Caching

2013-11-27 Thread Luke Plant
On 15/11/13 18:42, Erik van Zijst wrote:

> How do people feel about this approach and should it be merged into
> Django? If not, then I can turn it into a library instead. Maybe at our
> size we're not in Django's sweet spot anymore. However, in their current
> version the recommended hashers are just not usable for us.

>From my point of view, this is definitely something for an external
library, not for Django itself. The additional complexity makes it much
harder to review from a security point of view, and easier to make
mistakes when deploying, and we want to avoid that. Also, many people
will not need the additional performance, and we don't want to make it
easy for people to use a less secure option just because they want a
really fast site or something.

It seems like this can work fine as external code, and so I can't see a
reason why this needs to be in Django itself.

Thanks,

Luke

-- 
"DO NOT DISTURB.  I'm disturbed enough already."

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/5295D76B.8010606%40cantab.net.
For more options, visit https://groups.google.com/groups/opt_out.


Re: Proposal: Modifying the CSRF protection scheme

2013-08-09 Thread Luke Plant
On 03/08/13 23:57, Shai Berger wrote:

> This would work exactly like it works today, except with signed cookies. That 
> is, the "user specific element" is the cookie. CSRF is about tricking the 
> user 
> into submitting a request designed out of the site -- an attacker can't just 
> set (or read) cookies on a user's browser, nor read tokens from the page, 
> under the assumptions we're making about the general setup.

A signed cookie is not "user specific" in the sense I meant. It is only
user specific if it cannot be transferred to another user and still
work. But a signed CSRF cookie, with a matching token, can indeed be
transferred to another user (unless the signed data includes the session
or user id, for instance).

In this case, signing the cookie only adds protection if the SECRET_KEY
is changed after the exploit. It doesn't stop the attacker getting and
using a valid CSRF cookie/token in the first place.


Luke

-- 
"DO NOT DISTURB.  I'm disturbed enough already."

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Proposal: Modifying the CSRF protection scheme

2013-08-03 Thread Luke Plant
On 28/07/13 00:12, Shai Berger wrote:
> Hi everybody,
> 
> TL;DR: A simple change can make Django's CSRF protection a little better; an 
> additional, slightly less simple one, can also make it look better.
> 
> Django's CSRF protection scheme is a bit unusual; unlike most such schemes, 
> it 
> does not rely on a value stored in the server that needs to be matched by a 
> submitted token and is replaced with every submission, but rather on a 
> constant value stored in a cookie. This generally works (for details of how 
> and under what conditions exactly, see [1]), but has two minor problems:
> 
> 1) It is unusual, and in particular diverges from what OWASP[2] 
> recommends[3]; 
> as a result, security analysts often think it is not secure. They have been 
> proven wrong in all cases members of core are aware of, but proving it again 
> and again is a nuisance, and there may be bad PR related to this.

I understand your point, but personally I'm not that impressed by
everything that OWASP does. In general they are good, but some of their
previous recommendations have been way off. In one case, concerning CSRF
tokens in GET parameters, I had a long email exchange with them.
They did eventually (kind of) concede my point, but they didn't bother
to fix anything. Instead they asked me to do it, but it took me about 2
years to actually get a login for their wiki to be able to do that.

> 
> To improve on both problem issues, while keeping the advantages, I suggest 
> the 
> following modifications:
> 
> a) Use a signed cookie for csrftoken -- using Django's existing signing 
> facility[4], this means signing the cookie with the SECRET_KEY from the 
> settings; so that an attacker cannot set arbitrary cookies, and changing the 
> SECRET_KEY after a compromise immeiately invalidates csrftoken cookies.

I don't understand how this is supposed to work. For most Django sites,
it is trivial to get a page from a site and extract a CSRF token and/or
CSRF cookie value. (The same-origin policy means that you can't do it
client-side from a different website, but a tiny server-side script can
do it). An attacker can use this to forge a token or cookie that looks
like it was signed by the Django site, because it was.

If SECRET_KEY is changed, the attacker can just get a new signed value.

The only way this would work is if there is a user specific element that
stops the attacker from getting a CSRF token that will work on the
victim. To do this, you have to go back to tying CSRF tokens to the
session, or something equivalent.

It's for this reason that I'm pretty unenthusiastic about the proposed
changes. I think adding complexity is more likely to confuse us.

Luke


-- 
"Because Your lovingkindness is better than life,
 My lips shall praise You."  (Ps 63:3)

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Question about password salt and encryption

2013-06-15 Thread Luke Plant
On 15/06/13 14:17, Jon Dufresne wrote:

> I guess I need to decide which way to go. Either a custom password
> hasher that uses a static salt, or use Django's existing password hasher
> and not think about it.

There are two questions here:

1) What should you do for your system?

2) Should Django's security be improved by an additional salt that isn't
stored in the database?

Regarding number 2, this is not likely to happen quickly, due to
backwards compatibility issues, and the need to introduce a new setting
etc. (That may help you to decide question 1).

It's definitely worth considering, of course. We would have to consider
whether it is worth the work. For many installations, if an attacker has
the database they are very likely to have the source code too. Of
course, we should try to layer security so that it isn't all or nothing.
But given the difficulties of changing things, we'd have to consider
whether the increase in security, in a typical setup, would justify the
change.

Regards,

Luke

-- 
"Pessimism: Every dark cloud has a silver lining, but lightning
kills hundreds of people each year trying to find it." (despair.com)

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Question about password salt and encryption

2013-06-15 Thread Luke Plant
Hi Jon,

> I am in the process of porting an existing application to use Django. I
> am modifying the authentication portion of the existing application to
> be compatible with Django's authentication system. One thing that struck
> me, Django appears to use a single per user salt, stored in the
> database. However, the existing application uses two salts, one static
> salt stored outside the database, and a per user salt stored in the
> database. From all the advice I've received about secure authentication
> it seems the two salt method is standard behavior and considered a best
> practice. Is there a reason Django does not use the SECRET_KEY (or some
> other static salt) when encrypting passwords? Is this still considered a
> secure encryption mechanism? This feels like a step backwards for the
> authentication of this application.

The reason that SECRET_KEY is not used is that SECRET_KEY is used for
other applications which might require key cycling - typically for short
lived data where key cycling isn't going to cause too much of a problem.

So if it was used as a salt for passwords, you would lose the ability to
check passwords when you cycled the key.

That consideration doesn't stop you from using another value as a salt,
of course.

If you are trying to get authentication to match an existing system, it
seems like a better approach would be to write a custom Django
authentication backend, rather than the other way around, especially if
you don't want to lose the security features of what you have already:

https://docs.djangoproject.com/en/1.5/topics/auth/customizing/#writing-an-authentication-backend

Regards,

Luke

-- 
"Pessimism: Every dark cloud has a silver lining, but lightning
kills hundreds of people each year trying to find it." (despair.com)

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Migrations, commands and syncdb

2013-05-31 Thread Luke Plant
On 30/05/13 20:55, Andrew Godwin wrote:

> The way South works, and the way this will work (for new installs as
> well as tests) is that if migrations are present for an app, it will
> always create new databases by running through them from the very first
> migration to the latest one.

One problem with this is that you have to be careful to write migrations
that will always work from scratch. This is best practice, but I have on
occasion used data migrations that were for specific problems, and may
have depended on specific data in the database. I've also used them for
populating parts of the database at specific upgrade points. Usually I
wouldn't want this data to be installed for my tests - I want my tests
to explicitly do the setup they need, and not be complicated by data
from data migrations.

For these reasons, and because of the slowness of running all the
migrations, there are some projects where I have a settings file for
running the tests that excludes South from INSTALLED_APPS, which solves
the problem nicely.

The slowness problem can be fixed by squashing, but it seems a shame to
require that simply for the sake of running tests. And it doesn't solve
the other problems. I would like to be able to turn off migrations for
tests, and just skip to the final schema.

Luke

-- 
"I washed a sock. Then I put it in the dryer. When I took it out,
it was gone."  (Steven Wright)

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Perception of attitude in tickets

2013-05-16 Thread Luke Plant
On 16/05/13 13:29, Russell Keith-Magee wrote:

> Patching Trac sounds like a really good idea to me. While I completely
> appreciate the intent of these wiki messages, the way those messages are
> "deployed" at the present strikes me as something that could easily be
> interpreted as rude. I'd like to see a much more "humane" usage of these
> messages, so that new users to Trac don't feel like they're interaction
> with Django as a project isn't a mechanical rejection.

What kind of patching Trac are we talking about? I'm aware of two
suggestions I think:

1) If someone tries to re-open a ticket, we change it so they see some
message about the mailing list.

2) When a ticket is closed, a message is automatically added.

To me, both of these seem *more* mechanical and unfriendly than a
message that is composed by hand (which may link to an existing wiki
page or other docs). The first particularly will lead to people closing
tickets as WONTFIX without sufficient explanation, and the user getting
a 'doorslam' feeling (and probably won't get to the point of attempting
to re-open a ticket).

Regards,

Luke

-- 
"If something is hard, it's not worth doing." (Homer Simpson)

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Perception of attitude in tickets

2013-05-16 Thread Luke Plant
On 15/05/13 19:36, ptone wrote:

> I wonder if a slightly more concise version of this should be added to
> the triaging docs instead of a wiki page (fine place to draft it though).
> 
> https://docs.djangoproject.com/en/dev/internals/contributing/triaging-tickets/#closing-tickets
> 
> I feel that the wiki pages aren't very discoverable, and unless we are
> talking about patching trac to include this, such a comment won't carry
> the official weight of being in the project docs.

That's a good idea. The purpose of this wiki page is to make it easy for
triagers to link to - I personally hate having to go and find the right
page in the docs, but I can remember to do "DevelopersMailingList"
instead of "developers mailing list".


> One line I do feel needs a tweak:
> 
> "while the suggestion is good in theory, it lacks enough merit to exceed
> the cost it will add to the maintenance of Django"
> 
> The truth is, there are some suggestions that are just flat out
> incompatible. I'm fine to be gracious and thankful for the time someone
> takes to offer a suggestion, but that doesn't mean that all suggestions
> are automatically meritorious.

I guess we would normally use INVALID for something that was just a bad
idea, whereas WONTFIX recognises there is a valid issue, but we're not
going to do anything about it. I've already removed reference to INVALID
on that page, but I'll tweak the text - feel free to make more changes.

Luke

-- 
"If something is hard, it's not worth doing." (Homer Simpson)

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Perception of attitude in tickets

2013-05-15 Thread Luke Plant
Hi Joe,


On 14/05/13 00:55, Joe Tennies wrote:
> As a fellow lurker (sorry I've been using Flask more recently), I think
> this could simply be fixed via a form response. Here's a simple example:
> 
> This bug is being marked as "WONTFIX" because 
> 
> Please realize that every API/feature added to Django needs to be
> maintained across several versions. The more public APIs that are
> exposed to users, the more difficult it is to refactor and add other
> features. This request currently lacks enough merit to exceed the cost
> it will add to the maintenance of Django.
>
> ...

I think we need something shorter that developers can remember, i.e.
that we can type ourselves without resorting to a canned response,
1which can be off-putting, especially if some of it doesn't apply.

So I've gone ahead and created a wiki page, which can be longer and more
friendly, and require a shorter response on the actual ticket, something
like this:

  Closing as WONTFIX because ...

  If you want to persuade us otherwise, please bring it up on the
  DevelopersMailingList

The page:

https://code.djangoproject.com/wiki/DevelopersMailingList

That's my draft, feel free to edit. We don't want it too long, as that
is intimidating by itself, but some of the points you make might would
be good additions

What do people think?

Luke

-- 
"I asked mom if I was a gifted child. She said they certainly
wouldn't have paid for me." (Calvin and Hobbes)

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Perception of attitude in tickets

2013-05-10 Thread Luke Plant
Hi Simon,

> I feel that the general attitude expressed in some of the tickets is
> poor. The one which prompted this post
> is https://code.djangoproject.com/ticket/901. I think comment 20
> <https://code.djangoproject.com/ticket/901#comment:20> is a good
> demonstration of my point. A couple of users were getting frustrated at
> the lack of discussion/progress which resulted in a fairly sanctimonious
> rant. 

I'm afraid I really couldn't disagree more with your characterisation of
this situation.

If you just read the ticket, you'll find that different core developers
asked people to move discussion to the mailing list *3 times*, and quite
politely.

Everyone who comments after that point either hasn't read or has decided
to ignore *3 requests* about how to get the ticket to progress. And to
add insult to the injury of having wasted people's time already, some
start adding comments about how feature requests for Django are a waste
of time.

This is the height of rudeness, and if all they got was a sanctimonious
reply, they got better than they deserved.

I'm not claiming that we couldn't do better in terms of our clarifying
our processes and so on, but I think you picked an example that
demonstrates exactly the opposite of what you claimed.

Best regards,

Luke

-- 
"God demonstrates his love towards us in this, that while we were
still sinners, Christ died for us." (Romans 5:8)

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Recommending a Python 3-compatible MySQL connector

2013-05-10 Thread Luke Plant
On 10/05/13 14:12, Aymeric Augustin wrote:
> Hi Mark,
> 
> On 10 mai 2013, at 10:16, Mark Hughes <m...@cyki.com> wrote:
>> Another option to consider could be mysql-connector-python
>> 
>> https://pypi.python.org/pypi/mysql-connector-python/1.0.9
> 
> Thank you, it's the official library I was missing!
> 
> Unfortunately, it's licensed under the GPL. To the best of my
> understanding, importing modules in the same Python process triggers
> GPL contamination. Therefore, if Django officially supports this
> module, anyone distributing code that works with Django should either
> release it under the GPL or specify that it's illegal to use it with
> MySQL.

Can the GPL really do this? My own thoughts on this are here:

http://lukeplant.me.uk/blog/posts/python-and-copyright/

I'm not saying that we should use GPL code if there is BSD alternative,
but as far as I can see, it's impossible for the GPL to say *anything*
in this situation, because there is nothing a typical Django project
would be doing with that library that would actually require them to
accept the terms of the license.

The GPL allows *using* of the code for any purpose. It's only when a
project becomes a distributor of the GPL code that it is required to
abide by the other terms.

Regards,

Luke

-- 
"God demonstrates his love towards us in this, that while we were
still sinners, Christ died for us." (Romans 5:8)

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Ticket 19445

2013-05-08 Thread Luke Plant
On 07/05/13 02:04, Russell Keith-Magee wrote:

> As for the "ModelForm without a Meta" approach -- I see what you're
> driving at, and I can see how it's an elegant solution to the problem.
> My concern is that we'd be encouraging people to pass around
> "half-baked" ModelForm definitions -- i.e., under any other
> circumstances, a ModelForm without a Meta wouldn't be valid. If someone
> puts that ModelForm into a forms.py, it's going to appear like it can be
> used as a form in general usage… except it can't. 

Currently, a ModelForm without a Meta *is* valid, and will work in the
admin no problem. I don't know how long that has been true, but I've got
a Django 1.4 project where it works. ModelAdmin creates the Meta class
for you, or will fill in missing attributes (like 'model') if it is
incomplete.

The difference is that we would be encouraging that practice. But in the
docs, I would only be encouraging it for use in the admin, as the
solution to avoid having to specify 'fields' multiple times.

> The only alternative that immediately comes to mind is allowing a flag
> to be passed into the constructor for a form that explicitly allows
> "insecure default all-fields" behaviour. The admin would always pass in
> that flag, users could if they wanted to (but at least they'd be opting
> in to a known potentially insecure behaviour). I'm not saying I
> particularly like this option either; I'm just floating it as an
> alternative.

A flag to the constructor (by which I assume you mean __init__ not
__new__) is too late. If a model is inspected to create the form fields,
that happens when the ModelForm subclass is defined (within the
ModelFormMetaclass.__new__ method). And that isn't going to be something
we can change, because it would break all the code that depends on it,
like this:

class MyForm(forms.ModelForm):
class Meta:
model = MyModel

MyForm.base_fields['my_field'].widget = ...


...and lots of similar code

In many ways, setting 'Meta.fields = "__all__"' is exactly the flag you
are talking about, only it operates at the ModelForm metaclass level.

Regards,

Luke


-- 

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Ticket 19445

2013-05-01 Thread Luke Plant
r a complete failure; it can always serve as a
bad example.

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Setting aside easy-pickings for sprints

2013-04-29 Thread Luke Plant
On 29/04/13 15:55, Daniele Procida wrote:

> Between now and then would it be possible for some very simple
> tickets to be set aside for people who will then have a chance to
> tackle some real issues at their first sprint, after the workshop?

That sounds like a great idea. I think this can be handled by assigning
yourself as the owner of the ticket, perhaps with a comment to indicate
your intention.

Of course, we cannot stop other people from working on these tickets,
but this is the best way that we have to indicate that other people
intend to work on an issue.

You could start with this query:

https://code.djangoproject.com/query?status=assigned=new=1=Accepted=1=changetime

However, not everything marked "Easy pickings" really is. Also, you
might want to exclude things that already have patches.

Regards,

Luke

-- 
A woman's mind is cleaner than a man's. She changes it more often.
(Oliver Herford)

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Request method in urls.py

2013-04-15 Thread Luke Plant
On 15/04/13 10:21, Aymeric Augustin wrote:

> Django already has a syntax for that :
> 
> from django.conf.urls import *
> from django.views.decorators.http import *
> 
> urlpatterns = patterns('',
> url(require_GET(view_that_only_accepts_get), name='accept-get'),
> url(require_POST(view_that_only_accepts_post), name='accept-post'),
> url(require_http_methods(['OPTIONS',
> 'DELETE'])(err_why_would_you_do_that), name='accept-options-delete'),
> )
> 
> https://docs.djangoproject.com/en/dev/topics/http/decorators/#allowed-http-methods

This doesn't work if you want the same URL - the first one will match,
and return a 405 if the method isn't allowed, so you will never fall
through to the next one with the same URL where the method is allowed.

(Unless the URL dispatcher has started doing something very different
from what I what I expect it to do).

Luke

-- 
 A mosquito cried out in pain:
 "A chemist has poisoned my brain!"
 The cause of his sorrow
 was para-dichloro-
 diphenyltrichloroethane

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Request method in urls.py

2013-04-14 Thread Luke Plant
On 13/04/13 22:48, Brantley Harris wrote:
> There's a line in the django URL Dispatcher documentation that is pretty
> weird:
> 
> The URLconf doesn’t look at the request method. In other words, all
> request methods – POST, GET, HEAD, etc. – will be routed to the same
> function for the same URL.
> 
> 
> Well, why?  Most modern web frameworks allow you to specify the method
> in the routing configuration, Django seems to be an exception in this
> respect.
> 
> It would be extremely easy to implement, and would lead to vastly better
> code across new projects, including a simpler way of writing rest style
> interfaces:
> 
> url('^objects/$', 'views.create_object', methods=['post', 'put'],
> name='create_object'),
> url('^objects/$', 'views.get_objects', name='list_objects'),
> 
> 
> This has come up many times before and been swatted down for various
> reasons.  One is that it could be implemented with a one-off dispatcher,
> as in:
> 
> url('^objects/$', create_or_list(list=get_objects,
> create=create_object), name='create_or_list_objects')
> 
> 
> But this is overly complex for what should be a simple configuration,
> forces one to create the same name for the url, and worse, creates a
> level of indirection breaking the abstraction up; or in other words
> you're trying to do route configuration, why not do it in the place
> you're already doing route configuration?
>
> The other argument is that you can do this with Class Based Views.  I
> don't believe this is a good argument as one would have to utilize Class
> Based Views to get this basic functionality.  In fact CBV's, only really
> solve two common issues, one is the boilerplate inherit in forms, and
> the other method routing.  But the proposed solution to method routing
> is simpler and better.

You don't have to use Django's CBVs to get this functionality - you can
write your own, avoiding anything you dislike about them.

One reason for not doing this kind of despatch is that handling for
different HTTP methods often involves a lot of common code. The classic
form workflow would become longer, more complicated and/or less DRY if
it was implemented using two functions instead of one:

https://docs.djangoproject.com/en/dev/topics/forms/#using-a-form-in-a-view

So, I would disagree that dispatching on HTTP verb would lead to vastly
better code - it could easily make things worse.

However, this is not an argument against having the *option* to do
method-name dispatching in the URLconf - I can see that there are valid
use cases for that.

Regards,

Luke

-- 
Environmentalists are much too concerned with planet earth.  Their
geocentric attitude prevents them from seeing the greater picture
-- lots of planets are much worse off than earth is.

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Ticket 20147 - deprecate and replace request.META

2013-04-09 Thread Luke Plant
On 09/04/13 12:34, Tom Evans wrote:

> The basis of web development was CGI. From CGI came everything.
> Therefore, almost all webservers - Apache, nginx - almost all
> frameworks - RoR, PHP, Django - that deal with the web will have
> similar or equivalent environment hashes like this.
> The convention for headers (uppercase header name, s/-/_/g, prepend
> 'HTTP_') is similarly ubiquitous.
> 
> Your argument is that this structure is confusing to the absolute
> newbie who has never programmed a web application in his life. My
> counter argument is that changing it would be confusing to anyone who
> has ever programmed a web application in the last 20 years.

Well, that depends on which frameworks they use. From what I can tell,
Java servlets have an API like request.getHeader("Accept-Language")
without the HTTP_ name mangling, and ASP.NET has
Request.Headers["Accept-Language"]. It's entirely possible to be a
competent web developer without knowing about CGI name mangling.

I don't often follow Java/C#, but I'll gladly follow anyone that is
using a sensible API, and I really don't believe that current
familiarity with quirky historical artefacts should hold us back -
Python 3, to take one example, would never have happened with that attitude.

I don't have (too much) of a problem with things like WSGI following
CGI, if only because they had to in order to gain traction, but that
isn't a reason why developers should be forced to do CGI name mangling
to access a header.

>> The biggest problem is what to do with our test Client and
>> RequestFactory, which allow specifying headers as keyword arguments
>> using the CGI style of naming e.g.:
>>
>>   self.client.get('/path', HTTP_X_REQUESTED_WITH='XMLHttpRequest')
>>
>> Since keyword arguments can't have "-" in them, this is harder to
>> replace. We could either leave it as it is, or add a new 'headers'
>> keyword argument to these methods, deprecating **extra.
> 
> This seems a problem with the API to Client and RequestFactory, not a
> problem with request.META

Now that we've dropped the proposal to deprecate request.META, and just
add request.headers as an alternative for getting HTTP headers, these
classes don't need to change. It was simply for consistency that I
proposed fixing them.

Regards,

Luke

-- 
Clothes make the man.  Naked people have little or no influence on
society.
   -- Mark Twain

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Ticket 20147 - deprecate and replace request.META

2013-04-08 Thread Luke Plant
On 08/04/13 22:13, Carl Meyer wrote:

> Although the concept of a unified "request environ" that includes HTTP
> headers mashed together with various other environment and web server
> info may date back to CGI, it is not outdated; in fact it is a part of
> the WSGI specification too:
> http://www.python.org/dev/peps/pep-/#environ-variables

I realise it is part of the WSGI spec, but encoding the CGI
peculiarities into a more modern spec seems pretty misguided to me - you
have to create a WSGI-CGI gateway to run CGI programs anyway, and you
could put the backwards compatibility mapping there, instead of in the
WSGI spec. I actually wish that WSGI didn't do any HTTP parsing at all.

>> There is also the advantage of a *much* cleaner repr(request),
>> especially in a development environment, because you don't have all the
>> other junk from os.environ.
> 
> If we are trying to make repr(request) really be a full reproduction of
> all relevant request data (such that the request instance could be fully
> reconstructed from it) then I don't think this goal is achievable; it is
> not an option (IMO) to remove WSGI environ data from the request
> entirely, because this would make data that is part of the WSGI spec
> inaccessible to Django users.
> 
> (I haven't checked whether the current repr(request) meets the
> full-reconstruction criteria; if it already doesn't then I don't really
> care what we show in it, we could trim it down further with or without
> your proposed change.)

You can't currently reproduce the request this way - the stream for the
request body contents comes out as something opaque.

You're right we could trim the repr with or without my change - it would
simply have made the set of things to display more obvious.

We should probably consider the places where repr(request) is used. It's
probably just in logging systems. However, Sentry is one of the most
popular and it does it's own representation of the request object, it
seems, so if we left META alone it wouldn't be affected.

It seems to me that repr(request) is most useful for
development-environment debugging, and currently could be improved a lot
for that use case.

>> Is anyone strongly opposed to this? If not, in Aymeric's spirit of
>> decisiveness, I'll push it forward.
> 
> I'm fine with new request.headers API; I'm opposed to deprecation of
> request.META.

I would be fine with your modification of my proposal, not least because
it would be a *lot* less work!

The only disadvantage is "two ways to do it". If you want to grep for a
particular header, you've got 2 things to grep for now. However, that
problem already existed due to META - you've got things like
QUERY_STRING and request.GET, HTTP_HOST and request.get_host(),
X_REQUESTED_WITH and request.is_ajax().

Regards,

Luke


-- 
Clothes make the man.  Naked people have little or no influence on
society.
   -- Mark Twain

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Ticket 20147 - deprecate and replace request.META

2013-04-08 Thread Luke Plant
On 08/04/13 21:17, Michael Manfre wrote:
> +1 to a saner repr(request) and not having to type "HTTP_". What sort of
> deprecation cycle are you thinking for this?

I'm thinking the normal cycle:

1.6 - request.HEADERS added, probably a few friends too.
- request._META added
- accessing request.META gives PendingDeprecationWarning

1.7 - request.META gives DeprecationWarning

1.8 - request.META is removed.

If we find that there are some other attributes/method that need to be
added to HttpRequest in Django 1.7, and direct access to request._META
was still necessary, then we could extend the deprecation cycle - 1.7
would give PendingDeprecationWarning.

Regards,

Luke

-- 
Be careful of reading health books, you might die of a misprint.
  -- Mark Twain

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Ticket 20147 - deprecate and replace request.META

2013-04-08 Thread Luke Plant
Hi all,

This is already the subject of a ticket, but I didn't get a response
yet. Basically, the idea is replace things like:

  request.META['HTTP_ACCEPT']

with

  request.HEADERS['Accept']

request.META should be deprecated and replaced with request._META,
because it is just an implementation detail, and a really bizarre one at
that, full of cruft from a previous generation of web applications (CGI)
that should not be exposed in our API.

Anything else needed from META should also be replaced with a sensible API.

This might seem to be a big change simply for the sake of a clean API,
but I'm more and more motivated by these thoughts:

* Web development is hard enough as it is. "Explain this to a newbie
without getting embarrassed" is a good test.

* A general philosophy of pro-actively keeping things clean and sensible
is necessary to avoid being overrun with madness long term.

There is also the advantage of a *much* cleaner repr(request),
especially in a development environment, because you don't have all the
other junk from os.environ.

The biggest problem is what to do with our test Client and
RequestFactory, which allow specifying headers as keyword arguments
using the CGI style of naming e.g.:

  self.client.get('/path', HTTP_X_REQUESTED_WITH='XMLHttpRequest')

Since keyword arguments can't have "-" in them, this is harder to
replace. We could either leave it as it is, or add a new 'headers'
keyword argument to these methods, deprecating **extra.

The silliness has infected other places, like SECURE_PROXY_SSL_HEADER
which follows the same CGI convention (and in each case the docs have to
note how to do it correctly!). In this case we can detect people using
the old style 'HTTP_' and raise a deprecation warning, and allow the
sensible way.

We would probably also need to add a few methods/attributes to
HttpRequest to proxy the few things you need from request.META that are
not headers, like REMOTE_ADDRESS and REMOTE_USER

Is anyone strongly opposed to this? If not, in Aymeric's spirit of
decisiveness, I'll push it forward.

https://code.djangoproject.com/ticket/20147

Regards,

Luke


-- 
Be careful of reading health books, you might die of a misprint.
  -- Mark Twain

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: ModelForms and the Rails input handling vulnerability

2013-02-04 Thread Luke Plant
This is an old thread, but we never came to a conclusion.

I'll respond to Anssi below, and then add my own ideas.

> I find the option of raising warnings or errors on missing data
> elements the best option forward. There is one unfortunate downside,
> that is we can't do this for checkboxes. So, it would be possible to
> have a hidden-editable checkbox field.

I don't think this is a great solution at this point. The
hidden-editable checkbox field is going to be backwards incompatible in
a serious way, because many forms are rendered manually in HTML, and
they will break.

I'm not convinced that warnings are ever a useful security mechanism,
because they are so easily ignored. In production, they are invisible by
default, and in development they are only visible if you look at the
devserver output.

Further, when a warning is correct, it shouldn't be a warning, it should
be an error. When the warning is in fact incorrect, then it is a
nuisance, and can easily lead to people ignoring or silencing all
warnings, unless we also provide an easy and very fine grained way to
deal with them. Warnings that are only sometimes correct always do the
wrong thing.

This contrasts with deprecation warnings, for example, which are always
correct - because the functionality is indeed going to go away, and you
do need to do something about it, but it isn't an error because the code
is working OK now. The presence of the warning encourages you to do the
right thing to get rid of it - migrate your code.


My idea:

I think, given the lack of consensus in this thread, that we have to opt
for a conservative option.

I like Alex Ogier's solution of a sentinel "__all__" flag. This would be
introduced for ModelForm and UpdateView using a deprecation process, so
that a form without one of 'fields' or 'exclude' will raise a
PendingDeprecation warning initially, and eventually be illegal.

Both the '__all__' shortcut and the use of 'exclude' will be plastered
with warnings in the docs, and the docs will be re-written to assume
that you are going to provide 'fields' (at the moment the opposite is
assumed).

How does that sound?


Luke


-- 
"If you're not part of the solution, you're part of the
precipitate." (Steven Wright)

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.





Re: Writing class-based contrib.admin actions

2013-01-29 Thread Luke Plant
On 29/01/13 12:53, Timmy O'Mahony wrote:
> At the moment, writing custom admin actions
> <https://docs.djangoproject.com/en/dev/ref/contrib/admin/actions/#actions-as-modeladmin-methods>
> requires an old style view function that returns a Response object. The
> signature for this is similar to a old function-based view (except with
> modeladmin before request): 
> 
> func(modeladmin, request, queryset):
> ...
> return HttpResponse()
> 
> I wanted to write an action with an intermediate page
> <https://docs.djangoproject.com/en/dev/ref/contrib/admin/actions/#actions-that-provide-intermediate-pages>,
> but using class based views (for uniformity across my app). This doesn't
> seem to be doable without writing a custom base View object

Changing the signature would be backwards incompatible (or very hacky).

You can always do:

  def my_admin_action(modeladmin, request, queryset):
  return MyView.as_view(request, modeladmin, queryset)

And then take it to the next step:

  my_admin_action = cbv_to_admin_action(MyView)


Luke


-- 
"I am going to let you move around more, just to break up the
mahogany." (True Quotes From Induhviduals, Scott Adams)

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.




Re: Relative path support for TEMPLATE_DIRS and others in settings.py (django ticket 694)

2013-01-02 Thread Luke Plant
On 01/01/13 18:28, Aymeric Augustin wrote:

> There are two special cases that don't fit into apps: STATIC_ROOT and
> MEDIA_ROOT. (Technically, there's ALLOWED_INCLUDE_ROOTS too, but it
> isn't commonly used.)
> 
> Static files are collected from the apps into STATIC_ROOT that is
> then served by the web server. To avoid accidentally leaking Python
> code over the web, it's a good idea to keep this directory outside of
> your source tree.
> 
> Media files are written by the application server into MEDIA_ROOT.
> It's a good idea to put them on a separate partition (DoS by filling
> up / isn't fun), or at least in a directory outside of your source
> tree, which must be read-only for the web server.
> 
> For local development, it's certainly fine to store the code in
> /home/myproject, compile the static files in /home/myproject/static,
> and uploading the media files in /home/myproject/media, and it's
> convenient to express that with relative paths. But it's hardly a
> best practice in production — at least, not until you've spent 30
> seconds thinking about it.

You are assuming here that use of relative paths and PROJECT_ROOT for
media implies that you are putting your MEDIA_ROOT/STATIC_ROOT *inside*
PROJECT_ROOT. But you don't have to.

I often have the situation where I have multiple copies of a project on
a machine - often 'staging' and 'production' on the same machine (e.g.
shared hosting), and also for other reasons.  I have a layout something
like:


/home
  /myuser
/apps
  /foo_staging
/src
/static
/media
  /foo_production
/src
/media
/static

/src is PROJECT_ROOT, and STATIC_ROOT and MEDIA_ROOT will be calculated
relative to that. This system makes projects completely relocatable, and
is a good use case for PROJECT_ROOT IMO.

However, this isn't something that you could put into a default
settings.py, because it assumes things about directory structure outside
the project sources.

Common opinion amongst core devs seems to be against PROJECT_ROOT. If we
are consistent about that, we ought to be thinking about deprecating
TEMPLATE_DIRS, STATICFILES_DIRS,
django.template.loaders.filesystem.Loader,
django.contrib.staticfiles.finders.FileSystemFinder
etc., as mentioned by Shai.


Luke

-- 
 A mosquito cried out in pain:
 "A chemist has poisoned my brain!"
 The cause of his sorrow
 was para-dichloro-
 diphenyltrichloroethane

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: Relative path support for TEMPLATE_DIRS and others in settings.py (django ticket 694)

2012-12-30 Thread Luke Plant
On 29/12/12 04:08, Cal Leeming [Simplicity Media Ltd] wrote:

> Could we not have something like this in the settings.py, which in turn
> enabled the code pasted above?
> TEMPLATE_PATH_RELATIVE=True

For consistency, we'd need STATICFILES_PATH_RELATIVE,
STATIC_ROOT_PATH_RELATIVE, MEDIA_ROOT_PATH_RELATIVE etc. which is
craziness. Having just one extra setting is a big deal.

There are use cases for all of these being absolute paths (or at least
some of them), and use cases for all of them being relative. We've
already chosen absolute paths, and you can generate absolute from
relative using os.path.realpath etc.

The only option I can is whether we put that snippet of code (e.g.
PROJECT_ROOT=os.path.realpath(os.path.dirname(__file__)) ) into the
settings file generated when starting a new project.

Luke


-- 
"If we could just get everyone to close their eyes and visualise
world peace for an hour, imagine how serene and quiet it would be
until the looting started" -- Anon

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: Relative path support for TEMPLATE_DIRS and others in settings.py (django ticket 694)

2012-12-28 Thread Luke Plant


On 28/12/12 16:42, Daniel Sokolowski wrote:
> PROJECT_ROOT is what I have been using myself and seen it done by others
> so to me it makes sense to introduce an official setting for this purpose.

PROJECT_ROOT would still need to be defined inside the settings.py
module, using the os.path.dir(__file__) etc. dance, because it can't be
defined within django code (which doesn't know where your project
lives), and a utility function to do it isn't worth it (it's only one
line, and you don't want your settings file to be doing imports to
Django code).

So I agree with the original WONTFIX here.

I also think that app directories for the template loader is a better
solution, and making a 'project' app if necessary answers the objection.

However, I do see a case for putting the PROJECT_ROOT code into the
settings.py generated by creating a new template, and updating the help
text for TEMPLATE_DIRS and STATICFILES_DIRS to mention it.


Luke


-- 
The fashion wears out more apparel than the man.
-- William Shakespeare

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: Could prefetch_related be modified to utilize select_related for ForeignKey relations?

2012-11-26 Thread Luke Plant
On 20/11/12 12:08, tolomea wrote:
>>  it should do exactly what the developer asks.
> 
> How do I, the developer, request that it use select_related for topping_type
> part of the best_pizza__toppings__topping_type example given above?

Sorry for the slow reply. At the moment, there is no way to specify
that. (Unless you can use a default manager to do it, but that might be
constrained by other things).

It would be nice to come up with a better API for this kind of thing.
SQLAlchemy may have some good ideas in the way it does eager loading - I
believe it has support for equivalents of both select_related and
prefetch_related.

What I'm saying is that in the absence of that better API, or some way
of specifying the query you want, we shouldn't guess and convert one
optimisation into another.

Luke

-- 
OSBORN'S LAW
Variables won't, constants aren't.

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: proposal: post-collectstatic signal

2012-11-14 Thread Luke Plant
On 14/11/12 03:43, Justin Holmes wrote:

> My only concern is that we'll limit our audience by requiring users to
> use a specific STATICFILES_STORAGE.  What if they're already using a
> custom one?

One solution is to have your own COLDBREW_STATICFILES_STORAGE_BACKEND
setting, which can be used if people have their own STATICFILES_STORAGE,
and your one wraps it. django-mailer uses that approach to allow it to
wrap whatever real email backend people are using.

Luke

-- 
"It is a truth universally acknowledged, that a single man in
possession of a good fortune, must be in want of a wife." (Jane
Austen)

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



contrib.markup deprecation

2012-10-13 Thread Luke Plant
Hi all,

https://code.djangoproject.com/ticket/18054

I just came across this, and it seems slightly hasty. Most deprecations
of entire contrib modules would require some discussion on django-devs,
I would have thought.

The filters provided by this module are probably widely used, and I
think slightly better documentation of a migration route would be nice,
and some more explanation in the release notes. The nature of template
tags/filters like this is that they are necessarily glue code between
some functions and the Django template library, so it didn't seem that
inappropriate to me to have a contrib.markup module, any more than any
of the other contrib modules, even though they are relatively small
functions.

Also, hundreds of developers implementing their own solutions doesn't
seem sensible. That's especially true as it is easy to get those
functions wrong. I think the current state leaves people more likely to
be vulnerable, because many people will botch together an insecure
solution - and encouraging people to use the markup libraries directly,
as the release notes do, will make that worse.

For example, for restructured text, you need at least these settings to
be safe in a typical HTML/web app situation:

  { 'raw_enabled': False,
'file_insertion_enabled': False
  }

(This is implied by the current Django docs, but it really ought to be
enforced by the code)

To add further confusion, there are projects like django-rstify out
there, which has the same vulnerabilities, and also seems to be a bit
dead at the moment (github repo has disappeared).

I'm happy to work on this to provide an external solution for
restructured text, but don't want to compete with django-rstify if I can
avoid it.

I will invite Martin Mahner, the author of django-rstify to participate
in this thread. I think we should have recommendations for alternatives
for rendering markdown as well.

Regards,

Luke


-- 
"Christ Jesus came in to the world to save sinners" (1 Timothy 1:15)

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: Django 1.5: AUTH_USER_MODEL and GeoManager

2012-10-11 Thread Luke Plant
On 11/10/12 08:51, Max wrote:
> Hi there,
> this is my first post here; hope I'm posting to the right group.
> I'm currently working on getting to run an 1.4-application (using a
> profile model) on 1.5dev, using the the new (eagerly awaited by me) 
> custom user model.
> I used django.contrib.gis.db.GeoManager with my former profile-Model and
> so I wanted to use it with my new custom user model, too.
> The following exception was thrown:
> 
> " 'GeoManager' object has no attribute 'get_by_natural_key' "
> 
> Hacking contrib/gis/db/models/manager.py and making GeoManager subclass 
> 'django.contrib.auth.models.UserManager' 
> 
> instead of 'Manager' solved it for the moment.
> 
> Maybe this is something that hasn't been thought of yet.
> 
> I felt like I should post this.

If you could create a ticket, that will ensure this is not forgotten. It
sounds like it should be a release blocker.

Luke


-- 
"Because Your lovingkindness is better than life,
 My lips shall praise You."  (Ps 63:3)

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: Schema Alteration update

2012-10-11 Thread Luke Plant
On 28/09/12 08:41, Andrew Godwin wrote:
> Yeah, I think I mentioned it a couple of times at DjangoCon but perhaps
> not loudly enough - Jacob and I had a talk at DjangoCon EU where he said
> he wanted it all in core, and I tend to agree.
> 
> Preston has had a look at what I'm doing/planning with AppCache and
> apparently it'll be compatable with what's in app-loading with a little
> work, which is reassuring.
> 
> Only remaining question is whether migration-runner (the smarts) should
> be in contrib or core. I know Alex believes core; I'm split, seeing as
> some people will want to turn it off (so contrib), but it overrides core
> commands like syncdb (so core would be cleaner).

I'm very happy with South being in core/contrib, but I am aware of other
people who use different solutions. It would be nice if we didn't make
life hard for them. I don't know what that means in practice, but if we
got feedback from the developers of those other solutions it would be
good. We might need something like a 'syncdb --ignore-migrations' option.

Luke


-- 
"Because Your lovingkindness is better than life,
 My lips shall praise You."  (Ps 63:3)

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: Backporting some Python 3 support features to 1.4.x?

2012-09-06 Thread Luke Plant
On 06/09/12 19:09, Aymeric Augustin wrote:

> Now we have two alternatives:
> 1) tell them to roll their own compat or wait until they can target 1.5
> + 1.6 — quite a downer,
> 2) add some forwards compatibility tools to 1.4.
> 
> We generally don't add features to minor releases, but there's a
> precedent (csrf_noop), and the patch is as harmless as they come (see
> attachment).
> 
> What do you think?

This was something I was going to bring up myself, since it is a major
obstacle to re-usable django apps actually providing Python 3
compatibility. I'm +1 on adding forwards compatibility to 1.4.X,
assuming a safe patch.

Luke

-- 
"In your presence there is fullness of joy; at your right hand are
pleasures forevermore" Psalm 16:11

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: ORM refactoring, part 2

2012-08-27 Thread Luke Plant
Anssi,

I just got back from holiday. I hope to be able to review at least some
of these patches within the next 2 weeks. If you don't hear from me in
that time, I'd encourage you to carry on anyway.

Thanks,

Luke

On 25/08/12 20:35, Anssi Kääriäinen wrote:
> I have done some more ORM refactoring work. I thought it would be a
> good idea to post a summary of what is going on.
> 
> First, I haven't committed the utils.tree refactoring patch I was
> planning to commit [https://github.com/akaariai/django/commits/
> refactor_utils_tree]. The reason is that I now feel that add_filter()
> and deeper levels of the Query class need some refactorings first.
> 
> There is some work going on in the refactoring of the deeper levels of
> the ORM. I committed join promotion improvement patch today: [https://
> code.djangoproject.com/ticket/16715#comment:25]. I have more planned
> improvements to commit:
> 
> 
> * Remove "dupe avoidance" logic from the ORM (#18748).
> This is removing some code I strongly believe isn't needed any more.
> This is still pending Malcolm's review.
> 
> * Fix join promotion in disjunctive filters (#18854).
> This one should make join promotion in disjunction cases cleaner and
> more efficient (as in less OUTER JOINS). In addition, this will make
> add_q/add_filter a bit easier to understand. The problem currently is
> that the first ORed filter is added to the query with connector=AND,
> the rest of the filters in the disjunction with connector=OR. This is
> done for join promotion reasons. However, this is very confusing when
> trying to work with add_q and add_filter, and doesn't actually work
> that well (see the added tests in the ticket's patch).
> 
> * Remove "trim" argument from add_filter (#18816).
> The trim argument is only needed for split_exclude (that is, pushing
> negated m2m filters to subqueries). So, add_filter (and then also
> trim_joins) needs to handle split_exclude's special case. Handling
> this case inside split_exclude() turned out to be a little ugly, but
> IMO less ugly than the trim flag. This also allows further cleanups in
> the following item.
> 
> * A biggie: complete refactoring of setup_joins (#10790, a separate
> ticket could be good for this).
> Best described in the last post in the ticket [https://
> code.djangoproject.com/ticket/10790#comment:41]. The patch isn't
> completely ready (there are still stale comments floating around, the
> commit history is ugly).
> 
> 
> Applying the above patches should make the ORM code easier to follow.
> Further features like custom lookups should be easier to add. The
> produced queries should be of higher quality (less joins, less left
> joins). And, it should be easier to do cleanups in the ORM.
> 
> A note about extra_filters: The setup_joins() refactoring removes the
> "extra_filters" system used for generic relations. The system adds new
> filters to the query for any joins generated by generic relations.
> However, these are pushed into the WHERE clause, and this doesn't work
> nicely with LOUTER JOINS. The refactoring adds the extra condition
> directly into the join's ON clause, thus producing correct left outer
> join conditions.
> 
> The extra_filters is (as far as I know) private API, but I'd like to
> know if this is heavily used by the community. If so, it is easy
> enough to leave this API in place (while still fixing the generic
> relations stuff).
> 
> I hope I can get reviews for the above tickets. Getting reviews from
> people who do not know the ORM is valuable, too, as one of the goals
> is to make the ORM easier to understand. As the author I can't easily
> see if my attempts to make the code easier to follow actually improve
> anything.
> 
> Even if I do not get any reviews, I think it is a good idea to push
> these patches in. Thus far it has been hard to get reviews for larger
> ORM patches, and I am afraid that the refactoring work will stall if I
> have to wait for a full review for every patch. If you want to review
> the patches, but don't have time just now, please make a note in the
> tickets about this. There is no hurry.
> 
> If pushing these patches without reviews seems like a bad idea to you,
> then please say so (preferably before I commit anything)...
> 
> I am sorry if I haven't worked on other patches I thought I had time
> to work on. The core ORM refactorings are IMO really important to work
> on, and thus they have bypassed some other items in my admittedly too
> long TODO list.
> 
>  - Anssi
> 


-- 
Sometimes I wonder if men and women really suit each other. Perhaps
they should live next door and just visit now and then. (Katherine
Hepburn)

Luke Plant || http://lukeplant.me.uk/

-- 
You rece

Re: GSoC Check-in: Security Enhancements

2012-07-23 Thread Luke Plant
On 23/07/12 14:24, Rohan Jain wrote:
> With this, attacker won't be able to directly set arbitrary tokens on
> other sub domains through cookies, they will need a signature of the
> token with the form which is to be verified against the cookie.
> Plus it also puts a limit on the duration a token stays valid on the
> server side.
> 
> Yes, still with this, someone can spoof the whole pair using a separate
> legitimate session. So really it doesn't make it completely secure,
> just makes it little difficult for the attacker.

So, to make it clear:

Attacker controls evil.example.com, and wants to attack example.com. By
appropriate setting of a cookie, and by providing a matching token in
the form, they can forge a request to example.com

With your proposed change, they are in no way hampered. Using HMAC to do
sign the value, and a timestamp, as you mention, they can simply
regularly directly contact example.com and pull in a valid token/cookie
value pair, which they can use since there is no correlation to the
session of the person being attacked. I'm pretty sure this can be done
entirely in Javascript too.

Yes, this change would make it "a little difficult". But the value of
"little" is very small. It's like suggesting we add ROT 13 encryption to
one of the values - sure it makes it a "little" more difficult, but it
does not *materially* affect the feasibility of the attack. The
resources they need are identical: the ability to read the Django source
code, and the subdomain control that they have in both cases.

On the other hand, this adds significant complication to our code, which
is the last thing you need for security related code. I'm -1 on this
change. I did highlight all these things before.


> If it weren't for the possibility of attacker injecting cookies from
> other subdomains, I think CSRF token should be a fine check for
> CSRF.
>
> That is why I am siding on adding referer checking in case of non
> https scheme requests too.

I really don't think we can consider this - for HTTP, proxies can and do
strip the referer header. Quoting from Barth, Jackon and Mitchell:

<<<
Over HTTP, sites cannot afford
to block requests that lack a Referer header because
they would cease to be compatible with the sizable
percentage (roughly 3–11%) of users
>>

This makes strict referer checking a non-started, and lax referer
checking (only check it if it is present) has known flaws.

Regards,

Luke

-- 
"Pretension: The downside of being better than everyone else is
that people tend to assume you're pretentious." (despair.com)

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: OT: security announcements for Django-related libraries

2012-07-23 Thread Luke Plant
Hi Adam,

To avoid fragmenting the discussion, could you reply on the thread I
linked to on Python Security?

Thanks,

Luke

On 23/07/12 13:36, Adam "Cezar" Jenkins wrote:
> Now. I'm going to preface this with being that I am totally nieve about
> such things. Wouldn't it be nice if you could mark a release on PyPI as
> a security release and Pip could just do security updates? Somewhat like
> a few Linux distributions do.
> 
> Of course that's a long term goal. A mailing list is almost a given. For
> my needs, something with and RSS feed would be great.
> 
> On Mon, Jul 23, 2012 at 5:55 AM, Luke Plant <l.plant...@cantab.net
> <mailto:l.plant...@cantab.net>> wrote:
> 
> Hi all,
> 
> I started a thread on the 'Python security' list about the need for a
> place for 3rd party Django/Python libraries to announce security issues,
> for the very common case of small libraries that wouldn't even have
> their own mailing list - or would have a fraction of their user base
> subscribed to the mailing list - but could have real security
> vulnerabilities.
> 
> At the moment I'm suggesting a single purpose mailing list that Python
> web developers could be subscribed to.
> 
> The thread is here:
> https://groups.google.com/d/topic/python-security/NmHU_VA4V6I/discussion
> 
> The group is moderated, so I've got a couple of replies that haven't
> shown up yet.
> 
> Luke
> 
> --
> "Pretension: The downside of being better than everyone else is
> that people tend to assume you're pretentious." (despair.com
> <http://despair.com>)
> 
> Luke Plant || http://lukeplant.me.uk/
> 
> --
> You received this message because you are subscribed to the Google
> Groups "Django developers" group.
> To post to this group, send email to
> django-developers@googlegroups.com
> <mailto:django-developers@googlegroups.com>.
> To unsubscribe from this group, send email to
> django-developers+unsubscr...@googlegroups.com
> <mailto:django-developers%2bunsubscr...@googlegroups.com>.
> For more options, visit this group at
> http://groups.google.com/group/django-developers?hl=en.
> 
> 
> -- 
> You received this message because you are subscribed to the Google
> Groups "Django developers" group.
> To post to this group, send email to django-developers@googlegroups.com.
> To unsubscribe from this group, send email to
> django-developers+unsubscr...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/django-developers?hl=en.


-- 
"Pretension: The downside of being better than everyone else is
that people tend to assume you're pretentious." (despair.com)

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



OT: security announcements for Django-related libraries

2012-07-23 Thread Luke Plant
Hi all,

I started a thread on the 'Python security' list about the need for a
place for 3rd party Django/Python libraries to announce security issues,
for the very common case of small libraries that wouldn't even have
their own mailing list - or would have a fraction of their user base
subscribed to the mailing list - but could have real security
vulnerabilities.

At the moment I'm suggesting a single purpose mailing list that Python
web developers could be subscribed to.

The thread is here:
https://groups.google.com/d/topic/python-security/NmHU_VA4V6I/discussion

The group is moderated, so I've got a couple of replies that haven't
shown up yet.

Luke

-- 
"Pretension: The downside of being better than everyone else is
that people tend to assume you're pretentious." (despair.com)

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: GSoC Check-in: Security Enhancements

2012-07-23 Thread Luke Plant
On 23/07/12 08:07, Rohan Jain wrote:
> ###CSRF Cookies (Time signed):
> 
>  - A random token generated by the server stored in the browser cookies. For
>verification, every non get request will need to provide a signed version 
> of
>the same token. This can then be verified on the browser side.
>  - This can be implemented by adding signing to the existing csrf token 
> system,
>using the signing framework.
>  - A conventional method of CSRF checks, all the major frameworks have similar
>systems.
>  - Signing takes care of the side effects due to cross domain behaviour of
>cookies.
>  - Cons:
> 
> - Relies on the browser cookies system, which introduces insecurities.
> - Can be broken easily by having a parallel legitimate session, which 
> gives
>   a valid token, signature pair. This generator can then be used in MITM
>   attacks.

I don't understand the motivation for this part. Could you describe the
attack scenarios where this method improves our security with respect to
the current system?

Regards,

Luke

-- 
"Pretension: The downside of being better than everyone else is
that people tend to assume you're pretentious." (despair.com)

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: Skip session save on 500 responses

2012-07-09 Thread Luke Plant
On 09/07/12 20:07, Anssi Kääriäinen wrote:

> I have updated the branch [https://github.com/akaariai/django/tree/
> ticket_3881], I think it now has all the necessary doc changes. If
> somebody is kind enough to double-check the patch, that would be
> great. If that somebody is a committer, committing the code at the
> same time is fine for me. If no further feedback, I will commit the
> patch in a day or two.

LGTM, I'll leave to you to commit.

Luke


-- 
"Pessimism: Every dark cloud has a silver lining, but lightning
kills hundreds of people each year trying to find it." (despair.com)

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: Skip session save on 500 responses

2012-07-05 Thread Luke Plant
On 05/07/12 16:25, Anssi Kääriäinen wrote:
> Currently Django's session middleware saves sessions unconditionally
> in process_response. I have created a patch which skips session save
> on 500 responses. Reasons for this:
>  1. When saving the session after PostgreSQL query error into database
> backed session store, the save is guaranteed to fail due to aborted
> transaction error. The save error will mask the original error.
>  2. The session.save() will be cancelled by transaction middleware if
> that is installed.
>  3. Saving the session in 500 situations can be argued to be non-
> wanted behaviour. The request processing likely ended due to
> unexpected error. If so, it is also possible that the changes to
> session aren't valid, or are incomplete.
> 
> Now, this is clearly a change to existing behaviour. Should this be
> considered backwards incompatible or is this change not wanted at all?
> If that is the case I will create a patch targeting #1 above
> specifically.

I agree it should be changed, and I would regard it as a bug fix, but
make a note of it in the 1.5 release notes nonetheless.

Regards,

Luke


-- 
"Pessimism: Every dark cloud has a silver lining, but lightning
kills hundreds of people each year trying to find it." (despair.com)

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: I think adding a "first" method to the QuerySet be useful.

2012-07-03 Thread Luke Plant
On 03/07/12 05:27, Maxime Haineault wrote:
> One of the common pitfall I come across way to often with novices is
> something like this:
> 
> def getFirstUser():
> return User.objects.all()[0]
> 
> It looks innocuous and often wont raise any exceptions in dev because
> you develop and test with data,
> so they slip easily in production.
> 
> def getFirstUser():
> return User.objects.all().first()
> 
> If the QuerySet is empty it should just return None instead of raising
> an exception.

This very similar to #2659:

https://code.djangoproject.com/ticket/2659

except added as a QuerySet method not a shortcut, and .first() wouldn't
throw an exception for multiple objects. It was WONTFIXED by Adrian.

I'm not keen on this proposal either. There are many small shortcuts you
could add, all with slightly different semantics.

As mentioned by others, the fastest way to get the first item depends on
a lot of things, and also depends on whether you are then going to get
the other items. The vast majority of the times that I get the first
item of a queryset, I will get other items as well, and for that case
.first() would make more work.

The idiom I prefer for the case where I know I will only need the first
is just this:

  qs[:1]

which returns a queryset with zero or one item. In the context of data
passed into a template, it is just as easy to use as the 'item or None'
pattern provided by first():

{% if items %}
  {{ items.0.something }}
{% endif %}

Luke

-- 
Parenthetical remarks (however relevant) are unnecessary

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: Proposal: use SQLAlchemy Core for query generation

2012-06-30 Thread Luke Plant
On 30/06/12 20:23, Anssi Kääriäinen wrote:

> TL;DR ;) But I intend to do so shortly.
> 
> For now I have to comment on the "clear up sql/query.py" part. I am
> doubtful if moving to SQLAlchemy will solve the sql/query.py and sql/
> compiler.py complexities.
> 
> I have little knowledge of SQLAlchemy, but my understanding is that it
> does not do things like "when filtering on negated multijoin
> condition, push the condition to subquery", automatic grouping by the
> right set of columns or handle what kind of joins are needed by select
> related. It probably doesn't do join promotion ("should this join be
> INNER or LEFT OUTER join, if dealing with an ORed where condition,
> then LEFT OUTER, and so on). The sql/query.py deals mostly with these
> kinds of problems. The sql/compiler.py also deals in part with
> problems like this.

Mike Bayer pointed me to this code, which does something like Django's
join syntax on top of SQLAlchemy:

https://github.com/mitsuhiko/sqlalchemy-django-query/blob/master/sqlalchemy_django_query.py

I really don't know enough to know how well it is approximating what
Django does. It would be surprising if it was really doing the same thing!

I think it's one of those things where we really won't know the impact
until we've got most of the way there, and even then differences of
approach could make all the difference.

Luke


-- 
Parenthetical remarks (however relevant) are unnecessary

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: Proposal: use SQLAlchemy Core for query generation

2012-06-30 Thread Luke Plant
On 30/06/12 20:25, Jacob Kaplan-Moss wrote:

> Before we do get too deep into this, however, I want to talk about
> this "Django 2.0" thing:
> 
> Clearly there will be something called "Django 2.0" at some point --
> after 1.9, if we get there, comes 2.0. However, I think it would be a
> mistake to make "Django 2.0" backwards-incompatible. We've seen
> countless examples -- Perl 6, Python 3, Rails 3, ... -- that these
> sorts of "breaks from the past" really alienate and frustrate the
> community. Over the years we've actually gotten really good at
> balancing forward motion with stability. Our reputation as a stable,
> reliable platform is something I'm intensely proud of.
> 
> It's going to take a lot of work to convince me of the value of a
> "break from the past" sort of approach. If this can't be done in a way
> that promises a smooth upgrade path... I'm not sure it's worth doing.

That's exactly the approach I had in making this proposal. The only
publicly documented API that I'm expecting to break or be removed is
QuerySet.extra(), and none of us like that anyway.

The internals I expect will break:

 - anything that relies on manipulating QuerySet.query (I've got one
project where I do that a little bit, I've not seen anyone else do it).

 - DB backend implementations that provide their own SQLCompiler
classes. Actually most external DB backends would probably break.

I'm *not* expecting the vast majority of Model._meta to change in big
ways, which is the biggest 'internal' that people regularly use. Since
it isn't to do with query generation, it doesn't need to change.

Of course, reality can have other ideas with big changes like this, but
that's what I would be aiming for.

For the things that will break, I hope they would be replaced by much
more appealing options - QuerySet.query would be replaced by the
QuerySet.as_sqlalchemy() method that Anssi mentioned, and you won't need
most 3rd party DB backends, or can plug them in via SQLAlchemy's
extension points, which are cleaner than ours from what I can see.

Luke

-- 
Parenthetical remarks (however relevant) are unnecessary

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Proposal: use SQLAlchemy Core for query generation

2012-06-30 Thread Luke Plant
ome of which I've
incorporated into this.


Comments? It would be good to get other developers' comments on the
whole idea of "Django 2.0" as well - when do we see it happening?


Regards,

Luke


[1] http://goo.gl/uKQe9
[2] http://goo.gl/gJP15
[3] http://goo.gl/NVRdw
[4] http://gitorious.org/django-sqlalchemy/
[5] http://goo.gl/4Vhlb
[6] http://geoalchemy.org/index.html

-- 
"Outside of a dog, a book is a man's best friend... inside of a
dog, it's too dark to read."

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: XSS and string interpolation

2012-06-28 Thread Luke Plant
On 28/06/12 16:32, Alex Ogier wrote:

> That's an HTML-safe replacement of the str.format() method, so far as
> I can tell (except that all parameters must be [safe-]strings). That
> allows more idiomatic python, and won't require awkward shims in
> python 3, but it would mean that you can't directly translate %
> interpolations. I think thats a good tradeoff.

Yeah, I think it makes sense to move to str.format at this point. It
also helps ensure that, if you are switching code, you don't
accidentally pass a string that is already %-interpolated:

   html_fragment("Some stuff %s" % data)

As for the name, I'm not convinced by html_mark_safe - to my mind that
implies an HTML version of 'mark_safe', which doesn't make sense - you
should only be using 'mark_safe' on html anyway.

Jeremy wrote:

> I like the general approach, but I miss the security-minded namse of
> "escape" and "mark safe".   Maybe "safe_html_fragment" or
> "make_safe_html_fragment"? Getting annoyingly long, I know.
>
> (Apologies if this feels bike shedding)

No problem with bike-shedding - that's why I asked the question. My
response would be that the name 'Template' also doesn't imply anything
about security, but function. The same is true here - 'html_fragment' is
for building HTML fragments. Of course it is secure! Why would we call
it that if it wasn't fit for purpose? :-)

Actually my main objection is that it's a bit long, the above is just
rationalisation.

Some other alternatives: build_html, build_html_safe, format_html

Luke

-- 
Parenthetical remarks (however relevant) are unnecessary

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



XSS and string interpolation

2012-06-28 Thread Luke Plant
Hi all,

Django's code base has quite a few instances of string interpolation
being used to build up HTML e.g.:

contrib/admin/util.py

return mark_safe('%s: %s' %
 (escape(capfirst(opts.verbose_name)),
  admin_url,
  escape(obj)))


The problem with this is that it is easy to forget to use 'escape',
giving rise to an XSS vulnerability. This has led to at least one
instance in the past:

https://github.com/django/django/commit/9f6d50d02e

(I couldn't find others, there might be. I'm sure there could be many in
3rd party code - there was at least one instance in some code I wrote).

It also makes review hard. In the above fragment, is it still vulnerable
to XSS due to the unescaped 'admin_url'? (AFAICS after looking at it,
'no', but it's not that easy to tell).

I'm going to clean these up using the following pattern:

return html_fragment('%s: %s',
 capfirst(opts.verbose_name),
 admin_url,
 obj)

The implementation, which will be added to django.utils.html, is just:

 def html_fragment(template, *args):
 return mark_safe(template % tuple(map(conditional_escape, args)))


This is an all round win:

* It is secure by default, like autoescaping in templates
* It is easier to use - you only have to import 'html_fragment', instead
  of both 'mark_safe' and 'escape'
* The code is easier to read due to fewer parenthesis
* It makes XSS problems more greppable. You now have to grep for:

  * all string interpolations using % (which should be removed and
replaced with html_fragment if the result is eventually
mark_safe'd).

  As before, you have to audit:

  * mark_safe (but this will have far fewer instances now)
  * |safe
  * {% autoescape off %}

This utility will be public and documented, and suggested as an
alternative to ever using 'mark_safe' or 'escape' directly.

Apart from letting people know, I've got a few reasons for emailing
about this:

1) Are there are any better alternatives? I'm ruling out use of
   'Template' because it is overly verbose for this use case, both in
   API and template syntax.

2) Any better name than 'html_fragment'?

3) It made me realise we should have thought of this earlier, and
   that our security procedures need improving in this regard.

   When we had the XSS exploit I mentioned above, we simply fixed
   it by applying 'escape'. We didn't ask "why did this happen?
   What is the root cause? How can we stop it ever happening again?"

   We need to be much more rigorous about applying things like
   the "5 Whys" http://en.wikipedia.org/wiki/5_Whys
   especially for security problems.


Regards,

Luke

-- 
Parenthetical remarks (however relevant) are unnecessary

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: Reg Memcache issue.

2012-06-22 Thread Luke Plant

On 22/06/12 19:08, Ramesh-Nivista wrote:
> Hi,
> 
> We are facing one issue when we tried to update the memcache module.
> Please check below our issue which is explained indetail.
> 
> 
> We tried to deploy our django application and whenever we access a
> particular content based page( a page which fetches the data from DB)
> we are facing cache time out error.
> 
> We are facing this error when @cache_ananonymous decorator is called
> in memcache.py file. It says cache_timeout argument missing.

If you are having a problem with Django, the place to ask is the
django-users list, or file a ticket on our Trac instance
(code.djangoproject.com) if you think you've found a bug in Django

BTW, there is no cache_anonymous decorator in Django, so it is likely
your problem is elsewhere.

Thanks,

Luke


-- 
Parenthetical remarks (however relevant) are unnecessary

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: QuerySet refactoring

2012-06-13 Thread Luke Plant
On 13/06/12 08:09, Anssi Kääriäinen wrote:

> Accidentally clicked send... So, what I am asking is: Is there support
> for ORM refactoring, and the "small step at time" way of doing it? If
> the ORM refactorings are to be done, it will be hard to get reviews.
> In practice I would need to commit patches without full reviews.
> 
> For more technical questions: Is changing the API of utils.tree
> acceptable? What about removing old undocumented features ("anything
> containing add_to_query() will shortcut qs.add_q() - not tested, not
> documented"). qs.order_by("tablename.columname") - tested, but not
> documented. Syntax predates 1.0). What about the more radical changes,
> like using .clone() instead of .deepcopy() in query.clone() (ticket
> #16759).
> 
> I know I have taken too much stuff under work already... However, the
> ORM is what I really like to hack, and would like to concentrate on
> that for some time. To do so I will need to feel confident that there
> is support for getting the patches committed.

I think this is a very necessary piece of work. The problem with that
layer of code is that it is very difficult to really grok and therefore
to review patches. It would take almost as much effort to do a review of
a substantial patch as the patch itself. You have to really understand
what Query is doing, and it is a huge class, that takes hours to even
vaguely get the hang of and get in your head.

I would like to be able to help, and if I dropped everything else I
might otherwise do on Django, that should be possible. I think with two
pairs of eyes on these changes, and with a good test suite, we should be
reasonably safe, but getting more review than that would be hard.

I would say that any undocumented APIs are fair game for changing, which
covers all of the Query class and SQLCompiler classes, AFAIK. For
user-facing features, we should be much more slow to break them,
especially if they are tested.  qs.order_by("tablename.columnname") is
pretty strange though, I would be happy with getting rid of that,
assuming there is an alternative.

I do actually have another proposal, that has been a growing draft email
on my computer for a few weeks: that we rewrite our backend using
SQLAlchemy Core (not the ORM). I've used SQLAlchemy a bit, and I'm very
confident we could use it profitably. While the ORM works significantly
differently to ours, the lower layer (Core - the SQL Expression
Language) can indeed build queries that can do all the joins etc that we
would need - it's a full wrapper around SQL. Some of the complexity in
our code comes from not having this wrapper.

SQLAlchemy is a really excellent library, and I fear that long term if
we don't switch to it, we will just produce an ad-hoc, informally
specified, buggy, slow implementation of half of SQLAlchemy.

However, that is a longer term aim (Django 2.0 really, for various
reasons), and I'm confident this refactoring would help either way.

Nonetheless, I'll try to post that proposal soon. There is one strategy
for implementing it that might allow it to be started soon, and
developed alongside existing functionality without breaking anything.
(That depends on when we think 'Django 2.0' will happen). If you've got
a particular interest in the ORM, you might be interested in that proposal.

I completely agree regarding how to handle NoSQL as well.

Regards,

Luke


-- 
"Outside of a dog, a book is a man's best friend... inside of a
dog, it's too dark to read."

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



ModelForms and the Rails input handling vulnerability

2012-06-12 Thread Luke Plant
Hi all,

On django-core we've been discussing an issue that was security related.
However, we decided it wasn't urgent enough to warrant a security
release, and so we're moving the discussion here (especially because we
couldn't agree on what to do).

For the record, I brought up the issue initially, and favour the most
secure of the options outlined below, but I'll try to summarise with as
little bias as I can!

The issue was brought up by the Rails input handling vulnerability a
while back [1]. To sum that up, it seems that a common Rails idiom is
something like, using Django syntax:

   MyModel.objects.create(**request.POST)

(only more complicated). To avoid people having access to privileged
fields, you are supposed to set an attribute on MyModel to restrict the
fields that can be set in this way. This is a really poor design choice
(which they've finally admitted [2]), since it is insecure-by-default,
and led to the embarrassing github incident, and probably many more
unknown vulnerabilities in Rails apps.

For us, we don't have this issue because we have the forms layer that
sits between the HTTP request and model creation, and that's the
recommended way to do things.

However, in the case of ModelForms, you can easily get to a situation
where you've effectively got the same thing as Rails. In theory you've
got the forms layer, but in reality your form was autogenerated using
all the fields on the model. This happens if you use a ModelForm without
explicitly defining Meta.fields - which is the easiest thing to do since
it is less work.

While you can use 'Meta.exclude' to remove specific fields, you still
have to remember to do that.

This is particularly dangerous in two fairly common situations:

1) You add new fields to the model that are not supposed to be publicly
edited.

2) In the template, you are listing form fields individually, not just
doing {{ form.as_p }}, so you can't even see the fact that other fields
are editable, but the view/form code does allow an attacker to edit
those fields.

Also, the UpdateView CBV makes it very easy to be vulnerable - it will
generate a ModelForm class with all fields editable by default.

== Options ==

There were three main courses of action that we talked about on django-core.

= Option 1: Leave things as they are, just document the problem. This
was the least popular view on django-core.

= Option 2: Deprecate Meta.exclude, but still allow a missing
Meta.fields attribute to indicate that all fields should be editable.

The policy here is essentially this: if any fields the model are
sensitive, assume all are potentially, and require whitelisting, not
blacklisting.

= Option 3: Make the 'Meta.fields' attribute a required attribute, which
must list all the model fields that should be editable. Without it,
ModelForms would not work at all.

This also means deprecating Meta.exclude (it's redundant once you are
saying that all fields should be explicitly whitelisted).


Note that the admin would not be affected under any of these options -
the admin has its own mechanism for setting the Meta.fields, and "all
fields editable by default" is a good policy for something like the admin.

For either 2) or 3), we would be making the change in Django 1.6, with a
deprecation path - faster than our normal deprecation path, but not
immediate.

Also the UpdateView and CreateView CBVs would need modifying under at
least option 3, to match the requirements of the ModelForms they will
need to generate.

== Comparison ==

== Option 1: This is the least secure, but most convenient - you have
several ways to specify which fields should be editable, you can use
whichever you like. "We're all consenting adults here".

An argument in favour of keeping this is if we don't, people will just
use 'fields = [f.name for f in MyModel._meta.fields]' anyway.

== Option 2: the retains some of the convenience of option 1, while
encouraging more careful handling of "sensitive" models.

== Option 3: the most secure, the least convenient. You have to list all
fields for every ModelForm (except for cases of sub-classing forms,
where the base class's Meta.fields would still work, of course).
"Explicit is better than implicit".

The option doesn't make an assumption that models are either 'sensitive'
or not. It is also more consistent than option 2: if you add a field to
a model, you know that if it is meant to be publicly editable, you have
to edit the ModelForms to add it, and if it is not meant to be editable,
you don't, because the list is always "opt in".

 ~  ~  ~

So - discuss! If you have other options to bring to the table, please
do. Apologies to the core devs if I missed or misrepresented something.


Thanks,

Luke


[1] http://chrisacky.posterous.com/github-you-have-let-us-all-down
[2] http://weblog.rubyonrails.org/2012/3/21/strong-parameters/

-- 
OSBORN'S LAW
Variables won't, constants aren't.

Luke 

Re: json vs simplejson

2012-06-12 Thread Luke Plant
On 12/06/12 13:28, Alex Ogier wrote:

> Wait, 'import simplejson' works? Then that explains your problems. You
> are using a library you installed yourself that has C extensions,
> instead of the system json. If you switch to a system without
> simplejson installed, then you should see the "proper" behavior from
> django.utils.simplejson.loads(). If your program depends on some
> optimized behavior of the C parser such as returning str instances
> when it finds ASCII, it is bugged already on systems without
> simplejson. If Django depends on optimized behavior, then it is a bug,
> and a ticket should be filed.

I agree my existing program had a bug. I had simplejson installed
because a dependency pulled it in (which means it can be difficult to
get rid of).

The thing I was flagging up was that the release notes say "You can
safely change any use of django.utils.simplejson to json." I'm just
saying the two differences I've found probably warrant at least some
documentation.

The second issue is difficult to argue as a bug in my program or
dependencies. Django has moved from a providing a JSONEncoder object
that supported a certain keyword argument to one that doesn't. We could
'fix' it to some extent:

class DjangoJSONEncoder(json.JSONEncoder):
def __init__(self, *args, **kwargs):
kwargs.pop('namedtuple_as_object')
super(DjangoJSONEncoder, self).__init__(*args, **kwargs)

But like that, it would create more problems if the json module ever
gained that keyword argument in the future.


Luke


-- 
OSBORN'S LAW
    Variables won't, constants aren't.

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: json vs simplejson

2012-06-12 Thread Luke Plant
On 12/06/12 10:58, Vinay Sajip wrote:
> 
> I'm not sure there's any easy way out, other than comprehensive
> testing.

There is another issue I found.

Django's DateTimeAwareJSONEncoder now subclasses json.JSONEncoder
instead of simplejson.JSONEncoder. The two are not perfectly compatible.
simplejson.dumps() passes the keyword argument 'namedtuple_as_object' to
the JSON encoder class that you pass in, but json.JSONEncoder doesn't
accept that argument, resulting in a TypeError.

So any library that uses Django's JSONEncoder subclasses, but uses
simplejson.dumps() (either via 'import simplejson' or 'import
django.utils.simplejson') will break. I found this already with
django-piston.

I think we at least need a bigger section in the release notes about this.

Luke

-- 
OSBORN'S LAW
Variables won't, constants aren't.

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: json vs simplejson

2012-06-12 Thread Luke Plant
On 12/06/12 06:14, Alex Ogier wrote:

> This seemed strange to me because the standard library json shipping
> with python 2.7.3 is in fact simplejson 2.0.9, so I did some digging.
> It turns out that if the C extensions have been compiled and you pass
> a str instance to loads(), then you get that behavior in both
> versions. This isn't documented anywhere, but here's the offending
> pieces:
> 
> http://hg.python.org/releasing/2.7.3/file/7bb96963d067/Modules/_json.c#l419
> https://github.com/simplejson/simplejson/blob/master/simplejson/_speedups.c#L527
> 
> If the C extensions aren't enabled, or you pass a unicode string to
> loads(), then you get the "proper" behavior as documented. I'm not
> sure how you are triggering this optimized, iffy behavior in
> django.utils.simplejson though, without also triggering it in the
> standard library. Did you ever install simplejson with 'pip install
> simplejson' such that Django picked it up? Can you try running 'from
> django.utils import simplejson; print simplejson.__version__'?

Thanks for digging into that.

(BTW, in reply to Vinay, yes I meant "from simplejson to json", not the
other way around).

I've found the same difference of behaviour on both a production machine
where I'm running my app (CentOS machine, using a virtualenv, Python
2.7.3), and locally on my dev machine which is currently running Debian,
using the Debian Python 2.7.2 packages.

In both cases, json is always returning unicode objects, which implies I
don't have the C extensions for the json module according to your
analysis. I don't know enough about how this is supposed to work to
understand why.

It also implies I probably not the only one affected by this, if it's
happened on two quite different machines. Looking at this discussion:

http://stackoverflow.com/questions/712791/json-and-simplejson-module-differences-in-python

it seems that lots of people don't have the C extension for json
(reporting json 10x slower than simplejson).

Luke

-- 
OSBORN'S LAW
Variables won't, constants aren't.

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



json vs simplejson

2012-06-11 Thread Luke Plant
Hi all,

We've switched internally from json to simplejson. Our 1.5 release notes
say:

You can safely change any use of django.utils.simplejson to json

I just found a very big difference between json and simplejson

>>> simplejson.loads('{"x":"y"}')
{'x': 'y'}

>>> json.loads('{"x":"y"}')
{u'x': u'y'}

i.e. simplejson returns bytestrings if the string is ASCII (it returns
unicode objects otherwise), while json returns unicode objects always.

This was, unfortunately, a very unfortunate design decision on the part
of simplejson - json is definitely correct here - and a very big change
in semantics. It led to one very difficult to debug error for me already.

So, this is a shout out to other people to watch out for this, and a
call for ideas on what we can do to mitigate the impact of this. It's
likely to crop up in all kinds of horrible places, deep in libraries
that you can't do much about. In my case I was loading config, including
passwords, from a config file in JSON, and the password was now
exploding inside smtplib because it was a unicode object.

Yuck. Ideas?

Luke


-- 
OSBORN'S LAW
Variables won't, constants aren't.

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Git questions

2012-06-08 Thread Luke Plant
First, thanks so much to Aymeric and Anssi and others for the
contribution guidelines, they're very helpful.

I've got some questions that are due to my ignorance of git (I have
managed to avoid it as something I need in daily use, I still think it's
got a brain-damaged UI...)

In this section:

https://docs.djangoproject.com/en/dev/internals/contributing/committing-code/#handling-pull-requests

it's written you can use this:

  git push --dry-run upstream master

to check outgoing changes. However for me the output of that command is
a short and very unhelpful message, something like this:

To g...@github.com:django/django.git
   45d4331..2d5f9e4  master -> master

How is this supposed to help me check the outgoing changes? Do I need to
change something in my config?

The alternative for checking outgoing changes that I've found is using log:

  git log -p upstream/master..master

However, I've found this doesn't work as I expect sometimes, because
somehow after a pull, the branch pointer for 'remotes/upstream/master'
has not been updated to where I expect it to be (the last commit pulled
from upstream), but is left where it was. I've observed this several
times. If I do 'git fetch upstream', rather than 'git pull upstream
master', then the pointers always update, but I thought the whole point
of doing 'pull' was 'pull=fetch then merge'.  Am I doing something wrong?

Thanks in advance,

Luke

-- 
OSBORN'S LAW
Variables won't, constants aren't.

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: startproject template context

2012-06-07 Thread Luke Plant
On 01/05/12 22:58, Ramiro Morales wrote:
> On Tue, May 1, 2012 at 11:04 AM, Sam Simmons <s...@samiconductor.com> wrote:
>> For app/project templates I found the docs a little misleading when they say
>> 'Any option passed to the startapp command' will be added to the context.
> 
> You' ve understood the documentation correctly. This is a feature that is
> currently (and AFAICT was DOA) not fully implemented because there is code to
> process and add the custom command line switches to the context but the
> validation that the management commands framework performs on the command line
> options isn't allowing them to pass.

This sounds like it would be a misfeature.

It is a golden rule of command line apps that typos in options passed to
the command are not silently ignored.

If I type:

django-admin.py startproject --tempate=/home/me/foo

I should get an exception, not the default template rendered with
"tempate=/home/me/foo".

The feature given in the patch on ticket #18277, is however, much more
like it - you have to pass the context using --add-context

Regards,

Luke

-- 
OSBORN'S LAW
    Variables won't, constants aren't.

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: Will django escaping ever consider context of javascript and CSS?

2012-06-07 Thread Luke Plant
On 03/05/12 17:49, Voulnet wrote:
> The document you linked says it doesn't make it safe to use, but rather
> helps in fixing syntax errors.
> 
> " escapejs
> 
> Escapes characters for use in JavaScript strings. This does not make the
> string safe for use in HTML, but does protect you from syntax errors
> when using templates to generate JavaScript/JSON."

This means that it is not safe for use *in HTML*. It does guarantee that
all the data ends up as a single javascript string literal, but that
javascript string will still need HTML escaping if you are planning on
inserting it in the DOM. This needs to be done using a javascript escape
function (not provided).

We've looked at custom escape mechanisms in the past. There are big
difficulties due to the fact that builtin filters only work correctly
with the context of HTML escaping.

Some relevant previous discussions:

http://goo.gl/XZ7Pt

http://goo.gl/T8tkx

Luke

-- 
OSBORN'S LAW
Variables won't, constants aren't.

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: Django's CVB - Roadmap?

2012-06-04 Thread Luke Plant
On 01/06/12 15:54, Jacob Kaplan-Moss wrote:
> On Fri, Jun 1, 2012 at 10:14 AM, Victor Hooi <victorh...@gmail.com> wrote:
>> The reason for my post - is there anything from the Django core as a whole
>> on this? What's the future roadmap like in terms of CBV's? Are there going
>> to be any changes to it, or are we safe to assume things will be as they are
>> now.
> 
> I think as a whole we're divided. Luke's opinions differ from
> mine, and it's entirely unclear to me who's "right" or even if there's
> a "right" to be had. And that's just the two of us!

I personally found all the responses and discussion really enlightening,
and it moderated my opinions somewhat.

Here are the things I'd like to actually see change:

1) An easy one: Some documentation to the effect of this: "The
Django-supplied CBV base classes may not be the best fit for your
project. Consider two alternatives - use a function, or write your own
base classes."

I'm happy to write that paragraph if others agree.

2) A harder one: nicer functional way of using CBVs in the simple case,
so they can be used from traditional function view without subclassing.
In theory, you can do this:

def my_view(request):
return ListView.as_view(template_name='foo.html')

However, you've got a few problems:

* you can't pass in the extra context you need, which is pretty much a
  crucial requirement
* you have some gotchas with things like POST requests.

I found I had to write something like this snippet:

https://gist.github.com/2596285

But it's not ideal in a number of ways, like needing its own
documentation, since it doesn't just set parameters on ListView.


Luke

-- 
O'REILLY'S LAW OF THE KITCHEN
Cleanliness is next to impossible.

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: GitHub migration planning

2012-04-21 Thread Luke Plant
On 20/04/12 19:58, Daniel Sokolowski wrote:

> Was BitBucket (mercurial system which is python based) not considered?
> And could someone point me to a url where I can read the discussion on
> this migration; I am rather curious why it’s happening – the current
> system works so I see no reason to fix it.

Some of the discussion happened on django-core.

One of the reasons for this was that it affects core developers most of
all, so Adrian wanted their opinions first.

Another reason was that this kind of change is almost certainly going to
require a BDFL decision, because we will never come to consensus on Git
vs Mercurial etc. - even within the core developers they are strong
preferences in both directions, and even strong preferences to stick
with Subversion. And I guess that's the reason that we didn't have
further discussion on django-devs - since it already needed a BDFL
decision, there was no point making the pretence of discussion in a
wider forum. (Adrian/Jacob feel may correct me if I'm guessing wrongly).

Luke

-- 
"My capacity for happiness you could fit into a matchbox without
taking out the matches first." (Marvin the paranoid android)

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: GitHub migration planning

2012-04-21 Thread Luke Plant
On 20/04/12 18:26, Max Thayer wrote:
> Luke, maybe I don't understand something about Trac, but some of the
> issues raised by you or those you quoted seem easily fixed. Consider:
> 
> "- there isn't a notion of "component", so there's no way to ask
> "give me
> the list of all contrib.auth tickets, so I can find the duplicate
> quickly";"
> 
> 
> Why not tag all relevant issues "contrib.auth"?
> 
...

> 
> "- we can't put customized flags on tickets (easy, ui/ux) -- there are
> tags, but the result of the "Keywords" field in Trac shows the limits of
> unstructured tags;"
> 
> 
> Could you explain this more? "customized flag" sounds exactly like a tag.

They are very different things in reality.

With tags, it is up to people to decide which kind of tagging they think
is relevant. With flags, we've already decided, it's there in the UI,
and every time you create or update a ticket you scroll past the
questions we've decided are important and that you may need to update.

Without this, tagging quickly becomes next to useless for querying.

Also, tags are unstructured, so if you use it for more than one purpose,
everything lives in the same namespace. Sure, there are things you could
do to help matters, like colours and prefixes, but there are no
constraints to stop multiple assignments in the same category etc.

Also, the tracking on these things is basically non-existant in GitHub.
When I read a ticket, it tells me explicitly that such and such user set
such and such flag. For tags like "Ready for checkin", the flag is
*massively* less useful without this information (I will assess the
accuracy of the flag by the person who set it, and also as a core
developer looking for reliable triagers and potential developers, I'm
assessing the accuracy of the person by the flags they set).

It also seems that only managers can set tags in GitHub Issues, which
would kill the community triage process we have.

> "- it's hard to navigate when there are more than 200 open tickets
on a
> project."
>
>
> There are easily that many open tickets on Trac (a quick look seems to
> indicate there are about 2k open tickets). What about Trac makes the
> number of open tickets a non-issue?

For one thing, the Trac UI just makes much better use of screen space.
There is no comparison between these two in terms of easily finding the
information you want:

https://code.djangoproject.com/query
https://github.com/divio/django-cms/issues

Trac also has pretty nice reporting abilities, and report building
abilities:

https://code.djangoproject.com/wiki/Reports

No-one thinks Trac is ideal, it's just much better than GitHub Issues
which, in its own words, is a "lightweight" issue management system.

Luke

-- 
"My capacity for happiness you could fit into a matchbox without
taking out the matches first." (Marvin the paranoid android)

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: GitHub migration planning

2012-04-20 Thread Luke Plant
On 18/04/12 22:44, philipn wrote:
> Hey folks!
> 
> I started a wiki page to help plan a migration to GitHub:
> 
> https://code.djangoproject.com/wiki/GitHub%20Migration
> 
> I don't know what I'm doing, but I do know that the current Trac setup
> (attaching patches, etc) is less accessible to non-core contributors
> than GitHub and I'd love to do anything I can to help make this better.

In discussing the move to GitHub on django-core, we fairly quickly came
to the conclusion that we wouldn't be using GitHub issues.

One of my major points in this discussion was the need to be able to
import our current Trac database, because otherwise we are throwing away
a huge amount of important history. As a core committer I regularly
trace history to work out why a certain change was made, and often find
myself looking at bugs on Trac and reading the discussion there.

But importing our Trac database to GitHub issues would be basically
impossible as it doesn't support attachments, and various other things -
we would lose a huge amount of info if we attempted to port our current
Trac database.

There were a fair amount of other objections too. Some copy and paste
from that thread:

Aymeric wrote:
"""
I just looked at it again and here's what I noticed:
- there is no workflow, so we lose the ability for the community to
triage tickets;
- we can't upload patches (which forces every contributor to sign up for
GitHub and learn git) or arbitrary files (like logs, screenshots,
tracebacks: not everything is a pull request);
- there isn't a notion of "component", so there's no way to ask "give me
the list of all contrib.auth tickets, so I can find the duplicate quickly";
- we can't put customized flags on tickets (easy, ui/ux) -- there are
tags, but the result of the "Keywords" field in Trac shows the limits of
unstructured tags;
- it's hard to navigate when there are more than 200 open tickets on a
project.
"""

Justin Bronn wrote:
"""
GitHub's issue tracker is so much worse than Trac I don't know why we're
even considering it.  I can attest it has NOT gotten better with age,
and large projects on GitHub can't use it either.  For example, both
Chef and Puppet are hosted on GitHub yet use their own ticket solutions
(Puppet uses Redmine, Chef uses Jira).  The Pinax folks wrote their own
issue system rather than using GitHub's!
"""

Cheers,

Luke

-- 
"My capacity for happiness you could fit into a matchbox without
taking out the matches first." (Marvin the paranoid android)

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: GSoC 2012: Security Enhancements

2012-04-18 Thread Luke Plant
On 18/04/12 20:05, Paul McMillan wrote:

> My suggestion here is to include optional support for the Origin
> header as follows:
> - if present and null, fail the CSRF check
> - if present and not null, use in alongside the Referer header
> - if absent, keep current behavior
> 
> As a general rule, if a browser sends an origin header, that value is
> more reliable (harder for malicious sites to manipulate, less often
> stripped by firewalls, less often disabled by users) than the referer
> header. This addition won't improve CSRF protection for older
> browsers, but it also won't break anything for them. For users with
> newer browsers, it should prevent CSRF even in cases when the CSRF
> token is stolen due to misconfiguration or user error.

That does sound like a useful additional behaviour.

One query: are you sure it is harder to manipulate? In particular, I
remember from a while back that Flash allowed some headers to be
manipulated, which caused problems, and they fixed it by blacklisting
some headers, I think including referer. Did they also fix Origin?

The vulnerability I'm thinking about is this one I think:

http://lists.webappsec.org/pipermail/websecurity_lists.webappsec.org/2011-February/007533.html

Luke


-- 
"My capacity for happiness you could fit into a matchbox without
taking out the matches first." (Marvin the paranoid android)

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: GSoC 2012: Security Enhancements

2012-04-18 Thread Luke Plant
Sorry to reply twice, a comment on a different part:

On 15/04/12 05:23, Rohan Jain wrote:
> On 22:50 +0100 / 13 Apr, Luke Plant wrote:
>> .. At the moment, it seems that few browsers send the
>> 'Origin' header for normal HTML requests. (Recent versions of Chrome,
>> Firefox and Opera do not, I don't know about IE).
> 
> Page, http://caniuse.com/cors mentions the browsers and their versions
> which support CORS. A big share of browser does support it and another
> big one (constituting old IE and Opera) does not. We cannot expect
> these browsers to go away anytime soon, so we have to keep maintaining
> a compatibility system.
> 
> Since http referrer is already being used in case of secure requests,
> how about something similar in normal requests? Isn't the argument
> about referrer being absent only in 0.2% case or less valid here? Is
> 0.2% too significant for normal requests?

The page you linked to shows browsers that support CORS, which is quite
different from browsers that send Origin with normal HTTP requests (i.e.
non XMLHttpRequests requests) - in my own tests I can't find any browser
that sends it for normal HTML requests.

This means that it might be useful as an alternative way of addressing
the problem with AJAX, but even there I think it is of dubious value: if
we deploy a method that means that AJAX works automatically (without,
for example, the jQuery fix we include in our docs) on the basis of the
Origin header, everything will work fine in development, where most
people don't test IE regularly, and will fail for Internet Explorer in
production, which is not very nice. It is better to fail early.

Regards,

Luke

-- 
"My capacity for happiness you could fit into a matchbox without
taking out the matches first." (Marvin the paranoid android)

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



Re: GSoC 2012: Security Enhancements

2012-04-18 Thread Luke Plant
On 15/04/12 05:23, Rohan Jain wrote:
> On 22:50 +0100 / 13 Apr, Luke Plant wrote:
>> The reason for the strict referer checking under HTTPS is set out here:
>>
>> https://code.djangoproject.com/wiki/CsrfProtection
>>
>> Particularly, it is to fix the 'CSRF + MITM' attack that is possible
>> under HTTPS. The key elements are set out in the following scenario
>> (although it is not the only variation):
>>
>>  - a client connects to a site via HTTP: http://example.com/
>>  - in the response, an active MITM attacker sets a cookie over
>>HTTP for example.com
>>  - this cookie will be used by the client when it connects over HTTPS
>>to the same domain (this is the fundamental problem, but we can't
>>fix it - it's what browsers do).
>>  - the MITM also inserts a POST form in the HTTP response.
>>The form has a CSRF token that matches the cookie that was
>>set by the attacker.
>>The forms targets https://example.com/ and is automatically
>>submitted by javascript.
>>
>> Without strict referer checking, the POST request will succeed, even
>> though it is forged.
>>
>> Signing the cookie or token value does no good at all, because the
>> attacker can retrieve a valid cookie/token pair directly from
>> https://example.com/.
> 
> I am a bit confused about this. How can an attacker extract the token
> out of the signed cookie without the private key? There is a
> possibility that the attacker deletes and sets the cookie right out,
> but since that case won't be correctly signed server can handle it
> securely.

They don't need to extract the token, they just need to replay an
existing good token/cookie pair, which they can get directly from the
server any time they want.

(Also, signing does nothing to hide the token. Are you actually talking
about encryption here? But even if you encrypt it, it doesn't help - the
only thing that matters is that the CSRF form token 'matches' the CSRF
cookie, whatever your definition of 'match', and that can be achieved by
getting the pair from the server.)

Luke

-- 
"My capacity for happiness you could fit into a matchbox without
taking out the matches first." (Marvin the paranoid android)

Luke Plant || http://lukeplant.me.uk/

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.



  1   2   3   4   5   6   7   >