Re: reconsider re-opening ticket 901

2013-05-14 Thread Alex Ogier
On Tue, May 14, 2013 at 12:09 AM, Russell Keith-Magee <
russ...@keith-magee.com> wrote:

> As far as I can make out, that's exactly the same use case -- you're just
> making the example a little bit more explicit regarding the fact that 'a'
> is an object referred to by reference, so if 'a' is updated, b['a'] will
> also be updated.
>
> The point I was trying to make is that we're *not* talking about every
> instance of "object with PK 42" being transparently updated. It's an
> explicit API call on a specific object instance.
>

I think what he is saying is that this is not just shorthand for some other
way of achieving the same behavior. It's a totally new behavior that has
plenty of corner cases such as foreign keys, and especially OneToOneFields.

This is the shortest workaround I can come up with for the .refresh()
method: "a.__dict__ = dict(a.__dict__).update(type(a).objects.get(**{a._
meta.pk.name: a.pk}).__dict__)". Unfortunately, that clobbers any non-field
attributes you've changed since you created the instance (though it
preserves new ones). Alternatively, you could iterate over Meta.fields
calling "setattr(old_a, field_name, getattr(new_a, field_name))" for each
one, but that has the problem that field setters may expect to do some
massaging of the data on the way in which can cause data corruption.
Basically this is a Hard Problem(tm) with no obvious workaround.

Best,
Alex Ogier

-- 
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-14 Thread Daniele Procida
On Mon, May 13, 2013, Łukasz Rekucki  wrote:

>> The status WONTFIX sounds awfully rude to me. It's like saying "That's a
>> pony and you can't have one, ever." It implies a terminal finality which
>> actually isn't meant in some cases, because it is possible (as we've seen)
>> and even sometimes recommended by a core developer, for a sufficiently
>> determined person to push for change on the mailing list and make it happen.
>>
>
>You can blame this on my lack of social skills, but I really don't see how
>it's rude.

Maybe it's not rude, but it is off-putting. Perhaps there are some proposals 
that really do deserve to have the door closed firmly in their faces - that's 
what "WONTFIX" suggests to me, even if it's not what's intended.

Daniele

-- 
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: reconsider re-opening ticket 901

2013-05-14 Thread Shai Berger
On Tuesday 14 May 2013, Alex Ogier wrote:
> 
>  It's a totally new behavior that has
> plenty of corner cases such as foreign keys, and especially OneToOneFields.
> 
Another one is initializers: get() or any other method of fetching an object 
from the database will call __init__() with the fields as *args; this allows a 
model to manipulate these fields or calculate derived fields or whatever. 
refresh() may put such objects in an inconsistent state by default -- to 
prevent this, we would need a rule along the lines of "every model that 
overrides __init__() also needs to override refresh()".

Shai.

-- 
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: reconsider re-opening ticket 901

2013-05-14 Thread Alex Ogier
On Tue, May 14, 2013 at 7:38 AM, Shai Berger  wrote:

> On Tuesday 14 May 2013, Alex Ogier wrote:
> >
> >  It's a totally new behavior that has
> > plenty of corner cases such as foreign keys, and especially
> OneToOneFields.
> >
> Another one is initializers: get() or any other method of fetching an
> object
> from the database will call __init__() with the fields as *args; this
> allows a
> model to manipulate these fields or calculate derived fields or whatever.
> refresh() may put such objects in an inconsistent state by default -- to
> prevent this, we would need a rule along the lines of "every model that
> overrides __init__() also needs to override refresh()".


There's also a systemic problem with any field that contains a python
reference. What happens when the value mutates in the database? Do you
create new instances of the value? What if it *didn't* mutate, how do you
know that?

Imagine a hypothetical python dict field, that serializes a Python dict to
JSON or a string or something and stores it in the database. What happens
in the following case?

a = A(dict_field={"hello": "world"})
d = a.dict_field
a.save()
a.refresh()
d["hello"] = "planet"# does this mutate a.dict_field? does the answer
change if somebody changed the database in between saving and refreshing?

In the case of the OneToOneField, we need that the related Python instance
not be changed if the value didn't change, or else we will break the
one-to-one correspondence of the Python instances (two related one-to-one
models point back to our model). There doesn't really seem to be any way to
do that generally, so you probably have to create new instances every time
even when the value doesn't change except in this special case. Are
OneToOneFields special enough to warrant that? What about just your average
many-to-one relationship ("b = a.b_set[0]; a.refresh(); assert b not in
a.b_set")?

Basically, having a .refresh() necessitates having mutation semantics on
fields, where previously fields (not including deferred fields) were always
immutable. Either you are loading a new instance from the database, or you
are mutating a python value and re-serializing it to the database format.
You never have to reconcile python mutations with database mutations. Even
deferred fields have only one allowed mutation - from uninitialized to
initialized.

Best,
Alex Ogier

-- 
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: reconsider re-opening ticket 901

2013-05-14 Thread Tim Chase
On 2013-05-14 10:43, Alex Ogier wrote:
> What happens in the following case?
> 
> a = A(dict_field={"hello": "world"})
> d = a.dict_field
> a.save()
> a.refresh()
> d["hello"] = "planet"# does this mutate a.dict_field? does the
> answer change if somebody changed the database in between saving
> and refreshing?

I'd expect the same as the stdlib's pickle module:  when you load an
object from a pickled stream (what I'd consider analogous to
the .refresh() topic at hand), you create a new object.  So "d" would
still reference the original dict_field, while the a.dict_field would
contain a new dict object that doesn't contain "hello" as a key.

It is easy to explain, consistent with the stdlib, and unlikely to
harbor strange edge conditions once you understand what it's doing.
It also allows for doing things like

  d = a.dict_field
  a.save()
  # semi-lengthy-process
  a.refresh()
  if a.dict_field != d:
somebody_changed_something_while_we_were_occupied("!!!")

Prudent? Maybe, maybe not.  Believable? sure.  But if "d"
auto-updates upon refresh, there's no easy way to make this test
(short of doing a deep-copy of "d" to preserve it).

I think DB-trumps-local is pretty sensible in both cases you describe
(above, and the OneToOne), that if you reload, you get what the DB
tells you and you're responsible for refreshing any internal
references you have reaching into the object.  As our preschooler has
learned, "you get what you get, and you don't throw a fit." :-)

-tkc




-- 
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: reconsider re-opening ticket 901

2013-05-14 Thread Anssi Kääriäinen
On 14 touko, 18:07, Tim Chase  wrote:
> On 2013-05-14 10:43, Alex Ogier wrote:
>
> > What happens in the following case?
>
> > a = A(dict_field={"hello": "world"})
> > d = a.dict_field
> > a.save()
> > a.refresh()
> > d["hello"] = "planet"    # does this mutate a.dict_field? does the
> > answer change if somebody changed the database in between saving
> > and refreshing?
>
> I'd expect the same as the stdlib's pickle module:  when you load an
> object from a pickled stream (what I'd consider analogous to
> the .refresh() topic at hand), you create a new object.  So "d" would
> still reference the original dict_field, while the a.dict_field would
> contain a new dict object that doesn't contain "hello" as a key.
>
> It is easy to explain, consistent with the stdlib, and unlikely to
> harbor strange edge conditions once you understand what it's doing.
> It also allows for doing things like
>
>   d = a.dict_field
>   a.save()
>   # semi-lengthy-process
>   a.refresh()
>   if a.dict_field != d:
>     somebody_changed_something_while_we_were_occupied("!!!")
>
> Prudent? Maybe, maybe not.  Believable? sure.  But if "d"
> auto-updates upon refresh, there's no easy way to make this test
> (short of doing a deep-copy of "d" to preserve it).
>
> I think DB-trumps-local is pretty sensible in both cases you describe
> (above, and the OneToOne), that if you reload, you get what the DB
> tells you and you're responsible for refreshing any internal
> references you have reaching into the object.  As our preschooler has
> learned, "you get what you get, and you don't throw a fit." :-)

IMO we should always create new instances for mutable field values.
Else we are in for huge amount of complexity. An exception is cached
related instances. For those an useful optimization is to not throw
them away if the related object's local id hasn't changed. The user
can refresh() the related instances if need be, but there is no way to
keep them if they are automatically thrown out... And if the local id
has changed, then the local cached value + the remote cached value for
reverse o2o field should be cleared. Next access will fetch a fresh
object from DB, but refresh() itself wont do that.

As for how to implement the feature on technical level: I think we
will need to go through get() of new instance and then either direct
assignment to __dict__ for each fetched field, or use setattr() for
each fetched field. Getting a new instance is a good idea so that pre/
post_init signals are called (some fields rely on those). Direct
__dict__ assignment is what deferred field loading does currently so
that might be better idea than setattr(). And setattr() was already
called, but for different instance.

We should likely try to rely less on __init__ in general, and have a
different path for model instance creation when loading from DB.
Direct assignment to the object's __dict__ would make DB loading work
more like unpickle. See https://code.djangoproject.com/ticket/19501
for details.

 - Anssi

-- 
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-14 Thread Sam Solomon
As an outsider with very little data (so you can ignore this if you 
strongly disagree), I sort of agree with the notion that "WONTFIX" could be 
sending a different signal that it is being used for.

WONTFIX to me would mean, "We acknowledge that this is an annoyance for 
some people, but we're not going to fix it no matter what you or anyone 
else says".

Maybe a compromise is using a variation on the same terminology but 
softening it to "PROBABLYWONTFIX" when it's something that you don't think 
is a serious problem but could theoretically be swayed with a good proposal 
and other people stepping up to submit patches and fight for the feature.

"WONTFIX" would still be appropriate for firm "no, never, this isn't just a 
poorly stated proposal, it's either too difficult or is actually counter to 
our overall goals even though it is a valid 'issue'".

Some references of WONTFIX in the wild/in other contexts/discussions:

http://contribute.jquery.org/wont-fix/

http://wiki.eclipse.org/Development_Resources/HOWTO/Bugzilla_Use "WONTFIX 
is used for things that are valid requests, but that the team can't do"

http://programmers.stackexchange.com/questions/58950/defect-statuses-wont-fix-vs-cancelled




On Tuesday, May 14, 2013 3:56:26 AM UTC-7, Daniele Procida wrote:
>
> On Mon, May 13, 2013, Łukasz Rekucki > 
> wrote: 
>
> >> The status WONTFIX sounds awfully rude to me. It's like saying "That's 
> a 
> >> pony and you can't have one, ever." It implies a terminal finality 
> which 
> >> actually isn't meant in some cases, because it is possible (as we've 
> seen) 
> >> and even sometimes recommended by a core developer, for a sufficiently 
> >> determined person to push for change on the mailing list and make it 
> happen. 
> >> 
> > 
> >You can blame this on my lack of social skills, but I really don't see 
> how 
> >it's rude. 
>
> Maybe it's not rude, but it is off-putting. Perhaps there are some 
> proposals that really do deserve to have the door closed firmly in their 
> faces - that's what "WONTFIX" suggests to me, even if it's not what's 
> intended. 
>
> Daniele 
>
>

-- 
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-14 Thread Cal Leeming [Simplicity Media Ltd]
Hello all,

I just spent around 90 minutes reading through everyones comments (word for
word), and writing up a reply offering my two cents.

First off - a few years back someone introduced a 5-for-1 system where if
you triaged five other tickets, you could request for a core dev to give
detailed attention to any ticket of your choice. I think this is an
EXCELLENT way of giving something back to the community, keeping the ticket
queue down, and getting the results that you need.

>From core devs point of view - Posting a discussion to django-developers
and raising a ticket in Trac are not for the lighthearted. If you want
something in the core, you better have a good argument for it and be
prepared to follow it through to the bitter end. If you simply post a
suggestion without justification, then you can't expect the core dev to
sign it off, they are not mind readers. It's also generally accept that
although the core devs are polite, they will give you their brutally honest
truth which can sometimes be misinterpreted as rudeness. The core devs are
not here to be friendly, they are here to keep Django alive.

>From users point of view - One of the responses from the core developers
was, look if you want this feature, help us make it happen. But the
majority of users are not familiar with the internals of how Django works,
and would find it difficult to contribute the quality of code (if at all)
required for inclusion into the core. Sometimes people want to help and
contribute, but the process can be confusing and engaging with the core
devs in a discussion can often be a frustrating thing for those who are new
to the world of open source contributions.

However, Tom raises a very good point when he said "why should I waste my
time trying to jump through these arbitrary hoops? The short answer is I
don't, I work on my own
projects". Personally, I have become extremely frustrated at some of the
decisions and lack of attention being shown on some of these tickets in the
past. But it could also be argued that I should have stood my ground and
put forward a solid argument.

Yo-Yo Ma raises an important point of "The burden of proof is on the
originator of an idea", and this is in-line with my above comments. Shai
also raises a good point, that core devs time is scarce and often would
like some other people to give tickets a flick over before going back to
it.. core devs do not have time to give each ticket their full attention.
Imho, if you want the extra time, you have to earn it (either in
contributing, or putting forward a solid argument). Look at it like this,
for every 5 minutes you put in, you can get back roughly 1 minute from a
core dev (YMMV).

I think really this all comes down to a lack of understand about the Django
etiquette, and users feeling like the core devs are not really giving them
the attention they expected.

Therefore, I propose the following recommendations;

* Make the 5-for-1 (or 10-for-1) system official, not many people seem to
realise this exists. This will give incentive to core devs to spend a bit
longer on a ticket, maybe even throwing in a pleasentry or two (optional).
I often found that if I assisted with other tickets and showed myself to be
proactive on the ML, then my tickets would usually get the attention of a
core dev faster and/or with more detailed response.

* Explain what wontfix means to users, and what they can do to change it
(without having to read page after page of contribution instructions).
Perhaps some sort of automated response that explains all this, and points
the user to the mailing list. Until Kirby explained what wontfix meant a
few posts back, I had assumed it meant "this is not acknowledged".

To summarize my thoughts in a simple bullet point list;

* Core devs are not here to be friendly, expect polite yet brutal honesty,
with no pleasantries.
* If you want 5 minutes of core dev time, spend 1 hour triaging tickets and
link with proof (5-for-1).
* Trac could be so much better
* Explain what wontfix means to users, and that they need to present a
solid argument with proof to get it looked at again

Cal

On Fri, May 10, 2013 at 6:00 PM, Simon  wrote:

> Hi,
>
> When I started using Python a couple of months ago, a quick Google for
> frameworks turned up a lot of results for Django so I decided to give it a
> spin.
>
> I'd like to give some feedback on my experience to date. There are a lot
> of features I really love, some that are a little quirky and some that are
> downright inflexible. None of this will be news - it's the same for every
> framework. That said, I started to have doubts when I was attempting to
> find solutions/workarounds to the problems I encountered.
>
> Today was the 5th or 6th time that I've ended up at the ticket system and
> seen people saying "This would really help me" and a core developer saying
> "I don't see the need" (rather arbitrarily IMHO) and closing as wontfix.
> This is invariably followed by people asking for reconsi

djangoproject.com is down

2013-05-14 Thread Jacob Kaplan-Moss
FYI - djangoproject.com is currently down, I'm investigating and I'll
try to have it back up ASAP.

In the meantime, if you need to get to the docs, you can hit up the
ReadTheDocs mirror: http://django.rtfd.org/

Thanks for your patience,

Jacob

-- 
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: djangoproject.com is down

2013-05-14 Thread Jacob Kaplan-Moss
Hi folks -

Looks like we're back.

FTR, the cause was an issue with our hosting provider, more here:
http://status.mediatemple.net/maintenances/3148-emergency-maintenance-multiple-dvve-hostservers-rebooted/.
I'm going to look into adding a bit more redundancy so that we're more
resilient against any future outages like this.

Thanks for your patience!

Jacob

On Tue, May 14, 2013 at 5:53 PM, Jacob Kaplan-Moss  wrote:
> FYI - djangoproject.com is currently down, I'm investigating and I'll
> try to have it back up ASAP.
>
> In the meantime, if you need to get to the docs, you can hit up the
> ReadTheDocs mirror: http://django.rtfd.org/
>
> Thanks for your patience,
>
> Jacob

-- 
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.