omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    Welcome!

    This is the community forum for my apps Pythonista and Editorial.

    For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.


    You can't take my globals from me!

    Pythonista
    1.6 beta 160033
    3
    6
    5000
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • dgelessus
      dgelessus last edited by dgelessus

      The new pythonista_startup feature is nice. The fact that any globals coming from pythonista_startup aren't removed is also nice. Especially because I can now do this:

      from __future__ import division, print_function
      
      import sys
      import types
      
      class ContainAllTheThings(list):
          def __getitem__(self, key):
              try:
                  return super(ContainAllTheThings, self).__getitem__(key)
              except (IndexError, KeyError):
                  return None
          
          def __contains__(self, obj):
              return super(ContainAllTheThings, self).__contains__(obj) or True
      
      class DirAllTheThings(types.ModuleType):
          def __dir__(self):
              return ContainAllTheThings()
      
      new_module = DirAllTheThings(__name__, __doc__)
      vars(new_module).update(vars(sys.modules["pythonista_startup"]))
      sys.modules["pythonista_startup"] = new_module
      

      (Can't we just have an option to keep all globals? ;))

      1 Reply Last reply Reply Quote 1
      • omz
        omz last edited by

        Hehe, very clever! :)

        1 Reply Last reply Reply Quote 0
        • Webmaster4o
          Webmaster4o last edited by

          Can you explain it? can't tell what it does.

          dgelessus 1 Reply Last reply Reply Quote 0
          • dgelessus
            dgelessus @Webmaster4o last edited by

            @Webmaster4o said:

            Can you explain it? can't tell what it does.

            Every time you run a script, Pythonista deletes all global variables, except for those that come from the pythonista_startup module (which is run automatically when the app is started). Internally this is done by looking at dir(pythonista_startup) - any names listed there are not deleted from the globals. I'm abusing this feature just a tiny bit so that no globals are ever removed.

            The first class, ContainAllTheThings, is a subclass of list that pretends to contain every object, i. e. obj in ContainAllTheThings() is always True for any object. The second class, DirAllTheThings, is a subclass of module (aka types.ModuleType) with a modified __dir__ method that returns a ContainAllTheThings object. This means that obj in dir(DirAllTheThings()) is always True. Finally we replace the real module pythonista_startup with a DirAllTheThings object and copy all attributes over.

            To find out which global names come from pythonista_startup, Pythonista internally checks name in dir(pythonista_startup) for every name. Now we've replaced pythonista_startup with an instance of DirAllTheThings, meaning that when we call dir on it we get an instance of ContainAllTheThings. Now when Pythonista checks whether a name comes from pythonista_startup, the answer is always True, meaning that no name is ever deleted.

            1 Reply Last reply Reply Quote 1
            • Webmaster4o
              Webmaster4o last edited by

              Ah. Clever!

              1 Reply Last reply Reply Quote 0
              • dgelessus
                dgelessus last edited by dgelessus

                The original version no longer works in Pythonista 3. It seems that the dir function now converts the return value of __dir__ to an actual list, instead of allowing a subclass. This is the updated version:

                import sys
                import types
                
                class DirAllTheGlobals(types.ModuleType):
                    import __main__
                    
                    def __dir__(self):
                        return dir(type(self).__main__)
                
                # THESE LINES MUST COME LAST.
                # Anything past this point is executed in the context of the old
                # pythonista_startup module, which may already be partially
                # garbage-collected.
                new_module = DirAllTheGlobals(__name__, __doc__)
                vars(new_module).update(vars(sys.modules["pythonista_startup"]))
                sys.modules["pythonista_startup"] = new_module
                

                This should also still work in Pythonista 2.

                @omz please can you add the option to keep globals back?

                1 Reply Last reply Reply Quote 0
                • First post
                  Last post
                Powered by NodeBB Forums | Contributors