I ran into another case where I wish I had some sort of conditional if.

I was writing code to cache autogenerated demodata.

    import ubelt as ub
    from os.path import join
    import json
    kwargs = {'example': 'config'}

    dpath = ub.ensure_app_cache_dir('my_modname', 'demodata')
    fpath = join(dpath, 'data.json')

    stamp = ub.CacheStamp('demodata', depends=kwargs, dpath=dpath)
    if stamp.expired():
        data = {
            'complicated': 'data',
            'key1': 'val1',
            'key2': 'val2',
            'keyN': 'valN',
        }
        with open(fpath, 'w') as file:
            json.dump(data, file)
        stamp.renew()
    else:
        with open(fpath, 'r') as file:
            data = json.load(file)

I really wish I didn't have to have that stamp.renew() at the end of the if
block. It unnecessary boilerplate --- the caching logic would all be in a
contiguous block if not for the need for this. It wastes a little bit of
vertical, which while not critical, is a consideration.

I want to focus on the context:

    stamp = ub.CacheStamp('demodata', depends=kwargs, dpath=dpath)
    if stamp.expired():
        [code]
        stamp.renew()


I could make `CacheStamp` a context manager and tell it to do it in its
`__exit__` clause, as such:

    stamp = ub.CacheStamp('demodata', depends=kwargs, dpath=dpath)
    if stamp.expired():
        with stamp:
            [code]

This removes the need for the `stamp.renew`, makes the logic contiguous,
has the same vertical space, however, it adds a TON of horizontal space
depending on the complexity of the logic. It's often beneficial to minimize
nesting and try restricting it 2 or 3 levels.

BUT if we had just a tiny bit of new syntax rules we could write something
like this:

    stamp = ub.CacheStamp('demodata', depends=kwargs, dpath=dpath)
    if stamp.expired() with stamp:
        [code]

There are even more conservative changes, like requiring a colon before
the `with`: `if stamp.expired(): with stamp:`

I know this is just saving a line. But I use this pattern with
`ubelt.CacheStamp` and `ubelt.Cacher` frequently, and I always feel a
strong want for this syntactic sugar as I'm writing it. Wasting that
horizontal space is not an option, and I really would like the caching
logic to be contiguous.

To be clear, in the proposed syntax:

    if [condition] with [obj]:
        [code]

Would behave exactly as:

    if [condition]:
        with [obj]:
            [code]

Is there any chance that this conditional context manager syntax might be
considered? Does anyone but myself think this might be a good idea?
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/TR2JBOMPXBCAZOKJUB67OIU27Z6FTK6G/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to