Skip to content

bring Lib/copy.py to 100% coverage #55781

Description

@brandon-rhodes
BPO 11572
Nosy @ncoghlan, @abalkin, @pitrou, @benjaminp, @ezio-melotti, @merwok, @durban, @sandrotosi, @berkerpeksag, @serhiy-storchaka
PRs
  • bpo-11572: Make several minor improvements to copy module #207
  • bpo-11572: Make several minor improvements to copy module #8208
  • Files
  • test_copy.patch
  • test_copy2.patch
  • test_copy3.patch
  • test_copy4.patch: Fourth version of my patch to increase copy.py's test coverage
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = 'https://github.com/sandrotosi'
    closed_at = <Date 2018-07-09.20:15:28.690>
    created_at = <Date 2011-03-16.16:32:32.152>
    labels = ['3.8', 'type-feature', 'library']
    title = 'bring Lib/copy.py to 100% coverage'
    updated_at = <Date 2018-07-09.21:37:02.632>
    user = 'https://bugs.python.org/brandon-rhodes'

    bugs.python.org fields:

    activity = <Date 2018-07-09.21:37:02.632>
    actor = 'eric.araujo'
    assignee = 'sandro.tosi'
    closed = True
    closed_date = <Date 2018-07-09.20:15:28.690>
    closer = 'berker.peksag'
    components = ['Library (Lib)']
    creation = <Date 2011-03-16.16:32:32.152>
    creator = 'brandon-rhodes'
    dependencies = []
    files = ['21244', '21246', '21276', '22822']
    hgrepos = []
    issue_num = 11572
    keywords = ['patch', 'needs review']
    message_count = 36.0
    messages = ['131135', '131139', '131140', '131141', '131142', '131151', '131300', '131304', '131306', '131307', '131308', '131320', '131328', '131413', '131415', '131431', '131434', '131644', '131647', '132140', '141527', '141635', '141637', '141640', '141642', '141643', '141689', '141691', '141714', '288154', '288165', '288166', '288280', '321347', '321348', '321352']
    nosy_count = 12.0
    nosy_names = ['ncoghlan', 'belopolsky', 'pitrou', 'benjamin.peterson', 'ezio.melotti', 'eric.araujo', 'daniel.urban', 'sandro.tosi', 'brandon-rhodes', 'python-dev', 'berker.peksag', 'serhiy.storchaka']
    pr_nums = ['207', '8208']
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'enhancement'
    url = 'https://bugs.python.org/issue11572'
    versions = ['Python 3.8']

    Activity

    1. brandon-rhodes commented on Mar 16, 2011

      brandon-rhodesmannequin
      MannequinAuthor

      The attached patch will bring Lib/copy.py to 100% test coverage.

      A bug in "coverage" results in its only reporting 99% at the moment; see coverage issue #122 on bitbucket:

      https://bitbucket.org/ned/coveragepy/issue/122/for-else-always-reports-missing-branch

      This patch makes several minor improvements to "copy": when doing getattr lookups with a default of "None", it now uses an "is" comparison against None which is both faster and more correct; several special cases have been removed since Python 3 always has "CodeType" available; and an ancient obsolete test suite that had been appended to copy.py in ancient times has been removed.

    2. benjaminp commented on Mar 16, 2011

      @benjaminp
      Contributor
      1. I prefer that we don't have pragma statements sprinkled over the stdlib.
      2. You can use assertIs() instead of assertTrue(x is y) (Feel free to change the lot)
      3. Along the way you could also change those "raise support.TestFailed" over to calling the TestCase.fail method.
    3. abalkin commented on Mar 16, 2011

      @abalkin
      Member

      A bug in "coverage" results in its only reporting 99% at the moment

      It was concluded during discussion of bpo-2506 that this is not a bug. At least not a bug in "coverage" or the trace module. At most this is a peephole optimization issue or rather a missing feature to turn off peephole optimization in coverage runs.

    4. self-assigned this
      on Mar 16, 2011
    5. ncoghlan commented on Mar 16, 2011

      @ncoghlan
      Contributor

      Alexander: the coverage problem in this case has to do with it incorrectly handling an "else:" clause on a loop (it doesn't adjust the expected target for an empty sequence to be the body of the else clause)

      Benjamin: the pragma question is probably worth bringing up on python-dev. In the long run, it would be best to merge coverage data from the test suites of all the major implementations and platforms, but in the meantime we need a way to mark when modules are "done" from the point of view of the CPython test suite.

    6. benjaminp commented on Mar 16, 2011

      @benjaminp
      Contributor

      2011/3/16 Nick Coghlan <report@bugs.python.org>:

      Nick Coghlan <ncoghlan@gmail.com> added the comment:

      Alexander: the coverage problem in this case has to do with it incorrectly handling an "else:" clause on a loop (it doesn't adjust the expected target for an empty sequence to be the body of the else clause)

      Benjamin: the pragma question is probably worth bringing up on python-dev. In the long run, it would be best to merge coverage data from the test suites of all the major implementations and platforms, but in the meantime we need a way to mark when modules are "done" from the point of view of the CPython test suite.

      There's really no precedent for it.

    7. brandon-rhodes commented on Mar 16, 2011

      brandon-rhodesmannequin
      MannequinAuthor

      Benjamin, thanks for the pointers! The attached patch now uses assertIs() and assertIsNot(), and calls self.fail() instead of using the exception from "support".

      In the future I would like some way to determine when test coverage is fully achieved, so that I do not come back to this module every few months and have to re-discover why it is not 100%. But for the moment I have indeed removed the pragmas, pending a better approach!

    8. merwok commented on Mar 17, 2011

      @merwok
      Member

      Some code is removed by your patch, for example a check that prevented an error for builds that don’t include complex. If this type of builds still exist, the code should be compatible.

      Conversely, the code mentions unicode in some places, but it’s gone now.

    9. brandon-rhodes commented on Mar 17, 2011

      brandon-rhodesmannequin
      MannequinAuthor

      Éric, the Makefile in Python trunk seems to include Objects/complexobject.o in the build unilaterally without any way to turn it off. What is leading you to believe that Python 3 can conditionally turn the "complex" type off during a build?

      I do not understand your question about Unicode — could you reference the line number in the patch file that is worrying you?

    10. pitrou commented on Mar 18, 2011

      @pitrou
      Member

      +1 for not having pragma statements in the stdlib, especially when they target a third-party tool few of us know and use.
      Beside, while coverage measurements are useful, trusting them that actual coverage is complete is IMO a bit foolish. It's not just about running every line of code.

    11. brandon-rhodes commented on Mar 18, 2011

      brandon-rhodesmannequin
      MannequinAuthor

      Antoine, neither this issue, nor either version of my patch, was intended to assert that 100% test coverage indicates that a test of tests are complete. If you will point out where in the text this is implied, I will correct it. Thanks!

    12. abalkin commented on Mar 18, 2011

      @abalkin
      Member

      On Thu, Mar 17, 2011 at 8:03 PM, Antoine Pitrou <report@bugs.python.org> wrote:
      ..

      +1 for not having pragma statements in the stdlib, especially when they target a third-party tool few of us know and use.

      "#pragma NO COVER" is recognized by stdlib trace module, so it is not
      specific to a third-party tool. I don't like #pragma myself. This is
      very "unpythonic" choice. I would be much happier if it was simply '#
      NO COVER' or something even less conspicuous. I do believe, however
      that some mechanism should be used to prevent trace from highlighting
      spurious lines as lacking coverage.

      Beside, while coverage measurements are useful, trusting them that actual coverage is complete is IMO a bit foolish.
      It's not just about running every line of code.

      Agree, but running every line of code is a good first step. For
      example, it is *very* useful for identifying lack of coverage for
      error conditions.

    13. merwok commented on Mar 18, 2011

      @merwok
      Member

      A little research has found that building without complex is not possible anymore, so you’re good: http://bugs.python.org/issue7147

      Regarding “unicode”, see line 112.

    14. brandon-rhodes commented on Mar 18, 2011

      brandon-rhodesmannequin
      MannequinAuthor

      Éric, after checking line 112 of the two patches and then of the new file, I figured out that you meant line 112 of the old file — and, yes, that test can go away too since in python3 "complex" always exists and "unicode" never exists. A further improved patch (#3) is attached.

    15. merwok commented on Mar 19, 2011

      @merwok
      Member

      Nice cleanup.

      -            reductor = getattr(x, "__reduce__", None)
      -            if reductor:
      -                rv = reductor()
      -            else:
      -                raise Error("un(shallow)copyable object of type %s" % cls)
      +            raise Error("un(shallow)copyable object of type %s" % cls)
      Why change this?
          self.assertTrue(issubclass(copy.Error, Exception))
      

      You could change that to assertIsInstance.

      -def _test():
      I assume that all cases that were tested in that function are covered by unit tests.

    16. 16 remaining items

    17. sandrotosi commented on Aug 6, 2011

      @sandrotosi
      Contributor

      JFTR, the same kind of check of __reduce_ex__ and then falling back on __reduce__ is prenset in pickle too: maybe it's worth align them?

    18. added
      stdlibStandard Library Python modules in the Lib/ directory
      type-featureA feature request or enhancement
      on Sep 6, 2014
    19. serhiy-storchaka commented on Feb 19, 2017

      @serhiy-storchaka
      Member

      Is anything left to do with this issue? Many changes were made in the copy module and tests last year.

    20. berkerpeksag commented on Feb 19, 2017

      @berkerpeksag
      Member

      All changes to Lib/test/test_copy.py have already been committed.

      Perhaps the following hunks from the latest patch can still be useful:

      -try:
      -    d[types.CodeType] = _deepcopy_atomic
      -except AttributeError:
      -    pass
      +d[types.CodeType] = _deepcopy_atomic

       def _deepcopy_tuple(x, memo):
      +    if not x:
      +        return x

      -        try:
      -            issc = issubclass(cls, type)
      -        except TypeError: # cls is not a class (old Boost; see SF python/cpython#35903)
      -            issc = 0
      -        if issc:
      +        if issubclass(cls, type):
    21. serhiy-storchaka commented on Feb 19, 2017

      @serhiy-storchaka
      Member

      Agree. The latter simplification can be applied to pickle.py.

    22. serhiy-storchaka commented on Feb 21, 2017

      @serhiy-storchaka
      Member

      copy and pickle use the same protocol. The copy module shouldn't be changed independently, the changes should be synchronised with both implementations of the pickle module.

    23. berkerpeksag commented on Jul 9, 2018

      @berkerpeksag
      Member

      New changeset 2708578 by Berker Peksag in branch 'master':
      bpo-11572: Make minor improvements to copy module (GH-8208)
      2708578

    24. berkerpeksag commented on Jul 9, 2018

      @berkerpeksag
      Member

      Thanks, Brandon.

    25. merwok commented on Jul 9, 2018

      @merwok
      Member

      I realize now that calling self.fail at https://hg.python.org/cpython/rev/74e79b2c114a#l2.20 is a problem: self is an instance of the C class, not the TestCase instance.

      (The line is unreachable anyway so this doesn’t matter a lot. In other projects I’d use something like __reduce__ = raiser(AssertionError) to avoid this.)

    26. transferred this issue fromon Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Metadata

    Metadata

    Assignees

    Labels

    3.8 (EOL)end of lifestdlibStandard Library Python modules in the Lib/ directorytype-featureA feature request or enhancement

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions