for line in f.readlines():
		line = line.strip()
		if line[0:1]=='#': continue
		if line.find(':') < 0: continue
		key,value = line.split(':')
		manifest[key.strip()]=value.strip()

# Appcelerator Titanium Module Packager
import os, subprocess, sys, glob, string, optparse, subprocess
import zipfile
from datetime import date

cwd = os.path.abspath(os.path.dirname(sys._getframe(0).f_code.co_filename))
os.chdir(cwd)
required_module_keys = ['name','version','moduleid','description','copyright','license','copyright','platform','minsdk']
module_defaults = {
	'description':'My module',
	'author': 'Your Name',
	'license' : 'Specify your license',
	'copyright' : 'Copyright (c) %s by Your Company' % str(date.today().year),
}
module_license_default = "TODO: place your license here and we'll include it in the module distribution"

def find_sdk(config):
	sdk = config['TITANIUM_SDK']
	return os.path.expandvars(os.path.expanduser(sdk))

def replace_vars(config,token):
	idx = token.find('$(')
	while idx != -1:
		idx2 = token.find(')',idx+2)
		if idx2 == -1: break
		key = token[idx+2:idx2]
		if not config.has_key(key): break
		token = token.replace('$(%s)' % key, config[key])
		idx = token.find('$(')
	return token

def read_ti_xcconfig():
	contents = open(os.path.join(cwd,'titanium.xcconfig')).read()
	config = {}
	for line in contents.splitlines(False):
		line = line.strip()
		if line[0:2]=='//': continue
		idx = line.find('=')
		if idx > 0:
			key = line[0:idx].strip()
			value = line[idx+1:].strip()
			config[key] = replace_vars(config,value)
	return config

def generate_doc(config):
	docdir = os.path.join(cwd,'documentation')
	if not os.path.exists(docdir):
		warn("Couldn't find documentation file at: %s" % docdir)
		return None

	try:
		import markdown2 as markdown
	except ImportError:
		import markdown
	documentation = []
	for file in os.listdir(docdir):
		if file in ignoreFiles or os.path.isdir(os.path.join(docdir, file)):
			continue
		md = open(os.path.join(docdir,file)).read()
		html = markdown.markdown(md)
		documentation.append({file:html});
	return documentation

def compile_js(manifest,config):
	js_file = os.path.join(cwd,'assets','__MODULE_ID__.js')
	if not os.path.exists(js_file): return

	from compiler import Compiler
	try:
		import json
	except:
		import simplejson as json

	compiler = Compiler(cwd, manifest['moduleid'], manifest['name'], 'commonjs')
	root_asset, module_assets = compiler.compile_module()

	root_asset_content = """
%s

	return filterDataInRange([NSData dataWithBytesNoCopy:data length:sizeof(data) freeWhenDone:NO], ranges[0]);
""" % root_asset

	module_asset_content = """
%s

	NSNumber *index = [map objectForKey:path];
	if (index == nil) {
		return nil;
	}
	return filterDataInRange([NSData dataWithBytesNoCopy:data length:sizeof(data) freeWhenDone:NO], ranges[index.integerValue]);
""" % module_assets

	from tools import splice_code

	assets_router = os.path.join(cwd,'Classes','___PROJECTNAMEASIDENTIFIER___ModuleAssets.m')
	splice_code(assets_router, 'asset', root_asset_content)
	splice_code(assets_router, 'resolve_asset', module_asset_content)

	# Generate the exports after crawling all of the available JS source
	exports = open('metadata.json','w')
	json.dump({'exports':compiler.exports }, exports)
	exports.close()

def die(msg):
	print msg
	sys.exit(1)

def info(msg):
	print "[INFO] %s" % msg

def warn(msg):
	print "[WARN] %s" % msg

def validate_license():
	c = open(os.path.join(cwd,'LICENSE')).read()
	if c.find(module_license_default)!=-1:
		warn('please update the LICENSE file with your license text before distributing')

def validate_manifest():
	path = os.path.join(cwd,'manifest')
	f = open(path)
	if not os.path.exists(path): die("missing %s" % path)
	manifest = {}

	for key in required_module_keys:
		if not manifest.has_key(key): die("missing required manifest key '%s'" % key)
		if module_defaults.has_key(key):
			defvalue = module_defaults[key]
			curvalue = manifest[key]
			if curvalue==defvalue: warn("please update the manifest key: '%s' to a non-default value" % key)
	return manifest,path

ignoreFiles = ['.DS_Store','.gitignore','libTitanium.a','titanium.jar','README']
ignoreDirs = ['.DS_Store','.svn','.git','CVSROOT']

def zip_dir(zf,dir,basepath,ignoreExt=[]):
	if not os.path.exists(dir): return
	for root, dirs, files in os.walk(dir):
		for name in ignoreDirs:
			if name in dirs:
				dirs.remove(name)	# don't visit ignored directories
		for file in files:
			if file in ignoreFiles: continue
			e = os.path.splitext(file)
			if len(e) == 2 and e[1] in ignoreExt: continue
			from_ = os.path.join(root, file)
			to_ = from_.replace(dir, '%s/%s'%(basepath,dir), 1)
			zf.write(from_, to_)

def glob_libfiles():
	files = []
	for libfile in glob.glob('build/**/*.a'):
		if libfile.find('Release-')!=-1:
			files.append(libfile)
	return files

def build_module(manifest,config):
	from tools import ensure_dev_path
	ensure_dev_path()

	rc = os.system("xcodebuild -sdk iphoneos -configuration Release")
	if rc != 0:
		die("xcodebuild failed")
	rc = os.system("xcodebuild -sdk iphonesimulator -configuration Release")
	if rc != 0:
		die("xcodebuild failed")
    # build the merged library using lipo
	moduleid = manifest['moduleid']
	libpaths = ''
	for libfile in glob_libfiles():
		libpaths+='%s ' % libfile

	os.system("lipo %s -create -output build/lib%s.a" %(libpaths,moduleid))

def generate_apidoc(apidoc_build_path):
	global options

	if options.skip_docs:
		info("Skipping documentation generation.")
		return False
	else:
		info("Module apidoc generation can be skipped using --skip-docs")
	apidoc_path = os.path.join(cwd, "apidoc")
	if not os.path.exists(apidoc_path):
		warn("Skipping apidoc generation. No apidoc folder found at: %s" % apidoc_path)
		return False

	if not os.path.exists(apidoc_build_path):
	    os.makedirs(apidoc_build_path)
	ti_root = string.strip(subprocess.check_output(["echo $TI_ROOT"], shell=True))
	if not len(ti_root) > 0:
		warn("Not generating documentation from the apidoc folder. The titanium_mobile repo could not be found.")
		warn("Set the TI_ROOT environment variable to the parent folder where the titanium_mobile repo resides (eg.'export TI_ROOT=/Path').")
		return False
	docgen = os.path.join(ti_root, "titanium_mobile", "apidoc", "docgen.py")
	if not os.path.exists(docgen):
		warn("Not generating documentation from the apidoc folder. Couldn't find docgen.py at: %s" % docgen)
		return False

	info("Generating documentation from the apidoc folder.")
	rc = os.system("\"%s\" --format=jsca,modulehtml --css=styles.css -o \"%s\" -e \"%s\"" % (docgen, apidoc_build_path, apidoc_path))
	if rc != 0:
		die("docgen failed")
	return True

def package_module(manifest,mf,config):
	name = manifest['name'].lower()
	moduleid = manifest['moduleid'].lower()
	version = manifest['version']
	modulezip = '%s-iphone-%s.zip' % (moduleid,version)
	if os.path.exists(modulezip): os.remove(modulezip)
	zf = zipfile.ZipFile(modulezip, 'w', zipfile.ZIP_DEFLATED)
	modulepath = 'modules/iphone/%s/%s' % (moduleid,version)
	zf.write(mf,'%s/manifest' % modulepath)
	libname = 'lib%s.a' % moduleid
	zf.write('build/%s' % libname, '%s/%s' % (modulepath,libname))
	docs = generate_doc(config)
	if docs!=None:
		for doc in docs:
			for file, html in doc.iteritems():
				filename = string.replace(file,'.md','.html')
				zf.writestr('%s/documentation/%s'%(modulepath,filename),html)

	apidoc_build_path = os.path.join(cwd, "build", "apidoc")
	if generate_apidoc(apidoc_build_path):
		for file in os.listdir(apidoc_build_path):
			if file in ignoreFiles or os.path.isdir(os.path.join(apidoc_build_path, file)):
				continue
			zf.write(os.path.join(apidoc_build_path, file), '%s/documentation/apidoc/%s' % (modulepath, file))

	zip_dir(zf,'assets',modulepath,['.pyc','.js'])
	zip_dir(zf,'example',modulepath,['.pyc'])
	zip_dir(zf,'platform',modulepath,['.pyc','.js'])
	zf.write('LICENSE','%s/LICENSE' % modulepath)
	zf.write('module.xcconfig','%s/module.xcconfig' % modulepath)
	exports_file = 'metadata.json'
	if os.path.exists(exports_file):
		zf.write(exports_file, '%s/%s' % (modulepath, exports_file))
	zf.close()

if __name__ == '__main__':
	global options

	parser = optparse.OptionParser()
	parser.add_option("-s", "--skip-docs",
			dest="skip_docs",
			action="store_true",
			help="Will skip building documentation in apidoc folder",
			default=False)
	(options, args) = parser.parse_args()

	manifest,mf = validate_manifest()
	validate_license()
	config = read_ti_xcconfig()

	sdk = find_sdk(config)
	sys.path.insert(0,os.path.join(sdk,'iphone'))
	sys.path.append(os.path.join(sdk, "common"))

	compile_js(manifest,config)
	build_module(manifest,config)
	package_module(manifest,mf,config)
	sys.exit(0)


while idx != -1:
		idx2 = token.find(')',idx+2)
		if idx2 == -1: break
		key = token[idx+2:idx2]
		if not config.has_key(key): break
		token = token.replace('$(%s)' % key, config[key])
		idx = token.find('$(')

# Appcelerator Titanium Module Packager
import os, subprocess, sys, glob, string, optparse, subprocess
import zipfile
from datetime import date

cwd = os.path.abspath(os.path.dirname(sys._getframe(0).f_code.co_filename))
os.chdir(cwd)
required_module_keys = ['name','version','moduleid','description','copyright','license','copyright','platform','minsdk']
module_defaults = {
	'description':'My module',
	'author': 'Your Name',
	'license' : 'Specify your license',
	'copyright' : 'Copyright (c) %s by Your Company' % str(date.today().year),
}
module_license_default = "TODO: place your license here and we'll include it in the module distribution"

def find_sdk(config):
	sdk = config['TITANIUM_SDK']
	return os.path.expandvars(os.path.expanduser(sdk))

def replace_vars(config,token):
	idx = token.find('$(')

	return token

def read_ti_xcconfig():
	contents = open(os.path.join(cwd,'titanium.xcconfig')).read()
	config = {}
	for line in contents.splitlines(False):
		line = line.strip()
		if line[0:2]=='//': continue
		idx = line.find('=')
		if idx > 0:
			key = line[0:idx].strip()
			value = line[idx+1:].strip()
			config[key] = replace_vars(config,value)
	return config

def generate_doc(config):
	docdir = os.path.join(cwd,'documentation')
	if not os.path.exists(docdir):
		warn("Couldn't find documentation file at: %s" % docdir)
		return None

	try:
		import markdown2 as markdown
	except ImportError:
		import markdown
	documentation = []
	for file in os.listdir(docdir):
		if file in ignoreFiles or os.path.isdir(os.path.join(docdir, file)):
			continue
		md = open(os.path.join(docdir,file)).read()
		html = markdown.markdown(md)
		documentation.append({file:html});
	return documentation

def compile_js(manifest,config):
	js_file = os.path.join(cwd,'assets','__MODULE_ID__.js')
	if not os.path.exists(js_file): return

	from compiler import Compiler
	try:
		import json
	except:
		import simplejson as json

	compiler = Compiler(cwd, manifest['moduleid'], manifest['name'], 'commonjs')
	root_asset, module_assets = compiler.compile_module()

	root_asset_content = """
%s

	return filterDataInRange([NSData dataWithBytesNoCopy:data length:sizeof(data) freeWhenDone:NO], ranges[0]);
""" % root_asset

	module_asset_content = """
%s

	NSNumber *index = [map objectForKey:path];
	if (index == nil) {
		return nil;
	}
	return filterDataInRange([NSData dataWithBytesNoCopy:data length:sizeof(data) freeWhenDone:NO], ranges[index.integerValue]);
""" % module_assets

	from tools import splice_code

	assets_router = os.path.join(cwd,'Classes','___PROJECTNAMEASIDENTIFIER___ModuleAssets.m')
	splice_code(assets_router, 'asset', root_asset_content)
	splice_code(assets_router, 'resolve_asset', module_asset_content)

	# Generate the exports after crawling all of the available JS source
	exports = open('metadata.json','w')
	json.dump({'exports':compiler.exports }, exports)
	exports.close()

def die(msg):
	print msg
	sys.exit(1)

def info(msg):
	print "[INFO] %s" % msg

def warn(msg):
	print "[WARN] %s" % msg

def validate_license():
	c = open(os.path.join(cwd,'LICENSE')).read()
	if c.find(module_license_default)!=-1:
		warn('please update the LICENSE file with your license text before distributing')

def validate_manifest():
	path = os.path.join(cwd,'manifest')
	f = open(path)
	if not os.path.exists(path): die("missing %s" % path)
	manifest = {}
	for line in f.readlines():
		line = line.strip()
		if line[0:1]=='#': continue
		if line.find(':') < 0: continue
		key,value = line.split(':')
		manifest[key.strip()]=value.strip()
	for key in required_module_keys:
		if not manifest.has_key(key): die("missing required manifest key '%s'" % key)
		if module_defaults.has_key(key):
			defvalue = module_defaults[key]
			curvalue = manifest[key]
			if curvalue==defvalue: warn("please update the manifest key: '%s' to a non-default value" % key)
	return manifest,path

ignoreFiles = ['.DS_Store','.gitignore','libTitanium.a','titanium.jar','README']
ignoreDirs = ['.DS_Store','.svn','.git','CVSROOT']

def zip_dir(zf,dir,basepath,ignoreExt=[]):
	if not os.path.exists(dir): return
	for root, dirs, files in os.walk(dir):
		for name in ignoreDirs:
			if name in dirs:
				dirs.remove(name)	# don't visit ignored directories
		for file in files:
			if file in ignoreFiles: continue
			e = os.path.splitext(file)
			if len(e) == 2 and e[1] in ignoreExt: continue
			from_ = os.path.join(root, file)
			to_ = from_.replace(dir, '%s/%s'%(basepath,dir), 1)
			zf.write(from_, to_)

def glob_libfiles():
	files = []
	for libfile in glob.glob('build/**/*.a'):
		if libfile.find('Release-')!=-1:
			files.append(libfile)
	return files

def build_module(manifest,config):
	from tools import ensure_dev_path
	ensure_dev_path()

	rc = os.system("xcodebuild -sdk iphoneos -configuration Release")
	if rc != 0:
		die("xcodebuild failed")
	rc = os.system("xcodebuild -sdk iphonesimulator -configuration Release")
	if rc != 0:
		die("xcodebuild failed")
    # build the merged library using lipo
	moduleid = manifest['moduleid']
	libpaths = ''
	for libfile in glob_libfiles():
		libpaths+='%s ' % libfile

	os.system("lipo %s -create -output build/lib%s.a" %(libpaths,moduleid))

def generate_apidoc(apidoc_build_path):
	global options

	if options.skip_docs:
		info("Skipping documentation generation.")
		return False
	else:
		info("Module apidoc generation can be skipped using --skip-docs")
	apidoc_path = os.path.join(cwd, "apidoc")
	if not os.path.exists(apidoc_path):
		warn("Skipping apidoc generation. No apidoc folder found at: %s" % apidoc_path)
		return False

	if not os.path.exists(apidoc_build_path):
	    os.makedirs(apidoc_build_path)
	ti_root = string.strip(subprocess.check_output(["echo $TI_ROOT"], shell=True))
	if not len(ti_root) > 0:
		warn("Not generating documentation from the apidoc folder. The titanium_mobile repo could not be found.")
		warn("Set the TI_ROOT environment variable to the parent folder where the titanium_mobile repo resides (eg.'export TI_ROOT=/Path').")
		return False
	docgen = os.path.join(ti_root, "titanium_mobile", "apidoc", "docgen.py")
	if not os.path.exists(docgen):
		warn("Not generating documentation from the apidoc folder. Couldn't find docgen.py at: %s" % docgen)
		return False

	info("Generating documentation from the apidoc folder.")
	rc = os.system("\"%s\" --format=jsca,modulehtml --css=styles.css -o \"%s\" -e \"%s\"" % (docgen, apidoc_build_path, apidoc_path))
	if rc != 0:
		die("docgen failed")
	return True

def package_module(manifest,mf,config):
	name = manifest['name'].lower()
	moduleid = manifest['moduleid'].lower()
	version = manifest['version']
	modulezip = '%s-iphone-%s.zip' % (moduleid,version)
	if os.path.exists(modulezip): os.remove(modulezip)
	zf = zipfile.ZipFile(modulezip, 'w', zipfile.ZIP_DEFLATED)
	modulepath = 'modules/iphone/%s/%s' % (moduleid,version)
	zf.write(mf,'%s/manifest' % modulepath)
	libname = 'lib%s.a' % moduleid
	zf.write('build/%s' % libname, '%s/%s' % (modulepath,libname))
	docs = generate_doc(config)
	if docs!=None:
		for doc in docs:
			for file, html in doc.iteritems():
				filename = string.replace(file,'.md','.html')
				zf.writestr('%s/documentation/%s'%(modulepath,filename),html)

	apidoc_build_path = os.path.join(cwd, "build", "apidoc")
	if generate_apidoc(apidoc_build_path):
		for file in os.listdir(apidoc_build_path):
			if file in ignoreFiles or os.path.isdir(os.path.join(apidoc_build_path, file)):
				continue
			zf.write(os.path.join(apidoc_build_path, file), '%s/documentation/apidoc/%s' % (modulepath, file))

	zip_dir(zf,'assets',modulepath,['.pyc','.js'])
	zip_dir(zf,'example',modulepath,['.pyc'])
	zip_dir(zf,'platform',modulepath,['.pyc','.js'])
	zf.write('LICENSE','%s/LICENSE' % modulepath)
	zf.write('module.xcconfig','%s/module.xcconfig' % modulepath)
	exports_file = 'metadata.json'
	if os.path.exists(exports_file):
		zf.write(exports_file, '%s/%s' % (modulepath, exports_file))
	zf.close()

if __name__ == '__main__':
	global options

	parser = optparse.OptionParser()
	parser.add_option("-s", "--skip-docs",
			dest="skip_docs",
			action="store_true",
			help="Will skip building documentation in apidoc folder",
			default=False)
	(options, args) = parser.parse_args()

	manifest,mf = validate_manifest()
	validate_license()
	config = read_ti_xcconfig()

	sdk = find_sdk(config)
	sys.path.insert(0,os.path.join(sdk,'iphone'))
	sys.path.append(os.path.join(sdk, "common"))

	compile_js(manifest,config)
	build_module(manifest,config)
	package_module(manifest,mf,config)
	sys.exit(0)


try:
		import markdown2 as markdown
	except ImportError:
		import markdown

# Appcelerator Titanium Module Packager
import os, subprocess, sys, glob, string, optparse, subprocess
import zipfile
from datetime import date

cwd = os.path.abspath(os.path.dirname(sys._getframe(0).f_code.co_filename))
os.chdir(cwd)
required_module_keys = ['name','version','moduleid','description','copyright','license','copyright','platform','minsdk']
module_defaults = {
	'description':'My module',
	'author': 'Your Name',
	'license' : 'Specify your license',
	'copyright' : 'Copyright (c) %s by Your Company' % str(date.today().year),
}
module_license_default = "TODO: place your license here and we'll include it in the module distribution"

def find_sdk(config):
	sdk = config['TITANIUM_SDK']
	return os.path.expandvars(os.path.expanduser(sdk))

def replace_vars(config,token):
	idx = token.find('$(')
	while idx != -1:
		idx2 = token.find(')',idx+2)
		if idx2 == -1: break
		key = token[idx+2:idx2]
		if not config.has_key(key): break
		token = token.replace('$(%s)' % key, config[key])
		idx = token.find('$(')
	return token

def read_ti_xcconfig():
	contents = open(os.path.join(cwd,'titanium.xcconfig')).read()
	config = {}
	for line in contents.splitlines(False):
		line = line.strip()
		if line[0:2]=='//': continue
		idx = line.find('=')
		if idx > 0:
			key = line[0:idx].strip()
			value = line[idx+1:].strip()
			config[key] = replace_vars(config,value)
	return config

def generate_doc(config):
	docdir = os.path.join(cwd,'documentation')
	if not os.path.exists(docdir):
		warn("Couldn't find documentation file at: %s" % docdir)
		return None

	documentation = []
	for file in os.listdir(docdir):
		if file in ignoreFiles or os.path.isdir(os.path.join(docdir, file)):
			continue
		md = open(os.path.join(docdir,file)).read()
		html = markdown.markdown(md)
		documentation.append({file:html});
	return documentation

def compile_js(manifest,config):
	js_file = os.path.join(cwd,'assets','__MODULE_ID__.js')
	if not os.path.exists(js_file): return

	from compiler import Compiler
	try:
		import json
	except:
		import simplejson as json

	compiler = Compiler(cwd, manifest['moduleid'], manifest['name'], 'commonjs')
	root_asset, module_assets = compiler.compile_module()

	root_asset_content = """
%s

	return filterDataInRange([NSData dataWithBytesNoCopy:data length:sizeof(data) freeWhenDone:NO], ranges[0]);
""" % root_asset

	module_asset_content = """
%s

	NSNumber *index = [map objectForKey:path];
	if (index == nil) {
		return nil;
	}
	return filterDataInRange([NSData dataWithBytesNoCopy:data length:sizeof(data) freeWhenDone:NO], ranges[index.integerValue]);
""" % module_assets

	from tools import splice_code

	assets_router = os.path.join(cwd,'Classes','___PROJECTNAMEASIDENTIFIER___ModuleAssets.m')
	splice_code(assets_router, 'asset', root_asset_content)
	splice_code(assets_router, 'resolve_asset', module_asset_content)

	# Generate the exports after crawling all of the available JS source
	exports = open('metadata.json','w')
	json.dump({'exports':compiler.exports }, exports)
	exports.close()

def die(msg):
	print msg
	sys.exit(1)

def info(msg):
	print "[INFO] %s" % msg

def warn(msg):
	print "[WARN] %s" % msg

def validate_license():
	c = open(os.path.join(cwd,'LICENSE')).read()
	if c.find(module_license_default)!=-1:
		warn('please update the LICENSE file with your license text before distributing')

def validate_manifest():
	path = os.path.join(cwd,'manifest')
	f = open(path)
	if not os.path.exists(path): die("missing %s" % path)
	manifest = {}
	for line in f.readlines():
		line = line.strip()
		if line[0:1]=='#': continue
		if line.find(':') < 0: continue
		key,value = line.split(':')
		manifest[key.strip()]=value.strip()
	for key in required_module_keys:
		if not manifest.has_key(key): die("missing required manifest key '%s'" % key)
		if module_defaults.has_key(key):
			defvalue = module_defaults[key]
			curvalue = manifest[key]
			if curvalue==defvalue: warn("please update the manifest key: '%s' to a non-default value" % key)
	return manifest,path

ignoreFiles = ['.DS_Store','.gitignore','libTitanium.a','titanium.jar','README']
ignoreDirs = ['.DS_Store','.svn','.git','CVSROOT']

def zip_dir(zf,dir,basepath,ignoreExt=[]):
	if not os.path.exists(dir): return
	for root, dirs, files in os.walk(dir):
		for name in ignoreDirs:
			if name in dirs:
				dirs.remove(name)	# don't visit ignored directories
		for file in files:
			if file in ignoreFiles: continue
			e = os.path.splitext(file)
			if len(e) == 2 and e[1] in ignoreExt: continue
			from_ = os.path.join(root, file)
			to_ = from_.replace(dir, '%s/%s'%(basepath,dir), 1)
			zf.write(from_, to_)

def glob_libfiles():
	files = []
	for libfile in glob.glob('build/**/*.a'):
		if libfile.find('Release-')!=-1:
			files.append(libfile)
	return files

def build_module(manifest,config):
	from tools import ensure_dev_path
	ensure_dev_path()

	rc = os.system("xcodebuild -sdk iphoneos -configuration Release")
	if rc != 0:
		die("xcodebuild failed")
	rc = os.system("xcodebuild -sdk iphonesimulator -configuration Release")
	if rc != 0:
		die("xcodebuild failed")
    # build the merged library using lipo
	moduleid = manifest['moduleid']
	libpaths = ''
	for libfile in glob_libfiles():
		libpaths+='%s ' % libfile

	os.system("lipo %s -create -output build/lib%s.a" %(libpaths,moduleid))

def generate_apidoc(apidoc_build_path):
	global options

	if options.skip_docs:
		info("Skipping documentation generation.")
		return False
	else:
		info("Module apidoc generation can be skipped using --skip-docs")
	apidoc_path = os.path.join(cwd, "apidoc")
	if not os.path.exists(apidoc_path):
		warn("Skipping apidoc generation. No apidoc folder found at: %s" % apidoc_path)
		return False

	if not os.path.exists(apidoc_build_path):
	    os.makedirs(apidoc_build_path)
	ti_root = string.strip(subprocess.check_output(["echo $TI_ROOT"], shell=True))
	if not len(ti_root) > 0:
		warn("Not generating documentation from the apidoc folder. The titanium_mobile repo could not be found.")
		warn("Set the TI_ROOT environment variable to the parent folder where the titanium_mobile repo resides (eg.'export TI_ROOT=/Path').")
		return False
	docgen = os.path.join(ti_root, "titanium_mobile", "apidoc", "docgen.py")
	if not os.path.exists(docgen):
		warn("Not generating documentation from the apidoc folder. Couldn't find docgen.py at: %s" % docgen)
		return False

	info("Generating documentation from the apidoc folder.")
	rc = os.system("\"%s\" --format=jsca,modulehtml --css=styles.css -o \"%s\" -e \"%s\"" % (docgen, apidoc_build_path, apidoc_path))
	if rc != 0:
		die("docgen failed")
	return True

def package_module(manifest,mf,config):
	name = manifest['name'].lower()
	moduleid = manifest['moduleid'].lower()
	version = manifest['version']
	modulezip = '%s-iphone-%s.zip' % (moduleid,version)
	if os.path.exists(modulezip): os.remove(modulezip)
	zf = zipfile.ZipFile(modulezip, 'w', zipfile.ZIP_DEFLATED)
	modulepath = 'modules/iphone/%s/%s' % (moduleid,version)
	zf.write(mf,'%s/manifest' % modulepath)
	libname = 'lib%s.a' % moduleid
	zf.write('build/%s' % libname, '%s/%s' % (modulepath,libname))
	docs = generate_doc(config)
	if docs!=None:
		for doc in docs:
			for file, html in doc.iteritems():
				filename = string.replace(file,'.md','.html')
				zf.writestr('%s/documentation/%s'%(modulepath,filename),html)

	apidoc_build_path = os.path.join(cwd, "build", "apidoc")
	if generate_apidoc(apidoc_build_path):
		for file in os.listdir(apidoc_build_path):
			if file in ignoreFiles or os.path.isdir(os.path.join(apidoc_build_path, file)):
				continue
			zf.write(os.path.join(apidoc_build_path, file), '%s/documentation/apidoc/%s' % (modulepath, file))

	zip_dir(zf,'assets',modulepath,['.pyc','.js'])
	zip_dir(zf,'example',modulepath,['.pyc'])
	zip_dir(zf,'platform',modulepath,['.pyc','.js'])
	zf.write('LICENSE','%s/LICENSE' % modulepath)
	zf.write('module.xcconfig','%s/module.xcconfig' % modulepath)
	exports_file = 'metadata.json'
	if os.path.exists(exports_file):
		zf.write(exports_file, '%s/%s' % (modulepath, exports_file))
	zf.close()

if __name__ == '__main__':
	global options

	parser = optparse.OptionParser()
	parser.add_option("-s", "--skip-docs",
			dest="skip_docs",
			action="store_true",
			help="Will skip building documentation in apidoc folder",
			default=False)
	(options, args) = parser.parse_args()

	manifest,mf = validate_manifest()
	validate_license()
	config = read_ti_xcconfig()

	sdk = find_sdk(config)
	sys.path.insert(0,os.path.join(sdk,'iphone'))
	sys.path.append(os.path.join(sdk, "common"))

	compile_js(manifest,config)
	build_module(manifest,config)
	package_module(manifest,mf,config)
	sys.exit(0)


from odoo.tests import common
from datetime import datetime
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT as DF
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT as DT

class TestPurchaseLastPrice(common.TransactionCase):

super(TestPurchaseLastPrice, self).setUp()
        self.purchase_model = self.env['purchase.order']
        self.purchase_line_model = self.env['purchase.order.line']
        self.location = self.env.ref('stock.stock_location_suppliers')
        self.sale_order_model = self.env['sale.order']
        self.sale_line_model = self.env['sale.order.line']
        self.pricelist = self.env.ref('product.list0')
        partner_values = {'name': 'Peace and love'}
        self.partner = self.env['res.partner'].create(partner_values)
        self.partner_p = self.env.ref('base.res_partner_1')
        product_values = {'name': 'Gun',
                          'list_price': 5,
                          'type': 'product'}
        self.product = self.env['product.product'].create(product_values)
        self.product_uom_unit = self.env.ref('product.product_uom_unit')

    def create_sale_order(self):
        sale_obj = self.env['sale.order']
        values = {
            'partner_id': self.partner.id,
            'commitment_date': '02-02-2010',
            'order_line': [(0, 0, {
                'name': self.product.name,
                'product_id': self.product.id,
                'product_uom': self.product_uom_unit.id,
                'price_unit': 234.0,
                'product_uom_qty': 1})],
        }
        return sale_obj.create(values)

    def test_purchase_last_price(self):
        purchase_order = self.purchase_model.create({
            'partner_id': self.partner_p.id,
            'location_id': self.location.id,
            'pricelist_id': self.pricelist.id,
            'date': '01-01-2010',
            'order_line': [(0, 0, {
                'product_id': self.product.id,
                'price_unit': 123.0,
                'product_uom': self.env.ref('product.product_uom_unit').id,
                'product_qty': 5.0,
                'name': self.product.name,
                'date_planned': '01-01-2010'
            })]
        })
        purchase_order.button_confirm()
        sale = self.create_sale_order()
        p_date = datetime.strptime(purchase_order.date_order, DT)
        p_date = p_date.date().strftime(DF)
        for line in sale.order_line:
            self.assertEqual(line.last_supplier_id.id, self.partner_p.id)
            self.assertEqual(line.last_purchase_price, 123.0)
            self.assertEqual(line.last_purchase_date, p_date)


sale_obj = self.env['sale.order']
        values = {
            'partner_id': self.partner.id,
            'commitment_date': '02-02-2010',
            'order_line': [(0, 0, {
                'name': self.product.name,
                'product_id': self.product.id,
                'product_uom': self.product_uom_unit.id,
                'price_unit': 234.0,
                'product_uom_qty': 1})],
        }
        return sale_obj.create(values)

from odoo.tests import common
from datetime import datetime
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT as DF
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT as DT

class TestPurchaseLastPrice(common.TransactionCase):

    def setUp(self):
        super(TestPurchaseLastPrice, self).setUp()
        self.purchase_model = self.env['purchase.order']
        self.purchase_line_model = self.env['purchase.order.line']
        self.location = self.env.ref('stock.stock_location_suppliers')
        self.sale_order_model = self.env['sale.order']
        self.sale_line_model = self.env['sale.order.line']
        self.pricelist = self.env.ref('product.list0')
        partner_values = {'name': 'Peace and love'}
        self.partner = self.env['res.partner'].create(partner_values)
        self.partner_p = self.env.ref('base.res_partner_1')
        product_values = {'name': 'Gun',
                          'list_price': 5,
                          'type': 'product'}
        self.product = self.env['product.product'].create(product_values)
        self.product_uom_unit = self.env.ref('product.product_uom_unit')

    def create_sale_order(self):

    def test_purchase_last_price(self):
        purchase_order = self.purchase_model.create({
            'partner_id': self.partner_p.id,
            'location_id': self.location.id,
            'pricelist_id': self.pricelist.id,
            'date': '01-01-2010',
            'order_line': [(0, 0, {
                'product_id': self.product.id,
                'price_unit': 123.0,
                'product_uom': self.env.ref('product.product_uom_unit').id,
                'product_qty': 5.0,
                'name': self.product.name,
                'date_planned': '01-01-2010'
            })]
        })
        purchase_order.button_confirm()
        sale = self.create_sale_order()
        p_date = datetime.strptime(purchase_order.date_order, DT)
        p_date = p_date.date().strftime(DF)
        for line in sale.order_line:
            self.assertEqual(line.last_supplier_id.id, self.partner_p.id)
            self.assertEqual(line.last_purchase_price, 123.0)
            self.assertEqual(line.last_purchase_date, p_date)


from odoo.tests import common
from datetime import datetime
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT as DF
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT as DT

class TestPurchaseLastPrice(common.TransactionCase):

    def setUp(self):
        super(TestPurchase

        self.purchase_model = self.env['purchase.order']
        self.purchase_line_model = self.env['purchase.order.line']
        self.location = self.env.ref('stock.stock_location_suppliers')
        self.sale_order_model = self.env['sale.order']
        self.sale_line_model = self.env['sale.order.line']
        self.pricelist = self.env.ref('product.list0')
        partner_values = {'name': 'Peace and love'}
        self.partner = self.env['res.partner'].create(partner_values)
        self.partner_p = self.env.ref('base.res_partner_1')
        product_values = {'name': 'Gun',
                          'list_price': 5,
                          'type': 'product'}
        self.product = self.env['product.product'].create(product_values)
        self.product_uom_unit = self.env.ref('product.product_uom_unit')

    def create_sale_order(self):
        sale_obj = self.env['sale.order']
        values = {
            'partner_id': self.partner.id,
            'commitment_date': '02-02-2010',
            'order_line': [(0, 0, {
                'name': self.product.name,
                'product_id': self.product.id,
                'product_uom': self.product_uom_unit.id,
                'price_unit': 234.0,
                'product_uom_qty': 1})],
        }
        return sale_obj.create(values)

    def test_purchase_last_price(self):
        purchase_order = self.purchase_model.create({
            'partner_id': self.partner_p.id,
            'location_id': self.location.id,
            'pricelist_id': self.pricelist.id,
            'date': '01-01-2010',
            'order_line': [(0, 0, {
                'product_id': self.product.id,
                'price_unit': 123.0,
                'product_uom': self.env.ref('product.product_uom_unit').id,
                'product_qty': 5.0,
                'name': self.product.name,
                'date_planned': '01-01-2010'
            })]
        })
        purchase_order.button_confirm()
        sale = self.create_sale_order()
        p_date = datetime.strptime(purchase_order.date_order, DT)
        p_date = p_date.date().strftime(DF)
        for line in sale.order_line:
            self.assertEqual(line.last_supplier_id.id, self.partner_p.id)
            self.assertEqual(line.last_purchase_price, 123.0)
            self.assertEqual(line.last_purchase_date, p_date)


for line in sale.order_line:
            self.assertEqual(line.last_supplier_id.id, self.partner_p.id)
            self.assertEqual(line.last_purchase_price, 123.0)
            self.assertEqual(line.last_purchase_date, p_date)

from odoo.tests import common
from datetime import datetime
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT as DF
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT as DT

class TestPurchaseLastPrice(common.TransactionCase):

    def setUp(self):
        super(TestPurchaseLastPrice, self).setUp()
        self.purchase_model = self.env['purchase.order']
        self.purchase_line_model = self.env['purchase.order.line']
        self.location = self.env.ref('stock.stock_location_suppliers')
        self.sale_order_model = self.env['sale.order']
        self.sale_line_model = self.env['sale.order.line']
        self.pricelist = self.env.ref('product.list0')
        partner_values = {'name': 'Peace and love'}
        self.partner = self.env['res.partner'].create(partner_values)
        self.partner_p = self.env.ref('base.res_partner_1')
        product_values = {'name': 'Gun',
                          'list_price': 5,
                          'type': 'product'}
        self.product = self.env['product.product'].create(product_values)
        self.product_uom_unit = self.env.ref('product.product_uom_unit')

    def create_sale_order(self):
        sale_obj = self.env['sale.order']
        values = {
            'partner_id': self.partner.id,
            'commitment_date': '02-02-2010',
            'order_line': [(0, 0, {
                'name': self.product.name,
                'product_id': self.product.id,
                'product_uom': self.product_uom_unit.id,
                'price_unit': 234.0,
                'product_uom_qty': 1})],
        }
        return sale_obj.create(values)

    def test_purchase_last_price(self):
        purchase_order = self.purchase_model.create({
            'partner_id': self.partner_p.id,
            'location_id': self.location.id,
            'pricelist_id': self.pricelist.id,
            'date': '01-01-2010',
            'order_line': [(0, 0, {
                'product_id': self.product.id,
                'price_unit': 123.0,
                'product_uom': self.env.ref('product.product_uom_unit').id,
                'product_qty': 5.0,
                'name': self.product.name,
                'date_planned': '01-01-2010'
            })]
        })
        purchase_order.button_confirm()
        sale = self.create_sale_order()
        p_date = datetime.strptime(purchase_order.date_order, DT)
        p_date = p_date.date().strftime(DF)


import os
import sys
import signal
import errno

from . import util

__all__ = ['Popen']

# Start child process using fork

class Popen(object):
    method = 'fork'

    def __init__(self, process_obj):
        sys.stdout.flush()
        sys.stderr.flush()
        self.returncode = None
        self._launch(process_obj)

    def duplicate_for_child(self, fd):
        return fd

if self.returncode is None:
            while True:
                try:
                    pid, sts = os.waitpid(self.pid, flag)
                except OSError as e:
                    if e.errno == errno.EINTR:
                        continue
                    # Child process not yet created. See #1731717
                    return None
                else:
                    break
            if pid == self.pid:
                if os.WIFSIGNALED(sts):
                    self.returncode = -os.WTERMSIG(sts)
                else:
                    assert os.WIFEXITED(sts)
                    self.returncode = os.WEXITSTATUS(sts)
        return self.returncode

    def wait(self, timeout=None):
        if self.returncode is None:
            if timeout is not None:
                from multiprocess.connection import wait
                if not wait([self.sentinel], timeout):
                    return None
            # This shouldn't block if wait() returned successfully.
            return self.poll(os.WNOHANG if timeout == 0.0 else 0)
        return self.returncode

    def terminate(self):
        if self.returncode is None:
            try:
                os.kill(self.pid, signal.SIGTERM)
            except ProcessLookupError:
                pass
            except OSError:
                if self.wait(timeout=0.1) is None:
                    raise

    def _launch(self, process_obj):
        code = 1
        parent_r, child_w = os.pipe()
        self.pid = os.fork()
        if self.pid == 0:
            try:
                os.close(parent_r)
                if 'random' in sys.modules:
                    import random
                    random.seed()
                code = process_obj._bootstrap()
            finally:
                os._exit(code)
        else:
            os.close(child_w)
            util.Finalize(self, os.close, (parent_r,))
            self.sentinel = parent_r


sys.stdout.flush()
        sys.stderr.flush()
        self.returncode = None
        self._launch(process_obj)

import os
import sys
import signal
import errno

from . import util

__all__ = ['Popen']

# Start child process using fork

class Popen(object):
    method = 'fork'

    def __init__(self, process_obj):

    def duplicate_for_child(self, fd):
        return fd

    def poll(self, flag=os.WNOHANG):
        if self.returncode is None:
            while True:
                try:
                    pid, sts = os.waitpid(self.pid, flag)
                except OSError as e:
                    if e.errno == errno.EINTR:
                        continue
                    # Child process not yet created. See #1731717
                    return None
                else:
                    break
            if pid == self.pid:
                if os.WIFSIGNALED(sts):
                    self.returncode = -os.WTERMSIG(sts)
                else:
                    assert os.WIFEXITED(sts)
                    self.returncode = os.WEXITSTATUS(sts)
        return self.returncode

    def wait(self, timeout=None):
        if self.returncode is None:
            if timeout is not None:
                from multiprocess.connection import wait
                if not wait([self.sentinel], timeout):
                    return None
            # This shouldn't block if wait() returned successfully.
            return self.poll(os.WNOHANG if timeout == 0.0 else 0)
        return self.returncode

    def terminate(self):
        if self.returncode is None:
            try:
                os.kill(self.pid, signal.SIGTERM)
            except ProcessLookupError:
                pass
            except OSError:
                if self.wait(timeout=0.1) is None:
                    raise

    def _launch(self, process_obj):
        code = 1
        parent_r, child_w = os.pipe()
        self.pid = os.fork()
        if self.pid == 0:
            try:
                os.close(parent_r)
                if 'random' in sys.modules:
                    import random
                    random.seed()
                code = process_obj._bootstrap()
            finally:
                os._exit(code)
        else:
            os.close(child_w)
            util.Finalize(self, os.close, (parent_r,))
            self.sentinel = parent_r


import os
import sys
import signal
import errno

from . import util

__all__ = ['Popen']

# Start child process using fork

class Popen(object):
    method = 'fork'

    def __init__(self, process_obj):
        sys.stdout.flush()
        sys.stderr.flush()
        self.returncode = None
        self._launch(process_obj)

    def duplicate_for_child(self, fd):
        return fd

    def poll(self, flag=os.WNOHANG):
        if self.returncode is None:
            while True:
                try:
                    pid, sts = os.waitpid(self.pid, flag)
                except OSError as e:
                    if e.errno == errno.EINTR:
                        continue
                    # Child process not yet created. See #1731717
                    return None
                else:
                    break
            if pid == self.pid:
                if os.WIFSIGNALED(sts):
                    self.returncode = -os.WTERMSIG(sts)
                else:
                    assert os.WIFEXITED(sts)
                    self.returncode = os.WEXITSTATUS(sts)
        return self.returncode

    def wait(self, timeout=None):
        if self.returncode is None:
            if timeout is not None:
                from multiprocess.connection import wait
                if not wait([self.sentinel], timeout):
                    return None
            # This shouldn't block if wait() returned successfully.
            return self.poll(os.WNOHANG if timeout == 0.0 else 0)
        ret

    def terminate(self):
        if self.returncode is None:
            try:
                os.kill(self.pid, signal.SIGTERM)
            except ProcessLookupError:
                pass
            except OSError:
                if self.wait(timeout=0.1) is None:
                    raise

    def _launch(self, process_obj):
        code = 1
        parent_r, child_w = os.pipe()
        self.pid = os.fork()
        if self.pid == 0:
            try:
                os.close(parent_r)
                if 'random' in sys.modules:
                    import random
                    random.seed()
                code = process_obj._bootstrap()
            finally:
                os._exit(code)
        else:
            os.close(child_w)
            util.Finalize(self, os.close, (parent_r,))
            self.sentinel = parent_r


while True:
                try:
                    pid, sts = os.waitpid(self.pid, flag)
                except OSError as e:
                    if e.errno == errno.EINTR:
                        continue
                    # Child process not yet created. See #1731717
                    return None
                else:
                    break

import os
import sys
import signal
import errno

from . import util

__all__ = ['Popen']

# Start child process using fork

class Popen(object):
    method = 'fork'

    def __init__(self, process_obj):
        sys.stdout.flush()
        sys.stderr.flush()
        self.returncode = None
        self._launch(process_obj)

    def duplicate_for_child(self, fd):
        return fd

    def poll(self, flag=os.WNOHANG):
        if self.returncode is None:

            if pid == self.pid:
                if os.WIFSIGNALED(sts):
                    self.returncode = -os.WTERMSIG(sts)
                else:
                    assert os.WIFEXITED(sts)
                    self.returncode = os.WEXITSTATUS(sts)
        return self.returncode

    def wait(self, timeout=None):
        if self.returncode is None:
            if timeout is not None:
                from multiprocess.connection import wait
                if not wait([self.sentinel], timeout):
                    return None
            # This shouldn't block if wait() returned successfully.
            return self.poll(os.WNOHANG if timeout == 0.0 else 0)
        return self.returncode

    def terminate(self):
        if self.returncode is None:
            try:
                os.kill(self.pid, signal.SIGTERM)
            except ProcessLookupError:
                pass
            except OSError:
                if self.wait(timeout=0.1) is None:
                    raise

    def _launch(self, process_obj):
        code = 1
        parent_r, child_w = os.pipe()
        self.pid = os.fork()
        if self.pid == 0:
            try:
                os.close(parent_r)
                if 'random' in sys.modules:
                    import random
                    random.seed()
                code = process_obj._bootstrap()
            finally:
                os._exit(code)
        else:
            os.close(child_w)
            util.Finalize(self, os.close, (parent_r,))
            self.sentinel = parent_r


try:
                os.close(parent_r)
                if 'random' in sys.modules:
                    import random
                    random.seed()
                code = process_obj._bootstrap()
            finally:
                os._exit(code)

import os
import sys
import signal
import errno

from . import util

__all__ = ['Popen']

# Start child process using fork

class Popen(object):
    method = 'fork'

    def __init__(self, process_obj):
        sys.stdout.flush()
        sys.stderr.flush()
        self.returncode = None
        self._launch(process_obj)

    def duplicate_for_child(self, fd):
        return fd

    def poll(self, flag=os.WNOHANG):
        if self.returncode is None:
            while True:
                try:
                    pid, sts = os.waitpid(self.pid, flag)
                except OSError as e:
                    if e.errno == errno.EINTR:
                        continue
                    # Child process not yet created. See #1731717
                    return None
                else:
                    break
            if pid == self.pid:
                if os.WIFSIGNALED(sts):
                    self.returncode = -os.WTERMSIG(sts)
                else:
                    assert os.WIFEXITED(sts)
                    self.returncode = os.WEXITSTATUS(sts)
        return self.returncode

    def wait(self, timeout=None):
        if self.returncode is None:
            if timeout is not None:
                from multiprocess.connection import wait
                if not wait([self.sentinel], timeout):
                    return None
            # This shouldn't block if wait() returned successfully.
            return self.poll(os.WNOHANG if timeout == 0.0 else 0)
        return self.returncode

    def terminate(self):
        if self.returncode is None:
            try:
                os.kill(self.pid, signal.SIGTERM)
            except ProcessLookupError:
                pass
            except OSError:
                if self.wait(timeout=0.1) is None:
                    raise

    def _launch(self, process_obj):
        code = 1
        parent_r, child_w = os.pipe()
        self.pid = os.fork()
        if self.pid == 0:

        else:
            os.close(child_w)
            util.Finalize(self, os.close, (parent_r,))
            self.sentinel = parent_r


# This file contains commonly used parts of external libraries. The idea is
# to help in removing helpers from being used as a dependency by many files
# but at the same time making it easy to change for example the json lib
# NOTE:  This file is specificaly created for
# from ckan.common import x, y, z to be allowed

from collections import MutableMapping

import flask
import six

from werkzeug.local import Local, LocalProxy

from flask_babel import (gettext as flask_ugettext,
                         ngettext as flask_ungettext)

import simplejson as json

if six.PY2:
    import pylons
    from pylons.i18n import (ugettext as pylons_ugettext,
                             ungettext as pylons_ungettext)
    from pylons import response

current_app = flask.current_app

def is_flask_request():
    u'''
    A centralized way to determine whether we are in the context of a
    request being served by Flask or Pylons
    '''
    if six.PY3:
        return True
    try:
        pylons.request.environ
        pylons_request_available = True
    except TypeError:
        pylons_request_available = False

    return (flask.request and
            (flask.request.environ.get(u'ckan.app') == u'flask_app' or
             not pylons_request_available))

def streaming_response(
        data, mimetype=u'application/octet-stream', with_context=False):
    iter_data = iter(data)
    if is_flask_request():
        # Removal of context variables for pylon's app is prevented
        # inside `pylons_app.py`. It would be better to decide on the fly
        # whether we need to preserve context, but it won't affect performance
        # in any visible way and we are going to get rid of pylons anyway.
        # Flask allows to do this in easy way.
        if with_context:
            iter_data = flask.stream_with_context(iter_data)
        resp = flask.Response(iter_data, mimetype=mimetype)
    else:
        response.app_iter = iter_data
        resp = response.headers['Content-type'] = mimetype
    return resp

return flask_ugettext(*args, **kwargs)

_ = ugettext

def ungettext(*args, **kwargs):
    if is_flask_request():
        return flask_ungettext(*args, **kwargs)
    else:
        return pylons_ungettext(*args, **kwargs)

class CKANConfig(MutableMapping):
    u'''Main CKAN configuration object

    This is a dict-like object that also proxies any changes to the
    Flask and Pylons configuration objects.

    The actual `config` instance in this module is initialized in the
    `load_environment` method with the values of the ini file or env vars.

    '''

    def __init__(self, *args, **kwargs):
        self.store = dict()
        self.update(dict(*args, **kwargs))

    def __getitem__(self, key):
        return self.store[key]

    def __iter__(self):
        return iter(self.store)

    def __len__(self):
        return len(self.store)

    def __repr__(self):
        return self.store.__repr__()

    def copy(self):
        return self.store.copy()

    def clear(self):
        self.store.clear()

        try:
            flask.current_app.config.clear()
        except RuntimeError:
            pass

        if six.PY2:
            try:
                pylons.config.clear()
                # Pylons set this default itself
                pylons.config[u'lang'] = None
            except TypeError:
                pass

    def __setitem__(self, key, value):
        self.store[key] = value
        try:
            flask.current_app.config[key] = value
        except RuntimeError:
            pass

        if six.PY2:
            try:
                pylons.config[key] = value
            except TypeError:
                pass

    def __delitem__(self, key):
        del self.store[key]
        try:
            del flask.current_app.config[key]
        except RuntimeError:
            pass

        if six.PY2:
            try:
                del pylons.config[key]
            except TypeError:
                pass

def _get_request():
    if is_flask_request():
        return flask.request
    else:
        return pylons.request

class CKANRequest(LocalProxy):
    u'''Common request object

    This is just a wrapper around LocalProxy so we can handle some special
    cases for backwards compatibility.

    LocalProxy will forward to Flask or Pylons own request objects depending
    on the output of `_get_request` (which essentially calls
    `is_flask_request`) and at the same time provide all objects methods to be
    able to interact with them transparently.
    '''

    @property
    def params(self):
        u''' Special case as Pylons' request.params is used all over the place.
        All new code meant to be run just in Flask (eg views) should always
        use request.args
        '''
        try:
            return super(CKANRequest, self).params
        except AttributeError:
            return self.args

def _get_c():
    if is_flask_request():
        return flask.g
    else:
        return pylons.c

def _get_session():
    if is_flask_request():
        return flask.session
    else:
        return pylons.session

local = Local()

# This a proxy to the bounded config object
local(u'config')

# Thread-local safe objects
config = local.config = CKANConfig()

# Proxies to already thread-local safe objects
request = CKANRequest(_get_request)
# Provide a `c`  alias for `g` for backwards compatibility
g = c = LocalProxy(_get_c)
session = LocalProxy(_get_session)

truthy = frozenset([u'true', u'yes', u'on', u'y', u't', u'1'])
falsy = frozenset([u'false', u'no', u'off', u'n', u'f', u'0'])

def asbool(obj):
    if isinstance(obj, six.string_types):
        obj = obj.strip().lower()
        if obj in truthy:
            return True
        elif obj in falsy:
            return False
        else:
            raise ValueError(u"String is not true/false: {}".format(obj))
    return bool(obj)

def asint(obj):
    try:
        return int(obj)
    except (TypeError, ValueError):
        raise ValueError(u"Bad integer value: {}".format(obj))

def aslist(obj, sep=None, strip=True):
    if isinstance(obj, six.string_types):
        lst = obj.split(sep)
        if strip:
            lst = [v.strip() for v in lst]
        return lst
    elif isinstance(obj, (list, tuple)):
        return obj
    elif obj is None:
        return []
    else:
        return [obj]


# This file contains commonly used parts of external libraries. The idea is
# to help in removing helpers from being used as a dependency by many files
# but at the same time making it easy to change for example the json lib
# NOTE:  This file is specificaly created for
# from ckan.common import x, y, z to be allowed

from collections import MutableMapping

import flask
import six

from werkzeug.local import Local, LocalProxy

from flask_babel import (gettext as flask_ugettext,
                         ngettext as flask_ungettext)

import simplejson as json

if six.PY2:
    import pylons
    from pylons.i18n import (ugettext as pylons_ugettext,
                             ungettext as pylons_ungettext)
    from pylons import response

current_app = flask.current_app

def is_flask_request():
    u'''
    A centralized way to determine whether we are in the context of a
    request being served by Flask or Pylons
    '''
    if six.PY3:
        return True
    try:
        pylons.request.environ
        pylons_request_available = True
    except TypeError:
        pylons_request_available = False

    return (flask.request and
            (flask.request.environ.get(u'ckan.app') == u'flask_app' or
             not pylons_request_available))

def streaming_response(
        data, mimetype=u'application/octet-stream', with_context=False):
    iter_data = iter(data)
    if is_flask_request():
        # Removal of context variables for pylon's app is prevented
        # inside `pylons_app.py`. It would be better to decide on the fly
        # whether we need to preserve context, but it won't affect performance
        # in any visible way and we are going to get rid of pylons anyway.
        # Flask allows to do this in easy way.
        if with_context:
            iter_data = flask.stream_with_context(iter_data)
        resp = flask.Response(iter_data, mimetype=mimetype)
    else:
        response.app_iter = iter_data
        resp = response.headers['Content-type'] = mimetype
    return resp

def ugettext(*args, **kwargs):
    return flask_ugettext(*args, **kwargs)

_ = ugettext

def ungettext(*args, **kwargs):
    if is_flask_request():
        return flask_ungettext(*args, **kwargs)
    else:
        return pylons_ungettext(*args, **kwargs)

class CKANConfig(MutableMapping):
    u'''Main CKAN configuration object

    This is a dict-like object that also proxies any changes to the
    Flask and Pylons configuration objects.

    The actual `config` instance in this module is initialized in the
    `load_environment` method with the values of the ini file or env vars.

    '''

    def __init__(self, *args, **kwargs):
        self.store = dict()
        self.update(dict(*args, **kwargs))

    def __getitem__(self, key):
        return self.store[key]

    def __iter__(self):
        return iter(self.store)

    def __len__(self):
        return len(self.store)

    def __repr__(self):
        return self.store.__repr__()

    def copy(self):

    def clear(self):
        self.store.clear()

        try:
            flask.current_app.config.clear()
        except RuntimeError:
            pass

        if six.PY2:
            try:
                pylons.config.clear()
                # Pylons set this default itself
                pylons.config[u'lang'] = None
            except TypeError:
                pass

    def __setitem__(self, key, value):
        self.store[key] = value
        try:
            flask.current_app.config[key] = value
        except RuntimeError:
            pass

        if six.PY2:
            try:
                pylons.config[key] = value
            except TypeError:
                pass

    def __delitem__(self, key):
        del self.store[key]
        try:
            del flask.current_app.config[key]
        except RuntimeError:
            pass

        if six.PY2:
            try:
                del pylons.config[key]
            except TypeError:
                pass

def _get_request():
    if is_flask_request():
        return flask.request
    else:
        return pylons.request

class CKANRequest(LocalProxy):
    u'''Common request object

    This is just a wrapper around LocalProxy so we can handle some special
    cases for backwards compatibility.

    LocalProxy will forward to Flask or Pylons own request objects depending
    on the output of `_get_request` (which essentially calls
    `is_flask_request`) and at the same time provide all objects methods to be
    able to interact with them transparently.
    '''

    @property
    def params(self):
        u''' Special case as Pylons' request.params is used all over the place.
        All new code meant to be run just in Flask (eg views) should always
        use request.args
        '''
        try:
            return super(CKANRequest, self).params
        except AttributeError:
            return self.args

def _get_c():
    if is_flask_request():
        return flask.g
    else:
        return pylons.c

def _get_session():
    if is_flask_request():
        return flask.session
    else:
        return pylons.session

local = Local()

# This a proxy to the bounded config object
local(u'config')

# Thread-local safe objects
config = local.config = CKANConfig()

# Proxies to already thread-local safe objects
request = CKANRequest(_get_request)
# Provide a `c`  alias for `g` for backwards compatibility
g = c = LocalProxy(_get_c)
session = LocalProxy(_get_session)

truthy = frozenset([u'true', u'yes', u'on', u'y', u't', u'1'])
falsy = frozenset([u'false', u'no', u'off', u'n', u'f', u'0'])

def asbool(obj):
    if isinstance(obj, six.string_types):
        obj = obj.strip().lower()
        if obj in truthy:
            return True
        elif obj in falsy:
            return False
        else:
            raise ValueError(u"String is not true/false: {}".format(obj))
    return bool(obj)

def asint(obj):
    try:
        return int(obj)
    except (TypeError, ValueError):
        raise ValueError(u"Bad integer value: {}".format(obj))

def aslist(obj, sep=None, strip=True):
    if isinstance(obj, six.string_types):
        lst = obj.split(sep)
        if strip:
            lst = [v.strip() for v in lst]
        return lst
    elif isinstance(obj, (list, tuple)):
        return obj
    elif obj is None:
        return []
    else:
        return [obj]


# This file contains commonly used parts of external libraries. The idea is
# to help in removing helpers from being used as a dependency by many files
# but at the same time making it easy to change for example the json lib
# NOTE:  This file is specificaly created for
# from ckan.common import x, y, z to be allowed

from collections import MutableMapping

import flask
import six

from werkzeug.local import Local, LocalProxy

from flask_babel import (gettext as flask_ugettext,
                         ngettext as flask_ungettext)

import simplejson as json

if six.PY2:
    import pylons
    from pylons.i18n import (ugettext as pylons_ugettext,
                             ungettext as pylons_ungettext)
    from pylons import response

current_app = flask.current_app

def is_flask_request():
    u'''
    A centralized way to determine whether we are in the context of a
    request being served by Flask or Pylons
    '''
    if six.PY3:
        return True
    try:
        pylons.request.environ
        pylons_request_available = True
    except TypeError:
        pylons_request_available = False

    return (flask.request and
            (flask.request.environ.get(u'ckan.app') == u'flask_app' or
             not pylons_request_available))

def streaming_response(
        data, mimetype=u'application/octet-stream', with_context=False):
    iter_data = iter(data)
    if is_flask_request():
        # Removal of context variables for pylon's app is prevented
        # inside `pylons_app.py`. It would be better to decide on the fly
        # whether we need to preserve context, but it won't affect performance
        # in any visible way and we are going to get rid of pylons anyway.
        # Flask allows to do this in easy way.
        if with_context:
            iter_data = flask.stream_with_context(iter_data)
        resp = flask.Response(iter_data, mimetype=mimetype)
    else:
        response.app_iter = iter_data
        resp = response.headers['Content-type'] = mimetype
    return resp

def ugettext(*args, **kwargs):
    return flask_ugettext(*args, **kwargs)

_ = ugettext

def ungettext(*args, **kwargs):
    if is_flask_request():
        return flask_ungettext(*args, **kwargs)
    else:
        return pylons_ungettext(*args, **kwargs)

class CKANConfig(MutableMapping):
    u'''Main CKAN configuration object

    This is a dict-like object that also proxies any changes to the
    Flask and Pylons configuration objects.

    The actual `config` instance in this module is initialized in the
    `load_environment` method with the values of the ini file or env vars.

    '''

    def __init__(self, *args, **kwargs):
        self.store = dict()
        self.update(dict(*args, **kwargs))

    def __getitem__(self, key):
        return self.store[key]

    def __iter__(self):
        return iter(self.store)

    def __len__(self):
        return len(self.store)

    def __repr__(self):
        return sel

    def copy(self):
        return self.store.copy()

    def clear(self):
        self.store.clear()

        try:
            flask.current_app.config.clear()
        except RuntimeError:
            pass

        if six.PY2:
            try:
                pylons.config.clear()
                # Pylons set this default itself
                pylons.config[u'lang'] = None
            except TypeError:
                pass

    def __setitem__(self, key, value):
        self.store[key] = value
        try:
            flask.current_app.config[key] = value
        except RuntimeError:
            pass

        if six.PY2:
            try:
                pylons.config[key] = value
            except TypeError:
                pass

    def __delitem__(self, key):
        del self.store[key]
        try:
            del flask.current_app.config[key]
        except RuntimeError:
            pass

        if six.PY2:
            try:
                del pylons.config[key]
            except TypeError:
                pass

def _get_request():
    if is_flask_request():
        return flask.request
    else:
        return pylons.request

class CKANRequest(LocalProxy):
    u'''Common request object

    This is just a wrapper around LocalProxy so we can handle some special
    cases for backwards compatibility.

    LocalProxy will forward to Flask or Pylons own request objects depending
    on the output of `_get_request` (which essentially calls
    `is_flask_request`) and at the same time provide all objects methods to be
    able to interact with them transparently.
    '''

    @property
    def params(self):
        u''' Special case as Pylons' request.params is used all over the place.
        All new code meant to be run just in Flask (eg views) should always
        use request.args
        '''
        try:
            return super(CKANRequest, self).params
        except AttributeError:
            return self.args

def _get_c():
    if is_flask_request():
        return flask.g
    else:
        return pylons.c

def _get_session():
    if is_flask_request():
        return flask.session
    else:
        return pylons.session

local = Local()

# This a proxy to the bounded config object
local(u'config')

# Thread-local safe objects
config = local.config = CKANConfig()

# Proxies to already thread-local safe objects
request = CKANRequest(_get_request)
# Provide a `c`  alias for `g` for backwards compatibility
g = c = LocalProxy(_get_c)
session = LocalProxy(_get_session)

truthy = frozenset([u'true', u'yes', u'on', u'y', u't', u'1'])
falsy = frozenset([u'false', u'no', u'off', u'n', u'f', u'0'])

def asbool(obj):
    if isinstance(obj, six.string_types):
        obj = obj.strip().lower()
        if obj in truthy:
            return True
        elif obj in falsy:
            return False
        else:
            raise ValueError(u"String is not true/false: {}".format(obj))
    return bool(obj)

def asint(obj):
    try:
        return int(obj)
    except (TypeError, ValueError):
        raise ValueError(u"Bad integer value: {}".format(obj))

def aslist(obj, sep=None, strip=True):
    if isinstance(obj, six.string_types):
        lst = obj.split(sep)
        if strip:
            lst = [v.strip() for v in lst]
        return lst
    elif isinstance(obj, (list, tuple)):
        return obj
    elif obj is None:
        return []
    else:
        return [obj]


        try:
            return super(CKANRequest, self).params
        except AttributeError:
            return self.args

# This file contains commonly used parts of external libraries. The idea is
# to help in removing helpers from being used as a dependency by many files
# but at the same time making it easy to change for example the json lib
# NOTE:  This file is specificaly created for
# from ckan.common import x, y, z to be allowed

from collections import MutableMapping

import flask
import six

from werkzeug.local import Local, LocalProxy

from flask_babel import (gettext as flask_ugettext,
                         ngettext as flask_ungettext)

import simplejson as json

if six.PY2:
    import pylons
    from pylons.i18n import (ugettext as pylons_ugettext,
                             ungettext as pylons_ungettext)
    from pylons import response

current_app = flask.current_app

def is_flask_request():
    u'''
    A centralized way to determine whether we are in the context of a
    request being served by Flask or Pylons
    '''
    if six.PY3:
        return True
    try:
        pylons.request.environ
        pylons_request_available = True
    except TypeError:
        pylons_request_available = False

    return (flask.request and
            (flask.request.environ.get(u'ckan.app') == u'flask_app' or
             not pylons_request_available))

def streaming_response(
        data, mimetype=u'application/octet-stream', with_context=False):
    iter_data = iter(data)
    if is_flask_request():
        # Removal of context variables for pylon's app is prevented
        # inside `pylons_app.py`. It would be better to decide on the fly
        # whether we need to preserve context, but it won't affect performance
        # in any visible way and we are going to get rid of pylons anyway.
        # Flask allows to do this in easy way.
        if with_context:
            iter_data = flask.stream_with_context(iter_data)
        resp = flask.Response(iter_data, mimetype=mimetype)
    else:
        response.app_iter = iter_data
        resp = response.headers['Content-type'] = mimetype
    return resp

def ugettext(*args, **kwargs):
    return flask_ugettext(*args, **kwargs)

_ = ugettext

def ungettext(*args, **kwargs):
    if is_flask_request():
        return flask_ungettext(*args, **kwargs)
    else:
        return pylons_ungettext(*args, **kwargs)

class CKANConfig(MutableMapping):
    u'''Main CKAN configuration object

    This is a dict-like object that also proxies any changes to the
    Flask and Pylons configuration objects.

    The actual `config` instance in this module is initialized in the
    `load_environment` method with the values of the ini file or env vars.

    '''

    def __init__(self, *args, **kwargs):
        self.store = dict()
        self.update(dict(*args, **kwargs))

    def __getitem__(self, key):
        return self.store[key]

    def __iter__(self):
        return iter(self.store)

    def __len__(self):
        return len(self.store)

    def __repr__(self):
        return self.store.__repr__()

    def copy(self):
        return self.store.copy()

    def clear(self):
        self.store.clear()

        try:
            flask.current_app.config.clear()
        except RuntimeError:
            pass

        if six.PY2:
            try:
                pylons.config.clear()
                # Pylons set this default itself
                pylons.config[u'lang'] = None
            except TypeError:
                pass

    def __setitem__(self, key, value):
        self.store[key] = value
        try:
            flask.current_app.config[key] = value
        except RuntimeError:
            pass

        if six.PY2:
            try:
                pylons.config[key] = value
            except TypeError:
                pass

    def __delitem__(self, key):
        del self.store[key]
        try:
            del flask.current_app.config[key]
        except RuntimeError:
            pass

        if six.PY2:
            try:
                del pylons.config[key]
            except TypeError:
                pass

def _get_request():
    if is_flask_request():
        return flask.request
    else:
        return pylons.request

class CKANRequest(LocalProxy):
    u'''Common request object

    This is just a wrapper around LocalProxy so we can handle some special
    cases for backwards compatibility.

    LocalProxy will forward to Flask or Pylons own request objects depending
    on the output of `_get_request` (which essentially calls
    `is_flask_request`) and at the same time provide all objects methods to be
    able to interact with them transparently.
    '''

    @property
    def params(self):
        u''' Special case as Pylons' request.params is used all over the place.
        All new code meant to be run just in Flask (eg views) should always
        use request.args
        '''

def _get_c():
    if is_flask_request():
        return flask.g
    else:
        return pylons.c

def _get_session():
    if is_flask_request():
        return flask.session
    else:
        return pylons.session

local = Local()

# This a proxy to the bounded config object
local(u'config')

# Thread-local safe objects
config = local.config = CKANConfig()

# Proxies to already thread-local safe objects
request = CKANRequest(_get_request)
# Provide a `c`  alias for `g` for backwards compatibility
g = c = LocalProxy(_get_c)
session = LocalProxy(_get_session)

truthy = frozenset([u'true', u'yes', u'on', u'y', u't', u'1'])
falsy = frozenset([u'false', u'no', u'off', u'n', u'f', u'0'])

def asbool(obj):
    if isinstance(obj, six.string_types):
        obj = obj.strip().lower()
        if obj in truthy:
            return True
        elif obj in falsy:
            return False
        else:
            raise ValueError(u"String is not true/false: {}".format(obj))
    return bool(obj)

def asint(obj):
    try:
        return int(obj)
    except (TypeError, ValueError):
        raise ValueError(u"Bad integer value: {}".format(obj))

def aslist(obj, sep=None, strip=True):
    if isinstance(obj, six.string_types):
        lst = obj.split(sep)
        if strip:
            lst = [v.strip() for v in lst]
        return lst
    elif isinstance(obj, (list, tuple)):
        return obj
    elif obj is None:
        return []
    else:
        return [obj]


try:
        pylons.request.environ
        pylons_request_available = True
    except TypeError:
        pylons_request_available = False

# This file contains commonly used parts of external libraries. The idea is
# to help in removing helpers from being used as a dependency by many files
# but at the same time making it easy to change for example the json lib
# NOTE:  This file is specificaly created for
# from ckan.common import x, y, z to be allowed

from collections import MutableMapping

import flask
import six

from werkzeug.local import Local, LocalProxy

from flask_babel import (gettext as flask_ugettext,
                         ngettext as flask_ungettext)

import simplejson as json

if six.PY2:
    import pylons
    from pylons.i18n import (ugettext as pylons_ugettext,
                             ungettext as pylons_ungettext)
    from pylons import response

current_app = flask.current_app

def is_flask_request():
    u'''
    A centralized way to determine whether we are in the context of a
    request being served by Flask or Pylons
    '''
    if six.PY3:
        return True

    return (flask.request and
            (flask.request.environ.get(u'ckan.app') == u'flask_app' or
             not pylons_request_available))

def streaming_response(
        data, mimetype=u'application/octet-stream', with_context=False):
    iter_data = iter(data)
    if is_flask_request():
        # Removal of context variables for pylon's app is prevented
        # inside `pylons_app.py`. It would be better to decide on the fly
        # whether we need to preserve context, but it won't affect performance
        # in any visible way and we are going to get rid of pylons anyway.
        # Flask allows to do this in easy way.
        if with_context:
            iter_data = flask.stream_with_context(iter_data)
        resp = flask.Response(iter_data, mimetype=mimetype)
    else:
        response.app_iter = iter_data
        resp = response.headers['Content-type'] = mimetype
    return resp

def ugettext(*args, **kwargs):
    return flask_ugettext(*args, **kwargs)

_ = ugettext

def ungettext(*args, **kwargs):
    if is_flask_request():
        return flask_ungettext(*args, **kwargs)
    else:
        return pylons_ungettext(*args, **kwargs)

class CKANConfig(MutableMapping):
    u'''Main CKAN configuration object

    This is a dict-like object that also proxies any changes to the
    Flask and Pylons configuration objects.

    The actual `config` instance in this module is initialized in the
    `load_environment` method with the values of the ini file or env vars.

    '''

    def __init__(self, *args, **kwargs):
        self.store = dict()
        self.update(dict(*args, **kwargs))

    def __getitem__(self, key):
        return self.store[key]

    def __iter__(self):
        return iter(self.store)

    def __len__(self):
        return len(self.store)

    def __repr__(self):
        return self.store.__repr__()

    def copy(self):
        return self.store.copy()

    def clear(self):
        self.store.clear()

        try:
            flask.current_app.config.clear()
        except RuntimeError:
            pass

        if six.PY2:
            try:
                pylons.config.clear()
                # Pylons set this default itself
                pylons.config[u'lang'] = None
            except TypeError:
                pass

    def __setitem__(self, key, value):
        self.store[key] = value
        try:
            flask.current_app.config[key] = value
        except RuntimeError:
            pass

        if six.PY2:
            try:
                pylons.config[key] = value
            except TypeError:
                pass

    def __delitem__(self, key):
        del self.store[key]
        try:
            del flask.current_app.config[key]
        except RuntimeError:
            pass

        if six.PY2:
            try:
                del pylons.config[key]
            except TypeError:
                pass

def _get_request():
    if is_flask_request():
        return flask.request
    else:
        return pylons.request

class CKANRequest(LocalProxy):
    u'''Common request object

    This is just a wrapper around LocalProxy so we can handle some special
    cases for backwards compatibility.

    LocalProxy will forward to Flask or Pylons own request objects depending
    on the output of `_get_request` (which essentially calls
    `is_flask_request`) and at the same time provide all objects methods to be
    able to interact with them transparently.
    '''

    @property
    def params(self):
        u''' Special case as Pylons' request.params is used all over the place.
        All new code meant to be run just in Flask (eg views) should always
        use request.args
        '''
        try:
            return super(CKANRequest, self).params
        except AttributeError:
            return self.args

def _get_c():
    if is_flask_request():
        return flask.g
    else:
        return pylons.c

def _get_session():
    if is_flask_request():
        return flask.session
    else:
        return pylons.session

local = Local()

# This a proxy to the bounded config object
local(u'config')

# Thread-local safe objects
config = local.config = CKANConfig()

# Proxies to already thread-local safe objects
request = CKANRequest(_get_request)
# Provide a `c`  alias for `g` for backwards compatibility
g = c = LocalProxy(_get_c)
session = LocalProxy(_get_session)

truthy = frozenset([u'true', u'yes', u'on', u'y', u't', u'1'])
falsy = frozenset([u'false', u'no', u'off', u'n', u'f', u'0'])

def asbool(obj):
    if isinstance(obj, six.string_types):
        obj = obj.strip().lower()
        if obj in truthy:
            return True
        elif obj in falsy:
            return False
        else:
            raise ValueError(u"String is not true/false: {}".format(obj))
    return bool(obj)

def asint(obj):
    try:
        return int(obj)
    except (TypeError, ValueError):
        raise ValueError(u"Bad integer value: {}".format(obj))

def aslist(obj, sep=None, strip=True):
    if isinstance(obj, six.string_types):
        lst = obj.split(sep)
        if strip:
            lst = [v.strip() for v in lst]
        return lst
    elif isinstance(obj, (list, tuple)):
        return obj
    elif obj is None:
        return []
    else:
        return [obj]


"""
@brief      test log(time=2s)
"""
import os
import unittest
from pyquickhelper.loghelper import fLOG
from pyquickhelper.pycode import fix_tkinter_issues_virtualenv, ExtTestCase
from pyensae.finance.astock import StockPrices

class TestStockGraphOHLC(ExtTestCase):

    tick = 'MSFT'
    source = 'yahoo_new'

fLOG(
            __file__,
            self._testMethodName,
            OutputPrint=__name__ == "__main__")

        fix_tkinter_issues_virtualenv()

        from matplotlib import pyplot as plt

        cache = os.path.abspath(os.path.split(__file__)[0])
        cache = os.path.join(cache, "temp_cache_ohlc")
        stock = StockPrices(TestStockGraphOHLC.tick,
                            folder=cache, url=TestStockGraphOHLC.source)

        fig, ax = plt.subplots(figsize=(16, 8))
        ax = stock.plot(ax=ax, field="ohlc")
        img = os.path.abspath(
            os.path.join(
                os.path.split(__file__)[0],
                "temp_image_ohlc.png"))
        if os.path.exists(img):
            os.remove(img)
        fig.savefig(img)
        plt.close('all')
        self.assertExists(img)

if __name__ == "__main__":
    unittest.main()


"""
@brief      test log(time=2s)
"""
import os
import unittest
from pyquickhelper.loghelper import fLOG
from pyquickhelper.pycode import fix_tkinter_issues_virtualenv, ExtTestCase
from pyensae.finance.astock import StockPrices

class TestStockGraphOHLC(ExtTestCase):

    tick = 'MSFT'
    source = 'yahoo_new'

    def test_graph_ohlc(self):
        fLOG(
            __file__,
            self._testMethodName,
            OutputPrint=__name__ == "__main__")

        fix_tkinter_issues_virtualenv()

        from matplotlib import pyplot as plt

        cache = os.path.abspath(os.path.split(__file__)[0])
        cache = os.path.join(cache, "temp_cache_ohlc")
        stock = StockPrices(TestStockGraphOHLC.tick,
                            folder=cache, url=TestStockGraphOHLC.source)

        fig, ax = plt.subplots(figsize=(16, 8))
        ax = stock

        img = os.path.abspath(
            os.path.join(
                os.path.split(__file__)[0],
                "temp_image_ohlc.png"))
        if os.path.exists(img):
            os.remove(img)
        fig.savefig(img)
        plt.close('all')
        self.assertExists(img)

if __name__ == "__main__":
    unittest.main()


def finalize_options(self):
        # have to finalize 'plat_name' before 'bdist_base'

"""distutils.command.bdist

Implements the Distutils 'bdist' command (create a built [binary]
distribution)."""

import os
from distutils.core import Command
from distutils.errors import *
from distutils.util import get_platform

def show_formats():
    """Print list of available formats (arguments to "--format" option).
    """
    from distutils.fancy_getopt import FancyGetopt
    formats = []
    for format in bdist.format_commands:
        formats.append(("formats=" + format, None,
                        bdist.format_command[format][1]))
    pretty_printer = FancyGetopt(formats)
    pretty_printer.print_help("List of available distribution formats:")

class bdist(Command):

    description = "create a built (binary) distribution"

    user_options = [('bdist-base=', 'b',
                     "temporary directory for creating built distributions"),
                    ('plat-name=', 'p',
                     "platform name to embed in generated filenames "
                     "(default: %s)" % get_platform()),
                    ('formats=', None,
                     "formats for distribution (comma-separated list)"),
                    ('dist-dir=', 'd',
                     "directory to put final built distributions in "
                     "[default: dist]"),
                    ('skip-build', None,
                     "skip rebuilding everything (for testing/debugging)"),
                   ]

    boolean_options = ['skip-build']

    help_options = [
        ('help-formats', None,
         "lists available distribution formats", show_formats),
        ]

    # The following commands do not take a format option from bdist
    no_format_option = ('bdist_rpm',)

    # This won't do in reality: will need to distinguish RPM-ish Linux,
    default_format = {'posix': 'gztar',
                      'nt': 'zip'}

    # Establish the preferred order (for the --help-formats option).
    format_commands = ['rpm', 'gztar', 'bztar', 'ztar', 'tar',
                       'wininst', 'zip', 'msi']

    # And the real information.
    format_command = {'rpm':   ('bdist_rpm',  "RPM distribution"),
                      'gztar': ('bdist_dumb', "gzip'ed tar file"),
                      'bztar': ('bdist_dumb', "bzip2'ed tar file"),
                      'ztar':  ('bdist_dumb', "compressed tar file"),
                      'tar':   ('bdist_dumb', "tar file"),
                      'wininst': ('bdist_wininst',
                                  "Windows executable installer"),
                      'zip':   ('bdist_dumb', "ZIP file"),
                      'msi':   ('bdist_msi',  "Microsoft Installer")
                      }

    def initialize_options(self):
        self.bdist_base = None
        self.plat_name = None
        self.formats = None
        self.dist_dir = None
        self.skip_build = 0

if self.plat_name is None:
            if self.skip_build:
                self.plat_name = get_platform()
            else:
                self.plat_name = self.get_finalized_command('build').plat_name

        # 'bdist_base' -- parent of per-built-distribution-format
        # temporary directories (eg. we'll probably have
        if self.bdist_base is None:
            build_base = self.get_finalized_command('build').build_base
            self.bdist_base = os.path.join(build_base,
                                           'bdist.' + self.plat_name)

        self.ensure_string_list('formats')
        if self.formats is None:
            try:
                self.formats = [self.default_format[os.name]]
            except KeyError:
                raise DistutilsPlatformError(
                      "don't know how to create built distributions "
                      "on platform %s" % os.name)

        if self.dist_dir is None:
            self.dist_dir = "dist"

    def run(self):
        # Figure out which sub-commands we need to run.
        commands = []
        for format in self.formats:
            try:
                commands.append(self.format_command[format][0])
            except KeyError:
                raise DistutilsOptionError("invalid format '%s'" % format)

        # Reinitialize and run each command.
        for i in range(len(self.formats)):
            cmd_name = commands[i]
            sub_cmd = self.reinitialize_command(cmd_name)
            if cmd_name not in self.no_format_option:
                sub_cmd.format = self.formats[i]

            # If we're going to need to run this command again, tell it to
            # keep its temporary files around so subsequent runs go faster.
            if cmd_name in commands[i+1:]:
                sub_cmd.keep_temp = 1
            self.run_command(cmd_name)


self.bdist_base = None
        self.plat_name = None
        self.formats = None
        self.dist_dir = None
        self.skip_build = 0

"""distutils.command.bdist

Implements the Distutils 'bdist' command (create a built [binary]
distribution)."""

import os
from distutils.core import Command
from distutils.errors import *
from distutils.util import get_platform

def show_formats():
    """Print list of available formats (arguments to "--format" option).
    """
    from distutils.fancy_getopt import FancyGetopt
    formats = []
    for format in bdist.format_commands:
        formats.append(("formats=" + format, None,
                        bdist.format_command[format][1]))
    pretty_printer = FancyGetopt(formats)
    pretty_printer.print_help("List of available distribution formats:")

class bdist(Command):

    description = "create a built (binary) distribution"

    user_options = [('bdist-base=', 'b',
                     "temporary directory for creating built distributions"),
                    ('plat-name=', 'p',
                     "platform name to embed in generated filenames "
                     "(default: %s)" % get_platform()),
                    ('formats=', None,
                     "formats for distribution (comma-separated list)"),
                    ('dist-dir=', 'd',
                     "directory to put final built distributions in "
                     "[default: dist]"),
                    ('skip-build', None,
                     "skip rebuilding everything (for testing/debugging)"),
                   ]

    boolean_options = ['skip-build']

    help_options = [
        ('help-formats', None,
         "lists available distribution formats", show_formats),
        ]

    # The following commands do not take a format option from bdist
    no_format_option = ('bdist_rpm',)

    # This won't do in reality: will need to distinguish RPM-ish Linux,
    default_format = {'posix': 'gztar',
                      'nt': 'zip'}

    # Establish the preferred order (for the --help-formats option).
    format_commands = ['rpm', 'gztar', 'bztar', 'ztar', 'tar',
                       'wininst', 'zip', 'msi']

    # And the real information.
    format_command = {'rpm':   ('bdist_rpm',  "RPM distribution"),
                      'gztar': ('bdist_dumb', "gzip'ed tar file"),
                      'bztar': ('bdist_dumb', "bzip2'ed tar file"),
                      'ztar':  ('bdist_dumb', "compressed tar file"),
                      'tar':   ('bdist_dumb', "tar file"),
                      'wininst': ('bdist_wininst',
                                  "Windows executable installer"),
                      'zip':   ('bdist_dumb', "ZIP file"),
                      'msi':   ('bdist_msi',  "Microsoft Installer")
                      }

    def initialize_options(self):

    def finalize_options(self):
        # have to finalize 'plat_name' before 'bdist_base'
        if self.plat_name is None:
            if self.skip_build:
                self.plat_name = get_platform()
            else:
                self.plat_name = self.get_finalized_command('build').plat_name

        # 'bdist_base' -- parent of per-built-distribution-format
        # temporary directories (eg. we'll probably have
        if self.bdist_base is None:
            build_base = self.get_finalized_command('build').build_base
            self.bdist_base = os.path.join(build_base,
                                           'bdist.' + self.plat_name)

        self.ensure_string_list('formats')
        if self.formats is None:
            try:
                self.formats = [self.default_format[os.name]]
            except KeyError:
                raise DistutilsPlatformError(
                      "don't know how to create built distributions "
                      "on platform %s" % os.name)

        if self.dist_dir is None:
            self.dist_dir = "dist"

    def run(self):
        # Figure out which sub-commands we need to run.
        commands = []
        for format in self.formats:
            try:
                commands.append(self.format_command[format][0])
            except KeyError:
                raise DistutilsOptionError("invalid format '%s'" % format)

        # Reinitialize and run each command.
        for i in range(len(self.formats)):
            cmd_name = commands[i]
            sub_cmd = self.reinitialize_command(cmd_name)
            if cmd_name not in self.no_format_option:
                sub_cmd.format = self.formats[i]

            # If we're going to need to run this command again, tell it to
            # keep its temporary files around so subsequent runs go faster.
            if cmd_name in commands[i+1:]:
                sub_cmd.keep_temp = 1
            self.run_command(cmd_name)


"""distutils.command.bdist

Implements the Distutils 'bdist' command (create a built [binary]
distribution)."""

import os
from distutils.core import Command
from distutils.errors import *
from distutils.util import get_platform

def show_formats():
    """Print list of available formats (arguments to "--format" option).
    """
    from distutils.fancy_getopt import FancyGetopt
    formats = []
    for format in bdist.format_commands:
        formats.append(("formats=" + format, None,
                        bdist.format_command[format][1]))
    pretty_printer = FancyGetopt(formats)
    pretty_printer.print_help("List of available distribution formats:")

class bdist(Command):

    description = "create a built (binary) distribution"

    user_options = [('bdist-base=', 'b',
                     "temporary directory for creating built distributions"),
                    ('plat-name=', 'p',
                     "platform name to embed in generated filenames "
                     "(default: %s)" % get_platform()),
                    ('formats=', None,
                     "formats for distribution (comma-separated list)"),
                    ('dist-dir=', 'd',
                     "directory to put final built distributions in "
                     "[default: dist]"),
                    ('skip-build', None,
                     "skip rebuilding everything (for testing/debugging)"),
                   ]

    boolean_options = ['skip-build']

    help_options = [
        ('help-formats', None,
         "lists available distribution formats", show_formats),
        ]

    # The following commands do not take a format option from bdist
    no_format_option = ('bdist_rpm',)

    # This won't do in reality: will need to distinguish RPM-ish Linux,
    default_format = {'posix': 'gztar',
                      'nt': 'zip'}

    # Establish the preferred order (for the --help-formats option).
    format_commands = ['rpm', 'gztar', 'bztar', 'ztar', 'tar',
                       'wininst', 'zip', 'msi']

    # And the real information.
    format_command = {'rpm':   ('bdist_rpm',  "RPM distribution"),
                      'gztar': ('bdist_dumb', "gzip'ed tar file"),
                      'bztar': ('bdist_dumb', "bzip2'ed tar file"),
                      'ztar':  ('bdist_dumb', "compressed tar file"),
                      'tar':   ('bdist_dumb', "tar file"),
                      'wininst': ('bdist_wininst',
                                  "Windows executable installer"),
                      'zip':   ('bdist_dumb', "ZIP file"),
                      'msi':   ('bdist_msi',  "Microsoft Installer")
                      }

    def initialize_options(self):
        self.bdist_base = None
        self.plat_name = None
        self.formats = None
        self.dist_dir = None
        self.skip_build = 0

    def finalize_options(self):
        # have to finalize 'plat_name' before 'bdist_base'
        if self.plat_name is None:
            if self.skip_build:
                self.plat_name = get_platform()
            else:
                self.plat_name = self.get_finalized_command('build').plat_name

        # 'bdist_base' -- parent of per-built-distribution-format
        # temporary directories (eg. we'll probably have
        if self.bdist_base is None:
            build_base = self.get_finalized_command('build').build_base
            self.bdist_base = os.path.join(build_base,
                                           'bdist.' + self.plat_name)

        self.ensure_s

        if self.formats is None:
            try:
                self.formats = [self.default_format[os.name]]
            except KeyError:
                raise DistutilsPlatformError(
                      "don't know how to create built distributions "
                      "on platform %s" % os.name)

        if self.dist_dir is None:
            self.dist_dir = "dist"

    def run(self):
        # Figure out which sub-commands we need to run.
        commands = []
        for format in self.formats:
            try:
                commands.append(self.format_command[format][0])
            except KeyError:
                raise DistutilsOptionError("invalid format '%s'" % format)

        # Reinitialize and run each command.
        for i in range(len(self.formats)):
            cmd_name = commands[i]
            sub_cmd = self.reinitialize_command(cmd_name)
            if cmd_name not in self.no_format_option:
                sub_cmd.format = self.formats[i]

            # If we're going to need to run this command again, tell it to
            # keep its temporary files around so subsequent runs go faster.
            if cmd_name in commands[i+1:]:
                sub_cmd.keep_temp = 1
            self.run_command(cmd_name)