Advertisement
Guest User

Untitled

a guest
May 4th, 2020
658
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.60 KB | None | 0 0
  1. import inspect, ast
  2. from forbiddenfruit import curse
  3.  
  4. def get_from_outer_scope(name):
  5.     idx = 1
  6.     while True:
  7.         try:
  8.             return inspect.stack()[idx][0].f_locals[name]
  9.         except KeyError:
  10.             idx += 1
  11.  
  12. class dot_func:
  13.     def __init__(self, func):
  14.         self.func = func
  15.     def __getattr__(self, name):
  16.         var_name, *attr_names = name.split('ˈ')
  17.         val = get_from_outer_scope(var_name)
  18.         for attr in attr_names:
  19.             val = getattr(val, attr)
  20.         self.func(val)
  21. puts = dot_func(print)
  22.  
  23. class MutableString:
  24.     def __init__(self, string):
  25.         self._string = string
  26.  
  27.     def __str__(self):
  28.         return self._string
  29.  
  30.     def __repr__(self):
  31.         return f'MutableString({self._string!r})'
  32.  
  33.     def __setitem__(self, key, value):
  34.         if isinstance(key, int):
  35.             self._string = self._string[:key] + value + self._string[key+1:]
  36.         if isinstance(key, str):
  37.             self._string = self._string.replace(key, value)
  38.  
  39.     def __getattr__(self, name):
  40.         if name == 'upcase':
  41.             return self._string.upper()
  42.         return self.__getattribute__(name)
  43.  
  44.  
  45. def _times_impl(count):
  46.     curframe = inspect.currentframe()
  47.     calframe = inspect.getouterframes(curframe, 1)
  48.     call_str = repr(calframe[2][4])[2:-4]
  49.     expr = ''
  50.     lvl = 1
  51.     for char in reversed(call_str[:-1]):
  52.         if char == ')':
  53.             lvl += 1
  54.         if char == '(':
  55.             lvl -= 1
  56.         if lvl == 0:
  57.             break
  58.         expr = char + expr
  59.  
  60.     for _ in range(count-1):
  61.         eval(expr)
  62.  
  63. curse(str, 'm',lambda self: MutableString(self))
  64. curse(int, 'times', lambda self, expr: _times_impl(self))
  65.  
  66. '''
  67. The code I'm trying to copy:
  68.  
  69. # Output "I love Ruby"
  70. say = "I love Ruby"
  71. puts say
  72.  
  73. # Output "I *LOVE* RUBY"
  74. say['love'] = "*love*"
  75. puts say.upcase
  76.  
  77. # Output "I *love* Ruby"
  78. # five times
  79. 5.times { puts say }
  80. '''
  81.  
  82. # Output "I love Python"
  83. say = "I love Python".m()
  84. puts.say
  85.  
  86. # ^ I didn't find a way to modify str.__setitem__ (didn't work with forbiddenfruit)
  87. # so i made a different class that is returned by str.m()
  88.  
  89. # Output "I *LOVE* PYTHON"
  90. say['love'] = "*love*"
  91. puts.sayˈupcase
  92.  
  93. # ^ the puts method replaces ˈ with . when evaluating.
  94. # This is done because python evaluates __getattr__ from left to right
  95.  
  96. # Output "I *love* Python"
  97. # five times
  98. (5).times(puts.say)
  99.  
  100. # ^ I didn't find a way to cancel the evaluation of puts.say
  101. # when times is called, times evaluates the expression n-1 times.
  102. # therefore (0).times(something) unfortunately evaluates something once.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement