1

In a plugin I'm writing in Python for Sublime Text I've discovered a difference between Sublime Text v.2 and v.3. [I'm porting the plugin backwards to work with v.2 having written it with v.3.]

In the sublime.View class the method add_regions() takes various flags. To get a selection region outline in v.2 sublime.DRAW_OUTLINED is used, in v.3 sublime.DRAW_NO_FILL is used - it seems the developer has simply renamed DRAW_OUTLINED to DRAW_NO_FILL in v.3 as they both do the same thing.

After trying various approaches I resolved the situation when I realized that, although not documented in the API, sublime.DRAW_OUTLINED is also available in v.3 (although sublime.DRAW_NO_FILL is not available in v.2.)

However I'd quite like to know what approaches would be available to me had the developer not kept sublime.DRAW_OUTLINED in his v.3 code.

My approaches both centered around using the version number of the class.

Firstly:

sub_text_ver = sublime.version()

if sub_text_ver < 3000:
    flags = sublime.DRAW_OUTLINED | sublime.DRAW_EMPTY_AS_OVERWRITE
else:
    flags = sublime.DRAW_NO_FILL | sublime.DRAW_EMPTY_AS_OVERWRITE

# Code continues...

Secondly:

sub_text_ver = sublime.version()

if sub_text_ver < 3000:
    flags = self.get_regions_flags_sub_text_v2()
else:
    flags = self.get_regions_flags_sub_text_v3()

# Code continues to end of method and then...

def get_regions_flags_sub_text_v2(self):
    return sublime.DRAW_OUTLINED | sublime.DRAW_EMPTY_AS_OVERWRITE

def get_regions_flags_sub_text_v3(self):
    return sublime.DRAW_NO_FILL | sublime.DRAW_EMPTY_AS_OVERWRITE

Both gave me a traceback error like this:

Traceback (most recent call last):
  File "./ExpandSelectionByRegex.py", line 155, in on_change
  File "./ExpandSelectionByRegex.py", line 177, in get_regions_flags_sub_text_v3
AttributeError: 'module' object has no attribute 'DRAW_NO_FILL'

I would like to know what approaches I could have taken to sort this out. Would I have been forced to have two different files for the plugin, one for each version of Sublime Text? Could it have been resolved in one file with two different classes? Could it have been resolved in the same class? I feel that it's best to learn about these kind of things when you encounter them, rather than shelving them just because the current situation was resolved. [Clearly I am not the most experienced Python programmer.] Thanks.

mattst
  • 13,340
  • 4
  • 31
  • 43

1 Answers1

1

I would suggest using try and except statements do exception handling to make sure you get the right module attribute:

try:
    flags = sublime.DRAW_NO_FILL | sublime.DRAW_EMPTY_AS_OVERWRITE
except AttributeError:    # DRAW_NO_FILL was previously named DRAW_OUTLINED
    flags = sublime.DRAW_OUTLINED | sublime.DRAW_EMPTY_AS_OVERWRITE

This is known as the "Easier to Ask Forgiveness than Permission" (EAFP) style of programming. You write some code you know will raise an exception in some situations, and write a try/except structure to handle that exception with an alternative bit of code. EAFP style is usually preferred in Python over the "Look Before You Leap" (LBYL) style you were trying for with your if statements, though there are some situations where LBYL is easier.

Blckknght
  • 100,903
  • 11
  • 120
  • 169
  • Thanks, that's a sensible solution. However instinctively I don't like it, knowing an error will sometimes happen and relying on the error to take place to set the right attributes - it's not very elegant. Are there any other ways of getting around this using the LBYL approach? – mattst Oct 04 '14 at 10:35
  • 1
    Well, to an extent I'd say your instincts (if they come from other programming languages) are wrong. Exceptions are a core feature of Python, you shouldn't go out of your way to avoid them. That said, if you want a LBYL approach, you could try using `hasattr` to inspect the module object to see which attributes it has. – Blckknght Oct 04 '14 at 11:45
  • Thanks again. Looking for `hasattr` led me to this excellent SO Q/A: [Which is the best way to check for the existence of an attribute?](http://stackoverflow.com/questions/9748678/which-is-the-best-way-to-check-for-the-existence-of-an-attribute) – mattst Oct 04 '14 at 13:49