Created
March 23, 2015 09:16
-
-
Save tmr232/785966e73245e17e98b4 to your computer and use it in GitHub Desktop.
Python WTF - Attribute Abbreviation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""Attribute Abbreviation. | |
This file contains a metaclass that can be used to abbreviate attribute names for a class. | |
This is a POC made for fun. | |
Do yourself a favor and NEVER do this in actual code. | |
You've been warned. | |
""" | |
class AbbreviationError(Exception): | |
pass | |
class Abbreviate(type): | |
def __new__(mcs, name, bases, dict_): | |
abbreviate = {key for key in dict_ if | |
not key.startswith("__") and key.startswith(dict_.get("PREFIX", ""))} | |
if any(any(other.startswith(this) and other != this for other in abbreviate) for this in abbreviate): | |
raise AbbreviationError("Ambiguous naming prevents proper abbreviation.") | |
dict_["ABBREVIATE"] = abbreviate | |
def __getattr__(self, name): | |
names = [abbr for abbr in self.ABBREVIATE if abbr.startswith(self.PREFIX + name)] | |
if len(names) > 1: | |
abbrev_names = [abbrev_name[len(self.PREFIX):] for abbrev_name in names] | |
raise AttributeError("Abbreviation {!r} matches too many names: {!r}.".format(name, abbrev_names)) | |
if not names: | |
raise AttributeError("Abbreviation {!r} has no matches.".format(name)) | |
return getattr(self, names[0]) | |
dict_["__getattr__"] = __getattr__ | |
return type.__new__(mcs, name, bases, dict_) | |
class MyClass(object): | |
__metaclass__ = Abbreviate | |
PREFIX = "c_" | |
def c_print(self, text): | |
print text | |
def c_add(self, a, b): | |
return a + b | |
def c_min(self, a, b): | |
return min(a, b) | |
def c_max(self, a, b): | |
return max(a, b) | |
if __name__ == '__main__': | |
my_class = MyClass() | |
my_class.p("Hello, Abbreviation World!") # Calls `my_class.c_print` | |
print my_class.a(1, 2) # Calls `my_class.add` | |
print my_class.min(0, 1) # Calls `my_class.min` | |
print my_class.c_max(1, 2) # Original method names work as well | |
try: | |
print my_class.m(3, 4) # Ambiguity! | |
except AttributeError as ex: | |
print ex.message |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment