Broken font-locking

Bug #961231 reported by Barry Warsaw
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
python-mode.el
Fix Released
Medium
Andreas Roehler

Bug Description

r904 broke several font-lock colors

In this example:

def baz():
    foo = None
    bar = False
    baz = True
    foo, bar, baz = baz()
    return foo, bar, baz

None, False, and True get colored with font-lock-constant-face instead of py-pseudo-keyword-face

On the second to last line, "foo" "bar" and "baz" all get colored with font-lock-variable-name-face whereas I think they should get default face, just as they would if no comma or equal sign appeared on the line.

Revision history for this message
Barry Warsaw (barry) wrote :

Another one:

def baz(mydict):
    mydict['hello'] = 'baz'

'mydict' gets colored with font-lock-variable-name-face but it should be default face.

Changed in python-mode:
importance: Undecided → High
Revision history for this message
Barry Warsaw (barry) wrote :

Another one:

def baz(self):
    self.baz = 'hello'

'self' gets colored with font-lock-keyword-face instead of py-pseudo-keyword-face

Revision history for this message
Barry Warsaw (barry) wrote :

Another one:

def baz(self):
    return set(range(100))

'set' and 'range' get rendered in font-lock-builtin-face when they should get rendered in py-builtins-face

Changed in python-mode:
assignee: nobody → Andreas Roehler (a-roehler)
milestone: none → 6.0.6
status: New → Confirmed
Changed in python-mode:
status: Confirmed → Fix Committed
Revision history for this message
Barry Warsaw (barry) wrote :

Thanks for the quick fixes! Note however that 'range' in comment #3 gets default face instead of py-builtins-face. 'set' on that same line gets fontified correctly though.

Changed in python-mode:
status: Fix Committed → New
Revision history for this message
Andreas Roehler (a-roehler) wrote :

hmm, here its ok.

If you may have a look into the code, inside (setq python-font-lock-keywords...)
string "range" is in section following comment ;; Builtins
and only there

assume some interference from other side

Changed in python-mode:
status: New → Fix Committed
Revision history for this message
Barry Warsaw (barry) wrote : Re: [Bug 961231] Re: Broken font-locking

On Mar 22, 2012, at 04:20 PM, Andreas Roehler wrote:

>assume some interference from other side

Must have been. I restarted Emacs and now it's working correctly. Thanks!

Revision history for this message
Barry Warsaw (barry) wrote :

Actually, the 'mydict' case is still incorrect.

def baz(mydict):
    mydict['hello'] = 'baz'

'mydict' gets fontlocked with font-lock-variable-name-face.

Changed in python-mode:
status: Fix Committed → New
Revision history for this message
Barry Warsaw (barry) wrote :

Another one:

'hello {0}'.format('world')

The word 'format' gets py-builtins-face but in this case it should just be the default face because it's acting as an attribute, not a built-in.

Revision history for this message
Andreas Roehler (a-roehler) wrote :

Am 23.03.2012 00:46, schrieb Barry Warsaw:
> Actually, the 'mydict' case is still incorrect.
>
>
> def baz(mydict):
> mydict['hello'] = 'baz'
>
>
> 'mydict' gets fontlocked with font-lock-variable-name-face.
>
>
> ** Changed in: python-mode
> Status: Fix Committed => New
>

hmm, isn't it a variable holding a dict?

WDYT it should get?

Revision history for this message
Andreas Roehler (a-roehler) wrote :

Am 23.03.2012 00:48, schrieb Barry Warsaw:
> Another one:
>
>
> 'hello {0}'.format('world')
>
>
> The word 'format' gets py-builtins-face but in this case it should just be the default face because it's acting as an attribute, not a built-in.
>

I'm afraid we have reached the limits of current implementation.

Emacs get's noticed about builtins via hard-coded strings.

a builtin is a builtin

Maybe maintain this as a feature request, in which circumstances builtins should treated different and how?

However, don't see any chance for now. Altogether as we have already a speed issue.

Revision history for this message
Barry Warsaw (barry) wrote :

On Mar 23, 2012, at 08:43 AM, Andreas Roehler wrote:

>Am 23.03.2012 00:46, schrieb Barry Warsaw:
>> Actually, the 'mydict' case is still incorrect.
>>
>> def baz(mydict):
>> mydict['hello'] = 'baz'
>>
>>
>> 'mydict' gets fontlocked with font-lock-variable-name-face.
>
>hmm, isn't it a variable holding a dict?
>
>WDYT it should get?

I think it should get default face just like both lines inside this function:

def bar(mydict):
    mydict['foo'] = 7
    mydict = 7

The dict item assignment shouldn't color 'mydict' any differently.

Revision history for this message
Barry Warsaw (barry) wrote :

On Mar 23, 2012, at 08:56 AM, Andreas Roehler wrote:

>Am 23.03.2012 00:48, schrieb Barry Warsaw:
>> Another one:
>>
>>
>> 'hello {0}'.format('world')
>>
>>
>> The word 'format' gets py-builtins-face but in this case it should just be the default face because it's acting as an attribute, not a built-in.
>>
>
>I'm afraid we have reached the limits of current implementation.
>
>Emacs get's noticed about builtins via hard-coded strings.
>
>a builtin is a builtin
>
>
>Maybe maintain this as a feature request, in which circumstances builtins
>should treated different and how?
>
>However, don't see any chance for now. Altogether as we have already a speed
>issue.

Would it be possible to do a negative lookbehind for '.'?

IOW, if you see

   [.]<somebuiltin>

then it's being used as an attribute, but if you just see

   [^.]<somebuildin>

then you can assume it's a built in. Or alternatively, something like:

   (^|[ \t])<somebuiltin>

Or maybe in English: if the builtin symbol starts at the beginning of the line
or is preceded by whitespace, give it py-builtins-face, otherwise give it
default face.

Revision history for this message
Andreas Roehler (a-roehler) wrote :

>
> Would it be possible to do a negative lookbehind for '.'?
>
> IOW, if you see
>
> [.]<somebuiltin>
>
> then it's being used as an attribute, but if you just see
>
> [^.]<somebuildin>
>
> then you can assume it's a built in. Or alternatively, something like:
>
> (^|[ \t])<somebuiltin>
>
> Or maybe in English: if the builtin symbol starts at the beginning of the line
> or is preceded by whitespace, give it py-builtins-face, otherwise give it
> default face.
>

might consider that.

However, not being convinced its a good idea.
Why highlight builtins at all - finally to indicate its kind.
Does this nature of being built-in change if used attributive?

Revision history for this message
Barry Warsaw (barry) wrote :

On Mar 23, 2012, at 05:50 PM, Andreas Roehler wrote:

>> Would it be possible to do a negative lookbehind for '.'?
>>
>> IOW, if you see
>>
>> [.]<somebuiltin>
>>
>> then it's being used as an attribute, but if you just see
>>
>> [^.]<somebuildin>
>>
>> then you can assume it's a built in. Or alternatively, something like:
>>
>> (^|[ \t])<somebuiltin>
>>
>> Or maybe in English: if the builtin symbol starts at the beginning of the line
>> or is preceded by whitespace, give it py-builtins-face, otherwise give it
>> default face.
>>
>
>might consider that.
>
>However, not being convinced its a good idea. Why highlight builtins at all
>- finally to indicate its kind. Does this nature of being built-in change if
>used attributive?

I'm not personally sure what value there is in highlighting builtins, but I
guess some people find it useful. Note though that builtin's are only special
because they are attributes available at module global scope automatically.
Unlike some other globally available names like None, they aren't keywords so
they can be used as attribute names on other objects, or even redefined inside
a module, and Python doesn't care.

So while in this case, range() refers to the built-in function:

    >>> print range(10)

in this case, it's just a method on some object:

    >>> print myobj.range(10)

The two 'range's have no relationship at all. That's why I suggest that the
former be colored with py-builtins-face but the latter by default face. Of
course, if you really didn't care about the distinction, it's probably best to
continue to use py-builtins-face for the former, but just let people make that
face look like the default face.

Revision history for this message
Andreas Roehler (a-roehler) wrote :

Am 23.03.2012 19:16, schrieb Barry Warsaw:
> On Mar 23, 2012, at 05:50 PM, Andreas Roehler wrote:
>
>>> Would it be possible to do a negative lookbehind for '.'?
>>>
>>> IOW, if you see
>>>
>>> [.]<somebuiltin>
>>>
>>> then it's being used as an attribute, but if you just see
>>>
>>> [^.]<somebuildin>
>>>
>>> then you can assume it's a built in. Or alternatively, something like:
>>>
>>> (^|[ \t])<somebuiltin>
>>>
>>> Or maybe in English: if the builtin symbol starts at the beginning of the line
>>> or is preceded by whitespace, give it py-builtins-face, otherwise give it
>>> default face.
>>>
>>
>> might consider that.
>>
>> However, not being convinced its a good idea. Why highlight builtins at all
>> - finally to indicate its kind. Does this nature of being built-in change if
>> used attributive?
>
> I'm not personally sure what value there is in highlighting builtins, but I
> guess some people find it useful. Note though that builtin's are only special
> because they are attributes available at module global scope automatically.
> Unlike some other globally available names like None, they aren't keywords so
> they can be used as attribute names on other objects, or even redefined inside
> a module, and Python doesn't care.
>
> So while in this case, range() refers to the built-in function:
>
> >>> print range(10)
>
> in this case, it's just a method on some object:
>
> >>> print myobj.range(10)
>
> The two 'range's have no relationship at all.
> That's why I suggest that the
> former be colored with py-builtins-face but the latter by default face. Of
> course, if you really didn't care about the distinction, it's probably best to
> continue to use py-builtins-face for the former, but just let people make that
> face look like the default face.
>

I'll do my best. :)

Changed in python-mode:
status: New → Fix Committed
Changed in python-mode:
status: Fix Committed → Fix Released
Changed in python-mode:
status: Fix Released → Confirmed
importance: High → Medium
Revision history for this message
Andreas Roehler (a-roehler) wrote :

print range(10)

wrong face when written as

print(range(10))

Changed in python-mode:
status: Confirmed → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.