Add using_scope

Analog to .NET’s using statement, allow users to create a scope block

  • Allow users to create a scope within a function
  • the behavior would be exactly like a nested function, except it’s never explicitly called, I could imagine it would call itself using_scope.exit()
  • the scope need not be visible or callable outside its parent scope
  • variables inside the scope need not be visible in any outer scope
  • try, catch, finally should work as they would in a function
  • the scope need not except arguments..?..
  • the scope need not return a value, but may allow for early exit
class A:
    def __init__(self, name):
        self.name = name
        print(f"Object {self.name} created")

    def __del__(self):
        print(f"Object {self.name} destroyed")
        
# behavior
def my_function():
    database = A("One")
    def using_scope():
        entity = A("Two")
        entity = A("Three")
    using_scope()


# could be

# def my_function():
#     obj1 = A("One")
#     using_scope():
#         obj2 = A("Two")
#         obj3 = A("Three")

# or

# def my_function():
#     obj1 = A("One")
#     def_scope foo():
#         obj2 = A("Two")
#         obj3 = A("Three")


# exptected
Object One created
Object Two created
Object Three created
Object Two destroyed
Object Three destroyed
Object One destroyed

What would be the purpose of this construct?

1 Like

You are only saving a single line over the existing option of defining a function and then calling it. New syntax simply to save one line is unlikely to happen.

If you want something that (maybe, it’s a matter of opinion) expresses the intent more clearly,

>>> def scope(f):
...     f()
...     return f
...
>>>
>>> @scope
... def _():
...     a = 12
...     print(a)
...
12
>>> a
Traceback (most recent call last):
  File "<python-input-3>", line 1, in <module>
    a
NameError: name 'a' is not defined
>>>

Still one line extra, but it states up front that the function is just being used as a scope. If you don’t want to be able to access the function later, just remove return f from the decorator.

4 Likes

Well, that’s just exactly what I needed! My humble personage bows before your grandeur, I withdraw my request

import traceback
from pyrx import Ap, Db, Ap

def using_scope(f):
    f()

@Ap.Command()
def doit2():
    try:
        db = Db.Database(False, True)
        db.readDwgFile("E:\\temp\\Floor Plan Sample1.dwg")
        db.closeInput(True)

        @using_scope
        def _():
            ms = db.modelSpace()
            ents = [Db.Entity(id) for id in ms.objectIds(Db.Entity.desc())]
            types = [ent.isA().dxfName() for ent in ents]
            print(len(types))
    except Exception as err:
        traceback.print_exception(err)
Command: DOIT2
4422
4 Likes