Re: [Python-Dev] How far to go with user-friendliness

2015-07-16 Thread ISAAC J SCHWABACHER
From: Python-Dev  on 
behalf of Ben Finney 
Sent: Thursday, July 16, 2015 15:59
To: python-dev@python.org
Subject: Re: [Python-Dev] How far to go with user-friendliness

> Ethan Furman  writes:
> 
> > On 07/16/2015 01:29 PM, Michael Foord wrote:
> > > On Tuesday, 14 July 2015, Christie Wilson wrote:
> >
> > >> Unless the line silently executes and they don't notice the mistake for 
> > >> years :'(
> > >
> > > Indeed. This has been a problem with mock, misspelled (usually 
> > > misremembered) assert methods silently did nothing.
> > >
> > > With this fix in place several failing tests were revealed in code bases!
> >
> > This is good.  :)
> 
> It's good that bugs were found. That does not argue for making an alias
> in the library, though; it better argues for those projects adding a
> linter check for the common misspellings.
> 
> > > As for assret, it's the common misspelling people have told me
> > > about. It seems a ridiculous thing for people to get worked up
> > > about, but people enjoy getting worked up.
> 
> Advocating for a clean API is ridiculous? That's a disturbing attitude
> to hear from a Python standard library contributor.
> 
> > On the serious side, Python is not a DWIM language, and making
> > accommodations for a misspelling feels very DWIMish. As I said in an
> > earlier email part of writing good tests is double-checking that a
> > test is failing (and for the right reasons). And yes, I am guilty of
> > writing bad tests, and getting bit by it, and no, I still don't want
> > the testing framework (or any part of Python) guessing what I meant.
> 
> +1.
> 
> These checks are a good thing, but they belong in a linter tool not as
> aliases in the API.

+1

> --
>  \  “You say “Carmina”, and I say “Burana”, You say “Fortuna”, and |
>   `\I say “cantata”, Carmina, Burana, Fortuna, cantata, Let's Carl |
> _o__)the whole thing Orff.” —anonymous |

+1 000 000

ijs
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Status on PEP-431 Timezones

2015-07-24 Thread ISAAC J SCHWABACHER
Well, I was going to stay silent, but math is something I can do without 
wasting anyone's time or embarrassing myself. I don't think this mail answers 
Lennart's concerns, but I do want to get it out there to compete with the 
comment in `datetime.py`. I apologize if the LaTeX density is too high; I don't 
trust that my e-mail client would transmit the message faithfully were I to 
render it myself.

I disagree with the view Tim had of time zones when he wrote that comment (and 
that code). It sounds like he views US/Eastern and US/Central as time zones 
(which they are), but thinks of the various America/Indiana zones as switching 
back and forth between them, rather than being time zones in their own right. I 
think the right perspective is that a time zone *is* the function that its 
`fromutc()` method implements, although of course we need additional 
information in order to actually compute (rather than merely mathematically  
define) its inverse. Daylight Saving Time is a red herring, and assumptions 2 
and 4 in that exposition are just wrong from this point of view. In the worst 
case, Asia/Riyadh's two years of solar time completely shatter these 
assumptions.

I'm convinced that the right viewpoint on this is to view local time and UTC 
time each as isomorphic to $\RR$ (i.e., effectively as UNIX timestamps, minus 
the oft-violated guarantee that timestamps are in UTC), and to consider the 
time zone as
    \[ fromutc : \RR \to \RR. \]
(Leap seconds are a headache for this perspective, but it can still support 
them with well-placed epicycles.) Then our assumptions (inspired by zoneinfo) 
about the nature of this map are as follows:

* $fromutc$ is piecewise defined, with each piece being continuous and strictly 
monotonic increasing.  Let us call the set of discontinuities $\{ utc_i \in \RR 
| i \in \ZZ \}$, where the labels are in increasing order, and define 
$fromutc_i$ to be the $i$-th  piece. (The theoretical treatment doesn't suffer 
if there are only finitely many discontinuities, since we can place additional 
piece boundaries at will where no discontinuities exist; obviously, an 
implementation would not take this view.) 
* The piece $fromutc_i : [utc_i, utc_{i+1}) \to [local_{start, i}, local_{end, 
i})$ and its inverse, which we will call $fromlocal_i$, are both readily 
computable.  In particular, this means that $local_{start, i} = fromutc(utc_i)$ 
and $local_{end, i}$ is the limit of $fromutc(t)$ as $t$ approaches $utc_{i+1}$ 
from the left, and that these values are known.  Note that the (tzfile(5))[1] 
format and (zic(8)[2]) both assume that $fromutc_i$ is of the form $t \mapsto t 
+ off_i$, where $off_i$ is a constant.  This assumption is true in practice, 
but is stronger than we actually need.
* The sequences $\{ local_{start, i} | i \in \ZZ \}$ and $\{ local_{end, i} | i 
\in \ZZ \}$ are strictly increasing, and $local_{end, i-1} < local_{start, 
i+1}$ for all $i \in \ZZ$.  This final condition is enough to guarantee that 
the preimage of any local time under $fromutc$ contains at most two UTC times.  
This assumption would be violated if, for example, some jurisdiction decided to 
fall back two hours by falling back one hour and then immediately falling back 
a second hour.  I recommend the overthrow of any such jurisdiction and its 
(annexation by the Netherlands)[3].

Without the third assumption, it's impossible to specify a UTC time by a (local 
time, time zone, DST flag) triple since there may be more than two UTC times 
corresponding to the same local time, and computing $fromlocal$ becomes more 
complicated, but the problem can still be solved by replacing the DST flag by 
an index into the preimage.  (Lennart, I think this third assumption is the 
important part of your "no changes within 48 hours of each other" assumption, 
which is violated by Asia/Riyadh. Is it enough?)

Once we take this view, computing $fromutc(t)$ is trivial: find $i$ with $utc_i 
\le t < utc_{i+1}$ by binary search (presumably optimized to an $O(1)$ average 
case by using a good initial guess), and compute $fromutc_i(t)$.

Computing $fromlocal(t)$ is somewhat more difficult.  The first thing to 
address is that, as written, $fromlocal$ is not a function; in order to make it 
one, we need to pass it more information.  We could define $fromlocal(t, i) = 
fromlocal_i(t)$, but that's too circular to be useful.  Likewise with my 
(silly) earlier proposal to store $(local, offset)$ pairs-- then $fromlocal(t, 
off) = t - off$.  What we really need is a (partial, which is better than 
multi-valued!) function $fromlocal : \RR \times \{True, False\} \to \RR$ that 
takes a local time and a DST flag and returns a UTC time.  We define 
$fromlocal(local, flag)$ to be the first $utc \in \RR$ such that $fromutc(utc) 
= local$ when $flag$ is $True$ and the last such $utc$ when $flag$ is $False$.  
(Our implementation will presumably also allow $flag$ to be $None$, in which 
case we require $utc$ to be unique.)

Re: [Python-Dev] Status on PEP-431 Timezones

2015-07-24 Thread ISAAC J SCHWABACHER
> From: Tim Peters 
> Sent: Saturday, July 25, 2015 00:14
> To: ISAAC J SCHWABACHER
> Cc: Alexander Belopolsky; Lennart Regebro; Python-Dev
> Subject: Re: [Python-Dev] Status on PEP-431 Timezones

> [Tim]
> >> The formulas only produced approximations, and then
> >> rounded to 5-second boundaries because the tz data format didn't have
> >> enough bits.

> [ISAAC J SCHWABACHER ]
> > Little known fact: if you have a sub-minute-resolution UTC offset when a
> > leap second hits, it rips open a hole in the space-time continuum and
> > you find yourself in New Netherlands.

> Tell me about it!  Last time that happened I had to grow stinking
> tulips for 3 years to get enough money to sail back home.  I'll never
> use a sub-minute-resolution UTC offset again ;-)

I meant this one: https://what-if.xkcd.com/54/ :)

ijs
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Status on PEP-431 Timezones

2015-07-24 Thread ISAAC J SCHWABACHER
> The formulas only produced approximations, and then
> rounded to 5-second boundaries because the tz data format didn't have
> enough bits.

Little known fact: if you have a sub-minute-resolution UTC offset when a leap 
second hits, it rips open a hole in the space-time continuum and you find 
yourself in New Netherlands.

ijs


From: Tim Peters 
Sent: Saturday, July 25, 2015 00:07
To: ISAAC J SCHWABACHER
Cc: Alexander Belopolsky; Lennart Regebro; Python-Dev
Subject: Re: [Python-Dev] Status on PEP-431 Timezones

[Tim]
> Sure.  But, honestly, who cares?  Riyadh Solar Time was so
> off-the-wall that even the Saudis gave up on it 25 years ago (after a
> miserable 3-year experiment with it).  "Practicality beats purity".

Heh.  It's even sillier than that - the Saudis never used "Riyadh
Solar Time", and it's been removed from release 2015e of the tz
database:

https://www.ietf.org/timezones/data/NEWS
Release 2015e - 2015-06-13 10:56:02 -0700
...
The files solar87, solar88, and solar89 are no longer distributed.
They were a negative experiment - that is, a demonstration that
tz data can represent solar time only with some difficulty and error.
Their presence in the distribution caused confusion, as Riyadh
civil time was generally not solar time in those years.

Looking back, Paul Eggert explained more in 2013, but it took this
long for the patch to land:

http://comments.gmane.org/gmane.comp.time.tz/7717
> did Saudi Arabia really use this as clock time?

Not as far as I know, for civil time.  There was some use
for religious purposes but it didn't use the approximation
in those files.

These files probably cause more confusion than they're worth,
so I'll propose a couple of patches to remove them, in two followup
emails.  I haven't pushed these patches to the experimental
github version.

The position of the sun is vital to establishing prayer times in
Islam, but that's got little to do with civil time in Islamic
countries.  And Olson didn't take his "Riyadh Solar Time" rules from
the Saudis, he made up the times himself:  "Times were computed using
formulas in the U.S. Naval Observatory's Almanac for Computers
1987[89]".  The formulas only produced approximations, and then
rounded to 5-second boundaries because the tz data format didn't have
enough bits.

So, as a motivating example, it's hard to get less compelling:  Riyadh
Solar is a wholly artificial "time zone" made up by a time zone wonk
to demonstrate some limitations of the tz database he maintained.
Although I expect he could have done so just as effectively by writing
a brief note about it ;-)
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Status on PEP-431 Timezones

2015-07-25 Thread ISAAC J SCHWABACHER
> From: Tim Peters 
> Sent: Friday, July 24, 2015 20:39
> To: ISAAC J SCHWABACHER
> Cc: Alexander Belopolsky; Lennart Regebro; Python-Dev
> Subject: Re: [Python-Dev] Status on PEP-431 Timezones
>
> [ISAAC J SCHWABACHER ]
> > ...
> > I disagree with the view Tim had of time zones when he wrote that comment
> > (and that code). It sounds like he views US/Eastern and US/Central as time
> > zones (which they are), but thinks of the various America/Indiana zones as
> > switching back and forth between them, rather than being time zones in their
> > own right
>
> You can think of them anyway you like.  The point of the code was to
> provide a simple & efficient way to convert from UTC to local time in
> all "time zones" in known actual use at the time; the point of the
> comment was to explain the limitations of the code.  Although, as
> Allexander noted, the stated assumptions are stronger than needed.
>
> > I think the right perspective is that a time zone *is* the function that its
> > `fromutc()` method implements,
>
> Fine by me ;-)

My issue is that you're computing `fromutc()`, which is a function, in terms of 
`dst()` and `utcoffset()`, which aren't. I think this is backwards; `dst()` and 
`utcoffset()` should be computed from `fromutc()` plus some additional 
information that has to be present anyway in order to implement `fromutc()`. 
With the extra bit, `dst()` and `utcoffset()` become partial functions, which 
makes it *possible* to get the right answer in all cases, but it's still 
simpler to start with the total function and work from there.

> > although of course we need additional information in order to actually
> > compute (rather than merely mathematically define) its inverse. Daylight 
> > Saving
> > Time is a red herring,
>
> Overstated.  DST is in fact the _only_ real complication in 99.99% of
> time zones (perhaps even 99.9913% ;-) ).  As the docs say, if you have
> some crazy-ass time zone in mind, fine, that's why fromutc() was
> exposed (so your; crazy-ass tzinfo class can override it).

I stand by what I meant by this, even if I did a bad job of expressing the 
point. Assuming that all time zone discontinuities are due to DST changes 
breaks many time zones (really almost all of the Olson time zones, though only 
for a vanishingly small fraction of datetimes), but that's not the point I was 
making. The point is that it doesn't buy us anything. Though this is probably 
obscured by all the markup, the more general algorithm I gave is also simpler 
than the one in the comment in datetime.py, and the reason for that is that it 
solves an easier problem, but one that serves our practical purposes just as 
well.

> > and assumptions 2 and 4
>
> Nitpick:  4 is a consequence of 2, not an independent assumption.
>
> > in that exposition are just wrong from this point of view.
>
> As above, there is no particular POV in this code:  just a specific
> fromutc() implementation, comments that explain its limitations, and
> an invitation in the docs to override it if it's not enough for your
> case.

I went too far in inferring your viewpoint from your code.  I don't find fault 
with the explanation on its own terms. But adding zoneinfo to the stdlib, as 
PEP 431 proposes to do, requires making weaker assumptions and asking a 
different question than the one answered in the comment. 

> > In the worst case, Asia/Riyadh's two years of solar time completely shatter
> > these assumptions.
>
> Sure.  But, honestly, who cares?  Riyadh Solar Time was so
> off-the-wall that even the Saudis gave up on it 25 years ago (after a
> miserable 3-year experiment with it).  "Practicality beats purity".

As a mathematician at heart, I have a deep and abiding conviction, which I 
expect nobody else to share, that purity begets practicality in the long run. 
At least if you've found the right abstraction.

> > [eliding a more-general view of what time zones "really" are]

[note for people just joining this conversation: I think the information in the 
elision is critical to understanding what I'm talking about]

> I'm not eliding it because I disagree with it, but because time zones
> are political constructions.  "The math" we make up may or may not be
> good enough to deal with all future political abominations; for
> example:
>
> > ...
> > This assumption would be violated if, for example, some jurisdiction
> > decided to fall back two hours by falling back one hour and then
> > immediately falling back a second hour.  I recommend the overthrow
> > of any such jurisdiction and its (annexation by the Netherlands)[3].
>
> That's not objectively any more bizarr

Re: [Python-Dev] Status on PEP-431 Timezones

2015-07-27 Thread ISAAC J SCHWABACHER
Responses to several partial messages follow.

[Lennart Regebro]
> Then we can't implement timezones in a reasonable way with the current
> API, but have to have something like pytz's normalize() function or
> similar.
>
> I'm sorry I've wasted everyones time with this PEP.

[ijs]
I think that integrating pytz into the stdlib, which is what the PEP proposes, 
would be valuable even without changing datetime arithmetic. But I see ways to 
accomplish the latter without breaking backward compatibility. The dream ain't 
dead! See below.

[Paul Moore]
> 2. Arithmetic within a complex timezone. Theoretically, this is simple
> enough (convert to UTC, do the calculation naively, and convert back).
> But in practice, that approach doesn't always match user expectations.
> So you have 2 mutually incompatible semantic options - 1 day after 4pm
> is 3pm the following day, or adding 1 day adds 25 hours - either is a
> viable choice, and either will confuse *some* set of users. This, I
> think, is the one where all the debate is occurring, and the one that
> makes my head explode.

> It seems to me that the problem is that for this latter issue, it's
> the *timedelta* object that's not rich enough.

[ijs]
Yes! This is the heart of the matter. We can solve *almost* all the problems by 
having multiple competing timedelta classes-- which we already have. Do you 
care about what will happen after a fixed amount of elapsed time? Use 
`numpy.timedelta64` or `pandas.Timedelta`. Want this time tomorrow, come hell, 
high water, or DST transition? Use `dateutil.relativedelta.relativedelta` or 
`mx.DateTime.RelativeDateTime`. As long as the timedelta objects we're using 
are rich enough, we can make `dt + delta` say what we mean. There's no reason 
we can't have both naive and aware arithmetic in the stdlib at once.

All the stdlib needs is an added timedelta class that represents elapsed atomic 
clock time, and voila!

The biggest problem that this can't solve is subtraction. Which timedelta type 
do you get by subtracting two datetimes? Sure, you can have a 
`datetime.elapsed_since(self, other: datetime, **kwargs) -> 
some_timedelta_type` that determines what you want from the kwargs, but 
`datetime.__sub__` doesn't have that luxury. I think the right answer is that 
subtraction should yield the elapsed atomic clock time, but that would be a 
backward-incompatible change so I don't put a high probability on it happening 
any time soon. See the last message (below) for more on this.

> You can't say "add 1
> day, and by 1 day I mean keep the same time tomorrow" as opposed to
> "add 1 day, and by that I mean 24 hours"[1]. In some ways, it's
> actually no different from the issue of adding 1 month to a date
> (which is equally ill-defined, but people "know what they mean" to
> just as great an extent). Python bypasses the latter by not having a
> timedelta for "a month". C (and the time module) bypasses the former
> by limiting all time offsets to numbers of seconds - datetime gave us
> a richer timedelta object and hence has extra problems.

Because of the limits on the values of its members, `datetime.timedelta` is 
effectively just a counter of microseconds. It can't distinguish between 1 day, 
24 hours, 1440 minutes or 86400 seconds. They're all normalized to the same 
value. So it's not actually richer; it only appears so.

> I don't have any solutions to this final issue. But hopefully the
> above analysis (assuming it's accurate!) helps clarify what the actual
> debate is about, for those bystanders like me who are interested in
> following the discussion. With luck, maybe it also gives the experts
> an alternative perspective from which to think about the problem - who
> knows?
>
> Paul
>
> [1] Well, you can, actually - you say that a timedelta of "1 day"
> means "the same time tomorrow" and if you want 24 hours, you say "24
> hours" not "1 day". So timedelta(days=1) != timedelta(hours=24) even
> though they give the same result for every case except arithmetic
> involving complex timezones. Is that what Lennart has been trying to
> say in his posts?

I thought for a long time that this would be sufficient, and I still think it's 
a good spelling that makes it clear what the user wants most of the time, but I 
have wanted things like "the first time the clock shows 1 hour later than it 
shows right now" enough times that I no longer think this is quite sufficient. 
(I *think* you can do that with `dt + 
dateutil.relativedelta.relativedelta(hour=dt.hour+1, minute=0, second=0, 
microsecond=0)`, but I'm not sure.)

[Tim Peters]
> Ah, but it already happens that way - because the builtin datetime
> arithmetic is "naive".  The docs have always promised this:
>
> """
> datetime2 = datetime1 + timedelta (1)
> datetime2 = datetime1 - timedelta (2)
>
> 1) datetime2 is a duration of timedelta removed from datetime1, moving
> forward in time if timedelta.days > 0, or backward if timedelta.days <
> 0. The result has the same tzinfo at

Re: [Python-Dev] PEP-498: Literal String Formatting

2015-08-10 Thread ISAAC J SCHWABACHER
I don't know about you, but I sure like this better than what you have:

code.putlines(f"""
static char {entry.doc_cname}[] = "{
split_string_literal(escape_bytestring(docstr))}";

{ # nested!
f"""
#if CYTHON_COMPILING_IN_CPYTHON
struct wrapperbase {entry.wrapperbase_cname};
#endif
""" if entry.is_special else ''}

{(lambda temp, argn: # my kingdom for a let!
f"""
for ({temp}=0; {temp} on 
behalf of Stefan Behnel 
Sent: Sunday, August 9, 2015 04:53
To: python-dev@python.org
Subject: Re: [Python-Dev] PEP-498: Literal String Formatting

Stefan Behnel schrieb am 09.08.2015 um 10:06:
> Eric V. Smith schrieb am 08.08.2015 um 03:39:
>> Following a long discussion on python-ideas, I've posted my draft of
>> PEP-498. It describes the "f-string" approach that was the subject of
>> the "Briefer string format" thread. I'm open to a better title than
>> "Literal String Formatting".
>>
>> I need to add some text to the discussion section, but I think it's in
>> reasonable shape. I have a fully working implementation that I'll get
>> around to posting somewhere this weekend.
>>
>> >>> def how_awesome(): return 'very'
>> ...
>> >>> f'f-strings are {how_awesome()} awesome!'
>> 'f-strings are very awesome!'
>>
>> I'm open to any suggestions to improve the PEP. Thanks for your feedback.
>
> [copying my comment from python-ideas here]
>
> How common is this use case, really? Almost all of the string formatting
> that I've used lately is either for logging (no help from this proposal
> here) or requires some kind of translation/i18n *before* the formatting,
> which is not helped by this proposal either.

Thinking about this some more, the "almost all" is actually wrong. This
only applies to one kind of application that I'm working on. In fact,
"almost all" of the string formatting that I use is not in those
applications but in Cython's code generator. And there's a *lot* of string
formatting in there, even though we use real templating for bigger things
already.

However, looking through the code, I cannot see this proposal being of much
help for that use case either. Many of the values that get formatted into
the strings use some kind of non-trivial expression (function calls, object
attributes, also local variables, sometimes variables with lengthy names)
that is best written out in actual code. Here are some real example snippets:

code.putln(
'static char %s[] = "%s";' % (
entry.doc_cname,
split_string_literal(escape_byte_string(docstr

if entry.is_special:
code.putln('#if CYTHON_COMPILING_IN_CPYTHON')
code.putln(
"struct wrapperbase %s;" % entry.wrapperbase_cname)
code.putln('#endif')

temp = ...
code.putln("for (%s=0; %s < PyTuple_GET_SIZE(%s); %s++) {" % (
temp, temp, Naming.args_cname, temp))
code.putln("PyObject* item = PyTuple_GET_ITEM(%s, %s);" % (
Naming.args_cname, temp))

code.put("%s = (%s) ? PyDict_Copy(%s) : PyDict_New(); " % (
self.starstar_arg.entry.cname,
Naming.kwds_cname,
Naming.kwds_cname))
code.putln("if (unlikely(!%s)) return %s;" % (
self.starstar_arg.entry.cname, self.error_value()))

We use %-formatting for historical reasons (that's all there was 15 years
ago), but I wouldn't switch to .format() because there is nothing to win
here. The "%s" etc. place holders are *very* short and do not get in the
way (as "{}" would in C code templates). Named formatting would require a
lot more space in the templates, so positional, unnamed formatting helps
readability a lot. And the value expressions used for the interpolation
tend to be expressions rather than simple variables, so keeping those
outside of the formatting strings simplifies both editing and reading.

That's the third major real-world use case for string formatting now where
this proposal doesn't help. The niche is getting smaller.

Stefan


___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/ischwabacher%40wisc.edu
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP-498: Literal String Formatting

2015-08-11 Thread ISAAC J SCHWABACHER
Now with syntax highlighting, if my email client cooperates:

code.putlines(f"""
static char {entry.doc_cname}[] = "{
split_string_literal(escape_bytestring(docstr))}";

{ # nested!
f"""
#if CYTHON_COMPILING_IN_CPYTHON
struct wrapperbase {entry.wrapperbase_cname};
#endif
""" if entry.is_special else ''}

{(lambda temp, argn: # my kingdom for a let!
f"""
for ({temp}=0; {temp} on 
behalf of Stefan Behnel 
Sent: Sunday, August 9, 2015 04:53
To: python-dev@python.org
Subject: Re: [Python-Dev] PEP-498: Literal String Formatting

Stefan Behnel schrieb am 09.08.2015 um 10:06:
> Eric V. Smith schrieb am 08.08.2015 um 03:39:
>> Following a long discussion on python-ideas, I've posted my draft of
>> PEP-498. It describes the "f-string" approach that was the subject of
>> the "Briefer string format" thread. I'm open to a better title than
>> "Literal String Formatting".
>>
>> I need to add some text to the discussion section, but I think it's in
>> reasonable shape. I have a fully working implementation that I'll get
>> around to posting somewhere this weekend.
>>
>> >>> def how_awesome(): return 'very'
>> ...
>> >>> f'f-strings are {how_awesome()} awesome!'
>> 'f-strings are very awesome!'
>>
>> I'm open to any suggestions to improve the PEP. Thanks for your feedback.
>
> [copying my comment from python-ideas here]
>
> How common is this use case, really? Almost all of the string formatting
> that I've used lately is either for logging (no help from this proposal
> here) or requires some kind of translation/i18n *before* the formatting,
> which is not helped by this proposal either.

Thinking about this some more, the "almost all" is actually wrong. This
only applies to one kind of application that I'm working on. In fact,
"almost all" of the string formatting that I use is not in those
applications but in Cython's code generator. And there's a *lot* of string
formatting in there, even though we use real templating for bigger things
already.

However, looking through the code, I cannot see this proposal being of much
help for that use case either. Many of the values that get formatted into
the strings use some kind of non-trivial expression (function calls, object
attributes, also local variables, sometimes variables with lengthy names)
that is best written out in actual code. Here are some real example snippets:

code.putln(
'static char %s[] = "%s";' % (
entry.doc_cname,
split_string_literal(escape_byte_string(docstr

if entry.is_special:
code.putln('#if CYTHON_COMPILING_IN_CPYTHON')
code.putln(
"struct wrapperbase %s;" % entry.wrapperbase_cname)
code.putln('#endif')

temp = ...
code.putln("for (%s=0; %s < PyTuple_GET_SIZE(%s); %s++) {" % (
temp, temp, Naming.args_cname, temp))
code.putln("PyObject* item = PyTuple_GET_ITEM(%s, %s);" % (
Naming.args_cname, temp))

code.put("%s = (%s) ? PyDict_Copy(%s) : PyDict_New(); " % (
self.starstar_arg.entry.cname,
Naming.kwds_cname,
Naming.kwds_cname))
code.putln("if (unlikely(!%s)) return %s;" % (
self.starstar_arg.entry.cname, self.error_value()))

We use %-formatting for historical reasons (that's all there was 15 years
ago), but I wouldn't switch to .format() because there is nothing to win
here. The "%s" etc. place holders are *very* short and do not get in the
way (as "{}" would in C code templates). Named formatting would require a
lot more space in the templates, so positional, unnamed formatting helps
readability a lot. And the value expressions used for the interpolation
tend to be expressions rather than simple variables, so keeping those
outside of the formatting strings simplifies both editing and reading.

That's the third major real-world use case for string formatting now where
this proposal doesn't help. The niche is getting smaller.

Stefan


___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/ischwabacher%40wisc.edu
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP-498: Literal String Formatting

2015-08-12 Thread ISAAC J SCHWABACHER
Ruby already has this feature, and in my experience syntax highlighters handle 
it just fine.  Here's what vim's default highlighter shows me:

puts "we can #{
["include", "interpolate"].each { |s| puts s }
  .select { |s| s.include? "erp" }
#  .first
} arbitrary expressions!"

So an editor whose syntax highlighting is based on regular expressions already 
can't cope with the world as it is.  :)

Does anyone reading this know of a tool that successfully highlights python but 
not ruby?

ijs


From: Python-Dev  on 
behalf of Greg Ewing 
Sent: Tuesday, August 11, 2015 18:34
To: python-dev@python.org
Subject: Re: [Python-Dev] PEP-498: Literal String Formatting

Stefan Behnel wrote:
> Syntax highlighting and in-string expression completion should eventually
> help, once IDEs support it.

Concerning that, this is going to place quite a
burden on syntax highlighters. Doing it properly
will require the ability to parse arbitrary Python
expressions, or at least match nested brackets. An
editor whose syntax hightlighting engine is based
on regular expressions could have trouble with
that.

--
Greg

___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/ischwabacher%40wisc.edu
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP-498: Literal String Formatting

2015-08-13 Thread ISAAC J SCHWABACHER
Well, I seem to have succeeded in crystallizing opinions on the topic, even if 
the consensus is, "Augh! Make it stop!" :)

The primary objective of that code sample was to make the structure of the code 
as close as possible to the structure of the interpolated string, since having 
descriptive text like "{entry.doc_cname}" inline instead of "%s" is precisely 
what str.format gains over str.__mod__.

But there are several different elements in that code, and I'm curious what 
people find most off-putting. Is it the triple quoted format strings? The 
nesting? The interpolation with `"""...""" if cond else ''`? Just plain 
interpolations as are already available with str.format, but without explicitly 
importing names into the format string's scope via **kwargs? Trying to emulate 
let? Would a different indentation scheme make things better, or is this a 
problem with the coding style I've advanced here, or with the feature itself?

Also, should this be allowed:

def make_frob(foo):
def frob(bar):
f"""Frob the bar using {foo}"""

?

ijs

P.S.: I've translated the original snippet into ruby here: 
https://gist.github.com/ischwabacher/405afb86e28282946cc5, since it's already 
legal syntax there.

Ironically, github's syntax highlighting either fails to parse the 
interpolation (in edit mode) or fails to treat the heredoc as a string literal 
(in display mode), but you can open it in your favorite editor to see whether 
the highlighting makes the code clearer.


From: Python-Dev  on 
behalf of Ethan Furman 
Sent: Wednesday, August 12, 2015 18:11
To: python-dev@python.org
Subject: Re: [Python-Dev] PEP-498: Literal String Formatting

On 08/10/2015 04:05 PM, ISAAC J SCHWABACHER wrote:

> I don't know about you, but I sure like this better than what you have:
>
> code.putlines(f"""
> static char {entry.doc_cname}[] = "{
>  split_string_literal(escape_bytestring(docstr))}";
>
> { # nested!
> f"""
> #if CYTHON_COMPILING_IN_CPYTHON
>  struct wrapperbase {entry.wrapperbase_cname};
> #endif
> """ if entry.is_special else ''}
>
> {(lambda temp, argn: # my kingdom for a let!
> f"""
> for ({temp}=0; {temp}  PyObject *item = PyTuple_GET_ITEM({argn}, {temp});
> }}""")(..., Naming.args_cname)}
>
> {self.starstar_arg.entry.cname} =
>  ({Naming.kwds_cname}) ? PyDict_Copy({Naming.kwds_cname})
>: PyDict_New();
>
> if (unlikely(!{self.starstar_arg.entry.cname})) return {self.error_value()};
> """)
>
> What do others think of this PEP-498 sample?  (The PEP-501 version looks 
> pretty similar, so I omit it.)

Agh!  My brain is hurting!  ;)

No, I don't care for it at all.

--
~Ethan~
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/ischwabacher%40wisc.edu
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com