Created
May 13, 2016 18:42
Star
You must be signed in to star a gist
Python metaclass experimentation (python 2.7) applied on creating paths
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
""" experiment on whether we can make a more intuitive interface | |
for paths by (ab)using metaclasses :D | |
result : | |
s = DotPath.myfolder | |
versus: | |
s = os.path.join('home','user','myfolder')""" | |
import os | |
import codecs | |
def userpath(function, *args): | |
"""Decorator that can be used to wrap functions returning paths | |
so that they return user paths instead. Calling this function | |
on a path already user-expanded should have no effect.""" | |
def expand(*args): | |
joined_path = function(*args) | |
return os.path.expanduser(joined_path) | |
return expand | |
class DynamicStatic(type): | |
"""Classes which inherit this type get their constructor called with | |
any attempted attribute access on the class. | |
(on the class not the class instance - ex - Path.dog versus Path().dog)""" | |
def __getattr__(self, name): | |
""" return instance of class and pass name to its constructor""" | |
# uses DynamicStatic __call__ procedure | |
# since it is called with an instance of DynamicStatic | |
return self(name) | |
def __repr__(self): | |
""" do whatever the sub __repr__ func will do """ | |
# TODO check these exist.. | |
return repr(self()) | |
def __str__(self): | |
""" do whatever the sub __str__ func will do """ | |
# TODO check these exist.. | |
return str(self()) | |
def __call__(self, *args): | |
# We can't call our constructor since we have overrided call | |
# so we need to use __new__ and __init__ | |
cl = self.__new__(self) | |
cl.__init__(*args) | |
return cl | |
class DotPath(object): | |
__metaclass__ = DynamicStatic | |
READ = 'r' | |
WRITE = 'w' | |
PERMISSIONS = (READ, WRITE) | |
"""Docstring for DotPath. """ | |
def __init__(self, *items): | |
self.file_permission = DotPath.READ | |
self.path_tokens = ['~'] | |
self.path_tokens.extend(items) | |
def __getattr__(self, name): | |
""" Whenever we access something that doesnt exist | |
assume add it to the path we are creating.. """ | |
self.path_tokens.append(name) | |
return self | |
def __call__(self, permission, encoding='utf-8'): | |
if permission in DotPath.PERMISSIONS: | |
self.file_permission = permission | |
self.encoding = encoding | |
return self | |
else: | |
raise TypeError('permission must be in %s' % DotPath.PERMISSIONS) | |
def __enter__(self): | |
self.opened_file = codecs.open(str(self), | |
self.file_permission, | |
encoding=self.encoding) | |
return self.opened_file | |
def __exit__(self, exc_type, exc_val, exc_tb): | |
self.opened_file.close() | |
@userpath | |
def __repr__(self): | |
"""get string representation of the dotpath on the callers os""" | |
return os.path.join(*self.path_tokens) | |
@userpath | |
def __str__(self): | |
"""get string representation of the dotpath on the callers os""" | |
return os.path.join(*self.path_tokens) | |
if __name__ == "__main__": | |
# ok, so suppose we want to create a path to the file shrubbery | |
path = DotPath.Documents.shrubbery | |
# path is an instance of DotPath with a list of the path_tokens | |
# which grew each time . (getattr) was used on DotPath | |
print(path) | |
# well, since we got this far, why not make the class usable | |
# using the with - as statement? | |
# problem is - we need a way to pass arguments! | |
# but we can use override the __call__ function for that ^_^ | |
with path('w') as out: | |
msg = 'it works!' | |
print('writing message "%s" to %s\n' % (msg, path)) | |
out.write(msg) | |
with path('r') as out: | |
print('reading from %s' % path) | |
print(out.read()) |
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
/home/grv/Documents/shrubbery | |
writing message "it works!" to /home/grv/Documents/shrubbery | |
reading from /home/grv/Documents/shrubbery | |
it works! |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment