PyModule(G.py): Now Python has REAL globals -- and their scoped to boot!

R

Rick Johnson

# Copyright 2013, Rick "rantingrick" Johnson
#
# Permission to use, copy, modify, and distribute this software for
# any purpose and without fee is hereby granted, provided that the above
# copyright notice appear in all copies.
#
# THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#-----------------------------------------------------------------------------
#
# This script needs to be loaded when Python starts. But since i'm
# not supplying an installer, you'll have to tell Python how to load
# it yourself. Which is not very difficult really.
#
# The easiest method to "auto-load" this script is to create a .pth
# file and save it somewhere that python can find it. If your a noob
# and don't know what that means, then just throw the .pth file in
# your PythonXY folder.
#
# The contents of the .pth file MUST include the following line:
#
# import G
#
# Noob Note: You can name the .pth file anything you want, but this
# module must be named G.py. Yes, with a capital G!
#
# Enjoy.

import sys as _sys

class _Globals(object):
"""
DESIGN NOTES:
This object is meant to provide a namespace for true global
variables in Python -- with no need to import anything.

A toplevel Globals object is injected at runtime, and always
available within ANY Python module via the name "G". Note the
capital letter, it's significant!

I like global variables to be qualified, but not behind a
long name, and only a single letter can fulfill both.

And since "globals" is already a built-in function, "G" is the
next best thing.

I also wanted global access to be noticeable in the source,
but not overwhelming!!! Hence the choice of capital "G" over
lowercase "g".

Those of you with Java background should be comfortable
with "G" due to your experiences with the "R" object.

PUBLIC METHODS:
add_space(str name)
get_path()

USAGE:
Assignment:
G.name = value
Query:
G.name
Expansion:
G.add_namespace(name)

"""
MUTATE_MSG = "WARNING: The value of global variable {0!r} has changed!"
DELETE_MSG = 'WARNING: The global variable {0!r} was deleted!'
ACCESS_MSG = 'Access to private variable {0!r} is denied!'

def __init__(self, name):
self.__dict__["__private"] = {
"dirlst":[],
"name":name,
}

def __str__(self):
fmtstr1 = "{0}(\n{1}\n )"
fmtstr2 = "{0}(<empty>)"
lst = []
pDict = self.__dict__["__private"]
for name in pDict["dirlst"]:
value = self.__dict__[name]
lst.append( " {0} = {1!r}".format(name, value))
values = '\n'.join(lst)
if not values:
fmtstr1 = fmtstr2
return fmtstr1.format(pDict["name"], values)

def __dir__(self):
return self.__dict__["__private"]["dirlst"]

def __getattribute__(self, name):
## print "_Globals.__getattribute__({0!r})".format(name)
if name == "__private" :
# This only stops direct access!
raise Exception(self.ACCESS_MSG.format(self.__dict__["__private"]))
return object.__getattribute__(self, name)

def __setattr__(self, name, value):
## print "_Globals.__setattr__({0!r}, {1!r})".format(name, value)
if name in self.__dict__:
pDict = self.__dict__["__private"]
path = "{0}.{1}".format(pDict["name"], name)
if name == "__private":
# This only stops direct access!
raise Exception(self.ACCESS_MSG.format(name))
else:
print self.MUTATE_MSG.format(path)
else:
self.__dict__["__private"]["dirlst"].append(name)
self.__dict__[name] = value

def __delattr__(self, name):
## print "_Globals.__delattr__({0!r})".format(name)
pDict = self.__dict__["__private"]
path = "{0}.{1}".format(pDict["name"], name)
if name == "__private":
raise Exception(self.ACCESS_MSG.format(path))
elif name in self.__dict__:
print self.DELETE_MSG.format(path)
del self.__dict__[name]
pDict["dirlst"].remove(name)

def get_path(self):
return self.__dict__["__private"]["name"]

def add_namespace(self, name):
"""Add a new global namespace named <name>"""
pDict = self.__dict__["__private"]
pDict["dirlst"].append(name)
newname = pDict["name"] + ".{0}".format(name)
self.__dict__[name] = _Globals(newname)

#
# Inject a toplevel instance of _Globals (named "G") into the
# builtins module namespace.
_sys.modules['__builtin__'].__dict__['G'] = _Globals("G")

if __name__ == '__main__':
print G
print '\nAdding globals to "G"'
G.str = ""
G.int = 1
G.float = 1.333
print G
print '\nMutating globals of "G"'
G.str = "XXX"
G.int = 10
G.float = 5.333
print G
print '\nDeleting globals of "G"'
del G.int
del G.str
del G.float
print G
print '\nAdding new space "G.math"'
G.add_namespace("math")
G.math.PI = 3.14
print G.math
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top