Skip to content

Document what components make up the filecmp.cmp os.stat signature. #78077

Closed

Description

@DeanMorin
mannequin
BPO 33896
Nosy @bitdancer, @macrakis, @akulakov
Superseder
  • bpo-42958: filecmp.cmp(shallow=True) isn't actually shallow when only mtime differs
  • 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 = None
    closed_at = <Date 2021-08-16.23:30:26.656>
    created_at = <Date 2018-06-18.18:18:51.756>
    labels = ['3.11', 'type-bug', '3.9', '3.10', 'docs']
    title = 'Document what components make up the filecmp.cmp os.stat signature.'
    updated_at = <Date 2021-08-16.23:30:26.655>
    user = 'https://bugs.python.org/DeanMorin'

    bugs.python.org fields:

    activity = <Date 2021-08-16.23:30:26.655>
    actor = 'ned.deily'
    assignee = 'docs@python'
    closed = True
    closed_date = <Date 2021-08-16.23:30:26.656>
    closer = 'ned.deily'
    components = ['Documentation']
    creation = <Date 2018-06-18.18:18:51.756>
    creator = 'Dean Morin'
    dependencies = []
    files = []
    hgrepos = []
    issue_num = 33896
    keywords = []
    message_count = 7.0
    messages = ['319904', '319912', '319913', '319919', '319970', '379797', '398308']
    nosy_count = 5.0
    nosy_names = ['r.david.murray', 'docs@python', 'Dean Morin', 'macrakis', 'andrei.avk']
    pr_nums = []
    priority = 'normal'
    resolution = 'duplicate'
    stage = 'resolved'
    status = 'closed'
    superseder = '42958'
    type = 'behavior'
    url = 'https://bugs.python.org/issue33896'
    versions = ['Python 3.9', 'Python 3.10', 'Python 3.11']

    Activity

    1. DeanMorin commented on Jun 18, 2018

      DeanMorinmannequin
      MannequinAuthor

      By default filecmp.cmp() has shallow=True which can produce some surprising behavior.

      In the docs it states:

      If shallow is true, files with identical os.stat() signatures are taken to be equal.

      However the "signature" only considers the file mode, file size, and file modification time, which is not sufficient. cmp() will return True (files are equal) in some circumstances for files that actually differ. Depending on the underlying file system, the same python script will return True or False when cmp() is called on the exact same files. I'll add the long-winded details at the bottom.

      To fix, I believe st.st_ino should be included in _sig (https://github.com/python/cpython/blob/3.7/Lib/filecmp.py#L68).

      I'm in the middle of a move, but I can make a PR in the next couple weeks if this seems like a reasonable fix and no one else gets around to it.

      The long version is that we're migrating some existing reports to a new data source. The goal is to produce identical csv files from both data sources. I have a python script that pulls down both csv files and uses cmp() to compare them.

      On my machine, the script correctly discovers the differences between the two. One of the date columns has incorrect dates in the new version.

      However on my colleagues machine, the script fails to discover the differences and shows that the csv files are identical.

      The difference is that on my machine, os.stat(f).st_mtime is a timestamp which includes fractional seconds (1529108360.1955538), but only includes the seconds (1529108360.0) on my colleagues machine. Since only the dates differed within the csvs, both files had the same file mode, file size, and both were downloaded within the same second.

      We got a few more people to see what they got for st_mtime. The link could be the file system used. We're all using macs, but for those of us using an APFS Volume disk, st_mtime returns a timestamp which includes fractional seconds, and for those of us using a Logical Volume Mac OS Extended disk, it returns a timestamp which only includes the seconds (1529108360.0).

      When comparing os.stat() between the two differing csv files, the only difference (other than fractional seconds for various timestamps) was st_ino which is why I believe it should be included in _sig().

    2. added
      stdlibStandard Library Python modules in the Lib/ directory
      type-bugAn unexpected behavior, bug, or error
      on Jun 18, 2018
    3. bitdancer commented on Jun 18, 2018

      @bitdancer
      Member

      I understand your concern, but this is working as designed and documented. Using st_ino would mean you would return true if and only if it was the *same* file. That is not the intent. See bpo-27396 for some background discussion.

    4. bitdancer commented on Jun 18, 2018

      @bitdancer
      Member

      For your problem, just don't use the default shallow setting :)

    5. DeanMorin commented on Jun 18, 2018

      DeanMorinmannequin
      MannequinAuthor

      Fair enough, how about just making it clearer in the documentation? Currently you need to look at the source code to see what would be required for a signature clash to occur. Maybe something like:

      Note that the os.stat() signatures only consider st_mode, st_size, and st_mtime. In some circumstances it's possible for differing files to be considered equal when shallow is True.

    6. bitdancer commented on Jun 19, 2018

      @bitdancer
      Member

      I think it might be OK to document what goes in to the signature, but probably in a footnote, as it is somewhat of an implementation detail and could conceivably change. We could then also add a caution about mtime imprecision being a particular risk on some file systems. I wouldn't want to put such a caution in the main doc paragraphs, but in a footnote I think it would be OK.

    7. changed the title [-]filecmp.cmp returns True on files that differ[/-] [+]Document what components make up the filecmp.cmp os.stat signature.[/+] on Jun 19, 2018
    8. added
      docsDocumentation in the Doc dir
      and removed
      stdlibStandard Library Python modules in the Lib/ directory
      on Jan 4, 2019
    9. macrakis commented on Oct 27, 2020

      macrakismannequin
      Mannequin

      I agree completely that the documentation should be more explicit. The concept of "os.stat signature" is not defined anywhere as far as I can tell. The naive reader (like me) might mistakenly assume that the "os.stat signature" is a "digital signature" (i.e. a hash) of all of os.stat, and in particular that it includes the st_ino.

      I would suggest that the documentation be updated to read "If shallow is true, files with the same length, modification time, and mode are taken to be equal."

    10. akulakov commented on Jul 27, 2021

      @akulakov
      Contributor

      Can be closed as a dupe of https://bugs.python.org/issue42958, which has a PR ready for review.

    11. added
      3.11only security fixes
      and removed on Aug 16, 2021
    12. 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

    No one assigned

      Labels

      3.10 (EOL)end of life3.11only security fixes3.9 (EOL)end of lifedocsDocumentation in the Doc dirtype-bugAn unexpected behavior, bug, or error

      Projects

      No projects

        Milestone

        No milestone

        Relationships

        None yet

        Development

        No branches or pull requests

        Issue actions