Python Forum

Full Version: f-string error message not understood
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
i don't understand this error message
Output:
t2a/phil /home/phil 452> py py/cmd/lndir.py -v foo bar/a/b/c/x File "py/cmd/lndir.py", line 133 print(f'makedirs({dir!r},mode={mode!e}) todo{n}') ^ SyntaxError: f-string: invalid conversion character: expected 's', 'r', or 'a' lt2a/phil /home/phil 453>
my first thought was to check the line before it. i'm sure lots of you will beg for the code, since this is an open project, i can post it. so here it is:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
    
from os import link,makedirs,mkdir
from os.path import lexists,join,split
from sys import argv,stderr

modes = dict( # aliases for mode settings
    x         = 0o0100,
    xx        = 0o0110,
    xxx       = 0o0111,
    r         = 0o0400,
    rr        = 0o0440,
    rrr       = 0o0444,
    rx        = 0o0500,
    rxx       = 0o0510,
    rxxx      = 0o0511,
    rxr       = 0o0540,
    rxrx      = 0o0550,
    rxrxx     = 0o0551,
    rxrr      = 0o0544,
    rxrxr     = 0o0554,
    rxrxrx    = 0o0555,
    rw        = 0o0600,
    rwr       = 0o0640,
    rwrr      = 0o0644,
    rwrw      = 0o0660,
    rwrww     = 0o0662,
    rwrwr     = 0o0664,
    rwrwrw    = 0o0666,
    rwx       = 0o0700,
    rwxx      = 0o0710,
    rwxxx     = 0o0711,
    rwxr      = 0o0740,
    rwxrr     = 0o0744,
    rwxrx     = 0o0750,
    rwxrxx    = 0o0751,
    rwxrxr    = 0o0754,
    rwxrxrx   = 0o0755,
    rwxrwx    = 0o0770,
    rwxrwxx   = 0o0771,
    rwxrwxr   = 0o0774,
    rwxrwxrx  = 0o0775,
    rwxrwxrwx = 0o0777,
    rwxrwxrwt = 0o1777,
    rwxrwsrwx = 0o2777,
    rwxrwsrwt = 0o3777,
    rwsrwxrwx = 0o4777,
    rwsrwxrwt = 0o5777,
    rwsrwsrwx = 0o6777,
    rwsrwsrwt = 0o7777,
    dir       = 0o0750,
    read      = 0o0400,
    write     = 0o0600,
    public    = 0o0444,
    private   = 0o0400,
)

def help(*args):
    if args:
        arg = args[0]
        return arg.lower() in ('-h','--help')
    print('    lndir  [options]  srcpath  destdir')
    return 1

def version(*args):
    if args:
        arg = args[0]
        return arg.lower() in ('-v','--version')
    print('    lndir  version 0.0.6')
    return 1

def main(args):
    parents = True
    verbose = False
    mode = None
    names = []
    while args:
        arg = args.pop(0)
        if not arg:
            exit('error: empty argument in command line')
        elif arg[0] != '-':
            names.append(arg)
        elif arg in ('-','--'):
            break
        elif help(arg):
            help()
            version()
            exit(1)
        elif arg in ('-m' '--mode'):
            if not args:
                exit(f'error: missing argument for {arg}')
            mode = args.pop(0)
            if not mode:
                exit(f'error: empty argument for {arg}')
        elif arg.startswith('-m=') or arg.startswith('--mode='):
            mode = arg.split('=',1)[1]
            if not mode:
                exit(f'error: empty value in {arg}')
        elif arg in ('-np','--noparents'):
            parents = False
        elif arg in ('-v','--verbose'):
            verbose = True
        elif version(arg):
            version()
            exit(1)
    if len(names)!=2:
        exit(f'too {("many","few")[len(names)<2]} arguments, expect 2, got {len(names)}: {" ".join(args)!r}')
    src,dir = names
    par,base = split(src)
    dst = join(dir,base)
    if isinstance(mode,str):
        mode = mode.lower()
        if mode in modes:
            mode = modes[mode]
        try:
            mode = int(mode,8)
        except Exception:
            pass
    if isinstance(src,(bytes,bytearray)):
        src = ''.join(chr(x)for x in src)
    if isinstance(dir,(bytes,bytearray)):
        dir = ''.join(chr(x)for x in dir)
    for n in (0,1):
        try:
            print(f'link({src!r},{dst!r}) todo{n}')
            link(src,dst)
            print(f'link({src!r},{dst!r}) done{n}')
        except FileNotFoundError:
            if lexists(src):
                try:
                    if isinstance(mode,int):
                        print(f'makedirs({dir!r},mode={mode!e}) todo{n}')
                        (makedirs if parents else mkdir)(dir,mode=mode)
                        print(f'makedirs({dir!r},mode={mode!e}) done{n}')
                    else:
                        print(f'makedirs({dir!r}) todo{n}')
                        (makedirs if parents else mkdir)(dir)
                        print(f'makedirs({dir!r}) done{n}')
                except FileNotFoundError:
                    exit(f'parent directory missing while creating directory {dir!r}')
                except NotADirectoryError:
                    exit(f'parent directory not a directory while creating directory {dir!r}')
                except PermissionError:
                    exit(f'permission error while creating directory {dir!r}')
                except OSError:
                    exit(f'unknown error while creating directory {dir!r}')
            else:
                exit((f'{n} source file {src!r}' if lexists(dir) else f'target directory {dir!r}')+' not found')
        except FileExistsError:
            exit(f'target file {dst!r} exists')
        except NotADirectoryError:
            exit(f'target directory {dir!r} exists but is not a directory')
        except PermissionError:
            exit(f'target directory {dir!r} or source file {src!r} permission error')
        if verbose:
            print(f'{src!r} == {dst!r}',flush=True)
        return 0

if __name__ == '__main__':
    cmdpath = argv.pop(0)
    try:
        result = main(argv)
    except BrokenPipeError:
        exit(141)
    except KeyboardInterrupt:
        print(flush=True)
        exit(98)
    if isinstance(result,(bytes,bytearray)):
        result=''.join(chr(x)for x in result)
    if isinstance(result,str):
        print(result,file=stderr,flush=True)
        result=1
    if result is None or result is True:
        result=0
    elif result is False:
        result=1
    exit(int(float(result)))
What are you intending with the {mode!e} in that string? e isn't a valid conversion (unless you add it yourself).

If you're trying to print the mode as octal, that would be {mode:o}.

>>> mode = 0o0444
>>> mode
292
>>> print(f"{mode:o}")
444
doh! that was the error. i misunderstood "conversion" because the "^" pointer is in the wrong position. it should have been "!r" (it could have the value None) ... an adjacent key typo.
What benefit do you get from changing that conversion then? Integers and None should print identically among all built-in conversions.

>>> print(f"{None} {None!r} {33} {33!r}")
None None 33 33
probably no benefit in this case. my habits for adding temporary code to help debugging does not include thinking about the optimal choice of code since i will be removing it later.