Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #102989

Re: Make a unique filesystem path, without creating the file

Path csiph.com!fu-berlin.de!uni-berlin.de!not-for-mail
From Ben Finney <ben+python@benfinney.id.au>
Newsgroups comp.lang.python
Subject Re: Make a unique filesystem path, without creating the file
Date Tue, 16 Feb 2016 16:56:06 +1100
Lines 129
Message-ID <mailman.155.1455602182.22075.python-list@python.org> (permalink)
References <85egce6a8a.fsf@benfinney.id.au> <20160215230539.GA42677@cskk.homeip.net>
Mime-Version 1.0
Content-Type text/plain; charset=utf-8
Content-Transfer-Encoding 8bit
X-Trace news.uni-berlin.de sc5THvViEc3QlIMBZZ88KAz4V6oYXT3GL6TK3/oT055A==
Cancel-Lock sha1:7fBhaHZcRQh278lsCdv5oO9JEOU=
Return-Path <python-python-list@m.gmane.org>
X-Original-To python-list@python.org
Delivered-To python-list@mail.python.org
X-Spam-Status OK 0.001
X-Spam-Evidence '*H*': 1.00; '*S*': 0.00; '"""': 0.05; 'paths': 0.05; 'subject:file': 0.07; 'api': 0.09; 'alters': 0.09; 'complicate': 0.09; 'exist.': 0.09; 'filename)': 0.09; 'filesystem': 0.09; 'implemented,': 0.09; 'internally': 0.09; 'library),': 0.09; 'modes': 0.09; 'patches': 0.09; 'received:80.91': 0.09; 'received:80.91.229': 0.09; 'received:gmane.org': 0.09; 'received:list': 0.09; 'requested.': 0.09; 'returns,': 0.09; 'tempfile': 0.09; 'thread': 0.10; 'def': 0.13; '(but': 0.15; 'file,': 0.15; '8bit%:26': 0.16; 'all?': 0.16; 'expects': 0.16; 'feasible': 0.16; 'filesystem,': 0.16; 'function?': 0.16; 'paths.': 0.16; 'received:80.91.229.3': 0.16; 'received:io': 0.16; 'received:plane.gmane.org': 0.16; 'received:psf.io': 0.16; 'simpson': 0.16; 'supplying': 0.16; 'value;': 0.16; 'case.': 0.18; 'documented': 0.18; 'restrictions': 0.18; 'creates': 0.18; 'library': 0.20; 'function,': 0.22; 'file.': 0.22; 'import': 0.24; 'implemented': 0.24; 'properties': 0.24; 'url:bugs': 0.24; "i've": 0.25; 'header:User-Agent:1': 0.26; 'example': 0.26; 'header:X -Complaints-To:1': 0.26; 'earlier': 0.27; 'supported': 0.27; 'checking': 0.27; 'separate': 0.27; 'skip:t 40': 0.27; 'function': 0.28; 'this.': 0.28; 'actual': 0.28; 'behaving': 0.29; 'men': 0.29; "i'm": 0.30; "we're": 0.30; 'strongly': 0.30; 'skip:s 30': 0.31; "can't": 0.32; '"the': 0.32; 'are:': 0.32; 'possibly': 0.32; 'useful': 0.33; 'url:python': 0.33; 'reference,': 0.33; 'case,': 0.34; 'file': 0.34; 'running': 0.34; 'configured': 0.35; 'path': 0.35; 'expected': 0.35; "isn't": 0.35; 'unit': 0.35; 'but': 0.36; 'should': 0.36; 'url:org': 0.36; 'possible.': 0.36; 'to:addr :python-list': 0.36; 'subject:: ': 0.37; 'received:org': 0.37; 'available.': 0.37; 'names': 0.38; 'skip:p 20': 0.38; 'associate': 0.38; 'why': 0.39; 'test': 0.39; 'sure': 0.39; 'whatever': 0.39; 'does': 0.39; 'subject:the': 0.39; 'to:addr:python.org': 0.40; 'some': 0.40; 'your': 0.60; 'hope': 0.61; 'skip:u 10': 0.61; 'real': 0.62; 'providing': 0.62; 'skip:n 10': 0.62; 'making': 0.62; 'skip:w 30': 0.64; 'accessed': 0.66; 'cameron': 0.66; 'sit': 0.66; 'wanting': 0.66; 'therefore': 0.67; '8bit%:21': 0.70; '8bit%:27': 0.72; 'watching': 0.72; '\xe2\x80\x93': 0.72; 'obvious': 0.76; '_o__)': 0.84; 'calls,': 0.84; 'calm': 0.84; 'case?': 0.84; 'complication': 0.84; 'irrelevant': 0.84; 'received:125': 0.84; 'valid,': 0.84; 'alone.': 0.91; 'notion': 0.91; 'prone': 0.91; 'skip:\xe2 30': 0.91; 'subject:Make': 0.91; 'use"': 0.91; 'imagine': 0.96
X-Injected-Via-Gmane http://gmane.org/
X-Gmane-NNTP-Posting-Host jigong.madmonks.org
X-Public-Key-ID 0xAC128405
X-Public-Key-Fingerprint 517C F14B B2F3 98B0 CB35 4855 B8B2 4C06 AC12 8405
X-Public-Key-URL http://www.benfinney.id.au/contact/bfinney-pubkey.asc
X-Post-From Ben Finney <bignose+hates-spam@benfinney.id.au>
User-Agent Gnus/5.13 (Gnus v5.13) Emacs/24.4 (gnu/linux)
X-BeenThere python-list@python.org
X-Mailman-Version 2.1.21rc2
Precedence list
List-Id General discussion list for the Python programming language <python-list.python.org>
List-Unsubscribe <https://mail.python.org/mailman/options/python-list>, <mailto:python-list-request@python.org?subject=unsubscribe>
List-Archive <http://mail.python.org/pipermail/python-list/>
List-Post <mailto:python-list@python.org>
List-Help <mailto:python-list-request@python.org?subject=help>
List-Subscribe <https://mail.python.org/mailman/listinfo/python-list>, <mailto:python-list-request@python.org?subject=subscribe>
Xref csiph.com comp.lang.python:102989

Show key headers only | View raw


Cameron Simpson <cs@zip.com.au> writes:

> I've been watching this for a few days, and am struggling to
> understand your use case.

Yes, you're not alone. This surprises me, which is why I'm persisting.

> Can you elaborate with a concrete example and its purpose which would
> work with a mktemp-ish official function?

An example::

    import io
    import tempfile
    names = tempfile._get_candidate_names()

    def test_frobnicates_configured_spungfile():
        """ ‘foo’ should frobnicate the configured spungfile. """

        fake_file_path = os.path.join(tempfile.gettempdir(), names.next())
        fake_file = io.BytesIO("Lorem ipsum, dolor sit amet".encode("utf-8"))

        patch_builtins_open(
                when_accessing_path=fake_file_path,
                provide_file=fake_file)

        system_under_test.config.spungfile_path = fake_file_path
        system_under_test.foo()
        assert_correctly_frobnicated(fake_file)

So the test case creates a fake file, makes a valid filesystem path to
associate with it, then patches the ‘open’ function so that it will
return the fake file when that specific path is requested.

Then the test case alters the system under test's configuration, giving
it the generated filesystem path for an important file. The test case
then calls the function about which the unit test is asserting
behaviour, ‘system_under_test.foo’. When that call returns, the test
case asserts some properties of the fake file to ensure the system under
test actually accessed that file.


With a supported standard library API for this – ‘tempfile.makepath’ for
example – the generation of the filesystem path would change from four
separate function calls, one of which is a private API::

    names = tempfile._get_candidate_names()
    fake_file_path = os.path.join(tempfile.gettempdir(), names.next())

to a simple public function call::

    fake_file_path = tempfile.makepath()

This whole thread began because I expected such an API would exist.


> I don't see how it is useful to have a notion of a filepath at all
> in this case, and therefore I don't see why you would want a
> mktemp-like function available.

Because the system under test expects to be dealing with a filesystem,
including normal restrictions on filesystem paths.

The filesystem path needs to be valid because the test case isn't making
assertions about what the system does with invalid paths. A test case
should be very narrow in what it asserts so that the failure's cause is
as obvious as possible.

The filesystem path needs to be unpredictable to make sure we're not
using some hard-coded value; the test case asserts that the system under
test will access whatever file is named in the configuration.

The file object needs to be fake because the test case should not be
prone to irrelevant failures when the real filesystem isn't behaving as
expected; this test case makes assertions only about what
‘system_under_test.foo’ does internally, not what the filesystem does.

The system library functionality should be providing this because it's
*already implemented there* and well tested and maintained. It should be
in a public non-deprecated API because merely generating filesystem
paths is not a security risk.

> But.. then why a filesystem path at all in that case?

Because the system under test is expecting valid filesystem paths, and I
have no good reason to violate that constraint.

> Why use a filesystem as a reference at all?

An actual running filesystem is irrelevant to this inquiry.

I'm only wanting to use functionality, with the constraints I enumerated
earlier (already implemented in the standard library), to generate
filesystem paths.

> The only modes I can imagine for such a thing (a generated but unused
> filename) are:
>
>  checking that the name is syntactly valid, for whatever constrains
> you may have (but if you're calling an opaque mktemp-like function, is
> this feasible or remediable?)

Almost. I want the filesystem paths to be valid because the system under
test expects them, it may perform its own validation, and I have no good
reason to complicate the unit test by possibly supplying an invalid path
when that's not relevant to the test case.

>  generating test paths without using a real filesystem as a reference,
> but then you can't even use mktemp

I hadn't realised the filesystem was accessed by ‘tempfile.mktemp’, and
I apologise for the complication that entails.

I would prefer to access some standard public documented non-deprecated
function that internally uses ‘tempfile._get_candidate_names’ and
returns a new path each time.

> I think "the standard library clearly has this useful functionality
> implemented, but simultaneously warns strongly against its use" pretty
> much precludes this.

I hope to get that addressed with <URL:https://bugs.python.org/issue26362>.

-- 
 \       “Timid men prefer the calm of despotism to the boisterous sea |
  `\                                    of liberty.” —Thomas Jefferson |
_o__)                                                                  |
Ben Finney

Back to comp.lang.python | Previous | NextNext in thread | Find similar | Unroll thread


Thread

Re: Make a unique filesystem path, without creating the file Ben Finney <ben+python@benfinney.id.au> - 2016-02-16 16:56 +1100
  Re: Make a unique filesystem path, without creating the file Steven D'Aprano <steve@pearwood.info> - 2016-02-17 04:36 +1100
    Re: Make a unique filesystem path, without creating the file Ben Finney <ben+python@benfinney.id.au> - 2016-02-17 06:48 +1100
  Re: Make a unique filesystem path, without creating the file Alan Bawden <alan@csail.mit.edu> - 2016-02-16 19:24 -0500
    Re: Make a unique filesystem path, without creating the file Cameron Simpson <cs@zip.com.au> - 2016-02-22 07:35 +1100
      Re: Make a unique filesystem path, without creating the file Alan Bawden <alan@csail.mit.edu> - 2016-02-22 12:34 -0500
        Re: Make a unique filesystem path, without creating the file Cameron Simpson <cs@zip.com.au> - 2016-02-23 10:02 +1100
          Re: Make a unique filesystem path, without creating the file Alan Bawden <alan@csail.mit.edu> - 2016-02-29 00:47 -0500
            Re: Make a unique filesystem path, without creating the file Cameron Simpson <cs@zip.com.au> - 2016-02-29 17:38 +1100

csiph-web