[Python-ideas] Re: Suggestion for behaviour change import mechanics

2019-10-29 Thread Ethan Furman

On 10/29/2019 06:33 AM, mer...@gmx.net wrote:


Anyways, just failing later would not hurt the Python language I think ;)


It would, as Stephen D'Aprano explained.

--
~Ethan~
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/W5TVS65UAMI4ES7XSLQNKWOZBDOIBKDC/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Suggestion for behaviour change import mechanics

2019-10-29 Thread Richard Vogel

I basically agree with many of your points. I have to admit that I am
likely to be biased from my view, since I got hindered by the current
behavior in that scenario. As you correctly stated,


 import module
 from module import name
 assert name is module.name

and


  from module import spam
  from module import eggs

things can become confusing, especially if you are reading the code as a
third person that doesn't know someone might have added stuff to path
resulting into this conflict. Actually I am surprised that someone
actually things it through that far and comes up out of the nothing with
those examples. Makes me already a bit happy ;)

However, I don't see where


 # Support many different versions of Python, or old versions
 # of the module, or drop-in replacement of the module.
 try:
 from module import name
 except ImportError:
 from fallback_module import spam as name

might change a actual thing.
Case 1: Lets say "module" does not exist -> both fail
Case 2: Exactly one "module" exists but it does not contain "name" ->
both fail
Case 3: Multiple "module" exist. At least one having "name" inside
    - Current Variant suceeds if and only if the first touched "module"
does contain "name", otherwise fail
    - Proposed Variant will fail if and only if NO "module" at all
contains "name"

    --> Why the first variant would be anyhow more correct than the
second? A later module could have the "name" which you actually wanted,
but you don't load it and falsly do a fallback

Still, I see in sum that this at best is a trade-off, which one could
argue pros and cons.

So lets take a step back and maybe agree that the "shadowing" behaviour
may come in unexpected also. The thing I made (which I right now changed
completely thanks to the discussions to a setup.py X pip install -e
solution that basically solves it) other people will do also. Given
you're not too familiar with development installs or python setup at
all, this is a thing you might not even know of or see as an unneeded
obstacle. Hence, you will do some supposedly straight-forward thing like
making your libs available in path. On top you might not even know that
some dependency of a dependencies dependency might shadow your imports
at all or tempers also with the path on its own.

To conclude that, without changing the behaviour, Python might at least
recognize such a shadowing case and spill out a warning if something
shadows something else (Like "Unreachable module") since it obviously
could find it out for example with your proposed import algorithm
variant. Someone then could actually google it, find the reasoning and
would stumple about ways to fix his/her presumably bad practice.

Thanks anyways for taking the time thinking through the implications
clarifying your points!

Am 29.10.2019 um 23:41 schrieb Steven D'Aprano:

On Tue, Oct 29, 2019 at 01:26:36PM -, mer...@gmx.net wrote:

Yes :)

That looks similiar to my problem, which i fixed for the moment of writing by 
renaming one folder.
Basically, I would prefer if Python would not treat nth-level import fails 
different than first-level fails.

I think you mean that you would prefer if Python *would* treat nth-level
import failures differently. If the first level fails, the import search
stops immediately and raises; you want the import search to continue if
the second level fails.



Might seem like a small thing, but in my opinion it would:
- keep the behaviour straight forward
- Correct the error messages, since from the perspective of the user the import 
actually DOES exist
- Does not break anything currently working
- Makes me happy ;)

I disagree with all but the last.

Think about the behaviour of ``from module import name`` in pure
Python. Currently, it is straightforward to explain:

 try to import module, or fail if it doesn't exist;
 name = module.name, or fail if the name doesn't exist.

With your behaviour, it becomes something complicated:

 try to import module, or fail if it doesn't exist;
 remember where we are in the module import search path;
 try to set name = module.name;
 if that succeeds, return;
 else go back to line 1, but picking up the search from
 where we left off.

Re your point 2, I'm a user, and from my perspective, if module.name
doesn't exist in the first module found, then it doesn't exist until I
move or rename one of the clashing modules. That's how shadowing works,
and I like it that way because it makes it easy to reason about what my
code will do.

But the critical point is #3. Any change in behaviour could break
working code, and this could too:


 # Support many different versions of Python, or old versions
 # of the module, or drop-in replacement of the module.
 try:
 from module import name
 except ImportError:
 from fallback_module import spam as name

Same for the similar idiom:

 try:
 from module import 

[Python-ideas] Re: Suggestion for behaviour change import mechanics

2019-10-29 Thread Andrew Barnert via Python-ideas
On Oct 29, 2019, at 15:05, Richard Vogel  wrote:
> 
> Nevertheless, could Python cache that spec and cache also a checksum of whats 
> coming out after resolveing the loader ? 
> 
Sure. In addition to sys.modules mapping names to modules you could have a 
similar dict mapping specs to modules. It might require some minor changes to 
specs, and I’m only about 80% sure specs have exactly the info needed in the 
first place, but otherwise it seems like it would work.

I don’t think you need the checksum for anything, but let’s come back to that; 
if you do, it’s obviously easy to add another dict, or change the first dict to 
map specs to (checksum, module) pairs, or whatever.

If you’re not changing any existing behavior to rely on this, only adding new 
behavior, that sounds feasible to me. But if you are changing existing behavior 
in a way that relies on this, that would break backward compatibility. Most 
obviously, any existing code that modifies sys.modules assumes that it doesn’t 
have to modify anything else, so whatever it was trying to do will probably no 
longer work. And other things currently guaranteed by the import system and 
relied on by code would also probably break. So you’d need a really compelling 
reason to force people to change all that code over the next 3 versions.
> So given that Python could recognize the case where you actually import 
> something similiar with a different loader spec (for example the case where 
> something in path is imported fully quallified and non fully qualified). 
> 
The point of the spec is that (I think) you’d get the same spec for importing 
spam.eggs and also importing eggs when they’re both the same file (or zip 
entry, or whatever).

And Python assumes that it doesn’t have to deal with module source changing in 
the middle of a run, except when you go explicitly behind the importer’s back 
(e.g., with importlib.reload).

So I think just the spec itself tells you whether two modules are “the same” in 
the relevant sense. So you don’t need a checksum, or anything else, there.

Meanwhile, if two different modules happen to have identical checksums—say, 
because a.py and b.py are both empty files—they’re still different things. So I 
don’t think you _want_ a checksum either.

Also, checksum of what? It’s obvious what to checksum for a module defined by a 
.py file (but you still have to work out how that gets cached with the .pyc 
files), and probably not hard for a .so file, but what’s the checksum of 
package directory? Or an extension module linked into the interpreter 
executable? At the very least you’d have to come up with a checksum function 
for each loader type (and require third-party loaders to do the same—breaking 
all existing ones).
> Given that Python could spill out a warning that this happened (also in your 
> circular case for example) and just do what it does now still.
> 
This makes sense. If a spec is already in the new spec-to-module dict, but the 
module’s qualified name doesn’t match the name we’re trying to import it as, 
warn. I think this could be done in a single place in importlib and just work. 
The backward compatibility problem wouldn’t affect as many things, and a 
warning isn’t as bad as an error or different behavior—but still, I’m not sure 
you could convince people that the benefit is worth that cost.

It’s worth looking at why similar warnings have been rejected for the circular 
__main__ issue in the past (which I don’t remember).
> Then a import keyword extension like *import twin ~~~* would explicitly do 
> what it does now anyways (Giving you the same thing in a different 
> realization, so basically just removing the warning in that case) and *import 
> union ~~~* which returns the same realization and removing the warning. This 
> would force the user into knowing what they do and give the user the chance 
> to see that such a thing happened and start thinking about what they actually 
> wanted to do in the first place.
> 
Well, new keywords need to jump a pretty high hurdle. Either this would break 
all code that used twin or union as ordinary identifiers (including the builtin 
set class), or they would have to be “contextual keywords” that are special 
only in specific grammar contexts, which have a lot of problems of their own. 
(For just one example, they make best-effort-pseudo-parser tools as used by 
IDEs and indexers and code coloring scripts a lot more complicated.)

What if, instead of new syntax, this were just a pair or magic modules, where 
you write `import twin.spam` or `from twin import spam`?

I’m not sure that actually covers all reasonable use cases. But if it does, I 
think this would be doable (although not easy for someone who doesn’t already 
know importlib pretty solidly). And, if so, it should be doable in a way that 
can be written as a third-party library and packaged on PyPI and probably work 
with all Python 3.4+. Then, if it gets lots of uptake from PyPI it would be a 
lot 

[Python-ideas] Re: Make itertools recipes license easier

2019-10-29 Thread Guido van Rossum
On Tue, Oct 29, 2019 at 3:37 PM Todd  wrote:

> I think you might be mixing up two different things.
>
> First is the text of the Pytjon-2.0 license.  I don't want to change that,
> or the text of any other license.
>
> Second is the LICENSE file.  That file includes the text of the Python-2.0
> license, the text of every other license used in the project, the history
> licenses, and some other brief information.  This is what I am suggesting
> we edit.
>

That may be how it's used in other projects, but in Python, even that file
is carefully crafted by lawyers whom I don't want to wake up, despite it
being nearly 20 years later.


> At the very least the LICENSE file, as I understand it, should contain the
> text of every license used (or say it is in a separate file) and a brief
> note about where it is used if it isn't the "default" license.  As I
> mentioned, the current file does exactly that.  So we would need to add the
> CC0 license text and at least a very brief explanation of why we added it.
>

I think that a license that is strictly *less* restrictive as one of the
licenses in that file doesn't need to be mentioned there, since if you
abide by *just* the contents of that file you're still going to be alright.
Adding the CC0 text to that file would just add to the confusion -- to what
exactly would it apply? People could misunderstand this as CC0 applying to
all of Python.


> Thinking about it a bit more, considering there is already a license
> history, I think this is a significant enough change that it should
> probably be mentioned somewhere in that history.
>

Huh, I think we may need to talk to a lawyer at this point.


> Of course the other stuff you mentioned should be done, too.  Does this
> sound reasonable?
>

Let me see if I can get Van Lindberg to give his opinion.

-- 
--Guido van Rossum (python.org/~guido)
*Pronouns: he/him **(why is my pronoun here?)*

___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/GMIRRC56RPHDSNQ75KNZQ466U3BE7KZY/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Suggestion for behaviour change import mechanics

2019-10-29 Thread Steven D'Aprano
On Tue, Oct 29, 2019 at 01:26:36PM -, mer...@gmx.net wrote:
> Yes :)
> 
> That looks similiar to my problem, which i fixed for the moment of writing by 
> renaming one folder.
> Basically, I would prefer if Python would not treat nth-level import fails 
> different than first-level fails. 

I think you mean that you would prefer if Python *would* treat nth-level 
import failures differently. If the first level fails, the import search 
stops immediately and raises; you want the import search to continue if 
the second level fails.


> Might seem like a small thing, but in my opinion it would:
> - keep the behaviour straight forward
> - Correct the error messages, since from the perspective of the user the 
> import actually DOES exist
> - Does not break anything currently working
> - Makes me happy ;)

I disagree with all but the last.

Think about the behaviour of ``from module import name`` in pure 
Python. Currently, it is straightforward to explain:

try to import module, or fail if it doesn't exist;
name = module.name, or fail if the name doesn't exist.

With your behaviour, it becomes something complicated:

try to import module, or fail if it doesn't exist;
remember where we are in the module import search path;
try to set name = module.name;
if that succeeds, return;
else go back to line 1, but picking up the search from 
where we left off.

Re your point 2, I'm a user, and from my perspective, if module.name 
doesn't exist in the first module found, then it doesn't exist until I 
move or rename one of the clashing modules. That's how shadowing works, 
and I like it that way because it makes it easy to reason about what my 
code will do.

But the critical point is #3. Any change in behaviour could break 
working code, and this could too:


# Support many different versions of Python, or old versions
# of the module, or drop-in replacement of the module.
try:
from module import name
except ImportError:
from fallback_module import spam as name

Same for the similar idiom:

try:
from module import name
except ImportError:
def name(arg):
# re-implement basic version as a fallback


I use those two idioms frequently. The last thing I want is for the 
behaviour of import to change, which would potentially change the 
behaviour above from what's tested and works to something which might 
pick up *the wrong module* from what I'm expecting it to pick up.

You are asking us to change the behaviour of import in the case of 
shadowing, to support a use-case which is (in my, and probably most 
peoples, opinion) very poor practice. That has some pretty surprising 
consequences:

 from module import spam
 from module import eggs

You would expect that spam and eggs both come from the same module, 
right? Surprise! No they don't, with your proposal they might come from 
different modules. That's going to play havok with debugging.

import module
from module import name
assert name is module.name

You would expect that assertion to be true, right? (Importing doesn't 
copy objects.) Surprise! The assertion can raise AttributeError: 
module.name might not exist even if ``from module import name`` 
succeeds.

I expect that with a bit more thought I could come up with some more 
scenarios where the behaviour of Python programs could change in very 
surprising ways.

So I will argue against this proposed change.


-- 
Steven
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/NC4EJDM7WPPIVK3ZGSQDPE3YH6C4KP2V/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Make itertools recipes license easier

2019-10-29 Thread Todd
I think you might be mixing up two different things.

First is the text of the Pytjon-2.0 license.  I don't want to change that,
or the text of any other license.

Second is the LICENSE file.  That file includes the text of the Python-2.0
license, the text of every other license used in the project, the history
licenses, and some other brief information.  This is what I am suggesting
we edit.

At the very least the LICENSE file, as I understand it, should contain the
text of every license used (or say it is in a separate file) and a brief
note about where it is used if it isn't the "default" license.  As I
mentioned, the current file does exactly that.  So we would need to add the
CC0 license text and at least a very brief explanation of why we added it.

Thinking about it a bit more, considering there is already a license
history, I think this is a significant enough change that it should
probably be mentioned somewhere in that history.

Of course the other stuff you mentioned should be done, too.  Does this
sound reasonable?


On Tue, Oct 29, 2019, 14:25 Guido van Rossum  wrote:

> Thanks for thinking this through a bit more.
>
> I would be wary of changing the Python license -- it's got loads of
> baggage and legally I don't know if we can make that stick. Basically I
> think we should let leave well enough alone and let sleeping dogs lie. So I
> am not keen to add a sentence to the license.html file or to the LICENSE
> file in the repo and distro.
>
> But what I think we *can* do is add that sentence to the introduction of
> each of the documentation volumes (tutorial, library, reference and maybe
> 1-2 more). Ideally we would also do something to the Sphinx template to add
> this (and the CC0 logo) to the bottom of each HTML page next to the
> copyright notice, as you propose. I'm no Sphinx expert so I don't know how
> to do that, but I'm sure it's technically feasible and I can't see any
> legal objection to it.
>
> Maybe you could work on a PR with a patch to the doc files? (Maybe also
> file a bpo issue first to track it.) Final approval may require a roundtrip
> to the PSF's lawyer, but that's usually easy enough, and it helps
> tremendously if we have a PR with proposed text.
>
> PS. If you can't find where the copyright notice is in the Sphinx
> templates, maybe it's part of the python.org website? That has its own
> repo, follow the "Found a bug?" link on each page.
>
> --Guido
>
> On Tue, Oct 29, 2019 at 6:53 AM Todd  wrote:
>
>> I am not really a lawyer, so I don't know for certain how to effectively
>> do this or how fine-grained it has to be.  I can float some possibilities,
>> but someone more knowledgeable would have to assess them.
>>
>> There is a page on the python website about the license [1].  As far as I
>> can tell this page is duplicated in the "LICENSE" file in the root of the
>> Python sources (or there is something very similar).  It may be possible to
>> simply put some text there saying that all code present in the
>> documentation is under the CC0 license (probably with the text of the
>> license somewhere).  This would be a good thing to do, in my opinion, no
>> matter what, but whether it is sufficient I don't know.  If that is
>> sufficient, I think that would be the ideal solution.
>>
>> Perhaps text like: "The Python __ver__ software and documentation is
>> available under the [Python-2.0 license].  However, all code found in the
>> documentation has been released into the public domain or, in jurisdictions
>> where that is not allowed, is available under the [Creative Commons Zero
>> (CC0) license]."  ([] indicate links to the license text) I think this
>> would probably be best under the "Terms and conditions" section, but before
>> actual text of the license.
>>
>> If that isn't sufficient, it may be possible to also put that at the
>> bottom of all the documentation pages, where the copyright text already
>> is.  I assume the copyright text is some sort of automatically-added
>> footer, so hopefully this would be something that could be done once.
>> Perhaps something like "Code found on this page is under the [CC0
>> license]".  There would need to be care to make sure that this is applied
>> to the code in the documentation, rather than the html and/or javascript
>> code underlying the web page.  I don't know if my text does that or not.
>>
>> If even that isn't sufficient, there may be some way to add the CC0 icon
>> [3] to every piece of code in the documentation automatically, but I don't
>> know enough about how the code is generated to say, and I would hope that
>> wouldn't be necessary.
>>
>> Another possibility would be to amend the Python license itself.
>> Currently the license is known as the Python-2.0 license [4].  This would
>> probably be the Python-2.1 license.  However, not being a lawyer I would
>> not presume to touch the license text.
>>
>> [1] https://docs.python.org/license.html
>> [2]
>> 

[Python-ideas] Re: Suggestion for behaviour change import mechanics

2019-10-29 Thread Richard Vogel

Although I suspect the actual reasoning is just that, because these
are both rare use cases, nobody bothered to design the behavior around
either of them; instead, they just went with the simplest
implementation that handles the non-rare cases as intended, and then
just documented what it does in the rare cases as the behavior. And
then, in the years since then (especially at 3.0 and when the new
import system was implemented a few versions later) nobody had a
compelling reason to change the rules.

Thats propably what it mostly is. A mixture between there is no
straight-forward always correct way and history :)


Would you really want two different modules to be the same just
because they happened to have the same contents, or happened to get
those contents by executing the same source? You definitely wouldn’t
want them to be identical (imagine if a.py and b.py were empty, you
did `import a; import b; a.spam=2; b.spam=3`, and a.spam was now 3.)
And I don’t think you’d want two non-identical modules to be equal.


Don't think so, thats a point. So its not so straight forward to define
whats identical.


(As a side note, modules don’t always have an absolute path. The most
common way to get a module is as a .py file in a directory on
sys.path, but there are other ways—cached .pyc flies delivered without
the .py file, extension modules, modules inside zip archives, even
modules that use arbitrary custom finders to pull them off a web
server or out of a database, or simulate hierarchy on top of a flat
filesystem, or whatever. Some of these have a confusing path, some
have no path at all. They do always have a loader spec, which could
theoretically serve the same purpose. But modules don’t remember the
loader spec used to load them. Plus, loader specs, unlike names, are a
low-level detail that most Python developers probably never learn.)

That's  a lot of information and a lot of coner cases, which I partly
can't even understand. Guess for that one needs to understand the
concept of a loader spec.

Nevertheless, could Python cache that spec and cache also a checksum of
whats coming out after resolveing the loader ?
So given that Python could recognize the case where you actually import
something similiar with a different loader spec (for example the case
where something in path is imported fully quallified and non fully
qualified).
Given that Python could spill out a warning that this happened (also in
your circular case for example) and just do what it does now still.
Then a import keyword extension like *import twin ~~~* would explicitly
do what it does now anyways (Giving you the same thing in a different
realization, so basically just removing the warning in that case) and
*import union ~~~* which returns the same realization and removing the
warning. This would force the user into knowing what they do and give
the user the chance to see that such a thing happened and start thinking
about what they actually wanted to do in the first place.

Would that be a thing that - at least in terms of feasibility - could be
done?

Am 29.10.2019 um 20:54 schrieb Andrew Barnert:

On Oct 29, 2019, at 11:45, Richard Vogel mailto:mer...@gmx.net>> wrote:



What happens if you break this rule is exactly what you’re seeing.
The way Python ensures that doing `import spam` twice results in the
same spam module object (so your globals don’t all get duplicated)
is by storing modules by qualified name in sys.modules. So if the
same file has two different qualified names, it’s two separate modules.

I got that. That explains the behaviour I got, where Enum-Entries
suddenly where unequal to the "same" Enum-Entries causing a crash.
Which actually was better than having this behaviour happening unseen
and having the supposed same thing multiple times. That would have
resulted in two differen EventQueues. Cannot imagine all the time I
would have spent until I would have realized having two of them
suddenly ;)

Is there a reasoning for that behavior of Python?


I suspect this goes so far back into the mists of time that there’s no
mailing list discussion or anything. But I can take a guess.

First, the real issue here is that it’s confusing to have the same
module exist under two different names. Normally, the module spam.eggs
and the module eggs shouldn’t be the same thing. Especially given
that, unlike most objects in Python, modules know their qualified
names, and actually _need_ to know them for things like pickle and
multiprocessing to work. It would be misleading if you looked at the
qualified name of spam.eggs and got back something other than
"spam.eggs", and not just to human readers, but to code.

While there are rare occasions when you might want spam.eggs and eggs
to be the same thing, there are also rare occasions when you might
want the same source to import as two separate objects. And both are
less common than doing it mistakenly. Since these are both rare, the
One Obvious Way To Do each one ought to be something 

[Python-ideas] Re: Suggestion for behaviour change import mechanics

2019-10-29 Thread Andrew Barnert via Python-ideas
On Oct 29, 2019, at 11:45, Richard Vogel  wrote:
>> What happens if you break this rule is exactly what you’re seeing. The way 
>> Python ensures that doing `import spam` twice results in the same spam 
>> module object (so your globals don’t all get duplicated) is by storing 
>> modules by qualified name in sys.modules. So if the same file has two 
>> different qualified names, it’s two separate modules.
> I got that. That explains the behaviour I got, where Enum-Entries suddenly 
> where unequal to the "same" Enum-Entries causing a crash. Which actually was 
> better than having this behaviour happening unseen and having the supposed 
> same thing multiple times. That would have resulted in two differen 
> EventQueues. Cannot imagine all the time I would have spent until I would 
> have realized having two of them suddenly ;)
> Is there a reasoning for that behavior of Python?
> 
I suspect this goes so far back into the mists of time that there’s no mailing 
list discussion or anything. But I can take a guess.

First, the real issue here is that it’s confusing to have the same module exist 
under two different names. Normally, the module spam.eggs and the module eggs 
shouldn’t be the same thing. Especially given that, unlike most objects in 
Python, modules know their qualified names, and actually _need_ to know them 
for things like pickle and multiprocessing to work. It would be misleading if 
you looked at the qualified name of spam.eggs and got back something other than 
"spam.eggs", and not just to human readers, but to code.

While there are rare occasions when you might want spam.eggs and eggs to be the 
same thing, there are also rare occasions when you might want the same source 
to import as two separate objects. And both are less common than doing it 
mistakenly. Since these are both rare, the One Obvious Way To Do each one ought 
to be something obviously unusual (manipulating sys.modules, or manually using 
importlib) that signals your unusual intention to your readers.

Although I suspect the actual reasoning is just that, because these are both 
rare use cases, nobody bothered to design the behavior around either of them; 
instead, they just went with the simplest implementation that handles the 
non-rare cases as intended, and then just documented what it does in the rare 
cases as the behavior. And then, in the years since then (especially at 3.0 and 
when the new import system was implemented a few versions later) nobody had a 
compelling reason to change the rules.

The biggest consequence is the case where script.py is a runnable script but 
also a module, and thanks to a circular import somewhere it ends up getting 
imported indirectly by itself, so you have modules named "__main__" and 
"script" built from the same source. That one actually comes up, because you 
don’t really have to break any rules for it to happen (circular imports are 
legal, and work fine in some cases, even if they’re confusing in general and 
don’t work in other cases and should usually be avoided), but it’s effectively 
the same problem you’re running into. People have actually made proposals to 
fix that in some way (whether to make it a detectable error, or to special-case 
things so sys.modules['script'] = sys.modules['__main__'] from the start, or 
something else), but I don’t think anyone’s come up with a proposal that 
everyone else liked. If you want to know more about how people think about this 
whole wider issue, maybe search for the proposals on that narrower one.
> Why a thing isn't equal when its physically the same thing, meaning the 
> checksum is the same or its the same absolute path or 
> 
Some things in Python act like “values”, where there’s a notion of equality 
based on equal contents—int, str, tuple, namedtuple and dataclass types, etc. 
But most other things act like “objects”, where no object is equal to anything 
but itself. Sometimes it’s about implicit (especially mutable) state—two 
different file objects are never equal, even if they represent the same disk 
file with the same position. Sometimes it’s about needing to be able to create 
distinct things—two Enum members from different classes are never equal even if 
they have the same name and value, and two Enum classes are never equal even if 
they have exactly the same members. (Imagine if you had code that did different 
things with ForegroundColor and BackgroundColor objects, and then they 
magically became the same type when you added bright background colors.)

Would you really want two different modules to be the same just because they 
happened to have the same contents, or happened to get those contents by 
executing the same source? You definitely wouldn’t want them to be identical 
(imagine if a.py and b.py were empty, you did `import a; import b; a.spam=2; 
b.spam=3`, and a.spam was now 3.) And I don’t think you’d want two 
non-identical modules to be equal.

But of course their contents wouldn’t be equal, 

[Python-ideas] Re: add a .with_stem() method to pathlib objects

2019-10-29 Thread Ricky Teachey
>
> Cool. Sounds like
>
> def with_stem(self, new_stem):
> self.with_name(new_stem + self.suffix)
>
> is the preferred solution. I agree it seems like the right option.
>
> As I said, I don't think it's a big deal either way. A bugs.python.org
> issue with an attached PR implementing (and documenting) this seems
> like the way to go - no big need to debate it. Although it's good that
> we caught the difference in behaviour between the two options - any
> patch adding this should include tests for this particular corner case
> (and any others that you can think of ;-))
>
> Paul
>

*(Apologies to Paul who is receiving this a second time)*

Seems like the right implementation to me. Does anybody disagree that a bug
report with a PR is the way to move forward on this?

Also: I've filed bug reports before, but I don't think I've ever filed a
bug report with a PR and with tests against core python. Is there a link
that might help with learning the process, with an eye to how to setup and
run the test correctly for the project...? I believe I've already signed
the usage agreement and that sort of thing.
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/MEARZKOEGHTVSUOQJQSJ2ZPVDFVXSR4B/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Suggestion for behaviour change import mechanics

2019-10-29 Thread Richard Vogel

Please quote some text from the message you’re replying to, so we know
what you’re referencing. It’s very hard to carry on discussions on a
mailing list if we have to guess which of the four (or, in along
thread, forty) posts you might be talking about. If your mailing makes
it to much of a pain to quote inline like I’m doing, you should at
least be able to “top-post”, to include part of the original message
below your reply.

I used the websites reply function actually to generate that message. I
replyed to my own thread since this was more like a side-effect that I
encountered, which resulted in the kind of behaviour you described.


What happens if you break this rule is exactly what you’re seeing. The
way Python ensures that doing `import spam` twice results in the same
spam module object (so your globals don’t all get duplicated) is by
storing modules by qualified name in sys.modules. So if the same file
has two different qualified names, it’s two separate modules.

I got that. That explains the behaviour I got, where Enum-Entries
suddenly where unequal to the "same" Enum-Entries causing a crash. Which
actually was better than having this behaviour happening unseen and
having the supposed same thing multiple times. That would have resulted
in two differen EventQueues. Cannot imagine all the time I would have
spent until I would have realized having two of them suddenly ;)

Is there a reasoning for that behavior of Python? I am watching from
outside and I know its always easy to say this is strange while there
might be legit reasoning behind that. The thing is: From the point of
the user the fact that importing the very same thing two times resulting
in different realizations thereof is as counter-intuitive as it gets.
Its a bit like driving home coming from a different street than normal
brings me in a house that is my house but is not my house ;) To
simplify: Why a thing isn't equal when its physically the same thing,
meaning the checksum is the same or its the same absolute path or 

I hope that message ends up where it should. Have no idea, will just
send it and see what happens ;)

And thanks for all your patience and all the time reading and answering.
It helps me out. I will go with setup.py's in development mode for that
thing. Brings me almost to the same,and removes the local git submodules
I have currently.


Am 29.10.2019 um 17:16 schrieb Andrew Barnert:

On Oct 29, 2019, at 07:54, mer...@gmx.net  wrote:


I noticed some different (strange) behaviour when handling projects
like that.


Please quote some text from the message you’re replying to, so we know
what you’re referencing. It’s very hard to carry on discussions on a
mailing list if we have to guess which of the four (or, in along
thread, forty) posts you might be talking about. If your mailing makes
it to much of a pain to quote inline like I’m doing, you should at
least be able to “top-post”, to include part of the original message
below your reply.


Imagine following folder structure

# project_folder
 # a_submodule
* a.py
* b.py
* __init__.py

 * main.py

- content a.py:

class Foo:
 pass

- content b.py:

from a import Foo
foo = Foo()


content main.py:

from os.path import join as pjoin
import os
import sys

# put a_submodule into path
curr_dir = os.path.abspath(os.path.dirname(__file__))
sys.path.append(pjoin(curr_dir, 'a_submodule'))


This is your problem. Never put a package on your sys.path, only put
the directory containing the package on it.

What happens if you break this rule is exactly what you’re seeing. The
way Python ensures that doing `import spam` twice results in the same
spam module object (so your globals don’t all get duplicated) is by
storing modules by qualified name in sys.modules. So if the same file
has two different qualified names, it’s two separate modules.

This also means that if you do this:

    import spam
    spam1 = spam
    del sys.modules['spam']
    del spam
    import spam
    assert spam is spam1

… the assert will fail.

If you actually need this behavior for some reason, you usually want
to call importlib directly and avoid using the sys.modules cache. But
usually you don’t want this behavior.

See the docs on the import system
(https://docs.python.org/3/reference/import.html)for full details on
how this works. The docs for the importlib module are also helpful.
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/7D6RPBSM6PXLHFGAZCNYNP7MFU3ZAEMS/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Make itertools recipes license easier

2019-10-29 Thread Guido van Rossum
Thanks for thinking this through a bit more.

I would be wary of changing the Python license -- it's got loads of baggage
and legally I don't know if we can make that stick. Basically I think we
should let leave well enough alone and let sleeping dogs lie. So I am not
keen to add a sentence to the license.html file or to the LICENSE file in
the repo and distro.

But what I think we *can* do is add that sentence to the introduction of
each of the documentation volumes (tutorial, library, reference and maybe
1-2 more). Ideally we would also do something to the Sphinx template to add
this (and the CC0 logo) to the bottom of each HTML page next to the
copyright notice, as you propose. I'm no Sphinx expert so I don't know how
to do that, but I'm sure it's technically feasible and I can't see any
legal objection to it.

Maybe you could work on a PR with a patch to the doc files? (Maybe also
file a bpo issue first to track it.) Final approval may require a roundtrip
to the PSF's lawyer, but that's usually easy enough, and it helps
tremendously if we have a PR with proposed text.

PS. If you can't find where the copyright notice is in the Sphinx
templates, maybe it's part of the python.org website? That has its own
repo, follow the "Found a bug?" link on each page.

--Guido

On Tue, Oct 29, 2019 at 6:53 AM Todd  wrote:

> I am not really a lawyer, so I don't know for certain how to effectively
> do this or how fine-grained it has to be.  I can float some possibilities,
> but someone more knowledgeable would have to assess them.
>
> There is a page on the python website about the license [1].  As far as I
> can tell this page is duplicated in the "LICENSE" file in the root of the
> Python sources (or there is something very similar).  It may be possible to
> simply put some text there saying that all code present in the
> documentation is under the CC0 license (probably with the text of the
> license somewhere).  This would be a good thing to do, in my opinion, no
> matter what, but whether it is sufficient I don't know.  If that is
> sufficient, I think that would be the ideal solution.
>
> Perhaps text like: "The Python __ver__ software and documentation is
> available under the [Python-2.0 license].  However, all code found in the
> documentation has been released into the public domain or, in jurisdictions
> where that is not allowed, is available under the [Creative Commons Zero
> (CC0) license]."  ([] indicate links to the license text) I think this
> would probably be best under the "Terms and conditions" section, but before
> actual text of the license.
>
> If that isn't sufficient, it may be possible to also put that at the
> bottom of all the documentation pages, where the copyright text already
> is.  I assume the copyright text is some sort of automatically-added
> footer, so hopefully this would be something that could be done once.
> Perhaps something like "Code found on this page is under the [CC0
> license]".  There would need to be care to make sure that this is applied
> to the code in the documentation, rather than the html and/or javascript
> code underlying the web page.  I don't know if my text does that or not.
>
> If even that isn't sufficient, there may be some way to add the CC0 icon
> [3] to every piece of code in the documentation automatically, but I don't
> know enough about how the code is generated to say, and I would hope that
> wouldn't be necessary.
>
> Another possibility would be to amend the Python license itself.
> Currently the license is known as the Python-2.0 license [4].  This would
> probably be the Python-2.1 license.  However, not being a lawyer I would
> not presume to touch the license text.
>
> [1] https://docs.python.org/license.html
> [2]
> https://docs.python.org/license.html#terms-and-conditions-for-accessing-or-otherwise-using-python
> [3] https://licensebuttons.net/p/zero/1.0/88x31.png
> [4] https://spdx.org/licenses/Python-2.0.html
>
> On Thu, Oct 24, 2019 at 6:19 PM Guido van Rossum  wrote:
>
>> OK, let's see if we can do CC0. Todd, do you want to read through the
>> link Steven gave and find out how we should apply this, either to just the
>> itertools examples, or possibly to all examples in the docs?
>>
>> On Thu, Oct 24, 2019 at 2:01 PM Steven D'Aprano 
>> wrote:
>>
>>> On Thu, Oct 24, 2019 at 12:36:40PM -0700, Christopher Barker wrote:
>>> > IANAL, but if we could put a clause in the docs that all recipes are
>>> in the
>>> > public domain, that would be great.
>>>
>>> The public domain is *exceedingly* problematic. Many juristictions do
>>> not have any legal process for putting things into the public domain
>>> before the standard copyright expiry, or even prohibit the attempt to
>>> surrender such rights.
>>>
>>> That's why the Creative Commons folks have their CC0 licence, which
>>> seems to be the most appropriate for this case.
>>>
>>> https://creativecommons.org/share-your-work/public-domain/cc0/
>>> 

[Python-ideas] Re: add a .with_stem() method to pathlib objects

2019-10-29 Thread Ethan Furman

On 10/29/2019 10:41 AM, Paul Moore wrote:

On Tue, 29 Oct 2019 at 17:38, Ethan Furman  wrote:


On 10/29/2019 10:17 AM, Brian Skinn wrote:


I feel like the semantics of PurePath.suffix 
(https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.suffix) and 
PurePath.stem define this pretty unambiguously.


It does indeed -- it declares the last bit to be the suffix.  So 
correspondingly, .with_stem() should be everything before the last bit, or:

[corrected examples]

p = Path("foo.bar.txt")
p.with_stem("quux")

  "quux.bar.txt"


Um,


Path("foo.bar.txt").suffix

'.txt'

So if ".txt" is the suffix, then with_stem("quux") should be "quux.txt", surely?


Argh.  Can I plead lack of coffee?  And since I don't drink coffee, that 
explains a lot.  ;-)

--
~Ethan~
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/6YOWVLWKXEZQFROY46WDWFWKWMP5MTGX/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: add a .with_stem() method to pathlib objects

2019-10-29 Thread Paul Moore
On Tue, 29 Oct 2019 at 17:38, Ethan Furman  wrote:
>
> On 10/29/2019 10:17 AM, Brian Skinn wrote:
>
> > I feel like the semantics of PurePath.suffix 
> > (https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.suffix) 
> > and PurePath.stem define this pretty unambiguously.
>
> It does indeed -- it declares the last bit to be the suffix.  So 
> correspondingly, .with_stem() should be everything before the last bit, or:
>
> [corrected examples]
> > p = Path("foo.bar.txt")
> > p.with_stem("quux")
>  "quux.bar.txt"

Um,

>>> Path("foo.bar.txt").suffix
'.txt'

So if ".txt" is the suffix, then with_stem("quux") should be "quux.txt", surely?

Paul
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/XKEA3PLU7RJDP6ARFQPIRS55A6LTJ5OP/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: add a .with_stem() method to pathlib objects

2019-10-29 Thread Paul Moore
On Tue, 29 Oct 2019 at 17:08, Andrew Barnert  wrote:
>
> If you wanted my safe_create function to do Mac-like “copy 3 of 
> spam.eggs.txt” instead of Windows-style “spam.eggs (3).txt”, then you would 
> end up calling path.with_stem("copy 3 of spam.eggs"), and you would 
> definitely want the ".eggs" to be added to rather than replaced. So, the OP’s 
> first implementation would be the right one, not his second.

On Tue, 29 Oct 2019 at 17:19, Brian Skinn  wrote:
>
> I feel like the semantics of PurePath.suffix 
> (https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.suffix) and 
> PurePath.stem define this pretty unambiguously.
[...]
> p.with_stem("baz.quux")
>   "baz.quux.txt"

Cool. Sounds like

def with_stem(self, new_stem):
self.with_name(new_stem + self.suffix)

is the preferred solution. I agree it seems like the right option.

As I said, I don't think it's a big deal either way. A bugs.python.org
issue with an attached PR implementing (and documenting) this seems
like the way to go - no big need to debate it. Although it's good that
we caught the difference in behaviour between the two options - any
patch adding this should include tests for this particular corner case
(and any others that you can think of ;-))

Paul
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/PAFEC4GSSE4JVI5BCP754IFPNIGEAPTG/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: add a .with_stem() method to pathlib objects

2019-10-29 Thread Ricky Teachey
> As you say, it's a minor thing (either way) but I've never had the
> need for a `with_stem` method. Do you have a real-life use case (as
> opposed to just wanting it for completeness)?
>
> Having  a real example would help decide the appropriate behaviour for
> corner cases like x.with_stem('name.ext'). Your two suggested
> equivalents behave differently in that case:
>
> >>> old_path = Path(r"C:\x.txt")
> >>> old_path.with_name("y.xxx" + old_path.suffix)
> WindowsPath('C:/y.xxx.txt')
> >>> old_path.with_name("y.xxx").with_suffix(old_path.suffix)
> WindowsPath('C:/y.txt')
>

I hadn't considered that case. Worth discussing.

Not just "for completeness", I had a real-life use case this morning;
reached for it, wasn't there, frustrated.

The relevant chunk of the code below is here, in which you can see I would
have like to use this feature twice:

for ym in moduli:
update_soup(soup, moduli)
new_name =  filename_formatter.format(ym=ym)
new_path =
source_file_path.with_name(new_name).with_suffix(source_file_path.suffix)
new_path.write_text(soup.prettify())
run_model(new_path)
deflection = get_deflection()
discard_data()  # completed files are very large; close program and
don't save finished file
deflection_stem =
deflection_formatter.format(deflection=deflection)

new_path.rename(new_path.with_name(deflection_stem).with_suffix(source_file_path.suffix)

Would be nice to say:

for ym in moduli:
update_soup(soup, moduli)
new_name =  filename_formatter.format(ym=ym)
new_path = source_file_path.with_stem(new_name)  # yay!
new_path.write_text(soup.prettify())
run_model(new_path)
deflection = get_deflection()
discard_data()  # completed files are very large; close program and
don't save finished file
deflection_stem =  deflection_formatter.format(deflection=deflection)
new_path.rename(new_path.with_stem(deflection_stem)  # yay!


*Details*

I have a file named like so:

*5340 ksi 69% plastic E 90% plastic TIG - 25.02 mm.liml*

It is an XML format input file (for a finite element analysis program).

The file name is my own convention; it has the YM as part of the file name
(with some other info I'm not changing), and the deflection of a model of a
wall in mm at the end.

I'm doing a sensitivity analysis so the goal is to make a copy of the input
file changing a single input parameter for one of the materials (YM) and
name the new input file appropriately (with XX as an intial placeholder for
the final deflection), run the model, obtain the model deflection, and
finally rename the file with the final deflection.

I'm parsing the file name (using pent) and content (using beautifulsoup to
get the XML element), replacing the YM in the relevant XML attribute, and
copying the file to a new filename.

In the end I'll have a directory of files like this:

5340 ksi 69% plastic E 90% plastic TIG - 25.02 mm.liml
3041 ksi 69% plastic E 90% plastic TIG - XX mm.liml
2087 ksi 69% plastic E 90% plastic TIG - XX mm.liml
1693 ksi 69% plastic E 90% plastic TIG - XX mm.liml

(the XX of each will be replaced after the files have been run)

The code I am using to do much of this is, roughly:

# define starting file and some list of moduli i am interested in (strings)
moduli = [ "3041 ksi", "2087 ksi", "1693 ksi", ]
source_file_path =  Path("5340 ksi 69% plastic E 90% plastic TIG - 25.02
mm.liml")

# parse the filename
captured = pent.Parser(body="#.+i &. ~! #.+d
@.mm").parse_body(source_file_path.stem)[0][0]
captured_string = " ".join(captured)
filename_formatter = f"{{ym}} {captured_string} XX mm"
deflection_formatter = f"{{ym}} {captured_string} {{deflection:.2f} mm}"

# load the XML soup
with  source_file_path.open() as doc:
soup = bs4.bs.BeautifulSoup(doc, 'html.parser')

# create a file for each young's modulus, run it, and rename it
for ym in moduli:
update_soup(soup, moduli)
new_name =  filename_formatter.format(ym=ym)
new_path = source_file_path.with_stem(new_name)  # shorter code: yay!
new_path.write_text(soup.prettify())
run_model(new_path)
deflection = get_deflection()
discard_data()  # completed files are very large; close program and
don't save finished file
deflection_stem =  deflection_formatter.format(deflection=deflection,
ym=ym)
new_path.rename(new_path.with_stem(deflection_stem)  # shorter
code: yay!
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/JQQPWQ3YVZU64B62P3ZCYQZQ4ZHYA2CT/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: add a .with_stem() method to pathlib objects

2019-10-29 Thread Brian Skinn
I feel like the semantics of PurePath.suffix 
(https://docs.python.org/3/library/pathlib.html#pathlib.PurePath.suffix) and 
PurePath.stem define this pretty unambiguously.

I.e., it should be:

p = Path("foo.bar.txt")
p.with_stem("quux")
  "quux.txt"
p.with_stem("baz.quux")
  "baz.quux.txt"
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/VHADSSZDTMKPZPY2YNX2CIMV2475JVDM/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: add a .with_stem() method to pathlib objects

2019-10-29 Thread Andrew Barnert via Python-ideas
On Oct 29, 2019, at 09:05, Paul Moore  wrote:
> 
> Having  a real example would help decide the appropriate behaviour for
> corner cases like x.with_stem('name.ext').

I just realized that my use case doesn’t help answer your corner case. 
Hopefully the OP’s will have one. But I can imagine one that does.

If you wanted my safe_create function to do Mac-like “copy 3 of spam.eggs.txt” 
instead of Windows-style “spam.eggs (3).txt”, then you would end up calling 
path.with_stem("copy 3 of spam.eggs"), and you would definitely want the 
".eggs" to be added to rather than replaced. So, the OP’s first implementation 
would be the right one, not his second.

Hopefully that doesn’t contradict what you’d want from the OP’s use case. :)

___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/SGQB6LTXYDRISN2VL656YRYN47WQOAIY/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: add a .with_stem() method to pathlib objects

2019-10-29 Thread Andrew Barnert via Python-ideas
On Oct 29, 2019, at 09:05, Paul Moore  wrote:
> 
> I've never had the
> need for a `with_stem` method. Do you have a real-life use case (as
> opposed to just wanting it for completeness)?

I have a real-life use case, which I’ll simplify here:

def safe_create(path):
try:
return open(path, 'x')
except FileExistsError:
for i in itertools.count(1):
path2 = path.with_stem(f"{path.stem} ({i})")
try:
return open(path2, 'x')
except FileExistsError:
pass


___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/RC7E4HQWGSHYE4QAN6Z66LCJBUUPYZZZ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Suggestion for behaviour change import mechanics

2019-10-29 Thread Andrew Barnert via Python-ideas
On Oct 29, 2019, at 06:33, mer...@gmx.net wrote:
> 
> On the first scroll in the docs, that doesn't seem to map to the 
> namespace-concepts that are known from C++ or PHP, where you explicitly 
> define them within the file, right?

The meaning of “namespace” is a place where you can bind values to names and 
look them up by name, usually with dot syntax or something similar. Every 
module is a namespace containing its globals. A function activation frame is a 
namespace containing its locals (although it’s a hidden one you can’t access 
like a module). Every object is a namespace containing its attributes. And so 
on.

In C++ (until the upcoming C++20 version), there are no modules (if you 
#include a header file, you’re just including the header’s text in the middle 
of your file), so they added the namespace statement to create explicit 
module-like namespaces. I don’t know as much about PHP, but most of its design 
is intended to feel familiar to C and C++ developers even if it doesn’t quite 
make sense, so I’m guessing that’s why it has a similar feature.

Anyway, in Python, a “namespace package” is a package that’s _just_ a 
namespace—it contains modules and other packages that can be looked up by name, 
but doesn’t have any top-level code that gets run when you import it. This is 
similar to the SimpleNamespace type—it’s not a class whose instances are 
namespaces, because every class’s instances are namespaces; it’s a class whose 
instances are _just_ namespaces, with no other behavior on top of that. So, a 
namespace package is just one without an __init__.py file or equivalent.

It’s a bit weird that Python conflates the notion of namespace packages 
(packages that are just namespaces, with no other behavior) with open or 
composite packages (packages that can be added to by other packages); I believe 
it works that way for historical reasons that go back to the way you faked it 
in 2.x with a third-party library.

___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/OMCDJTUZOASPDW4BGRSO7LZG5XO2H3QN/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Suggestion for behaviour change import mechanics

2019-10-29 Thread Andrew Barnert via Python-ideas
On Oct 29, 2019, at 07:54, mer...@gmx.net wrote:
> 
> I noticed some different (strange) behaviour when handling projects like that.

Please quote some text from the message you’re replying to, so we know what 
you’re referencing. It’s very hard to carry on discussions on a mailing list if 
we have to guess which of the four (or, in along thread, forty) posts you might 
be talking about. If your mailing makes it to much of a pain to quote inline 
like I’m doing, you should at least be able to “top-post”, to include part of 
the original message below your reply.

> Imagine following folder structure
> 
> # project_folder
>  # a_submodule
> * a.py
> * b.py
> * __init__.py
> 
>  * main.py
> 
> - content a.py:
> 
> class Foo:
>  pass
> 
> - content b.py:
> 
> from a import Foo
> foo = Foo()
> 
> 
> content main.py:
> 
> from os.path import join as pjoin
> import os
> import sys
> 
> # put a_submodule into path
> curr_dir = os.path.abspath(os.path.dirname(__file__))
> sys.path.append(pjoin(curr_dir, 'a_submodule'))

This is your problem. Never put a package on your sys.path, only put the 
directory containing the package on it.

What happens if you break this rule is exactly what you’re seeing. The way 
Python ensures that doing `import spam` twice results in the same spam module 
object (so your globals don’t all get duplicated) is by storing modules by 
qualified name in sys.modules. So if the same file has two different qualified 
names, it’s two separate modules.

This also means that if you do this:

import spam
spam1 = spam
del sys.modules['spam']
del spam
import spam
assert spam is spam1

… the assert will fail. 

If you actually need this behavior for some reason, you usually want to call 
importlib directly and avoid using the sys.modules cache. But usually you don’t 
want this behavior.

See the docs on the import system 
(https://docs.python.org/3/reference/import.html)for full details on how this 
works. The docs for the importlib module are also helpful.
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/JUVXRY2ICFCCBLXE3OW4PG4OHRM2X4QL/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: add a .with_stem() method to pathlib objects

2019-10-29 Thread Paul Moore
On Tue, 29 Oct 2019 at 15:29, Ricky Teachey  wrote:
>
> There are already .with_suffix() and with_name() methods. Including 
> with_stem() seems obvious, no?

As you say, it's a minor thing (either way) but I've never had the
need for a `with_stem` method. Do you have a real-life use case (as
opposed to just wanting it for completeness)?

Having  a real example would help decide the appropriate behaviour for
corner cases like x.with_stem('name.ext'). Your two suggested
equivalents behave differently in that case:

>>> old_path = Path(r"C:\x.txt")
>>> old_path.with_name("y.xxx" + old_path.suffix)
WindowsPath('C:/y.xxx.txt')
>>> old_path.with_name("y.xxx").with_suffix(old_path.suffix)
WindowsPath('C:/y.txt')
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/WSKMYQLOCGU63BDN62ZSZOONHDKEMGWF/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: add a .with_stem() method to pathlib objects

2019-10-29 Thread Ricky Teachey
Correction; I intended to use with_suffix() for the second example:

>>> old_path = Path(r"C:\x.txt")
>>> old_path.with_name("y").with_suffix(old_path.suffix)
WindowsPath('C:/y.txt')
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/HTVJBJDJRIGL2FKZHLKI3AWOFWXVTQNB/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] add a .with_stem() method to pathlib objects

2019-10-29 Thread Ricky Teachey
This is obviously a small thing, but it would be nice to be able to say:

>>> Path(r"C:\x.txt").with_stem("y")
WindowsPath('C:/y.txt')

Rather than having to do some variation of:

>>> old_path = Path(r"C:\x.txt")
>>> old_path.with_name("y"+old_path.suffix)
WindowsPath('C:/y.txt')

Or:

>>> old_path = Path(r"C:\x.txt")
>>> old_path.with_name("y"+old_path.suffix)
WindowsPath('C:/y.txt')

Or (god forbid):

>>> (old_path := Path(r"C:\x.txt")).with_name("y"+old_path.suffix)
WindowsPath('C:/y.txt')

There are already .with_suffix() and with_name() methods. Including
with_stem() seems obvious, no?

---
Ricky.

"I've never met a Kentucky man who wasn't either thinking about going home
or actually going home." - Happy Chandler
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/OY3ZLUF4N7U4NSBOWJVEUBW7BFKA7AVX/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Suggestion for behaviour change import mechanics

2019-10-29 Thread mereep
I noticed some different (strange) behaviour when handling projects like that. 
Imagine following folder structure

# project_folder
  # a_submodule
 * a.py
 * b.py
 * __init__.py

  * main.py

- content a.py:

class Foo:
  pass

- content b.py:

from a import Foo
foo = Foo()


content main.py:

from os.path import join as pjoin
import os
import sys

# put a_submodule into path
curr_dir = os.path.abspath(os.path.dirname(__file__))
sys.path.append(pjoin(curr_dir, 'a_submodule'))

# import them using two different ways (1: directly, 2: resolving through path)
from a_submodule.b import foo as instance_1
from b import foo as instance_2

assert instance_1 is instance_2, "Instances are not the same"  # will raise(!)


is it intended that a different input mechanism results in completely ignoring 
the files as being the same. Python does not seem to understand that it already 
imported a thing when the import statement differs.

I noticed that in my code when suddenly Enums where different while being the 
same depending on which code part they where executed from. That brings me to a 
point where I cannot handle the project like this at all in that manner :/
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/LULH2LZQBUEY7ARMGOMFLDEEPTO5AU3Y/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Make itertools recipes license easier

2019-10-29 Thread Todd
I am not really a lawyer, so I don't know for certain how to effectively do
this or how fine-grained it has to be.  I can float some possibilities, but
someone more knowledgeable would have to assess them.

There is a page on the python website about the license [1].  As far as I
can tell this page is duplicated in the "LICENSE" file in the root of the
Python sources (or there is something very similar).  It may be possible to
simply put some text there saying that all code present in the
documentation is under the CC0 license (probably with the text of the
license somewhere).  This would be a good thing to do, in my opinion, no
matter what, but whether it is sufficient I don't know.  If that is
sufficient, I think that would be the ideal solution.

Perhaps text like: "The Python __ver__ software and documentation is
available under the [Python-2.0 license].  However, all code found in the
documentation has been released into the public domain or, in jurisdictions
where that is not allowed, is available under the [Creative Commons Zero
(CC0) license]."  ([] indicate links to the license text) I think this
would probably be best under the "Terms and conditions" section, but before
actual text of the license.

If that isn't sufficient, it may be possible to also put that at the bottom
of all the documentation pages, where the copyright text already is.  I
assume the copyright text is some sort of automatically-added footer, so
hopefully this would be something that could be done once.  Perhaps
something like "Code found on this page is under the [CC0 license]".  There
would need to be care to make sure that this is applied to the code in the
documentation, rather than the html and/or javascript code underlying the
web page.  I don't know if my text does that or not.

If even that isn't sufficient, there may be some way to add the CC0 icon
[3] to every piece of code in the documentation automatically, but I don't
know enough about how the code is generated to say, and I would hope that
wouldn't be necessary.

Another possibility would be to amend the Python license itself.  Currently
the license is known as the Python-2.0 license [4].  This would probably be
the Python-2.1 license.  However, not being a lawyer I would not presume to
touch the license text.

[1] https://docs.python.org/license.html
[2]
https://docs.python.org/license.html#terms-and-conditions-for-accessing-or-otherwise-using-python
[3] https://licensebuttons.net/p/zero/1.0/88x31.png
[4] https://spdx.org/licenses/Python-2.0.html

On Thu, Oct 24, 2019 at 6:19 PM Guido van Rossum  wrote:

> OK, let's see if we can do CC0. Todd, do you want to read through the link
> Steven gave and find out how we should apply this, either to just the
> itertools examples, or possibly to all examples in the docs?
>
> On Thu, Oct 24, 2019 at 2:01 PM Steven D'Aprano 
> wrote:
>
>> On Thu, Oct 24, 2019 at 12:36:40PM -0700, Christopher Barker wrote:
>> > IANAL, but if we could put a clause in the docs that all recipes are in
>> the
>> > public domain, that would be great.
>>
>> The public domain is *exceedingly* problematic. Many juristictions do
>> not have any legal process for putting things into the public domain
>> before the standard copyright expiry, or even prohibit the attempt to
>> surrender such rights.
>>
>> That's why the Creative Commons folks have their CC0 licence, which
>> seems to be the most appropriate for this case.
>>
>> https://creativecommons.org/share-your-work/public-domain/cc0/
>> ___
>> Python-ideas mailing list -- python-ideas@python.org
>> To unsubscribe send an email to python-ideas-le...@python.org
>> https://mail.python.org/mailman3/lists/python-ideas.python.org/
>> Message archived at
>> https://mail.python.org/archives/list/python-ideas@python.org/message/U3SMXGIWEXUKPN5QW2WR4NL2RPXACEVG/
>> Code of Conduct: http://python.org/psf/codeofconduct/
>>
>
>
> --
> --Guido van Rossum (python.org/~guido)
> *Pronouns: he/him **(why is my pronoun here?)*
> 
>
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/JIS32MXX36B56GNKLLWLEHR4M77AC5F3/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Suggestion for behaviour change import mechanics

2019-10-29 Thread mereep
Thanks for that hints!

This namespace module concept indeed looks like that is kind of the behaviour 
that would like to achieve. I will take a look at that. 


On the first scroll in the docs, that doesn't seem to map to the 
namespace-concepts that are known from C++ or PHP, where you explicitly define 
them within the file, right? I will take a look anyways, since the result seems 
to be the same.

Anyways, just failing later would not hurt the Python language I think ;)
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/C7YNEYUZ5AAH3QA7YEUZKML7KCHG3QX3/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Suggestion for behaviour change import mechanics

2019-10-29 Thread mereep
Yes :)

That looks similiar to my problem, which i fixed for the moment of writing by 
renaming one folder.
Basically, I would prefer if Python would not treat nth-level import fails 
different than first-level fails. 


Might seem like a small thing, but in my opinion it would:
- keep the behaviour straight forward
- Correct the error messages, since from the perspective of the user the import 
actually DOES exist
- Does not break anything currently working
- Makes me happy ;)
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/KSNKIS2UGGBNNIDUNOBLQK2I5AFU5D24/
Code of Conduct: http://python.org/psf/codeofconduct/