Re: Pylint false positives

2018-08-16 Thread Steven D'Aprano
On Fri, 17 Aug 2018 08:14:02 +0200, Frank Millman wrote:

> How would you extend it without a long chain of
> if isinstance(v, str):
>   [perform checks for str]
> elif isinstance(v, int)
>   [perform checks for int]
> etc
> etc
> 
> I find that using a separate method per subclass does exactly what I
> want, and that part of my project has been working stably for some time.

You might consider using single dispatch instead:

https://docs.python.org/3/library/functools.html#functools.singledispatch





-- 
Steven D'Aprano
"Ever since I learned about confirmation bias, I've been seeing
it everywhere." -- Jon Ronson

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


Re: Pylint false positives

2018-08-16 Thread Steven D'Aprano
On Wed, 15 Aug 2018 10:44:57 +, Jon Ribbens wrote:

> Obviously what I'm objecting to is not the presence of a loop, it's the
> presence of many obscure, bodgey and/or broken features all lumped
> together:

>   * using @abstractmethod without metaclass=ABCMeta 

I'll cop to that one -- it was a bug in my made-up pseudo-code. I simply 
assumed that people would know you need to use ABCMeta.

Meap culpa.


On the other hand, your objection to the following three idioms is as 
good an example of the Blurb Paradox as I've ever seen. Python is 
designed to do these sorts of things. Failing to use them when it 
simplifies your code is like hiring a fork-lift to lift and turn your car 
around because using reverse gear is "obscure, bodgey and/or broken".

>   * code running directly under the class definition 
>   * creating a method then changing its name with foo.__name__ 
>   * poking things into to the class namespace with locals() 

Each of these are standard Python techniques, utterly unexceptional.

"Code running directly under the class" describes every use of the class 
keyword (except those with an empty body). If you write:

class Spam:
x = 1

you are running code under the class. This is not just a pedantic 
technicality, it is fundamental to Python's execution model. If someone 
does not understand this fact, they don't understand Python.

The Python interpreter goes to great lengths to insert the class 
namespace into the execution scope while executing code under the class 
body, and has done so since Python 1.5 or older, even before it had 
lexical scoping!

[steve@ando ~]$ python1.5
Python 1.5.2 (#1, Aug 27 2012, 09:09:18)  [GCC 4.1.2 20080704 (Red Hat 
4.1.2-52)] on linux2
Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam
>>> x = 23
>>> class Spam:
... x = 42
... y = x + 1
...
>>> print x, Spam.x, Spam.y
23 42 43


"Creating a method then changing its name" -- that's precisely what we do 
anytime we create a closure and modify it using functools.wraps. The only 
difference is that wraps hides that behind a decorator. Some of us have 
been using Python long enough to remember when the standard idiom for 
decorating a function was to manually adjust its name, docstring etc:

# Something like this.
def decorate(func):
def inner(arg):
preprocess()
x = func(arg)
postprocess()
return x
inner.__name__ = func.__name__
inner.__doc__ = func.__doc__
inner.__dict__.update(func.__dict__)
return inner


Now functools.wraps hides all that behind a convenient decorator 
interface, but we're still changing the name.

If you *don't* change the function's name, you're effectively populating 
your code with functions that might as well be anonymous, or at least 
have generic names like "inner". Why would you not give your functions 
meaningful names, just because they came out of a factory?


"Poking things into the class namespace with locals()" -- I'll admit that 
this one is a little rarer. But again, the interpreter goes to deliberate 
lengths to ensure that locals in a class body is available for writing. 
If we're not supposed to use locals, why do you think Python makes it 
available? Its not like writing to locals inside a class is any more 
bizarre than using getattr, its just less common.

Not one of those three techniques is "bodgey and/or broken", and if you 
think they're obscure, well, I'm sorry but that says more about the 
breadth of your Python knowledge than the feature itself.

Nobody calling themselves an experienced Python programmer ought to have 
any trouble reading and maintaining code like that I showed. If they do, 
they have a serious hole in their knowledge of the language, like a C 
programmer who doesn't get pointers.


>   * dynamically adding @abstractmethod methods to a class

I simply don't get this objection at all. All methods are added 
dynamically to classes (that's how Python's execution model works, def is 
an executable statement not a declaration). Making them abstract doesn't 
change this.

You might be thinking of the warning in the docs:

"Dynamically adding abstract methods to a class, [...] 
[is] not supported."

but that is talking about the case where you add the method to the class 
after the class is created, from the outside:

class X(metaclass=ABCMeta):
def method(self):
pass

# Doesn't work.
X.method = abstractmethod(X.method)


But this works exactly as you would expect:


py> class Foo(metaclass=abc.ABCMeta):
... for name in ('spam', 'eggs'):
... @abc.abstractmethod
... def inner(self): pass
... inner.__name__ = name
... locals()[name] = inner
... del inner
...
py> class Bar(Foo):
... pass
...
py> Bar()
Traceback (most recent call last):
  File "", line 1, in 
TypeError: Can't instantiate abstract class Bar with abstract
methods eggs, spam



> (Not to mention your code mean

Re: Pylint false positives

2018-08-16 Thread Frank Millman
"D'Arcy Cain"  wrote in message 
news:6b4b8587-46c0-19b0-c538-efdf396f0...@vybenetworks.com...


On 2018-08-14 04:58 AM, Frank Millman wrote:
> As an example, I have a master class defining a unit of data (i.e. the
> value of a column) retrieved from a database. I have separate
> sub-classes for each data type - text, integer, date, etc. To ensure
> that a value is valid before storing it as an instance attribute, I call
> a method called 'check_value'. The details of check_value vary according
> to the data type, but that is transparent to the piece of code that
> calls check_value().

class classA:
  DATATYPE = None # Or default type

  def check_value(self, v)
if not isinstance(v, self.DATATYPE):
  raise RuntimeError("Invalid data type for '%s'" % v)

class classB(classA):
  DATATYPE = int

Very simplistic and untested but does that give you any ideas?
Hopefully your email client doesn't mess up the formatting.  You can
fill out check_value to do more than simply check the the type matches
and you can also do further checks based on the type.  Also, you can
have more than one sub-class doing the same check without having to cut
and paste code from another class.



Thanks, D'Arcy. That is a neat idea if all you want to do is check the data 
type, but I do a lot more than that.


How would you extend it without a long chain of
   if isinstance(v, str):
 [perform checks for str]
   elif isinstance(v, int)
 [perform checks for int]
   etc
   etc

I find that using a separate method per subclass does exactly what I want, 
and that part of my project has been working stably for some time.


The only thing that has changed is that I recently started using pylint (as 
a result of switching my editor to VS Code).


My main class has the following method (simplified) -

class Field:
   def setval(self, value):  # handle value received from external source

   """
   checkval is a method defined in each subclass
   it does a bit of typecasting, so value is replaced on return
   it can raise an exception, which is caught elsewhere
   """

   value = self.checkval(value)  # this is the line that pylint 
complains about


   [various other checks]
   if all checks are passed:
   self._value = value

Frank


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


Re: Program to output a subset of the composite numbers

2018-08-16 Thread tomusatov
Yes, I will try it! Thank you kindly.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Program to output a subset of the composite numbers

2018-08-16 Thread tomusatov
I'm sorry I did not correctly state the subset I was after:

"Composite numbers that are one less than twice a composite."

The output would begin:

DATA
15, 27, 35, 39, 49, 50, 51, 55, 63, 65, 69, 75, 77, 87, 91, 95, 99, 111, 115, 
119, 123, 125, 129, 135, 143, 147, 153, 155, 159, 161, 169, 171, 175, 183, 185, 
187, 189, 195, 203, 207, 209, 215, 219, 221
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Program to output a subset of the composite numbers

2018-08-16 Thread tomusatov
Thanks, I think that is an interesting tactic. From there what might the 
language look like to filter out the composites that are not one less than 
twice another composite number?
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Program to output a subset of the composite numbers

2018-08-16 Thread tomusatov
DATA 
15, 27, 35, 39, 49, 50, 51, 55, 63, 65, 69, 75, 77, 87, 91, 95, 99, 111, 115, 
119, 123, 125, 129, 135, 143, 147, 153, 155, 159, 161, 169, 171, 175, 183, 185, 
187, 189, 195, 203, 207, 209, 215, 219, 221 
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: printing to stdout

2018-08-16 Thread Cameron Simpson

On 16Aug2018 22:37, richard lucassen  wrote:

I can run a shell script from the commandline as root in which I start
a python script as user "ha". The output to stdout and stderr
generated by the python script is visible in an xterm:

#!/bin/dash
exec 2>&1
chpst -u ha:ha:i2c -U ha /usr/local/ha/init.sh
exec chpst -u ha:ha:i2c:gpio /usr/local/ha/wait4int.py

So far so good. But when I run the script supervised by runit, I can
see the output generated by the shell script "init.sh", but the output
of the python script is not transferred to the supervised logging. The
python script itself works, it reads out some I/O expanders on a
Raspberry Pi. But the output of the "print" commands seems to disappear:

[...]

This isn't specific to Python, you'll find it with most programmes. (The 
shell's builtin "echo" command is an exception.)


Some discussion: most output streams are buffered: this means that when you 
issue some kind of "write" operation to them, the output data are copied to a 
buffer area in memory, and only actually written out to the operating system 
(which mediates the data between programmes) at certain times. This reduces the 
OS level data transfers, which is generally a performance win overall.


When are the data sent on to the OS? That depends on the buffered arrangement.  
When the buffer fills, the data are always sent on because otherwise there's no 
room for more data. But otherwise, the data are sent on at specific times.


An unbuffered stream sends the data on immediately. The standard error stream 
is usually unbuffered, so that error messages get out immediately.


A fully buffered stream is sent on only when the buffer fills.

A line buffered stream is sent on when a newline lands in the buffer.

You can of course devise whatever system you like, but these three are the 
common presupplied automatic ones.


Also, you can usually force any buffered data to be send on by flushing the 
buffer.


On UNIX systems, the _default_ behaviour of the standard output stream depends 
on what it is connected to. Stdout is line buffered when connected to a 
terminal and fully buffered otherwise. This generally makes for nice 
interactive behaviour (you see timely output when working interactively) and 
better overall performance when the output is going to a file or a pipe.


So let's look at your script:


 print ("%x: %x" % (pcf, output))

[...]

 print ('[ALERT] possible INT loop, disable 10 seconds')


Your programme will be writing into a buffer. Your messages only go out when 
enough have accrued to fill the buffer.


To force te messages to go out in a timely manner you need to flush the buffer.  
You have two choices here: call sys.stdout.flush() or pass "flush=True" with 
the print call, eg:


 print(, flush=True)

Just looking at your loop I would be inclined to just call flush once at the 
bottom, _before_ the sleep() call:


 sys.stdout.flush()

Your call; the performance difference will be small, so it tends to come down 
to keeping your code readable and maintainable.


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


printing to stdout

2018-08-16 Thread richard lucassen
I can run a shell script from the commandline as root in which I start
a python script as user "ha". The output to stdout and stderr
generated by the python script is visible in an xterm:

#!/bin/dash
exec 2>&1
chpst -u ha:ha:i2c -U ha /usr/local/ha/init.sh
exec chpst -u ha:ha:i2c:gpio /usr/local/ha/wait4int.py

So far so good. But when I run the script supervised by runit, I can
see the output generated by the shell script "init.sh", but the output
of the python script is not transferred to the supervised logging. The
python script itself works, it reads out some I/O expanders on a
Raspberry Pi. But the output of the "print" commands seems to disappear:

[..]
while True:
  if GPIO.input(23) == 1: # if still 0, another event has occurred
GPIO.wait_for_edge(23, GPIO.FALLING)
  print ('---')
  while GPIO.input(23) == 0:
for pcf in pcf_present:
  output = bus.read_byte(pcf)
  print ("%x: %x" % (pcf, output))
  if GPIO.input(23) == 1:
loopcntr = 0
break
  else:
loopcntr += 1
if loopcntr >=20:
  print ('[ALERT] possible INT loop, disable 10 seconds')
  sleep (10)
GPIO.cleanup()

Anyone a hint? Note: I'm a newbie to python.

-- 
richard lucassen
http://contact.xaq.nl/
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: lxml namespace as an attribute

2018-08-16 Thread Skip Montanaro
> You seem to think that you need to take the namespace definitions
> from the XML document itself. This is not the case: you can
> provide them from whatever soure you want.

I was under the impression that XML was a self-describing format. I've
been disabused of that notion.

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


Re: How to pass Python command line options (vs arguments) when running script directly vs via Python interpreter?

2018-08-16 Thread Thomas Jollans
On 2018-08-16 14:33, Chris Angelico wrote:
> On Thu, Aug 16, 2018 at 8:32 PM, Thomas Jollans  wrote:
>> On 2018-08-16 01:05, Chris Angelico wrote:
>>> On Thu, Aug 16, 2018 at 8:51 AM, Cameron Simpson  wrote:
 And as an additional alternative, when I want something weird (extra python
 args or the like) I usually make my script.py into a module and invoke it
 via a shell script, eg:

  #!/bin/sh
  exec /particular/python python-opts... -m script_module ${1+"$@"}

 Obviously that'd need a little adaption under Windows.
>>>
>>> Since an executable file without a shebang should normally be invoked
>>> through /bin/sh, you can actually combine this technique into the
>>> script itself with a cool hack:
>>
>> Well, sorta. Executable text files without a shebang line are not
>> executable per se, but most shells pretend they are. If you try to run a
>> shebang-less script through, say, Python's subprocess module, it won't work.
> 
> Good point. Still, for a lot of situations, it does allow you to
> invoke the .py file. I wonder if there's some sort of sneaky way to
> make the exec line appear as a comment to Python - probably involving
> quoting rules.

Easy as pie: (with an extra line)

'''exec' /usr/bin/env python3 -u -E -W error "$0" "$@"
'''
import sys
print('hello', sys.executable)

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


Re: Pylint false positives

2018-08-16 Thread D'Arcy Cain
On 2018-08-14 04:58 AM, Frank Millman wrote:
> "D'Arcy Cain"  wrote in message
>> I am also getting a funny smell from your description.  Are you sure
>> that you need to redefine the methods?  Perhaps you just need to define
>> some class variables and use one method.  You can also define your own
>> method and call the classA method inside it for common functionality.
> 
> As an example, I have a master class defining a unit of data (i.e. the
> value of a column) retrieved from a database. I have separate
> sub-classes for each data type - text, integer, date, etc. To ensure
> that a value is valid before storing it as an instance attribute, I call
> a method called 'check_value'. The details of check_value vary according
> to the data type, but that is transparent to the piece of code that
> calls check_value().

class classA:
  DATATYPE = None # Or default type

  def check_value(self, v)
if not isinstance(v, self.DATATYPE):
  raise RuntimeError("Invalid data type for '%s'" % v)

class classB(classA):
  DATATYPE = int

Very simplistic and untested but does that give you any ideas?
Hopefully your email client doesn't mess up the formatting.  You can
fill out check_value to do more than simply check the the type matches
and you can also do further checks based on the type.  Also, you can
have more than one sub-class doing the same check without having to cut
and paste code from another class.

-- 
D'Arcy J.M. Cain
Vybe Networks Inc.
http://www.VybeNetworks.com/
IM:da...@vex.net VoIP: sip:da...@vybenetworks.com
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How to pass Python command line options (vs arguments) when running script directly vs via Python interpreter?

2018-08-16 Thread Chris Angelico
On Thu, Aug 16, 2018 at 8:32 PM, Thomas Jollans  wrote:
> On 2018-08-16 01:05, Chris Angelico wrote:
>> On Thu, Aug 16, 2018 at 8:51 AM, Cameron Simpson  wrote:
>>> And as an additional alternative, when I want something weird (extra python
>>> args or the like) I usually make my script.py into a module and invoke it
>>> via a shell script, eg:
>>>
>>>  #!/bin/sh
>>>  exec /particular/python python-opts... -m script_module ${1+"$@"}
>>>
>>> Obviously that'd need a little adaption under Windows.
>>
>> Since an executable file without a shebang should normally be invoked
>> through /bin/sh, you can actually combine this technique into the
>> script itself with a cool hack:
>
> Well, sorta. Executable text files without a shebang line are not
> executable per se, but most shells pretend they are. If you try to run a
> shebang-less script through, say, Python's subprocess module, it won't work.

Good point. Still, for a lot of situations, it does allow you to
invoke the .py file. I wonder if there's some sort of sneaky way to
make the exec line appear as a comment to Python - probably involving
quoting rules.

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


Re: How to pass Python command line options (vs arguments) when running script directly vs via Python interpreter?

2018-08-16 Thread Thomas Jollans
On 2018-08-16 01:05, Chris Angelico wrote:
> On Thu, Aug 16, 2018 at 8:51 AM, Cameron Simpson  wrote:
>> And as an additional alternative, when I want something weird (extra python
>> args or the like) I usually make my script.py into a module and invoke it
>> via a shell script, eg:
>>
>>  #!/bin/sh
>>  exec /particular/python python-opts... -m script_module ${1+"$@"}
>>
>> Obviously that'd need a little adaption under Windows.
> 
> Since an executable file without a shebang should normally be invoked
> through /bin/sh, you can actually combine this technique into the
> script itself with a cool hack:

Well, sorta. Executable text files without a shebang line are not
executable per se, but most shells pretend they are. If you try to run a
shebang-less script through, say, Python's subprocess module, it won't work.

> 
> 
> exec /usr/local/bin/python3 -x -W error $0 "$@"
> """
> This is an example script.
> 
> It is executable and will invoke itself through Python.
> """
> import warnings
> warnings.warn("This should be an error.")
> print("This shouldn't happen.")
> 
> 
> The "-x" parameter means "skip the first line", and in a sense, the
> exec line is a non-standard shebang. :)
-- 
https://mail.python.org/mailman/listinfo/python-list