classification
Title: Dead code should be removed
Type: enhancement Stage: patch review
Components: Versions: Python 3.4
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: ezio.melotti, georg.brandl, python-dev, r.david.murray, rhettinger, tshepang, vstinner
Priority: normal Keywords: patch

Created on 2013-03-22 01:03 by vstinner, last changed 2013-03-26 00:18 by vstinner. This issue is now closed.

Files
File name Uploaded Description Edit
deadcode.patch vstinner, 2013-03-22 01:24 review
Messages (11)
msg184934 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2013-03-22 01:03
Using my astoptimizer project and the hook proposed in the issue #17515, I found the following dead code.
https://bitbucket.org/haypo/astoptimizer

Some code is not dead or unreachable in the general case, but only on a specific platform. I ran astoptimizer with all optimizations enabled, so os.name is replaced with "posix" for example. So "return os.name" is seen as dead code in the following function:

def _get_default_scheme():
    if os.name == 'posix':
        # the default scheme for posix is posix_prefix
        return 'posix_prefix'
    return os.name


Unreachable
===========

Lib/_pyio.py:2057: Assign(targets=[Name(id='initial_value', ctx=Store())], value=Call(func=Name(id='str', ctx=Load()), ...
Lib/sre_compile.py:68: Expr(value=Call(func=Name(id='emit', ctx=Load()), args=[Subscript(value=Name(id='OPCODES', ctx=Load(...
Lib/sre_compile.py:69: Assign(targets=[Name(id='skip', ctx=Store())], value=Call(func=Name(id='_len', ctx=Load()), args=[Na...
Lib/sre_compile.py:69: Expr(value=Call(func=Name(id='emit', ctx=Load()), args=[Num(n=0)], keywords=[], starargs=None, kwarg...
Lib/sre_compile.py:70: Expr(value=Call(func=Name(id='emit', ctx=Load()), args=[Subscript(value=Name(id='av', ctx=Load()), s...
Lib/sre_compile.py:71: Expr(value=Call(func=Name(id='emit', ctx=Load()), args=[Subscript(value=Name(id='av', ctx=Load()), s...
Lib/sre_compile.py:72: Expr(value=Call(func=Name(id='_compile', ctx=Load()), args=[Name(id='code', ctx=Load()), Subscript(v...
Lib/sre_compile.py:73: Expr(value=Call(func=Name(id='emit', ctx=Load()), args=[Subscript(value=Name(id='OPCODES', ctx=Load(...
Lib/sre_compile.py:74: Assign(targets=[Subscript(value=Name(id='code', ctx=Load()), slice=Index(value=Name(id='skip', ctx=L...
Lib/sysconfig.py:185: Return(value=Str(s='posix'))
Lib/test/test_posix.py:682: FunctionDef(name='_create_and_do_getcwd', args=arguments(args=[arg(arg='dirname', annotation=None), ...
Lib/test/test_posix.py:697: Expr(value=Call(func=Name(id='_create_and_do_getcwd', ctx=Load()), args=[Name(id='dirname', ctx=Load...
Lib/test/test_unicode.py:1938: Expr(value=Call(func=Attribute(value=Name(id='self', ctx=Load()), attr='assertRaises', ctx=Load()), ...


Dead code
=========

Lib/datetime.py:2128: Expr(value=Str(s='\nSome time zone algebra.  For a datetime x, let\n    x.n = x stripped of its time...
Lib/email/_header_value_parser.py:1337: Expr(value=Str(s="Parse strings according to RFC822/2047/2822/5322 rules.\n\nThis is a stateless par...
Lib/pickletools.py:148: Expr(value=Str(s='\n"A pickle" is a program for a virtual pickle machine (PM, but more accurately\nc...
Tools/scripts/reindent.py:56: Expr(value=Str(s='A specified newline to be used in the output (set by --newline option)'))


Almost Dead code
================

Lib/sqlite3/test/dump.py:44: Expr(value=ListComp(elt=Call(func=Attribute(value=Attribute(value=Name(id='self', ctx=Load()), attr=...
Lib/sqlite3/test/dump.py:49: Expr(value=ListComp(elt=Call(func=Attribute(value=Name(id='self', ctx=Load()), attr='assertEqual', c...
Lib/test/test_grammar.py:369: Expr(value=Num(n=1))
Lib/test/test_grammar.py:370: Expr(value=Tuple(elts=[Num(n=1), Num(n=2), Num(n=3)], ctx=Load()))
Lib/test/test_grammar.py:474: Expr(value=Tuple(elts=[Num(n=1), Yield(value=Num(n=1))], ctx=Load()))
Lib/test/test_grammar.py:475: Expr(value=Tuple(elts=[Num(n=1), YieldFrom(value=Tuple(elts=[], ctx=Load()))], ctx=Load()))
Lib/test/test_optparse.py:731: Expr(value=Tuple(elts=[Call(func=Attribute(value=Name(id='self', ctx=Load()), attr='assertParseOK', ...
Lib/test/test_optparse.py:741: Expr(value=Tuple(elts=[Call(func=Attribute(value=Name(id='self', ctx=Load()), attr='assertParseOK', ...
Lib/test/test_optparse.py:746: Expr(value=Tuple(elts=[Call(func=Attribute(value=Name(id='self', ctx=Load()), attr='assertParseOK', ...
Lib/test/test_optparse.py:749: Expr(value=Tuple(elts=[Call(func=Attribute(value=Name(id='self', ctx=Load()), attr='assertParseOK', ...
Lib/test/test_optparse.py:754: Expr(value=Tuple(elts=[Call(func=Attribute(value=Name(id='self', ctx=Load()), attr='assertParseOK', ...
Lib/test/test_peepholer.py:116: Expr(value=Tuple(elts=[UnaryOp(op=Invert(), operand=List(elts=[Num(n=0), Num(n=1), Num(n=2), Num(n=3...
Lib/test/test_peepholer.py:50: Expr(value=NameConstant(value=None))
Lib/test/test_peepholer.py:51: Expr(value=NameConstant(value=None))
Lib/test/test_peepholer.py:54: Expr(value=NameConstant(value=True))
Lib/test/test_peepholer.py:57: Expr(value=NameConstant(value=False))
Lib/test/test_posix.py:1046: Expr(value=Attribute(value=Name(id='posix', ctx=Load()), attr='RTLD_LAZY', ctx=Load()))
Lib/test/test_posix.py:1047: Expr(value=Attribute(value=Name(id='posix', ctx=Load()), attr='RTLD_NOW', ctx=Load()))
Lib/test/test_posix.py:1048: Expr(value=Attribute(value=Name(id='posix', ctx=Load()), attr='RTLD_GLOBAL', ctx=Load()))
Lib/test/test_posix.py:1049: Expr(value=Attribute(value=Name(id='posix', ctx=Load()), attr='RTLD_LOCAL', ctx=Load()))
Lib/test/test_pow.py:102: Expr(value=BinOp(left=NameConstant(value=None), op=Pow(), right=Call(func=Name(id='TestRpow', ctx=Lo...
Lib/test/test_raise.py:320: Expr(value=Name(id='xyzzy', ctx=Load()))
Lib/test/test_richcmp.py:218: Expr(value=UnaryOp(op=Not(), operand=Name(id='bad', ctx=Load())))
Lib/test/test_scope.py:578: Expr(value=ListComp(elt=Name(id='bad', ctx=Load()), generators=[comprehension(target=Name(id='s', ct...
Lib/test/test_scope.py:590: Expr(value=Name(id='x', ctx=Load()))
Lib/test/test_set.py:613: Expr(value=Compare(left=Name(id='myset', ctx=Load()), ops=[Lt()], comparators=[Name(id='myobj', ctx=...
Lib/test/test_set.py:617: Expr(value=Compare(left=Name(id='myset', ctx=Load()), ops=[Gt()], comparators=[Name(id='myobj', ctx=...
Lib/test/test_set.py:621: Expr(value=Compare(left=Name(id='myset', ctx=Load()), ops=[LtE()], comparators=[Name(id='myobj', ctx...
Lib/test/test_set.py:625: Expr(value=Compare(left=Name(id='myset', ctx=Load()), ops=[GtE()], comparators=[Name(id='myobj', ctx...
Lib/test/test_socket.py:1316: Expr(value=Attribute(value=Name(id='socket', ctx=Load()), attr='AF_CAN', ctx=Load()))
Lib/test/test_socket.py:1317: Expr(value=Attribute(value=Name(id='socket', ctx=Load()), attr='PF_CAN', ctx=Load()))
Lib/test/test_socket.py:1318: Expr(value=Attribute(value=Name(id='socket', ctx=Load()), attr='CAN_RAW', ctx=Load()))
Lib/test/test_socket.py:1323: Expr(value=Attribute(value=Name(id='socket', ctx=Load()), attr='CAN_BCM', ctx=Load()))
Lib/test/test_socket.py:1326: Expr(value=Attribute(value=Name(id='socket', ctx=Load()), attr='CAN_BCM_TX_SETUP', ctx=Load()))
Lib/test/test_socket.py:1327: Expr(value=Attribute(value=Name(id='socket', ctx=Load()), attr='CAN_BCM_TX_DELETE', ctx=Load()))
Lib/test/test_socket.py:1328: Expr(value=Attribute(value=Name(id='socket', ctx=Load()), attr='CAN_BCM_TX_READ', ctx=Load()))
Lib/test/test_socket.py:1329: Expr(value=Attribute(value=Name(id='socket', ctx=Load()), attr='CAN_BCM_TX_SEND', ctx=Load()))
Lib/test/test_socket.py:1330: Expr(value=Attribute(value=Name(id='socket', ctx=Load()), attr='CAN_BCM_RX_SETUP', ctx=Load()))
Lib/test/test_socket.py:1331: Expr(value=Attribute(value=Name(id='socket', ctx=Load()), attr='CAN_BCM_RX_DELETE', ctx=Load()))
Lib/test/test_socket.py:1332: Expr(value=Attribute(value=Name(id='socket', ctx=Load()), attr='CAN_BCM_RX_READ', ctx=Load()))
Lib/test/test_socket.py:1333: Expr(value=Attribute(value=Name(id='socket', ctx=Load()), attr='CAN_BCM_TX_STATUS', ctx=Load()))
Lib/test/test_socket.py:1334: Expr(value=Attribute(value=Name(id='socket', ctx=Load()), attr='CAN_BCM_TX_EXPIRED', ctx=Load()))
Lib/test/test_socket.py:1335: Expr(value=Attribute(value=Name(id='socket', ctx=Load()), attr='CAN_BCM_RX_STATUS', ctx=Load()))
Lib/test/test_socket.py:1336: Expr(value=Attribute(value=Name(id='socket', ctx=Load()), attr='CAN_BCM_RX_TIMEOUT', ctx=Load()))
Lib/test/test_socket.py:1337: Expr(value=Attribute(value=Name(id='socket', ctx=Load()), attr='CAN_BCM_RX_CHANGED', ctx=Load()))
Lib/test/test_socket.py:1476: Expr(value=Attribute(value=Name(id='socket', ctx=Load()), attr='AF_RDS', ctx=Load()))
Lib/test/test_socket.py:1477: Expr(value=Attribute(value=Name(id='socket', ctx=Load()), attr='PF_RDS', ctx=Load()))
Lib/test/test_socket.py:727: Expr(value=Attribute(value=Name(id='socket', ctx=Load()), attr='AF_INET', ctx=Load()))
Lib/test/test_socket.py:728: Expr(value=Attribute(value=Name(id='socket', ctx=Load()), attr='SOCK_STREAM', ctx=Load()))
Lib/test/test_socket.py:729: Expr(value=Attribute(value=Name(id='socket', ctx=Load()), attr='SOCK_DGRAM', ctx=Load()))
Lib/test/test_socket.py:730: Expr(value=Attribute(value=Name(id='socket', ctx=Load()), attr='SOCK_RAW', ctx=Load()))
Lib/test/test_socket.py:731: Expr(value=Attribute(value=Name(id='socket', ctx=Load()), attr='SOCK_RDM', ctx=Load()))
Lib/test/test_socket.py:732: Expr(value=Attribute(value=Name(id='socket', ctx=Load()), attr='SOCK_SEQPACKET', ctx=Load()))
Lib/test/test_socket.py:733: Expr(value=Attribute(value=Name(id='socket', ctx=Load()), attr='SOL_SOCKET', ctx=Load()))
Lib/test/test_socket.py:734: Expr(value=Attribute(value=Name(id='socket', ctx=Load()), attr='SO_REUSEADDR', ctx=Load()))
Lib/test/test_ssl.py:105: Expr(value=Attribute(value=Name(id='ssl', ctx=Load()), attr='PROTOCOL_SSLv23', ctx=Load()))
Lib/test/test_ssl.py:106: Expr(value=Attribute(value=Name(id='ssl', ctx=Load()), attr='PROTOCOL_SSLv3', ctx=Load()))
Lib/test/test_ssl.py:107: Expr(value=Attribute(value=Name(id='ssl', ctx=Load()), attr='PROTOCOL_TLSv1', ctx=Load()))
Lib/test/test_ssl.py:108: Expr(value=Attribute(value=Name(id='ssl', ctx=Load()), attr='CERT_NONE', ctx=Load()))
Lib/test/test_ssl.py:109: Expr(value=Attribute(value=Name(id='ssl', ctx=Load()), attr='CERT_OPTIONAL', ctx=Load()))
Lib/test/test_ssl.py:110: Expr(value=Attribute(value=Name(id='ssl', ctx=Load()), attr='CERT_REQUIRED', ctx=Load()))
Lib/test/test_ssl.py:111: Expr(value=Attribute(value=Name(id='ssl', ctx=Load()), attr='OP_CIPHER_SERVER_PREFERENCE', ctx=Load(...
Lib/test/test_ssl.py:112: Expr(value=Attribute(value=Name(id='ssl', ctx=Load()), attr='OP_SINGLE_DH_USE', ctx=Load()))
Lib/test/test_string.py:10: Expr(value=Attribute(value=Name(id='string', ctx=Load()), attr='ascii_uppercase', ctx=Load()))
Lib/test/test_string.py:11: Expr(value=Attribute(value=Name(id='string', ctx=Load()), attr='ascii_letters', ctx=Load()))
Lib/test/test_string.py:12: Expr(value=Attribute(value=Name(id='string', ctx=Load()), attr='digits', ctx=Load()))
Lib/test/test_string.py:13: Expr(value=Attribute(value=Name(id='string', ctx=Load()), attr='hexdigits', ctx=Load()))
Lib/test/test_string.py:14: Expr(value=Attribute(value=Name(id='string', ctx=Load()), attr='octdigits', ctx=Load()))
Lib/test/test_string.py:15: Expr(value=Attribute(value=Name(id='string', ctx=Load()), attr='punctuation', ctx=Load()))
Lib/test/test_string.py:16: Expr(value=Attribute(value=Name(id='string', ctx=Load()), attr='printable', ctx=Load()))
Lib/test/test_string.py:8: Expr(value=Attribute(value=Name(id='string', ctx=Load()), attr='whitespace', ctx=Load()))
Lib/test/test_string.py:9: Expr(value=Attribute(value=Name(id='string', ctx=Load()), attr='ascii_lowercase', ctx=Load()))
Lib/test/test_super.py:79: Expr(value=Name(id='self', ctx=Load()))
Lib/test/test_sys_settrace.py:243: Expr(value=GeneratorExp(elt=Name(id='o', ctx=Load()), generators=[comprehension(target=Name(id='o', ...
Lib/test/test_time.py:25: Expr(value=Attribute(value=Name(id='time', ctx=Load()), attr='altzone', ctx=Load()))
Lib/test/test_time.py:26: Expr(value=Attribute(value=Name(id='time', ctx=Load()), attr='daylight', ctx=Load()))
Lib/test/test_time.py:27: Expr(value=Attribute(value=Name(id='time', ctx=Load()), attr='timezone', ctx=Load()))
Lib/test/test_time.py:28: Expr(value=Attribute(value=Name(id='time', ctx=Load()), attr='tzname', ctx=Load()))
Lib/test/test_weakref.py:129: Expr(value=Attribute(value=Name(id='proxy', ctx=Load()), attr='bar', ctx=Load()))
Lib/test/test_weakref.py:461: Expr(value=Attribute(value=Name(id='self', ctx=Load()), attr='J', ctx=Load()))
Lib/test/test_weakref.py:513: Expr(value=Attribute(value=Name(id='self', ctx=Load()), attr='J', ctx=Load()))
Lib/test/test_weakref.py:533: Expr(value=Attribute(value=Name(id='self', ctx=Load()), attr='me', ctx=Load()))
Lib/test/test_weakref.py:534: Expr(value=Attribute(value=Name(id='self', ctx=Load()), attr='c1', ctx=Load()))
Lib/test/test_weakref.py:535: Expr(value=Attribute(value=Name(id='self', ctx=Load()), attr='wr', ctx=Load()))
Lib/test/test_weakref.py:558: Expr(value=Attribute(value=Name(id='self', ctx=Load()), attr='me', ctx=Load()))
Lib/test/test_weakref.py:559: Expr(value=Attribute(value=Name(id='self', ctx=Load()), attr='c1', ctx=Load()))
Lib/test/test_weakref.py:560: Expr(value=Attribute(value=Name(id='self', ctx=Load()), attr='wr', ctx=Load()))
Lib/test/test_xml_etree.py:168: Expr(value=Subscript(value=Name(id='string', ctx=Load()), slice=Slice(lower=None, upper=Num(n=0), st...
msg184935 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2013-03-22 01:06
"Almost Dead code" is code generally considered as useless, but many Python unit tests use such code. Dummy example:

try:
   obj.attr
except AttributeError:
   pass

I don't think that we should touch this code, it's just for information.
msg184937 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2013-03-22 01:12
Your "dead code" looks like multiline comments (at least it is in the email case).  I thought those were optimized away when the pyc is written.

What is "almost dead code"?  If it is the stuff that is only applicable to a given platform, then presumably it is needed for that platform and why it it worth mentioning?
msg184938 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2013-03-22 01:24
Here is a concrete patch.

> Your "dead code" looks like multiline comments (at least it is
> in the email case).  I thought those were optimized away when
> the pyc is written.

Oh, it looks like you are right: useless strings are already removed during compilation. But it looks a little bit surprising to me to use a multiline string for a comment. I prefer classic # comments.

> What is "almost dead code"?  If it is the stuff that is only
> applicable to a given platform, then presumably it is needed
> for that platform and why it it worth mentioning?

It's just for information, just ignore these "warnings" :-)
msg184943 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2013-03-22 05:28
The code in test_peepholer should be removed.  That code isn't run directly.  Instead, it is tested for a correct disassembly.
msg185148 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2013-03-24 18:16
> Oh, it looks like you are right: useless strings are already removed 
> during compilation. But it looks a little bit surprising to me to use a 
> multiline string for a comment. I prefer classic # comments.

I was surprised by this as well.  I think the comment in _header_value_parser was originally a docstring and got moved around during editing.  It should probably get changed to a block comment.

I could have sworn that when I learned about the optimization it was in the context of documentation that specifically said the optimization was done so that triple quoted strings could be used as multi-line comments, but I cannot find it through google or guessing where I might have seen it in our docs, so perhaps I was imagining things.
msg185239 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2013-03-25 21:31
For the dead code in test_posix.py, see issue #9246.
msg185240 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2013-03-25 21:40
The instance in reindent.py uses the "docstring for attributes" feature that some documentation tools supports, which is a unused string *after* the attribute.

When you turn that into a comment, put the comment *before* the attribute.
msg185251 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2013-03-25 23:59
test_create_autospec_unbound_methods() of Lib/unittest/test/testmock/testhelpers.py contains dead code because of a known issue. I created issue #17548 to track this function.
msg185254 - (view) Author: Roundup Robot (python-dev) (Python triager) Date: 2013-03-26 00:16
New changeset 313bcff51900 by Victor Stinner in branch 'default':
Issue #17516: use comment syntax for comments, instead of multiline string
http://hg.python.org/cpython/rev/313bcff51900

New changeset 33bdd0a985b9 by Victor Stinner in branch 'default':
Issue #17516: do not create useless tuple: remove dummy commas in tests
http://hg.python.org/cpython/rev/33bdd0a985b9

New changeset 9dba3bc7c2a6 by Victor Stinner in branch 'default':
Issue #17516: remove dead code
http://hg.python.org/cpython/rev/9dba3bc7c2a6
msg185255 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2013-03-26 00:18
Thanks for the different reviews.
History
Date User Action Args
2013-03-26 00:18:33vstinnersetstatus: open -> closed
resolution: fixed
messages: + msg185255
2013-03-26 00:16:00python-devsetnosy: + python-dev
messages: + msg185254
2013-03-25 23:59:26vstinnersetmessages: + msg185251
2013-03-25 21:40:58georg.brandlsetnosy: + georg.brandl
messages: + msg185240
2013-03-25 21:31:44vstinnersetmessages: + msg185239
2013-03-24 18:16:06r.david.murraysetmessages: + msg185148
2013-03-24 14:26:06ezio.melottisetnosy: + ezio.melotti

type: enhancement
stage: patch review
2013-03-22 19:15:31tshepangsetnosy: + tshepang
2013-03-22 05:28:19rhettingersetnosy: + rhettinger
messages: + msg184943
2013-03-22 01:24:28vstinnersetfiles: + deadcode.patch
keywords: + patch
messages: + msg184938
2013-03-22 01:12:38r.david.murraysetnosy: + r.david.murray
messages: + msg184937
2013-03-22 01:06:29vstinnersetmessages: + msg184935
2013-03-22 01:03:52vstinnercreate