Commit 950d9e32 authored by Ole Streicher's avatar Ole Streicher

Upstream version 2.1.5

parent 93dec89e
Metadata-Version: 1.1
Name: pyraf
Version: 2.1.3
Version: 2.1.5
Summary: Provides a Pythonic interface to IRAF that can be used in place of
the existing IRAF CL
Home-page: http://www.stsci.edu/resources/software_hardware/pyraf
......
Metadata-Version: 1.1
Name: pyraf
Version: 2.1.3
Version: 2.1.5
Summary: Provides a Pythonic interface to IRAF that can be used in place of
the existing IRAF CL
Home-page: http://www.stsci.edu/resources/software_hardware/pyraf
......
......@@ -750,6 +750,7 @@ required_pkgs/d2to1/README.rst
required_pkgs/d2to1/ez_setup.py
required_pkgs/d2to1/setup.cfg
required_pkgs/d2to1/setup.py
required_pkgs/d2to1/tox.ini
required_pkgs/d2to1/d2to1/__init__.py
required_pkgs/d2to1/d2to1/core.py
required_pkgs/d2to1/d2to1/util.py
......
"""irafpar.py -- parse IRAF .par files and create lists of IrafPar objects
$Id: irafpar.py 1958 2013-04-08 21:08:11Z sontag $
$Id: irafpar.py 2080 2013-11-06 19:31:41Z sontag $
R. White, 2000 January 7
"""
......@@ -508,6 +508,8 @@ class IrafParList(taskpars.TaskPars):
"""
self.__pars = []
self.__hasPsets = False
self.__psets2merge = None # is a list when populated
self.__psetLock = False
self.__filename = filename
self.__name = taskname
self.__filecache = ParCache(filename, parlist)
......@@ -516,8 +518,9 @@ class IrafParList(taskpars.TaskPars):
def Update(self):
"""Check to make sure this list is in sync with parameter file"""
self.__pars, self.__pardict, self.__psetlist = \
self.__pars, self.__pardict, self.__psets2merge = \
self.__filecache.get()
if self.__psets2merge: self.__addPsetParams()
def setFilename(self, filename):
"""Change filename and create ParCache object
......@@ -557,19 +560,27 @@ class IrafParList(taskpars.TaskPars):
2013 that this is not happening correctly, and may be an unsafe plan.
Therefore the code was changed to allow clients to access both copies;
see getParObjects() and any related code. """
# return immediately if they have already been added
if self.__psetlist is None: return
# otherwise...
self.__hasPsets = True
# return immediately if they have already been added or
# if we are in the midst of a recursive call tree
if self.__psetLock or self.__psets2merge is None:
return
# otherwise, merge in any PSETs
if len(self.__psets2merge) > 0:
self.__hasPsets = True # never reset
self.__psetLock = True # prevent us from coming in recursively
# Work from the pset's pardict because then we get
# parameters from nested psets too
for p in self.__psetlist:
for p in self.__psets2merge:
# silently ignore parameters from psets that already are defined
psetdict = p.get().getParDict()
for pname in psetdict.keys():
if not self.__pardict.has_exact_key(pname):
self.__pardict.add(pname, psetdict[pname])
self.__psetlist = None
# back to normal state
self.__psets2merge = None
self.__psetLock = False
def addParam(self, p):
"""Add a parameter to the list"""
......@@ -605,13 +616,14 @@ class IrafParList(taskpars.TaskPars):
self.__pardict.add(p.name, p)
if isinstance(p, IrafParPset):
# parameters from this pset will be added too
if self.__psetlist is None:
if self.__psets2merge is None:
# add immediately
self.__psetlist = [p]
self.__psets2merge = [p]
self.__addPsetParams()
else:
# just add to the pset list
self.__psetlist.append(p)
self.__psets2merge.append(p)
# can't call __addPsetParams here as we may now be inside a call
def isConsistent(self, other):
"""Compare two IrafParLists for consistency
......@@ -693,7 +705,7 @@ class IrafParList(taskpars.TaskPars):
def hasPar(self,param):
"""Test existence of parameter named param"""
if self.__psetlist: self.__addPsetParams()
if self.__psets2merge: self.__addPsetParams()
param = irafutils.untranslateName(param)
return param in self.__pardict
......@@ -711,7 +723,7 @@ class IrafParList(taskpars.TaskPars):
return self.__pars
def getParDict(self):
if self.__psetlist: self.__addPsetParams()
if self.__psets2merge: self.__addPsetParams()
return self.__pardict
def getParObject(self,param):
......@@ -720,7 +732,7 @@ class IrafParList(taskpars.TaskPars):
any duplicated PSET pars via __addPsetParams), but does not look
down into PSETs. Note the difference between this and getParObjects
in their different return types. """
if self.__psetlist: self.__addPsetParams()
if self.__psets2merge: self.__addPsetParams()
try:
param = irafutils.untranslateName(param)
return self.__pardict[param]
......@@ -728,13 +740,13 @@ class IrafParList(taskpars.TaskPars):
raise e.__class__("Error in parameter '" +
param + "' for task " + self.__name + "\n" + str(e))
def getParObjects(self, param):
def getParObjects(self, param, typecheck=True):
"""
Returns _all_ IrafPar objects matching the string name given (param),
Returns all IrafPar objects matching the string name given (param),
in the form of a dict like:
{ scopename : <IrafPar instance>, ... }
where scope is '' if the par was found as a regular par in this list,
or, where scope is psetname if the par was found inside a PSET.
where scopename is '' if par was found as a regular par in this list,
or, where scopename is psetname if the par was found inside a PSET.
It is possible that some dict values will actually be the same object
in memory (see docs for __addPsetParams).
......@@ -742,10 +754,28 @@ class IrafParList(taskpars.TaskPars):
found at the "top level" (a regular par inside this par list)
even if it is also in a PSET.
typecheck: If multiple par objects are found, and typecheck is set to
True, only the first (e.g. top level) will be returned if those
par objects have a different value for their .type attribute.
Otherwise all par objects found are returned in the dict.
Note the difference between this and getParObject in their
different return types.
"""
if self.__psetlist: self.__addPsetParams()
# Notes:
# To accomplish the parameter setting (e.g. setParam) this calls up
# all possible exact-name-matching pars in this par list, whether
# they be on the "top" level with that name (param), or down in some
# PSET with that name (param). If we are simply an IRAFish task, then
# this is fine as we can assume the task likely does not have a par of
# its own and a PSET par, both of which have the same name. Thus any
# such case will acquire a copy of the PSET par at the top level. See
# discussion of this in __addPsetParams().
# BUT, if we are a CL script (e.g. mscombine.cl), we could have local
# vars which happen to have the same names as PSET pars. This is an
# issue that we need to handle and be aware of (see typecheck arg).
if self.__psets2merge: self.__addPsetParams()
param = irafutils.untranslateName(param)
retval = {}
......@@ -773,9 +803,15 @@ class IrafParList(taskpars.TaskPars):
if len(matching_pars) > 1:
raise RuntimeError('Unexpected multiple matches for par: '+ \
param+', are: '+str([p.name for p in matching_pars]))
# add it to outgoing dict
# found one with that name; add it to outgoing dict
if len(matching_pars) > 0:
retval[pset.name] = matching_pars[0]
addit = True
if typecheck and '' in retval:
# in this case we already found a top-level and we've been
# asked to make sure to return only same-type matches
addit = matching_pars[0].type == retval[''].type # attr is a char
if addit:
retval[pset.name] = matching_pars[0]
return retval
def getAllMatches(self,param):
......@@ -810,7 +846,8 @@ class IrafParList(taskpars.TaskPars):
"""Set task parameter 'param' to value (with minimum-matching).
scope, idxHint, and check are included for use as a task object
but they are currently ignored."""
for par_obj in self.getParObjects(param).values():
matches_dict = self.getParObjects(param)
for par_obj in matches_dict.values():
par_obj.set(value)
def setParList(self,*args,**kw):
......
......@@ -7,14 +7,14 @@ __all__ = ['__version__', '__vdate__', '__svn_revision__', '__svn_full_info__',
import datetime
__version__ = '2.1.3'
__version__ = '2.1.5'
__vdate__ = 'unspecified'
__svn_revision__ = "2047"
__svn_revision__ = "2095"
__svn_full_info__ = 'unknown'
__setup_datetime__ = datetime.datetime(2013, 8, 20, 12, 26, 1, 837603)
__setup_datetime__ = datetime.datetime(2013, 11, 25, 12, 17, 10, 987591)
# what version of stsci.distutils created this version.py
stsci_distutils_version = '0.3.5.dev'
stsci_distutils_version = '0.3.7.dev27596'
if '.dev' in __version__:
def update_svn_info():
......@@ -68,7 +68,7 @@ if '.dev' in __version__:
if pipe.wait() == 0:
stdout = pipe.stdout.read().decode('latin1').strip()
if stdout and stdout[0] in string.digits:
__svn_revision__ = "2047"
__svn_revision__ = "2095"
except OSError:
pass
......
......@@ -7,14 +7,14 @@ __all__ = ['__version__', '__vdate__', '__svn_revision__', '__svn_full_info__',
import datetime
__version__ = '2.1.3'
__version__ = '2.1.5'
__vdate__ = 'unspecified'
__svn_revision__ = 'Unable to determine SVN revision'
__svn_full_info__ = 'unknown'
__setup_datetime__ = datetime.datetime(2013, 8, 20, 12, 25, 53, 933220)
__setup_datetime__ = datetime.datetime(2013, 11, 25, 12, 17, 2, 831411)
# what version of stsci.distutils created this version.py
stsci_distutils_version = '0.3.5.dev'
stsci_distutils_version = '0.3.7.dev27596'
if '.dev' in __version__:
def update_svn_info():
......
......@@ -7,14 +7,14 @@ __all__ = ['__version__', '__vdate__', '__svn_revision__', '__svn_full_info__',
import datetime
__version__ = '2.1.3'
__version__ = '2.1.5'
__vdate__ = 'unspecified'
__svn_revision__ = 'Unable to determine SVN revision'
__svn_full_info__ = 'unknown'
__setup_datetime__ = datetime.datetime(2013, 8, 20, 12, 25, 53, 933220)
__setup_datetime__ = datetime.datetime(2013, 11, 25, 12, 17, 2, 831411)
# what version of stsci.distutils created this version.py
stsci_distutils_version = '0.3.5.dev'
stsci_distutils_version = '0.3.7.dev27596'
if '.dev' in __version__:
def update_svn_info():
......
......@@ -4,7 +4,7 @@ These are python stubs that are overloaded by a c version implementations.
If the c versions do not exist, then these routines will do nothing
$Id: wutil.py 2039 2013-08-05 21:23:13Z sontag $
$Id: wutil.py 2069 2013-10-09 15:33:36Z sontag $
"""
from __future__ import division # confidence high
......@@ -57,8 +57,8 @@ if WUTIL_ON_MAC and not _skipDisplay:
GRAPHICS_ALWAYS_ON_TOP = 'PYRAF_GRAPHICS_ALWAYS_ON_TOP' in os.environ
# attempt to override with xutil or aqua versions
_hasAqua = 0
_hasXWin = 0
_has_aqutil = 0
_has_xutil = 0
try:
if WUTIL_USING_X and not _skipDisplay:
# set an env var before importing xutil (see PyRAF FAQ on this)
......@@ -77,7 +77,7 @@ try:
# Successful intialization. Reset dummy methods with
# those from 'xutil' now.
from pyraf.xutil import *
_hasXWin = 1 # Flag to mark successful initialization of XWindow
_has_xutil = 1 # Flag to mark successful initialization of XWindow
closeGraphics = closeXGraphics
else:
......@@ -92,15 +92,16 @@ try:
# override the few Mac-specific functions needed
from aqutil import getFocalWindowID, setFocusTo, getParentID
from aqutil import moveCursorTo, getPointerPosition
_hasAqua = 1
_has_aqutil = 1
except:
_hasAqua = 0
_has_aqutil = 0
print "Could not import aqutil, please see the online PyRAF FAQ"
print "http://www.stsci.edu/institute/software_hardware/pyraf/pyraf_faq#5.13"
except ImportError:
_hasXWin = 0 # Unsuccessful init of XWindow
_has_xutil = 0 # Unsuccessful init of XWindow
except EnvironmentError:
_hasXWin = 0 # Unsuccessful init of XWindow
_has_xutil = 0 # Unsuccessful init of XWindow
# Clean up the namespace a bit...
try:
......@@ -151,7 +152,7 @@ def getTopID(WindowID):
# a "top ID" makes less sense if we are not using X
if not WUTIL_USING_X:
if _hasAqua:
if _has_aqutil:
return aqutil.getTopIdFor(wid)
else:
return wid # everything is its own top
......@@ -175,7 +176,7 @@ def forceFocusToNewWindow():
actually in the front, where focus would be. With X, any new window
comes to the front anyway, so this is a no-op. Currently this is
only necessary under Aqua. """
if _hasAqua:
if _has_aqutil:
aqutil.focusOnGui()
def isViewable(WindowID):
......@@ -256,7 +257,7 @@ class TerminalFocusEntity(FocusEntity):
self.windowID = getFocalWindowID()
if self.windowID == -1:
self.windowID = None
if _hasAqua:
if _has_aqutil:
scrnPosDict = aqutil.getPointerGlobalPosition()
self.lastScreenX = scrnPosDict['x']
self.lastScreenY = scrnPosDict['y']
......@@ -277,7 +278,7 @@ class TerminalFocusEntity(FocusEntity):
if self.windowID == getFocalWindowID():
# focus is already here
return
if _hasAqua:
if _has_aqutil:
if self.lastScreenX is not None and cursorToo:
moveCursorTo(self.windowID, self.lastScreenX, self.lastScreenY,
0, 0)
......@@ -290,7 +291,7 @@ class TerminalFocusEntity(FocusEntity):
def saveCursorPos(self):
if (not self.windowID) or (self.windowID != getFocalWindowID()):
return
if _hasAqua:
if _has_aqutil:
scrnPosDict = aqutil.getPointerGlobalPosition()
self.lastScreenX = scrnPosDict['x']
self.lastScreenY = scrnPosDict['y']
......@@ -513,7 +514,18 @@ def dumpspecs(outstream = None, skip_volatiles = False):
out += "\nPyRAF ver = "+pyrver
out += "\nPY3K = "+str(capable.PY3K)
out += "\nc.OF_GRAPHICS = "+str(capable.OF_GRAPHICS)
if capable.OF_GRAPHICS:
if hasattr(capable, 'get_dc_owner'): # rm hasattr at/after v2.2
if skip_volatiles:
out +="\n/dev/console owner = <skipped>"
else:
out +="\n/dev/console owner = "+str(capable.get_dc_owner(False, True))
if not capable.OF_GRAPHICS:
if hasattr(capable, 'TKINTER_IMPORT_FAILED'):
out += "\nTkinter import failed."
else:
out += "\nTkinter use unattempted."
else:
out += "\nTclVersion = "+str(capable.Tkinter.TclVersion)
out += "\nTkVersion = "+str(capable.Tkinter.TkVersion)
out += "\nWUTIL_ON_MAC = "+str(WUTIL_ON_MAC)
......@@ -524,10 +536,10 @@ def dumpspecs(outstream = None, skip_volatiles = False):
out += "\nwhich_darwin_linkage = "+str(capable.which_darwin_linkage())
else:
out += "\nwhich_darwin_linkage = (not darwin)"
out += "\nskipDisplay = "+str(_skipDisplay)
out += "\nhasGraphics = "+str(hasGraphics)
out += "\nhasAqua = "+str(_hasAqua)
out += "\nhasXWin = "+str(_hasXWin)
out += "\nskip display = "+str(_skipDisplay)
out += "\nhas graphics = "+str(hasGraphics)
out += "\nimported aqutil = "+str(bool(_has_aqutil))
out += "\nimported xutil = "+str(bool(_has_xutil))
if 'PYRAFGRAPHICS' in os.environ:
val = os.environ['PYRAFGRAPHICS']
......@@ -578,7 +590,7 @@ if _skipDisplay:
if hasattr(capable, 'TKINTER_IMPORT_FAILED'):
print "Tkinter import failed."
else:
if _hasXWin or _hasAqua:
if _has_xutil or _has_aqutil:
hasGraphics = focusController.hasGraphics
elif WUTIL_ON_MAC:
# Handle case where we are on the Mac with no X and no PyObjc. We can
......
......@@ -25,17 +25,6 @@ def setup_hook(config):
config['files']['scripts'] += '\n' + '\n'.join(additional_scripts)
# This installs the shortcut-like launcher exe onto the desktop
if 'USERPROFILE' in os.environ:
dtop = os.environ['USERPROFILE']+os.sep+'Desktop'
if os.path.exists(dtop):
shutil.copy('data'+os.sep+'PyRAF.exe', dtop+os.sep+'PyRAF.exe')
print('Installing PyRAF.exe to -> '+dtop)
else:
print('Error: Desktop not found at: '+dtop)
else:
print('Error: Desktop location unknown')
def build_ext_hook(command):
"""Adds the correct library directories for X11. I've found that on Linux
......
No preview for this file type
embray = Erik M. Bray <embray@stsci.edu>
sienkiew = Mark Sienkiewicz <sienkiew@stsci.edu>
sontag = Chris Sontag <sontag@stsci.edu>
iraf = iraf <iraf@stsci.edu>
......@@ -2,12 +2,24 @@ Changes
=========
0.2.11 (unreleased)
0.2.12 (unreleased)
-------------------
- Nothing changed yet.
0.2.11 (2013-08-29)
-------------------
- Replaced ``distribute_setup.py`` with ``ez_setup.py`` in order to bootstrap
with modern setuptools when necessary.
- Fixed a couple minor Python 3-specific issues. In particular the
``data_files`` option could be passed to ``setup()`` as a ``dict_items``
object instead of a ``list`` which is what would normally be expected.
- Added a tox.ini (frankly I thought there already was one).
0.2.10 (2013-04-10)
-------------------
......
......@@ -311,7 +311,7 @@ def setup_cfg_to_setup_kwargs(config):
if arg == 'data_files':
# the data_files value is a pointlessly different structure
# from the package_data value
data_files = data_files.items()
data_files = list(data_files.items())
in_cfg_value = data_files
elif arg == 'cmdclass':
cmdclass = {}
......
......@@ -18,6 +18,7 @@ is added then support for it should be included here as well.
import logging
import os
from .extern.six import print_
from .extern.six import moves as m
ConfigParser = m.configparser.ConfigParser
......@@ -88,19 +89,20 @@ def releaser_middle(data):
msg = "Tagging %s" % (version,)
cmd = 'git tag -s %s -m "%s"' % (version, msg)
if os.path.isdir('.git/svn'):
print "\nEXPERIMENTAL support for git-svn tagging!\n"
print_("\nEXPERIMENTAL support for git-svn tagging!\n")
cur_branch = open('.git/HEAD').read().strip().split('/')[-1]
print "You are on branch %s." % (cur_branch,)
print_("You are on branch %s." % (cur_branch,))
if cur_branch != 'master':
print "Only the master branch is supported for git-svn tagging."
print "Please tag yourself."
print "'git tag' needs to list tag named %s." % (version,)
print_("Only the master branch is supported for git-svn "
"tagging.")
print_("Please tag yourself.")
print_("'git tag' needs to list tag named %s." % (version,))
sys.exit()
cmd = [cmd]
local_head = open('.git/refs/heads/master').read()
trunk = open('.git/refs/remotes/trunk').read()
if local_head != trunk:
print "Your local master diverges from trunk.\n"
print_("Your local master diverges from trunk.\n")
# dcommit before local tagging
cmd.insert(0, 'git svn dcommit')
# create tag in svn
......@@ -119,18 +121,18 @@ def releaser_middle(data):
if not isinstance(cmds, list):
cmds = [cmds]
if len(cmds) == 1:
print "Tag needed to proceed, you can use the following command:"
print_("Tag needed to proceed, you can use the following command:")
for cmd in cmds:
print cmd
print_(cmd)
if utils.ask("Run this command"):
print system(cmd)
print_(system(cmd))
else:
# all commands are needed in order to proceed normally
print "Please create a tag for %s yourself and rerun." % \
(self.data['version'],)
print_("Please create a tag for %s yourself and rerun." % \
(self.data['version'],))
sys.exit()
if not self.vcs.tag_exists('v' + self.data['version']):
print "\nFailed to create tag %s!" % (self.data['version'],)
print_("\nFailed to create tag %s!" % (self.data['version'],))
sys.exit()
# Normally all this does is to return '--formats=zip', which is currently
......
[metadata]
name = d2to1
version = 0.2.11.dev
version = 0.2.12.dev
author = Erik M. Bray
author-email = embray@stsci.edu
summary = Allows using distutils2-like setup.cfg files for a package's metadata with a distribute/setuptools setup.py
......
[tox]
envlist = py25,py26,py27,py32,py33
[testenv]
deps =
nose
numpy
setuptools-subversion
commands =
python setup.py test
sitepackages = True
Changelog
===========
0.3.5 (unreleased)
0.3.7 (unreleased)
------------------
- Nothing changed yet.
0.3.6 (2013-11-21)
------------------
- Fixed a syntax error in Python 3 that was introduced in 0.3.5. This
could occur very early in the setup such that it bailed before even 2to3
could run on the rest of the package.
0.3.5 (2013-11-18)
------------------
- Fixed an obscure issue that could occur when trying to install with
easy_install on Python 2 systems that have lib2to3 installed but have never
used it.
0.3.4 (2013-07-31)
------------------
......
[metadata]
name = stsci.distutils
version = 0.3.5.dev
version = 0.3.7.dev
author = Erik M. Bray
author-email = embray@stsci.edu
home-page = http://www.stsci.edu/resources/software_hardware/stsci_python
......
......@@ -7,7 +7,9 @@ and a different version for 2.5.
import os
import sys
from distutils import log
try:
import ast # Python >= 2.6
......@@ -22,10 +24,14 @@ try:
try:
tree = ast.parse(open(filename, 'r').read())
except SyntaxError:
if sys.version_info[0] < 3:
e = sys.exc_info()[1]
log.warn('SyntaxError while parsing file %s: %s' %
(filename, str(e)))
return
# We're probably in Python 3 and looking at a file intended for
# Python 2. Otherwise there's an unintended SyntaxError in the
# file, so there are bigger problems anyways
# TODO: Maybe issue a warning?
try:
import lib2to3.refactor
......@@ -74,27 +80,27 @@ except ImportError:
for name in node.names:
self.importfroms.add((node.modname, name[0], name[1]))
try:
import lib2to3.refactor
class StringRefactoringTool(lib2to3.refactor.RefactoringTool):
"""A RefactoringTool that saves refactored files as strings in the
self.refactored dict rather than outputting to actual files.
This is used in case we're running in Python 3 and need to refactor a
file before parsing its syntax tree.
"""
def __init__(self, fixer_names, options=None, explicit=None):
super(StringRefactoringTool, self).__init__(fixer_names, options,
explicit)
self.refactored = {}
if sys.version_info[0] >= 3:
try:
import lib2to3.refactor
def write_file(self, new_text, filename, old_text, encoding=None):
self.refactored[filename] = new_text
class StringRefactoringTool(lib2to3.refactor.RefactoringTool):
"""A RefactoringTool that saves refactored files as strings in the
self.refactored dict rather than outputting to actual files.
except ImportError:
pass
This is used in case we're running in Python 3 and need to refactor
a file before parsing its syntax tree.
"""
def __init__(self, fixer_names, options=None, explicit=None):
super(StringRefactoringTool, self).__init__(fixer_names,
options,
explicit)
self.refactored = {}
def write_file(self, new_text, filename, old_text, encoding=None):
self.refactored[filename] = new_text
except ImportError:
pass
......@@ -412,7 +412,8 @@ def numpy_extension_hook(command_obj):
'Please install Numpy on your system first.\n\n')
sys.exit(1)
includes = [numpy.get_numarray_include(), numpy.get_include()]
includes = [numpy.get_include()]
#includes = [numpy.get_numarray_include(), numpy.get_include()]
for extension in command_obj.extensions:
if 'numpy' not in extension.include_dirs:
continue
......
......@@ -143,7 +143,8 @@ class TestHooks(StsciDistutilsTestCase):
# compile a c file to an object, so that should include all the
# include paths. This is of course not universally true, but it
# should hold true for this test case
for path in [numpy.get_include(), numpy.get_numarray_include()]:
for path in [numpy.get_include()]:
#for path in [numpy.get_include(), numpy.get_numarray_include()]:
assert '-I' + path in args
break
......@@ -162,7 +163,8 @@ class TestHooks(StsciDistutilsTestCase):
continue
if args[0] != compiler_cmd:
continue
for path in [numpy.get_include(), numpy.get_numarray_include()]:
for path in [numpy.get_include()]:
#for path in [numpy.get_include(), numpy.get_numarray_include()]:
assert '-I' + path not in args
def test_glob_data_files(self):
......
......@@ -3,7 +3,7 @@ This is meant to be fast and light, having no complicated dependencies, so
that any module can fearlessly import this without adverse affects or
performance concerns.
$Id: capable.py 25052 2013-05-29 21:41:03Z sontag $
$Id: capable.py 26617 2013-09-10 03:54:22Z sontag $
"""
from __future__ import division # confidence high
......@@ -55,6 +55,26 @@ def which_darwin_linkage(force_otool_check=False):
return "aqua"
def get_dc_owner(raises, mask_if_self):
""" Convenience function to return owner of /dev/console.
If raises is True, this raises an exception on any error.
If not, it returns any error string as the owner name.
If owner is self, and if mask_if_self, returns "<self>"."""
try:
from pwd import getpwuid
owner_uid = os.stat('/dev/console').st_uid
self_uid = os.getuid()
if mask_if_self and owner_uid == self_uid:
return "<self>"
owner_name = getpwuid(owner_uid).pw_name
return owner_name
except Exception, e:
if raises:
raise e
else:
return str(e)
OF_GRAPHICS = True
if 'PYRAF_NO_DISPLAY' in os.environ or 'PYTOOLS_NO_DISPLAY' in os.environ:
......@@ -73,11 +93,16 @@ if OF_GRAPHICS and sys.platform == 'darwin':
# any windows/graphics calls. See "console user" here:
# http://developer.apple.com/library/mac/#technotes/tn2083/_index.html
# If we are the console user, we own /dev/console and can read from it.
# When no one is logged in, /dev/console is owned by "root". When user "bob"
# is logged in locally/physically, /dev/console is owned by "bob".
# However, if "bob" restarts the X server while logged in, /dev/console
# may be owned by "sysadmin" - so we check for that.
#
if 'PYRAF_YES_DISPLAY' not in os.environ:
OF_GRAPHICS = os.access("/dev/console", os.R_OK)