Robert Moore
Robert Moore

Reputation: 2572

Python percent operator for strings not working

I have this code but it says TypeError not enough arguments for format string even though I gave it a tuple with the RIGHT amount of arguments. Can anybody help me on this? I have looked all over stack overflow and the python docs don't seem to help either.

image_urls = {
'horse.jpg': 'a.jpg',
'bison.jpg': 'b.jpg',
'bald_eagle.jpg': 'c.jpg',
'pig_in_mud.jpg': 'd.jpg',
'baby_monkey.jpg': 'e.jpg',
'cute_golden_retriever.jpg': 'f.jpg',
'cute_fluffy_bunny.jpg': 'g.jpg',
'fluffy_kitten.jpg': 'h.jpg',
'default_profile_pic.jpg': 'i.png'
}
mystr = '''<tr><td>Username:</td><td><input type='text' name='username'/></td></tr>
        <tr><td>Profile picture:</td><td>
            <table>
                <tr><td><img src='%s'/></td><img src='%s'/><td></td><td><img src='%s'/></td></tr>
                <tr><td><img src='%s'/></td><img src='%s'/><td></td><td><img src='%s'/></td></tr>
                <tr><td><img src='%s'/></td><img src='%s'/><td></td><td><img src='%s'/></td></tr>
            </table>
        </td></tr>
        <tr><td colspan="2" class="description"><i>Image must be 1MB or less.</i></td></tr>
        <tr><td>Website:</td><td><input type='url' name='website' placeholder='example.com'/><td/></tr>
        <tr><td colspan="2" class="description"><i>Got a home on the web? Put it here.</i></td></tr>
        <tr><td>Bio:</td><td><textarea name='bio' placeholder='I am John Doe, and I enjoy doing this, that and a little more of this. (more content more elaboration)'></textarea></td></tr>
        <tr><td colspan="2" class="description"><i>Tell about yourself here.</i></td></tr>
        <tr><td>Gender:</td><td><input type='radio' name='gender'/> M <input type='radio' name='gender'/> F</td></tr> 
        <tr><td>Age:</td><td><input type='text' name='age'/></td></tr>
        </table>
        <h4>Privacy</h4>
        <table>
        <tr><td>Hide age</td><td><input type="checkbox" name="hide-age"/></td></tr>
        <tr><td>Hide gender</td><td><input type="checkbox" name="hide-gender"/></td></tr>
        <tr><td>Hide email</td><td><input type="checkbox" name="hide-email"/></td></tr>
        </table>
        <div class='button-jumbo'>Create account</div>
        <script>
        function onPasswordChange() {
            var strength = this.value.length * 3;
            var weakPasswords = ['password', '123456', '12345678', '1234', 'qwerty', '12345', 'dragon', 'baseball', 'football', 'letmein', 'security', 'monkey', '696969', 'abc123', '111111', 'ncc2701', 'trustno1'];
            strength += (this.value.match(/[\/;'"\[\]\{\}\-_\!@#\$\\\%\^\&\*\)\(]/g) ? (this.value.match(/[\/;'"\[\]\{\}\-_\!@#\$\\\%\^\&\*\)\(]/g).length * 8 ): 0);
            strength += (this.value.match(/[A-Z]/g) ? (this.value.match(/[A-Z]/g).length * 5) : 0);
            strength += (this.value.match(/[0-9]/g) ? (this.value.match(/[0-9]/g).length * 6) : 0);
            if (weakPasswords.indexOf(this.value.toLowerCase()) !== -1) {
                strength = 5;
            }
            document.getElementById("password-meter").value = strength.toString();
        }
        var pswdElt = document.getElementsByName('password')[0];
        pswdElt.oninput = onPasswordChange;
        pswdElt.onchange = onPasswordChange;
        pswdElt.onkeydown = onPasswordChange;
        </script>
        ''' % ( image_urls['bald_eagle.jpg'], image_urls['pig_in_mud.jpg'], image_urls['cute_golden_retriever.jpg'], image_urls['bison.jpg'], image_urls['default_profile_pic.jpg'], image_urls['horse.jpg'], image_urls['baby_monkey.jpg'], image_urls['cute_fluffy_bunny.jpg'], image_urls['fluffy_kitten.jpg'] )

Upvotes: 1

Views: 242

Answers (2)

bgporter
bgporter

Reputation: 36524

The problem is in this line:

strength += (this.value.match(/[\/;'"\[\]\{\}\-_\!@#\$\\\%\^\&\*\)\(]/g)

Note that there's a % character hiding in there. The python string formatter looks at that, tries to interpret it as the (invalid) format specifier %\, and because there's no matching argument of it in the tuple, throws that exception. If you include an additional argument in the tuple, you'll instead get this exception:

ValueError: unsupported format character '\' (0x5c) at index 2017

The answer: escape out any % characters that aren't being used as format specifiers by adding another %:

strength += (this.value.match(/[\/;'"\[\]\{\}\-_\!@#\$\\\%%\^\&\*\)\(]/g)

This will result in the string formatter leaving a single percent in the output string.

Upvotes: 3

DorElias
DorElias

Reputation: 2313

you have % in your regex, and python thinks it should place values there too

replace the % in the regex with %% that is how you escape it in python

Upvotes: 1

Related Questions