Skip to main content

Show HN: Generic dual-paradigm hooking mechanism https://ift.tt/xaRUlIi

Show HN: Generic dual-paradigm hooking mechanism Hi HN ! I am Alex, a tech enthusiast, I'm excited to show you a major iteration of my library for performing hooking in Python. I redesigned the whole project because it didn't not cover all my needs. I'm happy with the current iteration that I've written tests for and look forward to spending weeks and months using it in my projects. Python has a concept called Decorator [1] which is a function that takes another function and extends the behavior. In the following script, the timeit decorator is used to measure the execution time of the heavy_computation function: import time from functools import wraps def timeit(text): def deco(target): @wraps(target) def wrapper(*args, **kwargs): # execute and measure the target run time start_time = time.perf_counter() result = target(*args, **kwargs) total_time = time.perf_counter() - start_time # print elapsed time print(text.format(total=total_time)) return result return wrapper return deco @timeit(text="Done in {total:.3f} seconds !") def heavy_computation(a, b): time.sleep(2) # doing some heavy computation ! return a*b if __name__ == "__main__": result = heavy_computation(6, 9) print("Result:", result) Output: $ python -m test Done in 2.001 seconds ! Result: 54 Besides benchmarking, there are many other cool things that can be done with the Python decorator. For example, the Flask [2] and Bottle [3] web frameworks implement routing with decorators. While decorators are cool, it's worth mentioning that using a decorator is much more intuitive than writing its code. The code is entirely different depending on whether the decorator takes arguments or not. The following code performs the same task as the previous one, except it is more clear and intuitive: import time from hooking import on_enter def timeit(context, *args, **kwargs): # execute and measure the target run time start_time = time.perf_counter() context.result = context.target(*args, **kwargs) total_time = time.perf_counter() - start_time # print elapsed time text = context.config.get("text") # get 'text' from config data print(text.format(total=total_time)) context.target = None @on_enter(timeit, text="Done in {total:.3f} seconds !") def heavy_computation(a, b): time.sleep(2) # doing some heavy computation ! return a*b if __name__ == "__main__": result = heavy_computation(6, 9) print("Result:", result) Output: $ python -m test Done in 2.001 seconds ! Result: 54 The Hooking library used in the code above uses Python decorators to wrap, augment, and override functions and methods. It is a generic hooking [4] mechanism which is perfect for creating a plug-in mechanism for a project, performing benchmarking and debugging, implementing routing in a web framework, et cetera. Also, it is a dual paradigm hooking mechanism since it supports tight and loose coupling [5]. The previous code uses the tight coupling paradigm, that's why the timeit hook is directly tied to the target function. In loose coupling paradigm, targets functions and methods are tagged using a decorator, and hooks are bound to these tags. So when a target is called, the bound hooks are executed upstream or downstream. This paradigm is served by a class designed for pragmatic access via class methods [6]. This class can be easily subclassed to group tags by theme for example. Here is an example of the loose coupling paradigm: import time from hooking import H @H.tag def heavy_computation(a, b): print("heavy computation...") time.sleep(2) # doing some heavy computation ! return a*b def upstream_hook(context, *args, **kwargs): print("upstream hook...") def downstream_hook(context, *args, **kwargs): print("downstream hook...") # bind upstream_hook and downstream_hook to the "heavy_computation" tag H.wrap("heavy_computation", upstream_hook, downstream_hook) if __name__ == "__main__": result = heavy_computation(6, 9) print("Result:", result) Output: $ python -m test upstream hook... heavy computation... downstream hook... Result: 54 This library is available on PyPI and you can play with the examples [7] which are on the project's README. I would like to know what you think [8] of this project. Your questions, suggestions and criticisms are welcome ! [1] https://ift.tt/d67TxCQ [2] https://ift.tt/rVecRns [3] https://ift.tt/jANcIMU [4] https://ift.tt/ZLilg5F [5] https://ift.tt/mvrSGcD... [6] https://ift.tt/xf2RW1X [7] https://ift.tt/UiBRkq0 [8] https://ift.tt/iYprVdH https://ift.tt/Za5w4bO November 9, 2022 at 07:10PM

Comments

Popular posts from this blog

Show HN: Launch VM workloads securely and instantaneously, without VMs https://ift.tt/2QwJ1Kd

Show HN: Launch VM workloads securely and instantaneously, without VMs Hello HN! We've been working on a new hypervisor https://kwarantine.xyz that can run strongly isolated containers. This is still a WIP, but we wanted to give the community an idea about our approach, its benefits, and various use cases it unlocks. Today, VMs are used to host containers, and make up for the lack of strong security as well as kernel isolation in containers. This work adds this missing security piece in containers. We plan on launching a free private beta soon. Meanwhile, we'd deeply appreciate any feedback, and happy to answer any questions here or on our slack channel. Thanks! April 29, 2021 at 07:50AM

Show HN: Comment on live websites just like you comment on Google Docs/Figma https://ift.tt/GRhrjX0

Show HN: Comment on live websites just like you comment on Google Docs/Figma I'd love your feedback on this new JS plugin we launched. With this, you can comment on live websites just like you comment on Google Docs or Figma. You can use is to get Copy or UI feedback right on the website you are building. Feedback can be provided in rich formats like audio and video. You can get started by installing a JS tag in the footer of the website. You can then turn the review mode on or off on demand by adding “?review=true” to the URL. Demo video (43s): https://www.youtube.com/watch?v=cdnfBEw8TfI Demo video: https://www.youtube.com/watch?v=h6vxzXJuh8o https://ift.tt/ocLpdEu October 26, 2022 at 02:18AM

Women Pioneers at Muni: Adeline Svendsen and Muni’s First Newsletter

Women Pioneers at Muni: Adeline Svendsen and Muni’s First Newsletter By Jeremy Menzies To close out Women’s History Month, here’s a look back at one woman whose work to bring Muni staff together in the late 1940s created a legacy that lives on to this day. Adeline “Addy” Svendsen was founding editor of Muni’s first internal newsletter, “ Trolley Topics .” Adeline Svendsen sits at her desk in the Geneva Carhouse office building in this 1949 shot. Trolley Topics was a new venture when it started in February 1946. As Svendsen wrote in the first issue it was created, “to bring a little fun, a little news, and a lot of good will to all our fellow employees in the Railway.” Just two years prior in 1944, Muni merged with the Market Street Railway Company, expanding the small municipal operation into the largest transit provider in the city with hundreds of employees, vehicles of every shape and size, and dozens of facilities scattered across town. The newsletter was meant to help unite ...