Re: Using pytest, sometimes does not capture stderr

2021-04-04 Thread David
On Mon, 5 Apr 2021 at 14:26, Cameron Simpson  wrote:
> On 05Apr2021 13:56, David  wrote:

> >Thanks for confirming my suspicions so quickly. What you wrote
> >makes sense, but there are two points that still puzzle me.
> >1) The final line of the pytest failure output seems to shows that
> >pytest did capture (or is at least aware of) the stderr message
> >from module_2.

> Yes. Unsure what's going on there. It could be timing. Suppose this
> happens:

> - pytest pushes a capturing stderr onto sys.stderr
> - pytest loads your module, which imports module_1 and module_2
> - the test runner pushes a separate stderr capturer for the test?
> - module_1 finds the per-test sys.stderr value
> - module_2 finds pytest's outermost capturer (present when it was
>   imported), and doesn't look up sys.stderr at test time, instead using
>   the outer capturer

Ok. I do understand that my function parameter defaults are defined
when the function is defined, so something like this could happen.

> >2) My actual code that I would like to test does look like module_2.
> >Is there any way to test it with pytest?

> I'd be inclined to give msg() an optional file= parameter:

Understood.

> If you truly need to test msg() _without_ the file= parameter, you could
> monkey patch module_2:

I tried this, it works too.

Thanks so much for your guidance! It's great to be steered through
puzzlement by experts. I hope you're having a good day, you made
mine better :)
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Using pytest, sometimes does not capture stderr

2021-04-04 Thread Cameron Simpson
On 05Apr2021 13:56, David  wrote:
>On Mon, 5 Apr 2021 at 13:44, Cameron Simpson  wrote:
>> On 05Apr2021 13:28, David  wrote:
>> >Can anyone explain why the module_2.py test fails?
>> >Is it because stderr during module import is not the same as during test?
>> >Is it something to do with mutable defaults?
>> >How to investigate this?
>> >And how can I get the test to pass without changing module_2?
>
>> The code in module_2.py runs at different times.
>
>> When it is imported, sys.stderr is the OS-provided stderr. That
>> reference is kept in MSG_DESTINATION.
>
>> Then your test code runs, and changes sys.stderr. It then runs msg(),
>> which writes to the _original_ sys.stderr as preserved by
>> MSG_DESTINATION. Thus not captured.
>
>> By contrast, module_1.py looks up sys.stderr inside msg(), and finds the
>> new one the code harness put at sys.stderr. So it writes to the thing
>> that captures stuff.
>
>Thanks for confirming my suspicions so quickly. What you wrote
>makes sense, but there are two points that still puzzle me.
>1) The final line of the pytest failure output seems to shows that
>pytest did capture (or is at least aware of) the stderr message
>from module_2.

Yes. Unsure what's going on there. It could be timing. Suppose this 
happens:

- pytest pushes a capturing stderr onto sys.stderr
- pytest loads your module, which imports module_1 and module_2
- the test runner pushes a separate stderr capturer for the test?
- module_1 finds the per-test sys.stderr value
- module_2 finds pytest's outermost capturer (present when it was 
  imported), and doesn't look up sys.stderr at test time, instead using 
  the outer capturer

>2) My actual code that I would like to test does look like module_2.
>Is there any way to test it with pytest?

I'd be inclined to give msg() an optional file= parameter:

def msg(*args, file=None):
if file is None:
file = MSG_DESTINATION
print(*args, file=file)

Then your test code can go:

msg("a", "message", file=sys.stderr)

which looks up sys.stderr as it is inside the test itself, and passes it 
to msg(). Thus captured.

If you truly need to test msg() _without_ the file= parameter, you could 
monkey patch module_2:

old_MSG_DESTINATION = module_2.MSG_DESTINATION
module_2.MSG_DESTINATION = sys.stderr
# now the module_2 module has an updated reference for sys.stderr
...
msg("a", "message")
...
module_2.MSG_DESTINATION = old_MSG_DESTINATION
# normality restored

Cheers,
Cameron Simpson 
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Using pytest, sometimes does not capture stderr

2021-04-04 Thread David
On Mon, 5 Apr 2021 at 13:44, Cameron Simpson  wrote:
> On 05Apr2021 13:28, David  wrote:

> >Can anyone explain why the module_2.py test fails?
> >Is it because stderr during module import is not the same as during test?
> >Is it something to do with mutable defaults?
> >How to investigate this?
> >And how can I get the test to pass without changing module_2?

> The code in module_2.py runs at different times.

> When it is imported, sys.stderr is the OS-provided stderr. That
> reference is kept in MSG_DESTINATION.

> Then your test code runs, and changes sys.stderr. It then runs msg(),
> which writes to the _original_ sys.stderr as preserved by
> MSG_DESTINATION. Thus not captured.

> By contrast, module_1.py looks up sys.stderr inside msg(), and finds the
> new one the code harness put at sys.stderr. So it writes to the thing
> that captures stuff.

Hi Cameron,

Thanks for confirming my suspicions so quickly. What you wrote
makes sense, but there are two points that still puzzle me.
1) The final line of the pytest failure output seems to shows that
pytest did capture (or is at least aware of) the stderr message
from module_2.
2) My actual code that I would like to test does look like module_2.
Is there any way to test it with pytest?

Thanks.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Using pytest, sometimes does not capture stderr

2021-04-04 Thread Cameron Simpson
On 05Apr2021 13:28, David  wrote:
>I have just begun using pytest at a basic level and I am
>seeing behaviour that I do not understand.
>
>My platform is Debian 10.9
>
>There are 3 files involved, contents are provided below, and attached.
>- module_1.py passes the test as expected
>- module_2.py has a tiny change, and fails unexpectedly.
>- my_test.py runs the same test on each module
>
>Can anyone explain why the module_2.py test fails?
>Is it because stderr during module import is not the same as during test?
>Is it something to do with mutable defaults?
>How to investigate this?
>And how can I get the test to pass without changing module_2?
>
>Thanks :)
>
>#-
>Here is the file module_1.py:
>#!/usr/bin/python3
>import sys
>def msg(*args):
>print(*args, file=sys.stderr)
>
>#-
>Here is the file module_2.py:
>#!/usr/bin/python3
>import sys
>MSG_DESTINATION = sys.stderr
>def msg(*args):
>print(*args, file=MSG_DESTINATION)

The code in module_2.py runs at different times.

When it is imported, sys.stderr is the OS-provided stderr. That 
reference is kept in MSG_DESTINATION.

Then your test code runs, and changes sys.stderr. It then runs msg(), 
which writes to the _original_ sys.stderr as preserved by 
MSG_DESTINATION. Thus not captured.

By contrast, module_1.py looks up sys.stderr inside msg(), and finds the 
new one the code harness put at sys.stderr. So it writes to the thing 
that captures stuff.

Cheers,
Cameron Simpson 
-- 
https://mail.python.org/mailman/listinfo/python-list


Using pytest, sometimes does not capture stderr

2021-04-04 Thread David
Hi,

I have just begun using pytest at a basic level and I am
seeing behaviour that I do not understand.

My platform is Debian 10.9

There are 3 files involved, contents are provided below, and attached.
- module_1.py passes the test as expected
- module_2.py has a tiny change, and fails unexpectedly.
- my_test.py runs the same test on each module

Can anyone explain why the module_2.py test fails?
Is it because stderr during module import is not the same as during test?
Is it something to do with mutable defaults?
How to investigate this?
And how can I get the test to pass without changing module_2?

Thanks :)

#-
Here is the file module_1.py:
#!/usr/bin/python3
import sys
def msg(*args):
print(*args, file=sys.stderr)

#-
Here is the file module_2.py:
#!/usr/bin/python3
import sys
MSG_DESTINATION = sys.stderr
def msg(*args):
print(*args, file=MSG_DESTINATION)

#-
Here is the file: my_test.py
#!/usr/bin/python3
import module_1
import module_2
def test__1(capsys):
module_1.msg("a", "message")
captured = capsys.readouterr()
assert captured.err == """a message\n"""
def test__2(capsys):
module_2.msg("a", "message")
captured = capsys.readouterr()
assert captured.err == """a message\n"""

#-
Here is the pytest output:

$ pytest-3
 test session starts =
platform linux -- Python 3.7.3, pytest-3.10.1, py-1.7.0, pluggy-0.8.0
rootdir: /mnt/hart/home/d10/david/work/src/py/lab/pytest/capture/bug, inifile:
collected 2 items
my_test.py .F  [100%]
== FAILURES ==
__ test__2 ___
capsys = <_pytest.capture.CaptureFixture object at 0x7ff6457134a8>
def test__2(capsys):
module_2.msg("a", "message")
captured = capsys.readouterr()
>   assert captured.err == """a message\n"""
EAssertionError: assert '' == 'a message\n'
E  + a message
my_test.py:14: AssertionError
 Captured stderr call 
a message
= 1 failed, 1 passed in 0.03 seconds =
= test session starts ==
platform linux -- Python 3.7.3, pytest-3.10.1, py-1.7.0, pluggy-0.8.0
rootdir: /mnt/hart/home/d10/david/work/src/py/lab/pytest/capture/bug, inifile:
collected 2 items

my_test.py .F[100%]

=== FAILURES ===
___ test__2 

capsys = <_pytest.capture.CaptureFixture object at 0x7f9f8cc33278>

def test__2(capsys):
module_2.msg("a", "message")
captured = capsys.readouterr()
>   assert captured.err == """a message\n"""
EAssertionError: assert '' == 'a message\n'
E  + a message

my_test.py:14: AssertionError
- Captured stderr call -
a message
== 1 failed, 1 passed in 0.03 seconds ==
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: About \033[m

2021-04-04 Thread Terry Reedy

On 4/4/2021 7:40 AM, Skip Montanaro wrote:

Porque quando se usa formatac,ao de cores, o python nao consegue


centralizar dentro da cadeia de 40 caracteres ?


Tive que colocar 54 no parametro pois de alguma forma esta sendo
considerado os caracteres de dentro do comando \033[m



Python doesn't know there is anything special about escape sequences (that
they take up no space on the screen). I think you will have better results
if you place the escape sequences in the format specifier:

  print("\033[7;30;43m{:^40}\033[m".format("Programac,ao Python"))


or
print(f"\033[7;30;43m{"Programac,ao Python":^40}\033[m")

--
Terry Jan Reedy

--
https://mail.python.org/mailman/listinfo/python-list


Re: Friday Finking: initialising values and implied tuples

2021-04-04 Thread 2QdxY4RzWzUUiLuE
On 2021-04-05 at 11:47:53 +1200,
dn via Python-list  wrote:

> Did you spot how various contributors identified when they prefer one
> method in a specific situation, but reach for another under differing
> circumstances!

What?  Use cases matter?  I'm *shocked*.  :-/

Of all the methodologies I used since those dinosaurs-on-the-treadmill
days (you had *dinosaurs*; we had to evolve fish with legs to relieve us
from having to run on our own treadmills), use cases was the one I
continued to pull out long after that department went away.

If I have a larger project that uses 3D points, I *might* reach for a
named tuple, but if it's smaller and I know that there will only ever be
two points, then px, py, pz, qx, qy, and qz is good enough.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Friday Finking: initialising values and implied tuples

2021-04-04 Thread Greg Ewing

On 5/04/21 11:47 am, dn wrote:

I think I've read that the compiler is smart-enough to realise that the
RHS 'literal-tuples'?'tuple-literals' are being used as a 'mechanism',
and thus the inits are in-lined.


It does indeed seem to do this in some cases:

>>> def g(i, j, k):
...  a, b, c = i, j, k
...
>>> dis(g)
  2   0 LOAD_FAST0 (i)
  2 LOAD_FAST1 (j)
  4 LOAD_FAST2 (k)
  6 ROT_THREE
  8 ROT_TWO
 10 STORE_FAST   3 (a)
 12 STORE_FAST   4 (b)
 14 STORE_FAST   5 (c)
 16 LOAD_CONST   0 (None)
 18 RETURN_VALUE

If the RHS is a literal, it's a bit different:

>>> def f():
...  a, b, c = 1, 2, 3
...
>>> dis(f)
  2   0 LOAD_CONST   1 ((1, 2, 3))
  2 UNPACK_SEQUENCE  3
  4 STORE_FAST   0 (a)
  6 STORE_FAST   1 (b)
  8 STORE_FAST   2 (c)
 10 LOAD_CONST   0 (None)
 12 RETURN_VALUE

Here the tuple creation is being done at compile time,
so there's still an unpacking operation. It might not be
much different speed-wise from loading the values separately,
though.

--
Greg

--
https://mail.python.org/mailman/listinfo/python-list


Re: Friday Finking: initialising values and implied tuples

2021-04-04 Thread dn via Python-list
On 04/04/2021 01.00, Rob Cliffe via Python-list wrote:
> 
> 
> On 03/04/2021 04:09, 2qdxy4rzwzuui...@potatochowder.com wrote:
>> On 2021-04-03 at 02:41:59 +0100,
>> Rob Cliffe via Python-list  wrote:
>>
>>>  x1 = 42; y1 =  3;  z1 = 10
>>>  x2 = 41; y2 = 12; z2 = 9
>>>  x3 =  8;  y3 =  8;  z3 = 10
>>> (please imagine it's in a fixed font with everything neatly vertically
>>> aligned).
>>> This has see-at-a-glance STRUCTURE: the letters are aligned vertically
>>> and the "subscripts" horizontally.  Write it as 9 lines and it becomes
>>> an amorphous mess in which mistakes are harder to spot.
>> I agree that writing it as 9 lines is an accident waiting to happen, but
>> if you must see that structure, then go all in:
>>
>>  (x1, y1, z1) = (43,  3, 10)
>>  (x2, y2, z2) = (41, 12,  9)
>>  (x3, y3, z3) = ( 8,  8, 10)
> Agreed, that is even easier to read.  (It would be kinda nice if the
> compiler could optimise the tuples away, for those of us who are
> paranoid about performance.)

I think I've read that the compiler is smart-enough to realise that the
RHS 'literal-tuples'?'tuple-literals' are being used as a 'mechanism',
and thus the inits are in-lined. Apologies: I can't find a web.ref.
Likely one of our colleagues, who is 'into' Python-internals, could
quickly clarify...


Can I invite you/us/all/each to think on these ideas a bit further?
(I'd like to conflate a few earlier contributions, if I may)


Way back, when people like @Alan and myself were young and innocent (and
the power to run mainframe computers was produced by dinosaurs running
in treadmills) we didn't have PEP-008 advice, but suffered hard-limits,
such as 80-column cards. Both RAM and secondary-storage costs were $big,
so we were taught all manner of 'conservation' techniques, eg

scX = 1# starting co-ordinates
scY = 2
scZ = 3

The abbreviated names required noticeably shorter processing times. The
comment was necessary because "sc" or "scX" could be interpreted as
abbreviations for many, diverse, things. However, the obvious draw-back?
Later in the code, when we came to "scX", we had no such
handy-reminder/Cliff-Notes!

(and yes, teaching-languages, such as Dartmouth BASIC, did limit
variable-names to single letters, etc, - and yes, once common letters
such as r, e, i, n, x, etc had been assigned one might be forced to use
"q" to count the number of eggs. What? Once such languages have warped
one's mind, recovery is all-but impossible! So, now you know...)


Accordingly, having over-come the limits of the past, current advice is
to choose names wisely - and in doing-so, obviate the need for such
comments, eg

starting_coordinate_X = 1
...


The initial 'complaint' against the idea of "long" identifiers relates
to typing competence. It's all very well to have meaningful-names, but
the more typing that has to be done, the more opportunity for errors to
be introduced/creep-in/insinuate themselves (let's be clear - it's not
my typing, it's all the error's fault!)

However, today's editors and IDEs are sufficient agile as to be able to
suggest intelligent and context-aware "completion" suggestions - most
even allowing the choice to be made without lifting hands from keyboard.
So, can we discard the 'too hard' complaint?


A point made earlier (in the thread), was that some of the data-items
'belonged together' and thus it would be reasonably sensible to group
them, eg

(x1, y1, z1) = (43,  3, 10)

This is often the reason for a longer 'list' of initialisations (but the
converse does not apply: a longer list may not consist of
closely-related data-items!)

The implication is that the x, y, and z values are related, eg a 3D
co-ordinate; and thus it does not impose "cognitive load" to initialise
them in a relative fashion (the second value "3", relates to the second
identifier "y1"). The small number of elements is relevant!

Good thinking!


Another suggestion for this situation, is to use a named-tuples. From
the (fine) manual:

"Named tuples assign meaning to each position in a tuple and allow for
more readable, self-documenting code. They can be used wherever regular
tuples are used, and they add the ability to access fields by name
instead of position index."
(https://docs.python.org/3/library/collections.html?highlight=namedtuple#collections.namedtuple)


Borrowing the manual's example-code (apologies for any unfortunate
word-wrapping by my email-client):

>>> # Basic example
>>> Point = namedtuple('Point', ['x', 'y'])
>>> p = Point(11, y=22) # instantiate with positional or keyword
arguments
>>> p[0] + p[1] # indexable like the plain tuple (11, 22)
33
>>> x, y = p# unpack like a regular tuple
>>> x, y
(11, 22)
>>> p.x + p.y   # fields also accessible by name
33
>>> p   # readable __repr__ with a name=value style
Point(x=11, y=22)

The drawback/cost/effort-required is that the named-tuple must have been
defined previously, and only then can we employ s

Re: Friday Finking: initialising values and implied tuples

2021-04-04 Thread dn via Python-list
On 03/04/2021 11.25, Marco Ippolito wrote:
>> (a) basic linear presentation:
>>
>> resource = "Oil"
>> time = 1
>> crude = 2
>> residue = 3
>> my_list = "long"
>>
>> (b) using explicit tuples:
>>
>> ( resource, time, crude, residue, my_list ) = ( "Oil", 1, 2, 3, "long" )
>>
>> (c) linear and indented tuples:
>>
>> (
>> resource,
>> time,
>> crude,
>> residue,
>> my_list
>> ) = (
>> "Oil",
>> 1,
>> 2,
>> 3,
>> "long"
>> )
> 
> Choose: (a).
> 
> In (b) I have a problem matching identifiers to values horizontally at a
> glance and in (c) I have the same problem vertically: i.e. "is 3 the value for
> residue or crude above/to-the-left?"
> 
> Cognitive burden slows down and fatigues.

+1


> Alternatively, if the data "fits together", use a `namedtuple` with kwarg
> initialisation or structured data types like `dataclasses`.

Whereas the other formats cannot, it would be very easy to turn an (a)
type of list into a dataclass!
-- 
Regards,
=dn
-- 
https://mail.python.org/mailman/listinfo/python-list


[RELEASE] Python 3.9.4 hotfix is now available

2021-04-04 Thread Łukasz Langa
Python 3.9.3 was released two days ago on Friday, April 2nd. It contains 
important security content listed below for reference. Unfortunately, it also 
introduced an unintentional ABI incompatibility, making some C extensions built 
with Python 3.9.0 - 3.9.2 crash with  Python 3.9.3 on 32-bit systems. To 
minimize disruption, I decided to recall 3.9.3 and introduce this hotfix 
release: 3.9.4.

We highly recommend upgrading your Python 3.9 installations to 3.9.4 at your 
earliest convenience.

Get it here:

https://www.python.org/downloads/release/python-394/ 

What is “ABI compatibility”?

Python guarantees that within a given language series (like the current 3.9) 
binary extensions written in C or C++ and compiled against headers of one 
release (like 3.9.0) will be importable from other versions in the same series 
(like 3.9.3). If this weren’t the case, library authors would have to ship 
separate binary wheels on PyPI for every single bugfix release of Python. That 
would be very inconvenient.

 
What
 broke in Python 3.9.3?

In a fix for a corner-case crash around recursion limits and exceptions, the 
PyThreadState struct needed to change. While PyThreadState’s only documented 
public member is the *interp field 
, it’s not 
uncommon for C extensions to access other fields in this struct as well.

When I approved the backport of this fix, I missed the fact that the variable 
size change would change the memory layout of said struct on 32-bit systems (on 
64-bit systems alignment rules made the size change backwards compatible). 
Merging the backport was a mistake, and so 3.9.4 reverts it to restore 
compatibility with binary extensions built against Python 3.9.0 - 3.9.2. 
Details in bpo-43710 .

 
Security
 Content in Python 3.9.3

bpo-43631 : high-severity CVE-2021-3449 and 
CVE-2021-3450 were published for OpenSSL, it’s been upgraded to 1.1.1k in CI, 
and macOS and Windows installers.
bpo-42988 : CVE-2021-3426: Remove the 
getfile feature of the pydoc module which could be abused to read arbitrary 
files on the disk (directory traversal vulnerability). Moreover, even source 
code of Python modules can contain sensitive data like passwords. Vulnerability 
reported by David Schwörer.
bpo-43285 : ftplib no longer trusts the IP 
address value returned from the server in response to the PASV command by 
default. This prevents a malicious FTP server from using the response to probe 
IPv4 address and port combinations on the client network. Code that requires 
the former vulnerable behavior may set a trust_server_pasv_ipv4_address 
attribute on their ftplib.FTP instances to True to re-enable it.
bpo-43439 : Add audit hooks for 
gc.get_objects(), gc.get_referrers() and gc.get_referents(). Patch by Pablo 
Galindo.
 
Release
 Calendar

Maintenance releases for the 3.9 series will continue at regular bi-monthly 
intervals, with 3.9.5 planned for May 3rd 2021 as well.

 
What’s
 new?

The Python 3.9 series contains many new features and optimizations over 3.8. 
See the “What’s New in Python 3.9  
” document for more information 
about features included in the 3.9 series. We also have a detailed change log 
for 3.9.3  
specifically.

Detailed information about all changes made in version 3.8.9 can be found in 
its respective changelog 
.

 
We
 hope you enjoy those new releases!

Thanks to all of the many volunteers who help make Python Development and these 
releases possible! Please consider supporting our efforts by volunteering 
yourself or through organization contributions to the Python Software 
Foundation.

Your friendly release team,
Łukasz Langa @ambv 
Ned Deily @nad 
Steve Dower @steve.dower 
-- 
https://mail.python.org/mailman/listinfo/python-list


Matplotlib scale

2021-04-04 Thread Julien Hofmann
Hi everyone,


I've created a code to run a 2D mapping using matplotlib from a .csv file.
I've tried to set the maximum color (red) of the scale as 80% of the maximum 
value and not as the maximum value of my .csv file.
Does someone know how to modify that?
I've tried different solution but it doesn't work.

Thanks

import os 
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from matplotlib import colorbar, colors
import matplotlib.tri as tri
 
#os.chdir("C:/Users/Julien Hofmann/Desktop/Nano-indentation")
data = pd.read_csv("Cartographie.csv",sep=';')
 
nb_lignes=21
nb_colonnes=27
 
 
fig = plt.figure(figsize=(15,12))
ax = plt.subplot(1,1,1)
x=np.linspace(0,(data["x"][len(data["x"])-1]-data["x"][0])*1000,nb_colonnes)
y=np.linspace(0,(data["y"][len(data["y"])-1]-data["y"][0])*1000,nb_lignes)
X,Y=np.meshgrid(x,y)
 
 
z=np.array(data["Durete"])
triang = tri.Triangulation(data["x"], data["y"])
interpolator = tri.LinearTriInterpolator(triang, z)
Xi, Yi = np.meshgrid(x, y)
zi = interpolator(Xi, Yi)
cntr1 = ax.contourf(x, y, z.reshape(nb_lignes,nb_colonnes), levels=150, 
cmap="jet")
cbar = fig.colorbar(cntr1, ax=ax)
ax.axis('on')
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Horrible abuse of __init_subclass__, or elegant hack?

2021-04-04 Thread Chris Angelico
On Mon, Apr 5, 2021 at 2:21 AM jak  wrote:
>
> I modified your code in the following way:
>
> line 65-66:
> from:
>
>  if (qty <= alternate["per_minute"]
> and (costs[Extractor], costs) > (alternate["costs"][Extractor],
> alternate["costs"])
>
> to:
>  if (qty <= alternate["per_minute"]
>  and (costs[Extractor], set(costs)) >
> (alternate["costs"][Extractor], set(alternate["costs"]))


Unfortunately, set comparisons aren't equivalent. The point of these
checks is to see if the quantities are also lower (or higher) than on
the other side.

It'd probably be easiest to monkeypatch the functionality in. You can
either borrow the implementation from the CPython sources (it uses
all() and a couple of nested loops to scan over everything), or use
this implementation:

class Counter(Counter):
def __le__(self, other):
return not (self - other)
def __gt__(self, other):
return not (self <= other)

When you subtract a Counter from a Counter, anything that would become
negative is omitted, so if subtracting the Counters results in an
empty container, this one is less than that one.

> The program runs now. Is the result correct?
>
> Specify one or more target items

Well, it successfully ran to completion, which is a good sign, but
it's impossible to say whether it's correct since it didn't actually
produce any real output. Try adding an argument:

PRODUCING: Fuel

Requires Oil at 100.00%
Produces 40/min Fuel
Produces 30/min Resin
Crude - Extractor at 100.00%
Fuel - Refinery at 100.00%

Requires Oil at 250.00%
Requires Water at 83.33%
Produces 100/min Fuel
Produces 100/min Plastic
Crude - Extractor at 250.00%
Plastic - Refinery at 500.00%
Water - Extractor at 83.33%
Diluted Fuel - Blender at 100.00%

Requires Oil at 125.00%
Requires Water at 83.33%
Produces 100/min Fuel
Produces 50/min Rubber
Crude - Extractor at 125.00%
Rubber - Refinery at 250.00%
Water - Extractor at 83.33%
Diluted Fuel - Blender at 100.00%

Requires Water at 83.33%
Requires Oil at 62.50%
Produces 100/min Fuel
Produces 25/min Resin
Crude - Extractor at 62.50%
Heavy Oil Residue - Refinery at 125.00%
Water - Extractor at 83.33%
Diluted Fuel - Blender at 100.00%


I've incorporated this change (and a small clarifying tweak to the
failure message) into the pushed version, so rather than manually
making the change, you could grab a fresh copy, if that's easier.

Thanks for pointing this out. I like to support more Python versions
than just the unreleased alpha!!

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Horrible abuse of __init_subclass__, or elegant hack?

2021-04-04 Thread jak

Il 04/04/2021 18:18, jak ha scritto:

Il 04/04/2021 11:13, Chris Angelico ha scritto:

On Sun, Apr 4, 2021 at 6:26 PM jak  wrote:


Il 01/04/2021 01:14, Chris Angelico ha scritto:


copy / paste corrupted the tabs, sorry
--
https://mail.python.org/mailman/listinfo/python-list


Re: Horrible abuse of __init_subclass__, or elegant hack?

2021-04-04 Thread jak

Il 04/04/2021 11:13, Chris Angelico ha scritto:

On Sun, Apr 4, 2021 at 6:26 PM jak  wrote:


Il 01/04/2021 01:14, Chris Angelico ha scritto:

I think this code makes some sort of argument in the debate about
whether Python has too much flexibility or if it's the best
metaprogramming toolset in the world. I'm not sure which side of the
debate it falls on, though.

class Building:
  resource = None
  @classmethod
  def __init_subclass__(bldg):
  super().__init_subclass__()
  print("Building:", bldg.__name__)
  def make_recipe(recip):
  print(recip.__name__.replace("_", " "), "is made in a",
bldg.__name__.replace("_", " "))
  bldg.__init_subclass__ = classmethod(make_recipe)


class Extractor(Building): ...
class Refinery(Building): ...

class Crude(Extractor):
  resource = "Oil"
  time: 1
  Crude: 1

class Plastic(Refinery):
  Crude: 3
  time: 6
  Residue: 1
  Plastic: 2

class Rubber(Refinery):
  Crude: 3
  time: 6
  Residue: 2
  Rubber: 2

Full code is here if you want context:
https://github.com/Rosuav/shed/blob/master/satisfactory-production.py

Subclassing Building defines a class that is a building. (The ellipsis
body is a placeholder; I haven't implemented stuff where the buildings
know about their power consumptions and such. Eventually they'll have
other attributes.) But subclassing a building defines a recipe that is
produced in that building. Markers placed before the "time" are
ingredients, those after the "time" are products.

There are actually a lot of interesting wrinkles to trying to replace
__init_subclass__ on the fly. Things get quite entertaining if you
don't use the decorator, or if you define and decorate the function
outside of the class, or various other combinations.

On a scale of 1 to "submit this to The Daily WTF immediately", how bad
is this code? :)

ChrisA



Hi,
from https://github.com/Rosuav/shed/blob/master/satisfactory-production.py
I get this error:

cmd console Win10:
$> py -V
Python 3.8.6

$> py CrisAngelico.py
Building: Extractor
Building: Refinery
Building: Blender
Building: Packager
Building: Assembler
Crude is made in a Extractor
Water is made in a Extractor
Plastic is made in a Refinery
Rubber is made in a Refinery
Traceback (most recent call last):
File "CrisAngelico.py", line 123, in 
  class Rubber(Refinery):
File "CrisAngelico.py", line 72, in make_recipe
  if net <= alternate["makes"] and costs >= alternate["costs"]:
TypeError: '<=' not supported between instances of 'Counter' and 'Counter'



Huh. I forget sometimes which version something was introduced in.
Apparently the comparison operators on Counters came in with Python
3.10. Sorry about that. As an alternative, subtraction is very
approximately equivalent (if subtracting one counter from another
yields nothing, then the first one is smaller in total content than
the second), so it should be possible to adjust it.

ChrisA


I modified your code in the following way:

line 65-66:
from:

if (qty <= alternate["per_minute"]
	and (costs[Extractor], costs) > (alternate["costs"][Extractor], 
alternate["costs"])


to:
if (qty <= alternate["per_minute"]
and (costs[Extractor], set(costs)) > 
(alternate["costs"][Extractor], set(alternate["costs"]))


and line 72:
from:
if net <= alternate["makes"] and costs >= alternate["costs"]:

to:
if set(net) <= set(alternate["makes"]) and set(costs) >= 
set(alternate["costs"]):



The program runs now. Is the result correct?

Building: Extractor
Building: Refinery
Building: Blender
Building: Packager
Building: Assembler
Crude is made in a Extractor
Water is made in a Extractor
Plastic is made in a Refinery
Rubber is made in a Refinery
Fuel is made in a Refinery
Heavy Oil Residue is made in a Refinery
Polymer Resin is made in a Refinery
Residual Fuel is made in a Refinery
Diluted Fuel is made in a Blender
Canister is made in a Extractor
Package Water is made in a Packager
Diluted Packaged Fuel is made in a Refinery
Unpackage Fuel is made in a Packager
Petroleum Coke is made in a Refinery
Residual Plastic is made in a Refinery
Residual Rubber is made in a Refinery
Recycled Plastic is made in a Refinery
Recycled Rubber is made in a Refinery
Sulfur is made in a Extractor
Coal is made in a Extractor
Compacted is made in a Assembler
Turbofuel is made in a Refinery
Turbo Heavy Fuel is made in a Refinery
Turbo Blend Fuel is made in a Blender
Specify one or more target items
Exit code:  0

(forgive me your trouble)
cheers
--
https://mail.python.org/mailman/listinfo/python-list


Re: About \033[m

2021-04-04 Thread Skip Montanaro
>Porque quando se usa formatac,ao de cores, o python nao consegue
>
   centralizar dentro da cadeia de 40 caracteres ?
>
>Tive que colocar 54 no parametro pois de alguma forma esta sendo
>considerado os caracteres de dentro do comando \033[m


Python doesn't know there is anything special about escape sequences (that
they take up no space on the screen). I think you will have better results
if you place the escape sequences in the format specifier:

 print("\033[7;30;43m{:^40}\033[m".format("Programac,ao Python"))

( haven't tried this, but I think it will work as you expect.)

Skip
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Horrible abuse of __init_subclass__, or elegant hack?

2021-04-04 Thread Chris Angelico
On Sun, Apr 4, 2021 at 6:26 PM jak  wrote:
>
> Il 01/04/2021 01:14, Chris Angelico ha scritto:
> > I think this code makes some sort of argument in the debate about
> > whether Python has too much flexibility or if it's the best
> > metaprogramming toolset in the world. I'm not sure which side of the
> > debate it falls on, though.
> >
> > class Building:
> >  resource = None
> >  @classmethod
> >  def __init_subclass__(bldg):
> >  super().__init_subclass__()
> >  print("Building:", bldg.__name__)
> >  def make_recipe(recip):
> >  print(recip.__name__.replace("_", " "), "is made in a",
> > bldg.__name__.replace("_", " "))
> >  bldg.__init_subclass__ = classmethod(make_recipe)
> >
> >
> > class Extractor(Building): ...
> > class Refinery(Building): ...
> >
> > class Crude(Extractor):
> >  resource = "Oil"
> >  time: 1
> >  Crude: 1
> >
> > class Plastic(Refinery):
> >  Crude: 3
> >  time: 6
> >  Residue: 1
> >  Plastic: 2
> >
> > class Rubber(Refinery):
> >  Crude: 3
> >  time: 6
> >  Residue: 2
> >  Rubber: 2
> >
> > Full code is here if you want context:
> > https://github.com/Rosuav/shed/blob/master/satisfactory-production.py
> >
> > Subclassing Building defines a class that is a building. (The ellipsis
> > body is a placeholder; I haven't implemented stuff where the buildings
> > know about their power consumptions and such. Eventually they'll have
> > other attributes.) But subclassing a building defines a recipe that is
> > produced in that building. Markers placed before the "time" are
> > ingredients, those after the "time" are products.
> >
> > There are actually a lot of interesting wrinkles to trying to replace
> > __init_subclass__ on the fly. Things get quite entertaining if you
> > don't use the decorator, or if you define and decorate the function
> > outside of the class, or various other combinations.
> >
> > On a scale of 1 to "submit this to The Daily WTF immediately", how bad
> > is this code? :)
> >
> > ChrisA
> >
>
> Hi,
> from https://github.com/Rosuav/shed/blob/master/satisfactory-production.py
> I get this error:
>
> cmd console Win10:
> $> py -V
> Python 3.8.6
>
> $> py CrisAngelico.py
> Building: Extractor
> Building: Refinery
> Building: Blender
> Building: Packager
> Building: Assembler
> Crude is made in a Extractor
> Water is made in a Extractor
> Plastic is made in a Refinery
> Rubber is made in a Refinery
> Traceback (most recent call last):
>File "CrisAngelico.py", line 123, in 
>  class Rubber(Refinery):
>File "CrisAngelico.py", line 72, in make_recipe
>  if net <= alternate["makes"] and costs >= alternate["costs"]:
> TypeError: '<=' not supported between instances of 'Counter' and 'Counter'
>

Huh. I forget sometimes which version something was introduced in.
Apparently the comparison operators on Counters came in with Python
3.10. Sorry about that. As an alternative, subtraction is very
approximately equivalent (if subtracting one counter from another
yields nothing, then the first one is smaller in total content than
the second), so it should be possible to adjust it.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Horrible abuse of __init_subclass__, or elegant hack?

2021-04-04 Thread jak

Il 01/04/2021 01:14, Chris Angelico ha scritto:

I think this code makes some sort of argument in the debate about
whether Python has too much flexibility or if it's the best
metaprogramming toolset in the world. I'm not sure which side of the
debate it falls on, though.

class Building:
 resource = None
 @classmethod
 def __init_subclass__(bldg):
 super().__init_subclass__()
 print("Building:", bldg.__name__)
 def make_recipe(recip):
 print(recip.__name__.replace("_", " "), "is made in a",
bldg.__name__.replace("_", " "))
 bldg.__init_subclass__ = classmethod(make_recipe)


class Extractor(Building): ...
class Refinery(Building): ...

class Crude(Extractor):
 resource = "Oil"
 time: 1
 Crude: 1

class Plastic(Refinery):
 Crude: 3
 time: 6
 Residue: 1
 Plastic: 2

class Rubber(Refinery):
 Crude: 3
 time: 6
 Residue: 2
 Rubber: 2

Full code is here if you want context:
https://github.com/Rosuav/shed/blob/master/satisfactory-production.py

Subclassing Building defines a class that is a building. (The ellipsis
body is a placeholder; I haven't implemented stuff where the buildings
know about their power consumptions and such. Eventually they'll have
other attributes.) But subclassing a building defines a recipe that is
produced in that building. Markers placed before the "time" are
ingredients, those after the "time" are products.

There are actually a lot of interesting wrinkles to trying to replace
__init_subclass__ on the fly. Things get quite entertaining if you
don't use the decorator, or if you define and decorate the function
outside of the class, or various other combinations.

On a scale of 1 to "submit this to The Daily WTF immediately", how bad
is this code? :)

ChrisA



Hi,
from https://github.com/Rosuav/shed/blob/master/satisfactory-production.py
I get this error:

cmd console Win10:
$> py -V
Python 3.8.6

$> py CrisAngelico.py
Building: Extractor
Building: Refinery
Building: Blender
Building: Packager
Building: Assembler
Crude is made in a Extractor
Water is made in a Extractor
Plastic is made in a Refinery
Rubber is made in a Refinery
Traceback (most recent call last):
  File "CrisAngelico.py", line 123, in 
class Rubber(Refinery):
  File "CrisAngelico.py", line 72, in make_recipe
if net <= alternate["makes"] and costs >= alternate["costs"]:
TypeError: '<=' not supported between instances of 'Counter' and 'Counter'

:^(
--
https://mail.python.org/mailman/listinfo/python-list