Lailin 4 lat temu
commit
5d457d72ae

+ 105 - 0
.gitignore

@@ -0,0 +1,105 @@
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+#  Usually these files are written by a python script from a template
+#  before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+.hypothesis/
+.pytest_cache/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# pyenv
+.python-version
+.idea/
+# celery beat schedule file
+celerybeat-schedule
+workspace.xml
+# SageMath parsed files
+*.sage.py
+.idea/workspace.xml
+# Environments
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+~$fanyi.xlsx

+ 173 - 0
ConversionToChineseKey.py

@@ -0,0 +1,173 @@
+# encoding: utf-8
+"""
+把翻译文件 全部转换为新的类型文件 "中文" = "Chinese"
+1、转换源码翻译 字段为"NSLocalizedString(@"key", @"Chinese")"
+2、转换翻译文档
+"""
+
+import os
+import os.path
+import re
+import time
+import TranslationProcess
+import CoverProcess
+
+global tmpStoreZhTrans, tmpStoreEnTrans, tmpStoreHKTrans, tmpNoTransKeys, tmpNotNeedTransKeys, fileCount
+tmpStoreZhTrans = dict() # 中文翻译 对应key保存字典
+tmpStoreEnTrans = dict() # 英文翻译
+tmpStoreHKTrans = dict() # 繁体
+fileCount = 1
+
+tmpNotNeedTransKeys = dict() # 不需要翻译的字段
+tmpNoTransKeys = dict() # 没有翻译的字段
+
+# 读取翻译文件
+def readTransformFile():
+	global tmpStoreZhTrans, tmpNotNeedTransKeys
+	TranslationProcess.readLanguageFilesToTmp()
+	for zh in TranslationProcess.zhHansFile:
+		key, value = removeTheTranslateLine(zh)
+		if len(key) > 0:
+			tmpStoreZhTrans[key] = value
+
+	with open(CoverProcess.savePath + "/NotNeedTrans.txt", "r", encoding="utf-8") as tFile:
+		datas = tFile.read().splitlines()
+		for str in datas:
+			tmpNotNeedTransKeys[str] = "1"
+
+# 转换翻译文件
+def switchTransformFile():
+	global tmpStoreEnTrans, tmpStoreHKTrans, tmpStoreZhTrans
+	readTransformFile()
+
+	for en in TranslationProcess.enFile:
+		key, value = removeTheTranslateLine(en)
+		if len(key) > 0:
+			zhKey = tmpStoreZhTrans.get(key)
+			if zhKey == None:
+				zhKey = key
+			tmpStoreEnTrans[zhKey] = value
+
+	for hk in TranslationProcess.zhHKFile:
+		key, value = removeTheTranslateLine(hk)
+		if len(key) > 0:
+			zhKey = tmpStoreZhTrans.get(key)
+			if zhKey == None:
+				zhKey = key
+			tmpStoreHKTrans[zhKey] = value
+
+	print("fileOk")
+	zhTrans = dict()
+	for zh in TranslationProcess.zhHansFile:
+		key, value = removeTheTranslateLine(zh)
+		if len(key) > 0:
+			zhKey = tmpStoreZhTrans.get(key)
+			if zhKey == None:
+				zhKey = key
+			zhTrans[zhKey] = value
+
+	#writeToPath(zhTrans, TranslationProcess.zhHansPath)
+	#writeToPath(tmpStoreHKTrans, TranslationProcess.zhHantPath)
+	#writeToPath(tmpStoreHKTrans, TranslationProcess.zhHKPath)
+	#writeToPath(tmpStoreEnTrans, TranslationProcess.enPath)
+
+# 写入文件
+def writeToPath(file = {}, path = ""):
+	content = ""
+
+	header = "/*\nLocalizable.strings\nYunPOS\n\nCreated by Vyron_Lee on 2018/11/22.\nCopyright © 2018 莫艳. All rights reserved.\n*/\n"
+	content += header
+
+	for key in file.keys():
+		content += ("\"" + key + "\" = \"" + file.get(key) + "\";\n")
+
+	with open(path, "w", encoding="utf-8") as tFile:
+		tFile.write(content)
+
+# 去除 引号,分号,空格,返回key,value 值
+def removeTheTranslateLine(line = ""):
+	return TranslationProcess.removeTheTranslateLine(line)
+
+# 查找文件中 翻译
+def findTheLocalizedString(filePath):
+	global tmpStoreZhTrans, tmpNoTransKeys, fileCount
+	print("\r处理第 " + str(fileCount) + " 文件")
+	fileCount += 1
+
+	tmpFile = ""
+	hasChange = False
+	with open(filePath, 'r', encoding="utf-8") as mFile:
+		datas = mFile.read().splitlines()
+		for line in datas:
+			hasLocalized = CoverProcess.regularLocalizedKey.findall(line)
+			for localizedString in hasLocalized:
+				key = getLocalizedKey(localizedString)
+				if len(key) > 0:
+					value = tmpStoreZhTrans.get(key)
+					if value != None:
+						#replace = "@\"" + value + "\".localized"
+						#line = line.replace(localizedString, replace)
+						#hasChange = True
+						print("**翻译了")
+					elif tmpNotNeedTransKeys.get(key) != None:
+						print("***不需要翻译")
+					else:
+						tmpNoTransKeys[key] = ""
+						print("*****未找到翻译的:" + key)
+
+			tmpFile += (line + "\n")
+
+	if hasChange == True and 0:
+		with open(filePath, "w", encoding="utf-8") as changeFile:
+			changeFile.write(tmpFile)
+
+# 提取代码中翻译的key值 @"".localized
+def getLocalizedKey(str = ""):
+	str = str.strip(".localized")
+	str = str.strip("@")
+	str = str.strip("\"")
+	return str
+
+# 提取代码中翻译的key值 NSLocalizedString(@"", @"")
+def getNSLocalizedStringKey(str = ""):
+	str = str.strip("NSLocalizedString")
+	str = str.strip("(")
+	str = str.strip(")")
+	result = str.split(",")
+	key = result[0]
+	key = key.strip()
+	key = key.strip("@")
+	key = key.strip("\"")
+	return key
+
+# 遍历 path 文件夹下所有 .m 文件
+def beginSearch(path):
+	for root, dirs, files in os.walk(path, topdown=True):
+		if len(files) > 0:
+			for fileName in files:
+				if os.path.splitext(fileName)[1] == ".m":
+					realPath = root + "/" + fileName
+					findTheLocalizedString(realPath)
+
+		# if len(dirs) > 0:
+		# 	for subPath in dirs:
+		# 		realPath = root + "/" + subPath
+		# 		beginSearch(realPath)
+
+if __name__ == "__main__":
+	project = CoverProcess.dirPath
+
+	print("begin!")
+	# 翻译转换
+	#switchTransformFile()
+
+	# 提取翻译
+	readTransformFile()
+	beginSearch(project)
+
+	if len(tmpNoTransKeys) > 0:
+		fileName = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
+		CoverProcess.saveSetInPath(tmpNoTransKeys.keys(), CoverProcess.savePath + "/" + fileName + ".txt")
+	print("end!")
+
+	# 保存未翻译的字段

Plik diff jest za duży
+ 1 - 0
CoverProcess.py


+ 156 - 0
Translate/NotNeedTrans.txt

@@ -0,0 +1,156 @@
+        手机
+M月d日 HH:mm
+%ld年前
+线上订单发货蓝
+原单(123)
+货品录入数量不能超过9999
+货品录入数量不能小于-9999
+%@: 0款 0%@
+已选3人
+合计2
+2月22日 星期五
+王尼玛
+微信支付微信支付微信支付
+YB001232-条纹格子衬衫大衣
+1件
+白色/0/XXL
+1000人
+销售类型_正常销售
+销售类型_赠送
+销售类型_内购
+销售类型_团购
+销售类型_直销
+销售类型_预售自提
+销售类型_预售直发
+销售类型_退换(有票)
+销售类型_退换(无票)
+销售类型_定金单
+销售类型_引用定金单
+销售类型_手工补单
+销售类型_门店自提
+销售类型_向右
+跳转单选营业员/多选营业员自动分配比例 code=100
+跳转主辅营业员->需要计算促销 code=101
+跳转主辅营业员->不需要计算促销 code=102
+有效日期:2017.12.12~2017有效日期:2017.12.12~2017有效日期:2017.12.12~2017有效日期:2017.12.12~2017有效日期:2017.12.12~2017有效日期:2017.12.12~2017有效日期:2017.12.12~2017有效日期:2017.12.12~2017
+备注:正价店、天河城店、百佳店三个店这周备注:正价店、天河城店、百佳店三个店这周备注:正价店、天河城店、百佳店三个店这周备注:正价店、天河城店、百佳店三个店这周备注:正价店、天河城店、百佳店三个店这周备注:正价店、天河城店、百佳店三个店这周
+折扣券(0)
+元不可用
+小白
+请联系彭勇!
+销售小票尺码排版
+尺寸竖排
+尺寸横排
+打印机1
+tableView高度自适应高度
+北京
+北京市
+东城区
+秋冬套头羊绒毛衣
+列表
+ios手机
+丽晶
+配货时间:2017-06-28 09:42
+物流公司:申通快运
+%ld件
+收件人/联系电话:JOYLIU/18620851875
+备注:不要发错尺码
+2017秋冬高腰黑色紧身加绒高弹力大体长裤
+C17E127N;N01黑色;M;90CM
+库存23
+2800件
+寄 件 码:3645686796967
+123件
+2件
+收件人:JOYLIU
+联系电话:18620851875
+地址:广东省广州番禺天安节能科技园15号楼202室
+备注:卖家
+货号:C17E123535467
+品名:长袖衬衫
+物流单号数(12)
+10单
+客户备注:不要发错尺码
+卖家备注:卖家
+客服备注:备注
+请求参数不完整
+没有 子模块ID
+%d款 %d件
+在请求数据
+条码录入数量范围-99999 ~ 999999
+最大输入11位
+36666件
+%@库存不足,可用库存为%ld件,\n确定录入吗?
+保存暂存
+ios平板
+单据编号11
+单据日期11
+档口11
+档口地址11
+档口电话11
+开单人11
+客户111
+备注111
+应付111
+实付111
+本单欠款111
+客户总欠款11
+%ld-米白
+货号+名字
+内长11
+结算价1
+金额1
+001-红色
+佳博打印机(80mm)
+货号:C17E123535467
+测试标题
+品名:长袖衬衫
+显示日志
+返回主登录界面
+%@:王晓军、Peter
+崩溃日志
+压测
+打印日志
+关闭快速登陆
+测试快捷操作
+当前语言:%@
+崩溃列表
+繁体
+英文
+中文
+选中打开日志信息
+点击 账号 可切换账号/返回主登录页面\n*目前只支持 %@
+清除崩溃日志
+请选择匹配公司
+网络监控
+开启快速登陆
+请选择用户
+更改语言
+选择切换语言
+流量共%.1lfMB
+中崎AB-341M(110mm)
+佳博80250i蓝牙版(80mm)
+芝柯HDT334(110mm)
+mq分享
+网易
+百度
+组头
+原因111
+错误
+请求进店人数服务器返回数据结构不一致:%@
+测试
+快速测试页面
+非会员
+扫码录入
+已扫描条码总数:%ld
+数据未保存,返回将丢失,确定返回吗?
+销售小票打印尺码
+库位:测试库位内容
+¥
+验收测试请设置系统语言!\n当前语言:%@
+操作数据库失败:没有传moduleModel
+操作数据库失败:没有moduleId
+插入数据库失败:没有ID
+查询数据库失败:没有ID
+操作数据库失败:没有moduleType
+仓库零售单(无尺码)

BIN
Translate/fanyi.xlsx


BIN
Translate/settings.jar


+ 4 - 0
Translate/translateLog.txt

@@ -0,0 +1,4 @@
+线上
+自提
+直发
+不能使用券

+ 291 - 0
TranslationProcess.py

@@ -0,0 +1,291 @@
+"""
+	整理翻译文件,通过匹配翻译的excel表格,写入未翻译的字段
+"""
+
+import CoverProcess as func
+import langconv
+
+# 读取 excel
+import xlrd
+from xlrd.book import Book
+from xlrd.sheet import Sheet
+from xlrd.sheet import Cell
+
+"""
+基础配置文件
+:param excellPath: 翻译excel表格路径
+:param translationSheetName: 翻译表单名称
+"""
+isSave = True
+excelPath = func.savePath + "/fanyi.xlsx"
+translationSheetName = "翻译登记表" # 历史翻译【所有】/ 翻译登记表
+baseLanguagePath = func.projectPath + "/YunPOS-iOS/YunPOS/language"
+
+# 翻译文件路径
+zhTransFilePath = func.savePath + "/aa.txt"
+
+# 翻译文件路径
+zhHansPath = baseLanguagePath + "/zh-Hans.lproj/Localizable.strings"
+zhHantPath = baseLanguagePath + "/zh-Hant.lproj/Localizable.strings"
+zhHKPath = baseLanguagePath + "/zh-HK.lproj/Localizable.strings"
+enPath = baseLanguagePath + "/en.lproj/Localizable.strings"
+
+# excel 暂存
+global tmpExcelFile
+tmpExcelFile = None
+tmpExcelIndex = dict() # excel 索引
+
+# 需要翻译的字段列表
+global zhNeedList
+zhNeedList = []
+
+# 文件存储
+global zhHansFile, zhHantFile, zhHKFile, enFile
+global tmpStoreZhTrans
+zhHansFile = [] # 简体中文
+tmpStoreZhTrans = dict() # 简体中文
+
+zhHantFile = [] # 繁体中文
+zhHKFile = []   # 繁体中文
+enFile = []     # 英文
+
+global tmpNotNeedTransKeys
+tmpNotNeedTransKeys = dict() # 不需要翻译的字段
+
+# 判读 是否已经翻译了
+# return: True 已经存在翻译;False 没有存在翻译;
+def matchExcelTranslationToStr(aRow = []):
+	zhValue = aRow[0]
+	zhResult = func.findWordInFile(zhValue)
+	if zhResult:
+		for zh in zhResult:
+			if "=" in zh:
+				return True
+	return False
+
+# excel 相关
+# 读取excel表格/获取翻译sheet表
+def readExcelFile(excelPath, sheetName):
+	excel = xlrd.open_workbook(excelPath)
+	translation = excel.sheet_by_name(sheetName)
+	return translation;
+
+# 读入翻译文件至 缓存中
+def readLanguageFilesToTmp():
+	global zhHansFile, zhHantFile, zhHKFile, enFile
+	global tmpStoreZhTrans, tmpNotNeedTransKeys
+
+	# 中文简体
+	zhHansFile = readFileNoReturn(zhHansPath)
+	# 中文繁体
+	zhHantFile = readFileNoReturn(zhHantPath)
+	# 中文繁体
+	zhHKFile = readFileNoReturn(zhHKPath)
+	# 英文
+	enFile = readFileNoReturn(enPath)
+
+	# 中文简体暂存为 Dict,方便查询是否已经翻译了
+	for zh in zhHansFile:
+		key, value = removeTheTranslateLine(zh)
+		if len(key) > 0:
+			tmpStoreZhTrans[key] = value
+
+	try:
+		with open(func.savePath + "/NotNeedTrans.txt", "r", encoding="utf-8") as tFile:
+			datas = tFile.read().splitlines()
+			for str in datas:
+				tmpNotNeedTransKeys[str] = "1"
+	except IOError:
+		print("File is not accessible.")
+
+# 去除 引号,分号,空格,返回key,value 值
+def removeTheTranslateLine(line = ""):
+	if "=" not in line:
+		return "", ""
+	line = line.split(";")[0]
+
+	result = line.split("=")
+
+	tmpKey = ""
+	tmpValue = ""
+	if len(result) == 4:
+		# 包含 = 的翻译
+		tmpKey = result[0] + "=" + result[1]
+		tmpValue = result[2] + "=" + result[3]
+	elif len(result) == 3:
+		tmpKey = result[0]
+		tmpValue = result[1] + "=" + result[2]
+	elif len(result) == 2:
+		tmpKey = result[0]
+		tmpValue = result[1]
+	else:
+		print("error")
+
+	key = tmpKey.strip()
+	value = tmpValue.strip()
+	key = key.strip("\"")
+	value = value.strip("\"")
+	return key, value
+
+# 读取文件,并去除换行符号
+def readFileNoReturn(path):
+	with open(path) as file:
+		datas = file.read().splitlines()
+		return datas
+	return None
+
+
+# 读取需要翻译的文件
+def readNeedTranslationFile():
+	global zhNeedList
+
+	if True:
+		tmpFile = open(zhTransFilePath, 'r', encoding="utf-8")
+		zhNeedList = list(tmpFile)
+		tmpFile.close()
+	else:
+		# 读取中文翻译文件
+		func.readZhLocalizedFile()
+
+		func.isReplace = True
+		# 筛选需要翻译的数据
+		subTranslateStr, subBeTranslateStr = func.search(func.dirPath)
+		zhNeedList = subTranslateStr
+
+# 去除首尾可能存在的空格
+def dealStartEndSpace(str = ""):
+	str = str.strip()
+	return str
+
+# 去除翻译文字\n 和 "
+def dealStartEndChar(str = ""):
+	str = str.strip("\n")
+	str = str.strip("\"")
+	return str
+
+# 转换简体到繁体
+def chsToCht(line):
+	line = langconv.Converter('zh-hant').convert(line)
+	line.encode('utf-8')
+	return line
+
+# 生成翻译文件 line
+def createTranslateLine(zh, translate):
+	return "\""+zh+"\""+" = "+"\""+translate+"\";";
+
+"""
+# 查看字段是否在excel中是否已经翻译
+# return:   成功 返回 中文,英文,繁体
+#           失败 Null
+"""
+def searchZhTranslationInExcel(zh = "", excel = excelPath, sheet = translationSheetName):
+	global tmpExcelFile, tmpExcelIndex
+	# 读入excel文件
+	if tmpExcelFile == None:
+		tmpExcelFile = readExcelFile(excel, sheet)
+		tmpExcelIndex = createExcelIndexDict(tmpExcelFile)
+
+	indexStr = tmpExcelIndex.get(zh)
+	if indexStr != None:
+		index = int(indexStr)
+
+		row = tmpExcelFile.row_values(index)
+		"""
+		if (index > 1 and index < 2644) or (index > 2953):
+			print(str(index) + "--匹配成功")
+			enStr = dealStartEndSpace(row[1])
+			if len(enStr) > 0:
+				return zh, enStr, chsToCht(zh)
+			else:
+				print("--录入,但是未翻译:" + zh)
+		"""
+		print(str(index) + "--匹配成功")
+		enStr = dealStartEndSpace(row[2])
+		if len(enStr) > 0:
+			return zh, enStr, chsToCht(zh)
+		else:
+			print("--录入,但是未翻译:" + zh)
+
+	return zh, None, None
+
+# 生成excel索引
+def createExcelIndexDict(tmpExcelFile = []):
+	tmpExcelIndex = dict()
+
+	rowCount = 0  # 行数,<2644 行文件格式 "中文" "英文" "繁体" >2644 格式:"None" "中文" "英文" "繁体" >2953 情况1
+	spaceCount = 0  # 中间空行记录,最多10行,当>10就认为结束了
+	for row in tmpExcelFile.get_rows():
+		if (len(row[0].value) == 0 and len(row[1].value) == 0) or row[0].value == " ":
+			spaceCount += 1
+			if spaceCount > 10:
+				break
+			else:
+				rowCount += 1
+				continue
+		"""
+		if (rowCount > 1 and rowCount < 2644) or (rowCount > 2953):
+			zhStr = dealStartEndSpace(row[0].value)
+			tmpExcelIndex[zhStr] = str(rowCount)
+		"""
+		zhStr = dealStartEndSpace(row[1].value)
+		tmpExcelIndex[zhStr] = str(rowCount)
+
+		if len(row[1].value) > 0:
+			spaceCount = 0
+		rowCount += 1
+
+	return tmpExcelIndex
+
+"""
+ 写入翻译到 对应的翻译文件中去
+ 总共有4个翻译文件 -中文 -英文 -繁体 -繁体
+"""
+def writeTranslateToFile(zh, en, hk):
+	zhStr = createTranslateLine(zh, zh)
+	hkStr = createTranslateLine(zh, hk)
+	enStr = createTranslateLine(zh, en)
+
+	zhHansFile.append(zhStr)
+	zhHantFile.append(hkStr)
+	zhHKFile.append(hkStr)
+	enFile.append(enStr)
+
+	zh
+
+	print("插入翻译: ", zhStr, enStr, hkStr)
+
+# 写入翻译文件
+def writeTmpToTrans():
+	func.saveSetInPath(zhHansFile, zhHansPath)
+	func.saveSetInPath(zhHantFile, zhHantPath)
+	func.saveSetInPath(zhHKFile, zhHKPath)
+	func.saveSetInPath(enFile, enPath)
+	print("写入文件完成")
+
+# 主运行
+if __name__ == "__main__":
+	# 读取文件缓存
+	readNeedTranslationFile()
+	readLanguageFilesToTmp()
+
+	# 循环遍历需要翻译的字段
+	zhNoTrans = set()
+	for zhStr in zhNeedList:
+		zhStr = dealStartEndChar(zhStr)
+		zhNoTrans.add(zhStr)
+		print("begin\n匹配:" + zhStr)
+		zh, en, hk = searchZhTranslationInExcel(zhStr, excelPath, translationSheetName)
+		if zh != None:
+			if tmpStoreZhTrans.get(zh) == None:
+				if en != None:
+					writeTranslateToFile(zh, en, hk)
+					zhNoTrans.remove(zhStr)
+		print("---end\n")
+
+	# 保存处理的文件
+	func.saveSetInPath(zhNoTrans, zhTransFilePath)
+
+	if isSave == True:
+		writeTmpToTrans()
+	# 结果
+	#print("\n已经翻译:" + str(succCount) + "\n没有翻译:" + str(falureCount) + "\n总处理:" + str(rowCount))

+ 0 - 0
__init__.py


+ 241 - 0
bin/bin/Activate.ps1

@@ -0,0 +1,241 @@
+<#
+.Synopsis
+Activate a Python virtual environment for the current PowerShell session.
+
+.Description
+Pushes the python executable for a virtual environment to the front of the
+$Env:PATH environment variable and sets the prompt to signify that you are
+in a Python virtual environment. Makes use of the command line switches as
+well as the `pyvenv.cfg` file values present in the virtual environment.
+
+.Parameter VenvDir
+Path to the directory that contains the virtual environment to activate. The
+default value for this is the parent of the directory that the Activate.ps1
+script is located within.
+
+.Parameter Prompt
+The prompt prefix to display when this virtual environment is activated. By
+default, this prompt is the name of the virtual environment folder (VenvDir)
+surrounded by parentheses and followed by a single space (ie. '(.venv) ').
+
+.Example
+Activate.ps1
+Activates the Python virtual environment that contains the Activate.ps1 script.
+
+.Example
+Activate.ps1 -Verbose
+Activates the Python virtual environment that contains the Activate.ps1 script,
+and shows extra information about the activation as it executes.
+
+.Example
+Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv
+Activates the Python virtual environment located in the specified location.
+
+.Example
+Activate.ps1 -Prompt "MyPython"
+Activates the Python virtual environment that contains the Activate.ps1 script,
+and prefixes the current prompt with the specified string (surrounded in
+parentheses) while the virtual environment is active.
+
+.Notes
+On Windows, it may be required to enable this Activate.ps1 script by setting the
+execution policy for the user. You can do this by issuing the following PowerShell
+command:
+
+PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
+
+For more information on Execution Policies: 
+https://go.microsoft.com/fwlink/?LinkID=135170
+
+#>
+Param(
+    [Parameter(Mandatory = $false)]
+    [String]
+    $VenvDir,
+    [Parameter(Mandatory = $false)]
+    [String]
+    $Prompt
+)
+
+<# Function declarations --------------------------------------------------- #>
+
+<#
+.Synopsis
+Remove all shell session elements added by the Activate script, including the
+addition of the virtual environment's Python executable from the beginning of
+the PATH variable.
+
+.Parameter NonDestructive
+If present, do not remove this function from the global namespace for the
+session.
+
+#>
+function global:deactivate ([switch]$NonDestructive) {
+    # Revert to original values
+
+    # The prior prompt:
+    if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) {
+        Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt
+        Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT
+    }
+
+    # The prior PYTHONHOME:
+    if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) {
+        Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME
+        Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME
+    }
+
+    # The prior PATH:
+    if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) {
+        Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH
+        Remove-Item -Path Env:_OLD_VIRTUAL_PATH
+    }
+
+    # Just remove the VIRTUAL_ENV altogether:
+    if (Test-Path -Path Env:VIRTUAL_ENV) {
+        Remove-Item -Path env:VIRTUAL_ENV
+    }
+
+    # Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether:
+    if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) {
+        Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force
+    }
+
+    # Leave deactivate function in the global namespace if requested:
+    if (-not $NonDestructive) {
+        Remove-Item -Path function:deactivate
+    }
+}
+
+<#
+.Description
+Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the
+given folder, and returns them in a map.
+
+For each line in the pyvenv.cfg file, if that line can be parsed into exactly
+two strings separated by `=` (with any amount of whitespace surrounding the =)
+then it is considered a `key = value` line. The left hand string is the key,
+the right hand is the value.
+
+If the value starts with a `'` or a `"` then the first and last character is
+stripped from the value before being captured.
+
+.Parameter ConfigDir
+Path to the directory that contains the `pyvenv.cfg` file.
+#>
+function Get-PyVenvConfig(
+    [String]
+    $ConfigDir
+) {
+    Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg"
+
+    # Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue).
+    $pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue
+
+    # An empty map will be returned if no config file is found.
+    $pyvenvConfig = @{ }
+
+    if ($pyvenvConfigPath) {
+
+        Write-Verbose "File exists, parse `key = value` lines"
+        $pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath
+
+        $pyvenvConfigContent | ForEach-Object {
+            $keyval = $PSItem -split "\s*=\s*", 2
+            if ($keyval[0] -and $keyval[1]) {
+                $val = $keyval[1]
+
+                # Remove extraneous quotations around a string value.
+                if ("'""".Contains($val.Substring(0, 1))) {
+                    $val = $val.Substring(1, $val.Length - 2)
+                }
+
+                $pyvenvConfig[$keyval[0]] = $val
+                Write-Verbose "Adding Key: '$($keyval[0])'='$val'"
+            }
+        }
+    }
+    return $pyvenvConfig
+}
+
+
+<# Begin Activate script --------------------------------------------------- #>
+
+# Determine the containing directory of this script
+$VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition
+$VenvExecDir = Get-Item -Path $VenvExecPath
+
+Write-Verbose "Activation script is located in path: '$VenvExecPath'"
+Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)"
+Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)"
+
+# Set values required in priority: CmdLine, ConfigFile, Default
+# First, get the location of the virtual environment, it might not be
+# VenvExecDir if specified on the command line.
+if ($VenvDir) {
+    Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values"
+}
+else {
+    Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir."
+    $VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/")
+    Write-Verbose "VenvDir=$VenvDir"
+}
+
+# Next, read the `pyvenv.cfg` file to determine any required value such
+# as `prompt`.
+$pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir
+
+# Next, set the prompt from the command line, or the config file, or
+# just use the name of the virtual environment folder.
+if ($Prompt) {
+    Write-Verbose "Prompt specified as argument, using '$Prompt'"
+}
+else {
+    Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value"
+    if ($pyvenvCfg -and $pyvenvCfg['prompt']) {
+        Write-Verbose "  Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'"
+        $Prompt = $pyvenvCfg['prompt'];
+    }
+    else {
+        Write-Verbose "  Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virutal environment)"
+        Write-Verbose "  Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'"
+        $Prompt = Split-Path -Path $venvDir -Leaf
+    }
+}
+
+Write-Verbose "Prompt = '$Prompt'"
+Write-Verbose "VenvDir='$VenvDir'"
+
+# Deactivate any currently active virtual environment, but leave the
+# deactivate function in place.
+deactivate -nondestructive
+
+# Now set the environment variable VIRTUAL_ENV, used by many tools to determine
+# that there is an activated venv.
+$env:VIRTUAL_ENV = $VenvDir
+
+if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) {
+
+    Write-Verbose "Setting prompt to '$Prompt'"
+
+    # Set the prompt to include the env name
+    # Make sure _OLD_VIRTUAL_PROMPT is global
+    function global:_OLD_VIRTUAL_PROMPT { "" }
+    Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT
+    New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt
+
+    function global:prompt {
+        Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) "
+        _OLD_VIRTUAL_PROMPT
+    }
+}
+
+# Clear PYTHONHOME
+if (Test-Path -Path Env:PYTHONHOME) {
+    Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME
+    Remove-Item -Path Env:PYTHONHOME
+}
+
+# Add the venv to the PATH
+Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH
+$Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH"

+ 76 - 0
bin/bin/activate

@@ -0,0 +1,76 @@
+# This file must be used with "source bin/activate" *from bash*
+# you cannot run it directly
+
+deactivate () {
+    # reset old environment variables
+    if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then
+        PATH="${_OLD_VIRTUAL_PATH:-}"
+        export PATH
+        unset _OLD_VIRTUAL_PATH
+    fi
+    if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then
+        PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}"
+        export PYTHONHOME
+        unset _OLD_VIRTUAL_PYTHONHOME
+    fi
+
+    # This should detect bash and zsh, which have a hash command that must
+    # be called to get it to forget past commands.  Without forgetting
+    # past commands the $PATH changes we made may not be respected
+    if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then
+        hash -r
+    fi
+
+    if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then
+        PS1="${_OLD_VIRTUAL_PS1:-}"
+        export PS1
+        unset _OLD_VIRTUAL_PS1
+    fi
+
+    unset VIRTUAL_ENV
+    if [ ! "${1:-}" = "nondestructive" ] ; then
+    # Self destruct!
+        unset -f deactivate
+    fi
+}
+
+# unset irrelevant variables
+deactivate nondestructive
+
+VIRTUAL_ENV="/Users/poto/Documents/OB_FileTransfate/bin"
+export VIRTUAL_ENV
+
+_OLD_VIRTUAL_PATH="$PATH"
+PATH="$VIRTUAL_ENV/bin:$PATH"
+export PATH
+
+# unset PYTHONHOME if set
+# this will fail if PYTHONHOME is set to the empty string (which is bad anyway)
+# could use `if (set -u; : $PYTHONHOME) ;` in bash
+if [ -n "${PYTHONHOME:-}" ] ; then
+    _OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}"
+    unset PYTHONHOME
+fi
+
+if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then
+    _OLD_VIRTUAL_PS1="${PS1:-}"
+    if [ "x(bin) " != x ] ; then
+	PS1="(bin) ${PS1:-}"
+    else
+    if [ "`basename \"$VIRTUAL_ENV\"`" = "__" ] ; then
+        # special case for Aspen magic directories
+        # see http://www.zetadev.com/software/aspen/
+        PS1="[`basename \`dirname \"$VIRTUAL_ENV\"\``] $PS1"
+    else
+        PS1="(`basename \"$VIRTUAL_ENV\"`)$PS1"
+    fi
+    fi
+    export PS1
+fi
+
+# This should detect bash and zsh, which have a hash command that must
+# be called to get it to forget past commands.  Without forgetting
+# past commands the $PATH changes we made may not be respected
+if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then
+    hash -r
+fi

+ 37 - 0
bin/bin/activate.csh

@@ -0,0 +1,37 @@
+# This file must be used with "source bin/activate.csh" *from csh*.
+# You cannot run it directly.
+# Created by Davide Di Blasi <[email protected]>.
+# Ported to Python 3.3 venv by Andrew Svetlov <[email protected]>
+
+alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; test "\!:*" != "nondestructive" && unalias deactivate'
+
+# Unset irrelevant variables.
+deactivate nondestructive
+
+setenv VIRTUAL_ENV "/Users/poto/Documents/OB_FileTransfate/bin"
+
+set _OLD_VIRTUAL_PATH="$PATH"
+setenv PATH "$VIRTUAL_ENV/bin:$PATH"
+
+
+set _OLD_VIRTUAL_PROMPT="$prompt"
+
+if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then
+    if ("bin" != "") then
+        set env_name = "bin"
+    else
+        if (`basename "VIRTUAL_ENV"` == "__") then
+            # special case for Aspen magic directories
+            # see http://www.zetadev.com/software/aspen/
+            set env_name = `basename \`dirname "$VIRTUAL_ENV"\``
+        else
+            set env_name = `basename "$VIRTUAL_ENV"`
+        endif
+    endif
+    set prompt = "[$env_name] $prompt"
+    unset env_name
+endif
+
+alias pydoc python -m pydoc
+
+rehash

+ 75 - 0
bin/bin/activate.fish

@@ -0,0 +1,75 @@
+# This file must be used with ". bin/activate.fish" *from fish* (http://fishshell.org)
+# you cannot run it directly
+
+function deactivate  -d "Exit virtualenv and return to normal shell environment"
+    # reset old environment variables
+    if test -n "$_OLD_VIRTUAL_PATH"
+        set -gx PATH $_OLD_VIRTUAL_PATH
+        set -e _OLD_VIRTUAL_PATH
+    end
+    if test -n "$_OLD_VIRTUAL_PYTHONHOME"
+        set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME
+        set -e _OLD_VIRTUAL_PYTHONHOME
+    end
+
+    if test -n "$_OLD_FISH_PROMPT_OVERRIDE"
+        functions -e fish_prompt
+        set -e _OLD_FISH_PROMPT_OVERRIDE
+        functions -c _old_fish_prompt fish_prompt
+        functions -e _old_fish_prompt
+    end
+
+    set -e VIRTUAL_ENV
+    if test "$argv[1]" != "nondestructive"
+        # Self destruct!
+        functions -e deactivate
+    end
+end
+
+# unset irrelevant variables
+deactivate nondestructive
+
+set -gx VIRTUAL_ENV "/Users/poto/Documents/OB_FileTransfate/bin"
+
+set -gx _OLD_VIRTUAL_PATH $PATH
+set -gx PATH "$VIRTUAL_ENV/bin" $PATH
+
+# unset PYTHONHOME if set
+if set -q PYTHONHOME
+    set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME
+    set -e PYTHONHOME
+end
+
+if test -z "$VIRTUAL_ENV_DISABLE_PROMPT"
+    # fish uses a function instead of an env var to generate the prompt.
+
+    # save the current fish_prompt function as the function _old_fish_prompt
+    functions -c fish_prompt _old_fish_prompt
+
+    # with the original prompt function renamed, we can override with our own.
+    function fish_prompt
+        # Save the return status of the last command
+        set -l old_status $status
+
+        # Prompt override?
+        if test -n "(bin) "
+            printf "%s%s" "(bin) " (set_color normal)
+        else
+            # ...Otherwise, prepend env
+            set -l _checkbase (basename "$VIRTUAL_ENV")
+            if test $_checkbase = "__"
+                # special case for Aspen magic directories
+                # see http://www.zetadev.com/software/aspen/
+                printf "%s[%s]%s " (set_color -b blue white) (basename (dirname "$VIRTUAL_ENV")) (set_color normal)
+            else
+                printf "%s(%s)%s" (set_color -b blue white) (basename "$VIRTUAL_ENV") (set_color normal)
+            end
+        end
+
+        # Restore the return status of the previous command.
+        echo "exit $old_status" | .
+        _old_fish_prompt
+    end
+
+    set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV"
+end

+ 8 - 0
bin/bin/easy_install

@@ -0,0 +1,8 @@
+#!/Users/poto/Documents/OB_FileTransfate/bin/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from setuptools.command.easy_install import main
+if __name__ == '__main__':
+    sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+    sys.exit(main())

+ 8 - 0
bin/bin/easy_install-3.8

@@ -0,0 +1,8 @@
+#!/Users/poto/Documents/OB_FileTransfate/bin/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from setuptools.command.easy_install import main
+if __name__ == '__main__':
+    sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+    sys.exit(main())

+ 8 - 0
bin/bin/pip

@@ -0,0 +1,8 @@
+#!/Users/poto/Documents/OB_FileTransfate/bin/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from pip._internal.cli.main import main
+if __name__ == '__main__':
+    sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+    sys.exit(main())

+ 8 - 0
bin/bin/pip3

@@ -0,0 +1,8 @@
+#!/Users/poto/Documents/OB_FileTransfate/bin/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from pip._internal.cli.main import main
+if __name__ == '__main__':
+    sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+    sys.exit(main())

+ 8 - 0
bin/bin/pip3.8

@@ -0,0 +1,8 @@
+#!/Users/poto/Documents/OB_FileTransfate/bin/bin/python3.8
+# -*- coding: utf-8 -*-
+import re
+import sys
+from pip._internal.cli.main import main
+if __name__ == '__main__':
+    sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
+    sys.exit(main())

+ 1 - 0
bin/bin/python

@@ -0,0 +1 @@
+python3.8

+ 1 - 0
bin/bin/python3

@@ -0,0 +1 @@
+python3.8

+ 1 - 0
bin/bin/python3.8

@@ -0,0 +1 @@
+/usr/local/bin/python3.8

+ 420 - 0
bin/bin/runxlrd.py

@@ -0,0 +1,420 @@
+#!/usr/local/opt/[email protected]/bin/python3.8
+# Copyright (c) 2005-2012 Stephen John Machin, Lingfo Pty Ltd
+# This script is part of the xlrd package, which is released under a
+# BSD-style licence.
+
+from __future__ import print_function
+
+cmd_doc = """
+Commands:
+
+2rows           Print the contents of first and last row in each sheet
+3rows           Print the contents of first, second and last row in each sheet
+bench           Same as "show", but doesn't print -- for profiling
+biff_count[1]   Print a count of each type of BIFF record in the file
+biff_dump[1]    Print a dump (char and hex) of the BIFF records in the file
+fonts           hdr + print a dump of all font objects
+hdr             Mini-overview of file (no per-sheet information)
+hotshot         Do a hotshot profile run e.g. ... -f1 hotshot bench bigfile*.xls
+labels          Dump of sheet.col_label_ranges and ...row... for each sheet
+name_dump       Dump of each object in book.name_obj_list
+names           Print brief information for each NAME record
+ov              Overview of file
+profile         Like "hotshot", but uses cProfile
+show            Print the contents of all rows in each sheet
+version[0]      Print versions of xlrd and Python and exit
+xfc             Print "XF counts" and cell-type counts -- see code for details
+
+[0] means no file arg
+[1] means only one file arg i.e. no glob.glob pattern
+"""
+
+options = None
+if __name__ == "__main__":
+
+    PSYCO = 0
+
+    import xlrd
+    import sys
+    import time
+    import glob
+    import traceback
+    import gc
+
+    from xlrd.timemachine import xrange, REPR
+
+
+    class LogHandler(object):
+
+        def __init__(self, logfileobj):
+            self.logfileobj = logfileobj
+            self.fileheading = None
+            self.shown = 0
+
+        def setfileheading(self, fileheading):
+            self.fileheading = fileheading
+            self.shown = 0
+
+        def write(self, text):
+            if self.fileheading and not self.shown:
+                self.logfileobj.write(self.fileheading)
+                self.shown = 1
+            self.logfileobj.write(text)
+
+    null_cell = xlrd.empty_cell
+
+    def show_row(bk, sh, rowx, colrange, printit):
+        if bk.ragged_rows:
+            colrange = range(sh.row_len(rowx))
+        if not colrange: return
+        if printit: print()
+        if bk.formatting_info:
+            for colx, ty, val, cxfx in get_row_data(bk, sh, rowx, colrange):
+                if printit:
+                    print("cell %s%d: type=%d, data: %r, xfx: %s"
+                        % (xlrd.colname(colx), rowx+1, ty, val, cxfx))
+        else:
+            for colx, ty, val, _unused in get_row_data(bk, sh, rowx, colrange):
+                if printit:
+                    print("cell %s%d: type=%d, data: %r" % (xlrd.colname(colx), rowx+1, ty, val))
+
+    def get_row_data(bk, sh, rowx, colrange):
+        result = []
+        dmode = bk.datemode
+        ctys = sh.row_types(rowx)
+        cvals = sh.row_values(rowx)
+        for colx in colrange:
+            cty = ctys[colx]
+            cval = cvals[colx]
+            if bk.formatting_info:
+                cxfx = str(sh.cell_xf_index(rowx, colx))
+            else:
+                cxfx = ''
+            if cty == xlrd.XL_CELL_DATE:
+                try:
+                    showval = xlrd.xldate_as_tuple(cval, dmode)
+                except xlrd.XLDateError as e:
+                    showval = "%s:%s" % (type(e).__name__, e)
+                    cty = xlrd.XL_CELL_ERROR
+            elif cty == xlrd.XL_CELL_ERROR:
+                showval = xlrd.error_text_from_code.get(cval, '<Unknown error code 0x%02x>' % cval)
+            else:
+                showval = cval
+            result.append((colx, cty, showval, cxfx))
+        return result
+
+    def bk_header(bk):
+        print()
+        print("BIFF version: %s; datemode: %s"
+            % (xlrd.biff_text_from_num[bk.biff_version], bk.datemode))
+        print("codepage: %r (encoding: %s); countries: %r"
+            % (bk.codepage, bk.encoding, bk.countries))
+        print("Last saved by: %r" % bk.user_name)
+        print("Number of data sheets: %d" % bk.nsheets)
+        print("Use mmap: %d; Formatting: %d; On demand: %d"
+            % (bk.use_mmap, bk.formatting_info, bk.on_demand))
+        print("Ragged rows: %d" % bk.ragged_rows)
+        if bk.formatting_info:
+            print("FORMATs: %d, FONTs: %d, XFs: %d"
+                % (len(bk.format_list), len(bk.font_list), len(bk.xf_list)))
+        if not options.suppress_timing:
+            print("Load time: %.2f seconds (stage 1) %.2f seconds (stage 2)"
+                % (bk.load_time_stage_1, bk.load_time_stage_2))
+        print()
+
+    def show_fonts(bk):
+        print("Fonts:")
+        for x in xrange(len(bk.font_list)):
+            font = bk.font_list[x]
+            font.dump(header='== Index %d ==' % x, indent=4)
+
+    def show_names(bk, dump=0):
+        bk_header(bk)
+        if bk.biff_version < 50:
+            print("Names not extracted in this BIFF version")
+            return
+        nlist = bk.name_obj_list
+        print("Name list: %d entries" % len(nlist))
+        for nobj in nlist:
+            if dump:
+                nobj.dump(sys.stdout,
+                    header="\n=== Dump of name_obj_list[%d] ===" % nobj.name_index)
+            else:
+                print("[%d]\tName:%r macro:%r scope:%d\n\tresult:%r\n"
+                    % (nobj.name_index, nobj.name, nobj.macro, nobj.scope, nobj.result))
+
+    def print_labels(sh, labs, title):
+        if not labs:return
+        for rlo, rhi, clo, chi in labs:
+            print("%s label range %s:%s contains:"
+                % (title, xlrd.cellname(rlo, clo), xlrd.cellname(rhi-1, chi-1)))
+            for rx in xrange(rlo, rhi):
+                for cx in xrange(clo, chi):
+                    print("    %s: %r" % (xlrd.cellname(rx, cx), sh.cell_value(rx, cx)))
+
+    def show_labels(bk):
+        # bk_header(bk)
+        hdr = 0
+        for shx in range(bk.nsheets):
+            sh = bk.sheet_by_index(shx)
+            clabs = sh.col_label_ranges
+            rlabs = sh.row_label_ranges
+            if clabs or rlabs:
+                if not hdr:
+                    bk_header(bk)
+                    hdr = 1
+                print("sheet %d: name = %r; nrows = %d; ncols = %d" %
+                    (shx, sh.name, sh.nrows, sh.ncols))
+                print_labels(sh, clabs, 'Col')
+                print_labels(sh, rlabs, 'Row')
+            if bk.on_demand: bk.unload_sheet(shx)
+
+    def show(bk, nshow=65535, printit=1):
+        bk_header(bk)
+        if 0:
+            rclist = xlrd.sheet.rc_stats.items()
+            rclist = sorted(rclist)
+            print("rc stats")
+            for k, v in rclist:
+                print("0x%04x %7d" % (k, v))
+        if options.onesheet:
+            try:
+                shx = int(options.onesheet)
+            except ValueError:
+                shx = bk.sheet_by_name(options.onesheet).number
+            shxrange = [shx]
+        else:
+            shxrange = range(bk.nsheets)
+        # print("shxrange", list(shxrange))
+        for shx in shxrange:
+            sh = bk.sheet_by_index(shx)
+            nrows, ncols = sh.nrows, sh.ncols
+            colrange = range(ncols)
+            anshow = min(nshow, nrows)
+            print("sheet %d: name = %s; nrows = %d; ncols = %d" %
+                (shx, REPR(sh.name), sh.nrows, sh.ncols))
+            if nrows and ncols:
+                # Beat the bounds
+                for rowx in xrange(nrows):
+                    nc = sh.row_len(rowx)
+                    if nc:
+                        sh.row_types(rowx)[nc-1]
+                        sh.row_values(rowx)[nc-1]
+                        sh.cell(rowx, nc-1)
+            for rowx in xrange(anshow-1):
+                if not printit and rowx % 10000 == 1 and rowx > 1:
+                    print("done %d rows" % (rowx-1,))
+                show_row(bk, sh, rowx, colrange, printit)
+            if anshow and nrows:
+                show_row(bk, sh, nrows-1, colrange, printit)
+            print()
+            if bk.on_demand: bk.unload_sheet(shx)
+
+    def count_xfs(bk):
+        bk_header(bk)
+        for shx in range(bk.nsheets):
+            sh = bk.sheet_by_index(shx)
+            nrows = sh.nrows
+            print("sheet %d: name = %r; nrows = %d; ncols = %d" %
+                (shx, sh.name, sh.nrows, sh.ncols))
+            # Access all xfindexes to force gathering stats
+            type_stats = [0, 0, 0, 0, 0, 0, 0]
+            for rowx in xrange(nrows):
+                for colx in xrange(sh.row_len(rowx)):
+                    xfx = sh.cell_xf_index(rowx, colx)
+                    assert xfx >= 0
+                    cty = sh.cell_type(rowx, colx)
+                    type_stats[cty] += 1
+            print("XF stats", sh._xf_index_stats)
+            print("type stats", type_stats)
+            print()
+            if bk.on_demand: bk.unload_sheet(shx)
+
+    def main(cmd_args):
+        import optparse
+        global options, PSYCO
+        usage = "\n%prog [options] command [input-file-patterns]\n" + cmd_doc
+        oparser = optparse.OptionParser(usage)
+        oparser.add_option(
+            "-l", "--logfilename",
+            default="",
+            help="contains error messages")
+        oparser.add_option(
+            "-v", "--verbosity",
+            type="int", default=0,
+            help="level of information and diagnostics provided")
+        oparser.add_option(
+            "-m", "--mmap",
+            type="int", default=-1,
+            help="1: use mmap; 0: don't use mmap; -1: accept heuristic")
+        oparser.add_option(
+            "-e", "--encoding",
+            default="",
+            help="encoding override")
+        oparser.add_option(
+            "-f", "--formatting",
+            type="int", default=0,
+            help="0 (default): no fmt info\n"
+                 "1: fmt info (all cells)\n",
+        )
+        oparser.add_option(
+            "-g", "--gc",
+            type="int", default=0,
+            help="0: auto gc enabled; 1: auto gc disabled, manual collect after each file; 2: no gc")
+        oparser.add_option(
+            "-s", "--onesheet",
+            default="",
+            help="restrict output to this sheet (name or index)")
+        oparser.add_option(
+            "-u", "--unnumbered",
+            action="store_true", default=0,
+            help="omit line numbers or offsets in biff_dump")
+        oparser.add_option(
+            "-d", "--on-demand",
+            action="store_true", default=0,
+            help="load sheets on demand instead of all at once")
+        oparser.add_option(
+            "-t", "--suppress-timing",
+            action="store_true", default=0,
+            help="don't print timings (diffs are less messy)")
+        oparser.add_option(
+            "-r", "--ragged-rows",
+            action="store_true", default=0,
+            help="open_workbook(..., ragged_rows=True)")
+        options, args = oparser.parse_args(cmd_args)
+        if len(args) == 1 and args[0] in ("version", ):
+            pass
+        elif len(args) < 2:
+            oparser.error("Expected at least 2 args, found %d" % len(args))
+        cmd = args[0]
+        xlrd_version = getattr(xlrd, "__VERSION__", "unknown; before 0.5")
+        if cmd == 'biff_dump':
+            xlrd.dump(args[1], unnumbered=options.unnumbered)
+            sys.exit(0)
+        if cmd == 'biff_count':
+            xlrd.count_records(args[1])
+            sys.exit(0)
+        if cmd == 'version':
+            print("xlrd: %s, from %s" % (xlrd_version, xlrd.__file__))
+            print("Python:", sys.version)
+            sys.exit(0)
+        if options.logfilename:
+            logfile = LogHandler(open(options.logfilename, 'w'))
+        else:
+            logfile = sys.stdout
+        mmap_opt = options.mmap
+        mmap_arg = xlrd.USE_MMAP
+        if mmap_opt in (1, 0):
+            mmap_arg = mmap_opt
+        elif mmap_opt != -1:
+            print('Unexpected value (%r) for mmap option -- assuming default' % mmap_opt)
+        fmt_opt = options.formatting | (cmd in ('xfc', ))
+        gc_mode = options.gc
+        if gc_mode:
+            gc.disable()
+        for pattern in args[1:]:
+            for fname in glob.glob(pattern):
+                print("\n=== File: %s ===" % fname)
+                if logfile != sys.stdout:
+                    logfile.setfileheading("\n=== File: %s ===\n" % fname)
+                if gc_mode == 1:
+                    n_unreachable = gc.collect()
+                    if n_unreachable:
+                        print("GC before open:", n_unreachable, "unreachable objects")
+                if PSYCO:
+                    import psyco
+                    psyco.full()
+                    PSYCO = 0
+                try:
+                    t0 = time.time()
+                    bk = xlrd.open_workbook(
+                        fname,
+                        verbosity=options.verbosity, logfile=logfile,
+                        use_mmap=mmap_arg,
+                        encoding_override=options.encoding,
+                        formatting_info=fmt_opt,
+                        on_demand=options.on_demand,
+                        ragged_rows=options.ragged_rows,
+                    )
+                    t1 = time.time()
+                    if not options.suppress_timing:
+                        print("Open took %.2f seconds" % (t1-t0,))
+                except xlrd.XLRDError as e:
+                    print("*** Open failed: %s: %s" % (type(e).__name__, e))
+                    continue
+                except KeyboardInterrupt:
+                    print("*** KeyboardInterrupt ***")
+                    traceback.print_exc(file=sys.stdout)
+                    sys.exit(1)
+                except BaseException as e:
+                    print("*** Open failed: %s: %s" % (type(e).__name__, e))
+                    traceback.print_exc(file=sys.stdout)
+                    continue
+                t0 = time.time()
+                if cmd == 'hdr':
+                    bk_header(bk)
+                elif cmd == 'ov': # OverView
+                    show(bk, 0)
+                elif cmd == 'show': # all rows
+                    show(bk)
+                elif cmd == '2rows': # first row and last row
+                    show(bk, 2)
+                elif cmd == '3rows': # first row, 2nd row and last row
+                    show(bk, 3)
+                elif cmd == 'bench':
+                    show(bk, printit=0)
+                elif cmd == 'fonts':
+                    bk_header(bk)
+                    show_fonts(bk)
+                elif cmd == 'names': # named reference list
+                    show_names(bk)
+                elif cmd == 'name_dump': # named reference list
+                    show_names(bk, dump=1)
+                elif cmd == 'labels':
+                    show_labels(bk)
+                elif cmd == 'xfc':
+                    count_xfs(bk)
+                else:
+                    print("*** Unknown command <%s>" % cmd)
+                    sys.exit(1)
+                del bk
+                if gc_mode == 1:
+                    n_unreachable = gc.collect()
+                    if n_unreachable:
+                        print("GC post cmd:", fname, "->", n_unreachable, "unreachable objects")
+                if not options.suppress_timing:
+                    t1 = time.time()
+                    print("\ncommand took %.2f seconds\n" % (t1-t0,))
+
+        return None
+
+    av = sys.argv[1:]
+    if not av:
+        main(av)
+    firstarg = av[0].lower()
+    if firstarg == "hotshot":
+        import hotshot
+        import hotshot.stats
+        av = av[1:]
+        prof_log_name = "XXXX.prof"
+        prof = hotshot.Profile(prof_log_name)
+        # benchtime, result = prof.runcall(main, *av)
+        result = prof.runcall(main, *(av, ))
+        print("result", repr(result))
+        prof.close()
+        stats = hotshot.stats.load(prof_log_name)
+        stats.strip_dirs()
+        stats.sort_stats('time', 'calls')
+        stats.print_stats(20)
+    elif firstarg == "profile":
+        import cProfile
+        av = av[1:]
+        cProfile.run('main(av)', 'YYYY.prof')
+        import pstats
+        p = pstats.Stats('YYYY.prof')
+        p.strip_dirs().sort_stats('cumulative').print_stats(30)
+    elif firstarg == "psyco":
+        PSYCO = 1
+        main(av[1:])
+    else:
+        main(av)

+ 3 - 0
bin/pyvenv.cfg

@@ -0,0 +1,3 @@
+home = /usr/local/bin
+include-system-site-packages = true
+version = 3.8.5

+ 277 - 0
langconv.py

@@ -0,0 +1,277 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from copy import deepcopy
+import re
+
+try:
+    import psyco
+    psyco.full()
+except:
+    pass
+
+try:
+    from zh_wiki import zh2Hant, zh2Hans
+except ImportError:
+    from zhtools.zh_wiki import zh2Hant, zh2Hans
+
+import sys
+py3k = sys.version_info >= (3, 0, 0)
+
+if py3k:
+    UEMPTY = ''
+else:
+    _zh2Hant, _zh2Hans = {}, {}
+    for old, new in ((zh2Hant, _zh2Hant), (zh2Hans, _zh2Hans)):
+        for k, v in old.items():
+            new[k.decode('utf8')] = v.decode('utf8')
+    zh2Hant = _zh2Hant
+    zh2Hans = _zh2Hans
+    UEMPTY = ''.decode('utf8')
+
+# states
+(START, END, FAIL, WAIT_TAIL) = list(range(4))
+# conditions
+(TAIL, ERROR, MATCHED_SWITCH, UNMATCHED_SWITCH, CONNECTOR) = list(range(5))
+
+MAPS = {}
+
+class Node(object):
+    def __init__(self, from_word, to_word=None, is_tail=True,
+            have_child=False):
+        self.from_word = from_word
+        if to_word is None:
+            self.to_word = from_word
+            self.data = (is_tail, have_child, from_word)
+            self.is_original = True
+        else:
+            self.to_word = to_word or from_word
+            self.data = (is_tail, have_child, to_word)
+            self.is_original = False
+        self.is_tail = is_tail
+        self.have_child = have_child
+
+    def is_original_long_word(self):
+        return self.is_original and len(self.from_word)>1
+
+    def is_follow(self, chars):
+        return chars != self.from_word[:-1]
+
+    def __str__(self):
+        return '<Node, %s, %s, %s, %s>' % (repr(self.from_word),
+                repr(self.to_word), self.is_tail, self.have_child)
+
+    __repr__ = __str__
+
+class ConvertMap(object):
+    def __init__(self, name, mapping=None):
+        self.name = name
+        self._map = {}
+        if mapping:
+            self.set_convert_map(mapping)
+
+    def set_convert_map(self, mapping):
+        convert_map = {}
+        have_child = {}
+        max_key_length = 0
+        for key in sorted(mapping.keys()):
+            if len(key)>1:
+                for i in range(1, len(key)):
+                    parent_key = key[:i]
+                    have_child[parent_key] = True
+            have_child[key] = False
+            max_key_length = max(max_key_length, len(key))
+        for key in sorted(have_child.keys()):
+            convert_map[key] = (key in mapping, have_child[key],
+                    mapping.get(key, UEMPTY))
+        self._map = convert_map
+        self.max_key_length = max_key_length
+
+    def __getitem__(self, k):
+        try:
+            is_tail, have_child, to_word  = self._map[k]
+            return Node(k, to_word, is_tail, have_child)
+        except:
+            return Node(k)
+
+    def __contains__(self, k):
+        return k in self._map
+
+    def __len__(self):
+        return len(self._map)
+
+class StatesMachineException(Exception): pass
+
+class StatesMachine(object):
+    def __init__(self):
+        self.state = START
+        self.final = UEMPTY
+        self.len = 0
+        self.pool = UEMPTY
+
+    def clone(self, pool):
+        new = deepcopy(self)
+        new.state = WAIT_TAIL
+        new.pool = pool
+        return new
+
+    def feed(self, char, map):
+        node = map[self.pool+char]
+
+        if node.have_child:
+            if node.is_tail:
+                if node.is_original:
+                    cond = UNMATCHED_SWITCH
+                else:
+                    cond = MATCHED_SWITCH
+            else:
+                cond = CONNECTOR
+        else:
+            if node.is_tail:
+                cond = TAIL
+            else:
+                cond = ERROR
+
+        new = None
+        if cond == ERROR:
+            self.state = FAIL
+        elif cond == TAIL:
+            if self.state == WAIT_TAIL and node.is_original_long_word():
+                self.state = FAIL
+            else:
+                self.final += node.to_word
+                self.len += 1
+                self.pool = UEMPTY
+                self.state = END
+        elif self.state == START or self.state == WAIT_TAIL:
+            if cond == MATCHED_SWITCH:
+                new = self.clone(node.from_word)
+                self.final += node.to_word
+                self.len += 1
+                self.state = END
+                self.pool = UEMPTY
+            elif cond == UNMATCHED_SWITCH or cond == CONNECTOR:
+                if self.state == START:
+                    new = self.clone(node.from_word)
+                    self.final += node.to_word
+                    self.len += 1
+                    self.state = END
+                else:
+                    if node.is_follow(self.pool):
+                        self.state = FAIL
+                    else:
+                        self.pool = node.from_word
+        elif self.state == END:
+            # END is a new START
+            self.state = START
+            new = self.feed(char, map)
+        elif self.state == FAIL:
+            raise StatesMachineException('Translate States Machine '
+                    'have error with input data %s' % node)
+        return new
+
+    def __len__(self):
+        return self.len + 1
+
+    def __str__(self):
+        return '<StatesMachine %s, pool: "%s", state: %s, final: %s>' % (
+                id(self), self.pool, self.state, self.final)
+    __repr__ = __str__
+
+class Converter(object):
+    def __init__(self, to_encoding):
+        self.to_encoding = to_encoding
+        self.map = MAPS[to_encoding]
+        self.start()
+
+    def feed(self, char):
+        branches = []
+        for fsm in self.machines:
+            new = fsm.feed(char, self.map)
+            if new:
+                branches.append(new)
+        if branches:
+            self.machines.extend(branches)
+        self.machines = [fsm for fsm in self.machines if fsm.state != FAIL]
+        all_ok = True
+        for fsm in self.machines:
+            if fsm.state != END:
+                all_ok = False
+        if all_ok:
+            self._clean()
+        return self.get_result()
+
+    def _clean(self):
+        if len(self.machines):
+            self.machines.sort(key=lambda x: len(x))
+            # self.machines.sort(cmp=lambda x,y: cmp(len(x), len(y)))
+            self.final += self.machines[0].final
+        self.machines = [StatesMachine()]
+
+    def start(self):
+        self.machines = [StatesMachine()]
+        self.final = UEMPTY
+
+    def end(self):
+        self.machines = [fsm for fsm in self.machines
+                if fsm.state == FAIL or fsm.state == END]
+        self._clean()
+
+    def convert(self, string):
+        self.start()
+        for char in string:
+            self.feed(char)
+        self.end()
+        return self.get_result()
+
+    def get_result(self):
+        return self.final
+
+
+def registery(name, mapping):
+    global MAPS
+    MAPS[name] = ConvertMap(name, mapping)
+
+registery('zh-hant', zh2Hant)
+registery('zh-hans', zh2Hans)
+del zh2Hant, zh2Hans
+
+
+def run():
+    import sys
+    from optparse import OptionParser
+    parser = OptionParser()
+    parser.add_option('-e', type='string', dest='encoding',
+            help='encoding')
+    parser.add_option('-f', type='string', dest='file_in',
+            help='input file (- for stdin)')
+    parser.add_option('-t', type='string', dest='file_out',
+            help='output file')
+    (options, args) = parser.parse_args()
+    if not options.encoding:
+        parser.error('encoding must be set')
+    if options.file_in:
+        if options.file_in == '-':
+            file_in = sys.stdin
+        else:
+            file_in = open(options.file_in)
+    else:
+        file_in = sys.stdin
+    if options.file_out:
+        if options.file_out == '-':
+            file_out = sys.stdout
+        else:
+            file_out = open(options.file_out, 'wb')
+    else:
+        file_out = sys.stdout
+
+    c = Converter(options.encoding)
+    for line in file_in:
+        # print >> file_out, c.convert(line.rstrip('\n').decode(
+        file_out.write(c.convert(line.rstrip('\n').decode(
+            'utf8')).encode('utf8'))
+
+
+if __name__ == '__main__':
+    run()
+

Plik diff jest za duży
+ 8287 - 0
zh_wiki.py