Python: with someRegion: inside with block someRegion gets what SCREEN is outside

Asked by Rainer

The following code

print(SCREEN)
with Region(1, 2, 3, 4):
    print(SCREEN)
    print(Screen())
print(SCREEN)

results in:
R[0,0 1680x1050]@S(0)

R[1,2 3x4]@S(0)
R[0,0 1680x1050]@S(0)

R[0,0 1680x1050]@S(0)

Within a "with" Region, the SCREEN variable obviously points to the "with" Region, and is afterwards reassigned the Screen() Region.

Is this the intended behavior?

Question information

Language:
English Edit question
Status:
Solved
For:
SikuliX Edit question
Assignee:
No assignee Edit question
Solved by:
RaiMan
Solved:
Last query:
Last reply:
Revision history for this message
RaiMan (raimund-hocke) said :
#1

The reason behind is the historical implementation of undotted Region methods:
- in the normal script they are dynamically (at runtime) bound to the constant object SCREEN, which is globally initialised to Screen(0) (the primary screen)
- using with someRegion: they are bound dynamically to the given someRegion, by dynamically assigning it to the object SCREEN.

I will not change anything here. If someone has a better implementation: welcome as a pull request.

the same effect can be done by using setROI(someRegion)/setROI(Screen(0)) or by using use(someRegion)/use().

I admit, that with: has some advantage due to the evident scope by the block.

Revision history for this message
Rainer (formulator) said :
#2

Not a problem. I just was not aware of this behavior, because the SCREEN object is described everywhere as "constant".

I noticed an unexpected behavior of a function (that uses the SCREEN object) that is called from different modules, although I had not changed anything in that function. It took me some time to realize that the difference came from the fact that on this one occasion I call this function from within a with: block, which changed the SCREEN region.

Now that we know this, we can even use it to our advantage – we don't need to transfer the with: region as a parameter to the called function. The SCREEN "constant" takes care of that. The whole screen can still be accessed by Screen(0), and it is of course always possible to assign SCREEN or Screen(0) to a separate variable and then use this variable as reference to the whole screen. So in my opinion there is no need to change that behavior.

One more question:
I did some additional testing. The following code:

print("1", SCREEN)
with Region(1,1,1,1):
    print("2", SCREEN)
    with Region(2,2,2,2):
        print("3", SCREEN)
    print("4", SCREEN)
print("5", SCREEN)

results in

('1', R[0,0 1680x1050]@S(0))
('2', R[1,1 1x1]@S(0))
('3', R[2,2 2x2]@S(0))
('4', R[0,0 1680x1050]@S(0))
('5', R[0,0 1680x1050]@S(0))

Obvioulsy the with: blocks cannot really be nested – otherwise "4" should be back to (1,1,1,1) again …

Is this the intended behavior?

Revision history for this message
Best RaiMan (raimund-hocke) said :
#3

I am sorry for the confusion.

After looking again into the code, I had to realize, that the support for with (__entry__, __exit__) is switched off at the Java level.
So the effects are completely caused by Jython (no where else special support for with by SikuliX).

So simply for now: we have to live with it :-(

The historical implementation of the SCREEN object (and hence the use of undotted methods) was a nice idea for supporting scripting newbies, but has many bad implications, that usually hit the ones like you, who want to make reliable code.

Currently I am experimenting with py4j, that would allow to use SikuliX features directly from Python (the real one ;-) up to 3.7.
Some areas in SikuliX have to be changed so, to fully support this environment, but it is promising.

Revision history for this message
Rainer (formulator) said :
#4

Thanks RaiMan, that solved my question.

Revision history for this message
Rainer (formulator) said :
#5

Thanks, Raiman, for your explanation.

Avoiding with: blocks altogether is easily doable. They are just a quite "pythonic" shortcut, and I like to use them when they come handy. So really not that big of a deal at all.

Getting rid of Jython, on the other hand, is a move that I would really like to support as strongly as possible. Jython seems to remain stuck at Python 2.7 (not even the latest 2.7.x - there has been no new installer since nearly two years now), requires complicated setups and odd configurations in 3rd party IDEs etc.

Directly usable "real" Python would be a huge improvement in every conceivable aspect.

Revision history for this message
RaiMan (raimund-hocke) said :
#6

fully agreed
see: bug 1818514

watch the achievements there and optionally add ideas and/or comments