1"""
2Find out if Numeric of numarray is going to be used as its array package
3
4WARNING: PyGSL has used Numeric as its core. This is to test to see
5if we can support both, but sooner or later the favour has to be given
6to one of these packages.
7
8When imported this module:
9     1.) Looks on the command line if it can find a flag of type
10         --array-object=[Numeric|nummarray|numpy]
11
12     2.) Tries to import these modules.
13
14     3.) Tries to use the preferred one.
15
16     4.) Or goes with the other one found
17
18
19"""
20import re
21import string
22import sys
23import os
24from distutils.errors import DistutilsModuleError
25
26
27packagedir = os.path.dirname(os.path.abspath(__file__))
28includedir = os.path.join(packagedir, "Include", "pygsl")
29pygsldir   = os.path.join(packagedir, "pygsl")
30gsl_dist   = os.path.join(packagedir, "gsl_dist")
31
32def extractpattern():
33	"""
34	Try to find if the array object was specified at the command line
35	"""
36	array_pattern = re.compile("--array-object=(.+)")
37	pos=0
38	array_preference = None
39
40	result = ""
41	while pos<len(sys.argv):
42		match=array_pattern.match(sys.argv[pos])
43		if match:
44		    result=match.group(1)
45		    result.strip()
46		    sys.argv[pos:pos+1]=[]
47		    break
48		pos+=1
49	return result
50
51def switchpreference(array_preference):
52	"""
53	Find out if the set preference can be used ...
54	"""
55	have_numeric = 0
56	have_numarray = 0
57	have_numpy = 0
58	use_numeric = 0
59	use_numarray = 0
60	use_numpy = 0
61	try:
62		import numpy
63		have_numpy = 1
64	except ImportError:
65		pass
66
67	try:
68		import Numeric
69		have_numeric = 1
70	except ImportError:
71		pass
72
73	try:
74		import numarray
75		have_numarray = 1
76	except ImportError:
77		pass
78
79	#array_preference = 'numarray'
80	if array_preference != None:
81	    if array_preference == 'numpy':
82                if have_numpy == 1:
83                        use_numpy = 1
84                else:
85                        sys.stdout.write( "Did not find the numpy module you asked for")
86
87	    if array_preference == 'Numeric':
88                    sys.stdout.write("Numeric supported any longer. If you still need it write to pygsl-discuss@lists.sourceforge.net")
89#		if have_numeric == 1:
90#		    use_numeric = 1
91#		else:
92#                         sys.stdout.write("Did not find the Numeric module you asked for")
93	    elif array_preference == 'numarray':
94                        sys.stdout.write("numarray supported any longer. If you still need it write to pygsl-discuss@lists.sourceforge.net")
95#		    if have_numarray == 1:
96#			use_numarray = 1
97#		    else:
98#			sys.stdout.write( "Did not find the numarray module you asked for")
99
100	if use_numeric == 0 and use_numarray == 0 and use_numpy == 0:
101	    if have_numpy == 1:
102                    use_numpy = 1
103	    elif have_numarray == 1:
104                    use_numarray = 1
105	    elif have_numeric == 1:
106                    use_numeric = 1
107	    else:
108                    raise  DistutilsModuleError("I need either numpy, nummarray, or Numeric!")
109
110	if use_numpy == 1:
111		use_numeric = 0
112		use_numarray = 0
113		nummodule = "numpy"
114
115	elif use_numeric == 1:
116		#print "Using Numeric as array Package"
117		use_numpy = 0
118		use_numarray = 0
119		nummodule = "Numeric"
120
121	elif use_numarray == 1:
122		#print "Using nummarray as array Package"
123		use_numeric = 0
124		use_numpy = 0
125		nummodule = "numarray"
126	else:
127		raise  DistutilsModuleError( "I need either numpy, nummarray or Numeric!")
128	return nummodule
129
130def writenumobj(nummodule):
131	# Write the chosen module to a file so it is automatically inculded when pygsl starts up
132	file = open(os.path.join(pygsldir, "_numobj.py"), "w")
133	warnmsg = """
134	       WARNING: File Generated during build. DO NOT MODIFY!!!
135	"""
136	file.write('"""\n')
137	file.write(warnmsg)
138	file.write('"""\n')
139	file.write('\n')
140	file.write('from %s import *\n\n' % nummodule)
141	file.write('nummodule = "%s"\n' % nummodule)
142	file.close()
143	del file
144
145	file = open(os.path.join(gsl_dist, "array_includes.py"), "w")
146	file.write('"""\n')
147	file.write(warnmsg)
148	file.write('"""\n')
149	file.write('\n')
150	file.write('array_include_dirs = []\n')
151	if nummodule == "numpy":
152		file.write('from numpy.distutils.misc_util import get_numpy_include_dirs\n')
153		file.write('array_include_dirs = get_numpy_include_dirs()\n')
154	file.close()
155	del file
156
157	# Write the chosen module to a include header
158	file = open(os.path.join(includedir, "arrayobject.h"), "w")
159	file.write('/*')
160	file.write(warnmsg)
161	file.write('*/\n')
162	#file.write('#include <%s/arrayobject.h>\n' % nummodule)
163	file.write('#define PyGSL_%s 1\n' % (nummodule).upper())
164	file.close()
165	del file
166
167	# Write the chosen module to a include header
168	file = open(os.path.join(pygsldir, "_mlab.py"), "w")
169	file.write('"""\n')
170	file.write(warnmsg)
171	file.write('"""\n')
172	if  nummodule == "numpy":
173		file.write('from numpy.oldnumeric.mlab import *\n')
174	elif nummodule == "Numeric":
175		file.write('from MLab import *\n')
176	elif nummodule == "numarray":
177		file.write('from numarray.linear_algebra.mlab import *\n')
178	else:
179		raise ValueError("Unknown array object %s" % nummodule)
180	file.close()
181	del file
182
183
184def read_numobj():
185	"""
186	read the nummodule from the file
187	"""
188	path = os.path.join(pygsldir, "_numobj.py")
189	g = {}
190	l = {}
191	module = None
192	try:
193		pathtext =open(path).read()
194		exec(pathtext, g, l)
195		module = l["nummodule"]
196		return module
197	except IOError:
198		sys.stdout.write("No array object was selected.\n")
199		return None
200	except ImportError:
201		pass
202
203	# Try to find the name of the set module
204	line = open(path).readlines()[-1]
205	lastobject =  string.strip(string.split(line, "=")[1])
206	sys.stdout.write("Array object %s found in pygsl._numobj can not be imported!\n" % (lastobject,))
207	return None
208
209def build_guess(selectedmodule):
210	"""
211	Find out which array module to use ...
212	"""
213	# See if --array-object was given on the command line
214
215	lastmodule = read_numobj()
216	# If not return the last selection if possible ....
217	if selectedmodule == "" and lastmodule != None:
218		return lastmodule
219
220	sys.stdout.write("Looking for a suitable array module")
221	# If given, find out if it can be used ...
222	nummodule = switchpreference(selectedmodule)
223
224	# find out if it is a change ...
225	if lastmodule == None or lastmodule != nummodule:
226		if lastmodule != nummodule:
227			sys.stdout.write( "SELECTED a NEW array module ->%s\n" % (nummodule,))
228			sys.stdout.write( "Please make sure that all modules are built with the same setting.\n")
229			sys.stdout.write( "e.g. remove the build directory and start the build process again!\n")
230		else:
231			sys.stdout.write("SELECTED as array module ->%s\n" %( nummodule,))
232		writenumobj(nummodule)
233	return nummodule
234
235def read_from_numobj(default):
236	"""
237	tries to read from the file. If this fails it searches if one of the
238	array objects can be found
239	"""
240	tmp = read_numobj()
241	if tmp != None:
242		return tmp
243	return build_guess(default)
244
245
246class _nummodule:
247	"""
248	Delay finding the array object until really needed
249	"""
250	def __init__(self):
251		self.__arrayobject = None
252		self.__preference = extractpattern()
253		pass
254
255	def __findarrayobject(self):
256		if "build" in sys.argv:
257			nummodule = build_guess(self.__preference)
258		else:
259			nummodule = read_from_numobj(self.__preference)
260		self.__arrayobject = nummodule
261
262	def __str__(self):
263		if self.__arrayobject == None:
264			self.__findarrayobject()
265		#print "Using '%s' as array object" %  self.__arrayobject
266		return self.__arrayobject
267
268
269nummodule = _nummodule()
270sys.stdout.write("%s\n" %(nummodule,))
271