helper.py 設定
背景
因 ckan 為 python 為基底作為伺服器處理的核心語言,大部分於 jinja 等內執行的網頁,皆須透過 helper 進行處裡來取得內容。
主要 helper.py 位置 (plugin 也可以進行擴增)
/usr/lib/ckan/default/src/ckan/ckan/lib/helpers.py
依目前使用的語言回傳該語言的字串
# customized function
# desc : return a string based on current language selected, english or chinese
# para : a english string and a chinese string
def getLangLabel(en,tw):
if lang() == "en":
return en
elif lang() == "zh_TW":
return tw
# 因為可能由網頁進行讀取,須放置在 ** __allowed_functions__ ** 中
__allowed_functions__ = [
...
'time_ago_from_timestamp',
'get_organization',
'has_more_facets',
'getLangLabel'
...
]
回傳 List 內的元素總數
# customized function
# desc : return the length of a list
# para : a list
def getLen(getObj):
return len(getObj)
# 因為可能由網頁進行讀取,須放置在 ** __allowed_functions__ ** 中
__allowed_functions__ = [
...
'time_ago_from_timestamp',
'get_organization',
'has_more_facets',
'getLangLabel',
'getLen',
...
]
取代子自串
# customized function
# desc : return a replaced string
# para : a string content, a target substring, a replaced string for target substring
def strReplace(getStr,getTarget,getReplace):
return getStr.replace(getTarget,getReplace)
# 因為可能由網頁進行讀取,須放置在 ** __allowed_functions__ ** 中
__allowed_functions__ = [
...
'time_ago_from_timestamp',
'get_organization',
'has_more_facets',
'getLangLabel',
'getLen',
'strReplace',
...
]
對各 organization 頁面底下的標籤進型語言切換
先針對 help.py 進行設定,並加入 allowed_functions 中
# ...
# customized function
# desc : get organization or group title
# ret : return English or Chinese title
def getGroupStr(getItem):
check = ""
for group in get_featured_groups(200):
if group["title"] == getItem["display_name"]:
check = getLangLabel(group["etitle"],group["title"])
break
return check
def getOrganizationStr(getItem):
check = ""
for org in get_featured_organizations(count=200):
if org["title"] == getItem["display_name"]:
check = getLangLabel(org["etitle"],org["title"])
break
return check
def getGroupOrOrganizationLangStr(getTitle, getItem):
check = ""
if getTitle == "Organizations" or getTitle == u"組織":
check = getOrganizationStr(getItem)
elif getTitle == "Groups" or getTitle == u"群組":
check = getGroupStr(getItem)
else:
check = "N"
return check
# ...
__allowed_functions__ = [
# ...
'list_dict_filter',
'new_activities',
'time_ago_from_timestamp',
'get_organization',
'has_more_facets',
'getLangLabel',
'getLen',
'strReplace',
'retGroupList',
'getGroupStr',
'getOrganizationStr',
'getGroupOrOrganizationLangStr',
# imported into ckan.lib.helpers
# ...
修正 Licenses 語言切換
# ...
# customized function
# desc : get chinese and english title
# return : specific title in chinese and english
def getLicenseLabel(getLicense, getColumn):
register = model.Package.get_license_register()
sorted_licenses = sorted(register.values(), key=lambda x: x.title)
getTitle = ""
for i in range(0, len(sorted_licenses), 1):
if sorted_licenses[i].title == getLicense[getColumn]:
getTitle = getLangLabel(sorted_licenses[i].etitle, sorted_licenses[i].title)
break
return getTitle
# ...
__allowed_functions__ = [
# ...
'list_dict_filter',
'new_activities',
'time_ago_from_timestamp',
'get_organization',
'has_more_facets',
'getLangLabel',
'getLen',
'strReplace',
'retGroupList',
'getGroupStr',
'getOrganizationStr',
'getGroupOrOrganizationLangStr',
'getLicenseLabel',
# imported into ckan.lib.helpers
# ...
偵測中文標籤
# ...
#
# desc : detect chinese or not
# usage : in dataset page
#
def checkChineseTag(getStr):
for i in range(0,len(getStr),1):
if u'\u4e00' <= getStr[i] <= u'\u9fff':
return True
return False
#
# desc : show the tags in the same lang environment
# usage : in dataset page
#
def checkLangTag(getStr):
if lang() == "en" and not checkChineseTag(getStr):
return True
elif lang() == "zh_TW" and checkChineseTag(getStr):
return True
else:
return False
# ...
__allowed_functions__ = [
# ...
'getGroupStr',
'getOrganizationStr',
'getGroupOrOrganizationLangStr',
'getLicenseLabel',
'checkChineseTag',
'checkLangTag',
取得 request (POST, GET) 的參數與値
#
# desc : parse request body
# retn : dict as key => value (&key=value in URL)
#
def parsePostRequestBodyAsList(getStr):
bodyDict = {}
parsePair = []
for pair in getStr.split("&"):
parsePair = pair.split("=")
bodyDict.setdefault(parsePair[0],parsePair[1])
return bodyDict
#
# desc : get value of key in request body
#
def getPostRequestParamValue(getStr, getParaKey):
getDict = parsePostRequestBodyAsList(getStr)
if getParaKey in getDict.keys():
return getDict[getParaKey]
else:
return ''
# ...
__allowed_functions__ = [
# ...
'getGroupStr',
'getOrganizationStr',
'getGroupOrOrganizationLangStr',
'getLicenseLabel',
'checkChineseTag',
'checkLangTag',
'parsePostRequestBodyAsList',
'getPostRequestParamValue',
加入新欄位於註冊選單中
import psycopg2
from py2psql import *
# ...
#
# desc : get user list for requesting to organization
# retn : list contains tuple
#
def getReq2OrgList(getOrg, getCrtUser):
p2l = py2psql("127.0.0.1","5432","ckan_default","public.user","ckan_default","ckan")
data = p2l.select({"organ":getOrg["name"]},["id","name","fullname","email"],asdict=True)
if len(data) < 1:
return []
else:
retList = []
crtList = [item[0] for item in getCrtUser]
for item in data:
if item["id"] not in crtList:
tmpTuple = (item["name"], item["fullname"], item["email"])
retList.append(tmpTuple)
return retList
#
# desc : get current user state
#
def getUserState(getID):
p2l = py2psql("127.0.0.1","5432","ckan_default","public.user","ckan_default","ckan")
data = p2l.select({"id":getID},["state"],asdict=True)
return data[0]["state"]
#
# desc : set current user state
#
def setUserState(getID,setState):
p2l = py2psql("127.0.0.1","5432","ckan_default","public.user","ckan_default","ckan")
return p2l.update({"state":setState},{"id":getID})
#
# desc : get user organ
#
def getUserOrgan(getID):
p2l = py2psql("127.0.0.1","5432","ckan_default","public.user","ckan_default","ckan")
data = p2l.select({"id":getID},["organ"],asdict=True)
return data[0]["organ"]
# ...
__allowed_functions__ = [
# ...
'getGroupStr',
'getOrganizationStr',
'getGroupOrOrganizationLangStr',
'getLicenseLabel',
'checkChineseTag',
'checkLangTag',
'parsePostRequestBodyAsList',
'getPostRequestParamValue',
'getReq2OrgList',
'getUserState',
'setUserState',
'getUserOrgan',
同步至 NDC
- 透過 threading 方式及 lock 處理與國發會同步
# 加入函式庫
from py2psql import *
from REQUESTMETHOD2 import *
import thread
import threading
import time
import datetime
import urllib2
import json
#
# desc : system current time
# retn : return time string
#
def getSysTime(option):
if option == "date":
return str(datetime.datetime.now())[0:10]
elif option == "minute":
return str(datetime.datetime.now())[11:19]
else:
return str(datetime.datetime.now())[0:19]
#
# desc : transform time format
# retn : return time string
#
def transTime(option, getDatetime):
if option == "date":
return str(getDatetime)[0:10]
elif option == "minute":
return str(getDatetime)[11:19]
else:
return str(getDatetime)[0:19]
#
# desc : get corresponding action for front html btn and also current state of each action
# retn : { "show" : "" , "clicking" : "", "note" : "" }
# |- show : before clicking, text is note
# |- clicking : after clicking, text is note
#
def syncNDCState(dbHost, dbPort, dbDB, dbTB, dbUser, dbPwd, pkg):
# connect to postgresql
p2l = py2psql(dbHost, dbPort, dbDB, dbTB, dbUser, dbPwd)
# select conditions
data = p2l.select({"cdcid":pkg[u"id"]},["state","operation","beginning","progress"],asdict=True)
# set operation
retState = {"show" : "" , "clicking" : "", "note" : ""}
# state = {"none"|"existing"}
# none : not in ndc databases
# existing : already in ndc databases
# len(data) < 1 : not in postgresql dataset (untracking)
if len(data) < 1 or data[0]["state"] == "none":
# cond : not existing in ndc, and it is not submitted to NDC yet
# clicking action : post (create)
# len(data) < 1 : not in postgresql dataset (untracking)
if len(data) < 1 or data[0]["operation"] == "none":
retState["show"] = "submit"
retState["clicking"] = "post"
retState["note"] = "First Submit"
# cond : not existing in ndc, clicking to sync and a success sync
# this cond would be transformed to { state : "existing", clicking : "success", note : "" }
# clicking action : put (update)
elif data[0]["operation"] == "success":
retState["show"] = "success"
retState["clicking"] = "put"
retState["note"] = "Success in " + transTime("date", data[0]["beginning"])
# cond : not existing in ndc, clicking to sync and a failure sync, this cond would be more action
# clicking action : post (create)
elif data[0]["operation"] == "failure":
retState["show"] = "failure"
retState["clicking"] = "post"
retState["note"] = "Failure in " + transTime("date", data[0]["beginning"])
# cond : not existing in ndc, clicking to sync and is still in syncing
# clicking action : no action
elif data[0]["operation"] == "syncing":
retState["show"] = "sync"
retState["clicking"] = "sync"
retState["note"] = "Syncing (" + data[0]["progress"] + ") "
elif data[0]["state"] == "existing":
# cond : existing in ndc, clicking to sync and a success sync
# clicking action : put (update)
if data[0]["operation"] == "success":
retState["show"] = "success"
retState["clicking"] = "put"
retState["note"] = "Success in " + transTime("date", data[0]["beginning"])
# cond : existing in ndc, clicking to sync and a failure sync
# clicking action : put (update)
elif data[0]["operation"] == "failure":
retState["show"] = "failure"
retState["clicking"] = "put"
retState["note"] = "Failure in " + transTime("date", data[0]["beginning"])
# cond : existing in ndc, clicking to sync and is still in syncing
# clicking action : no action
elif data[0]["operation"] == "syncing":
retState["show"] = "sync"
retState["clicking"] = "sync"
retState["note"] = "Syncing (" + data[0]["progress"] + ") "
# cond : existing in ndc, but not submitted first in the local postgresql yet
elif data[0]["operation"] == "none":
retState["show"] = "success"
retState["clicking"] = "put"
retState["note"] = "Success in " + transTime("date", data[0]["beginning"])
elif data[0]["state"] == "deleted":
# cond : re-POST after deleting dataset from NDC
# clicking action : no action
if data[0]["operation"] == "syncing":
retState["show"] = "sync"
retState["clicking"] = "sync"
retState["note"] = "Syncing (" + data[0]["progress"] + ") "
# cond : after doing deleting from NDC
# clicking action : re-POST
else:
retState["show"] = "deleted"
retState["clicking"] = "post"
retState["note"] = "Deleted on " + transTime("date", data[0]["beginning"])
return retState
#
# def : multithreading POST/PUT/DELETE
#
class ASSEMBLEDATA:
# -------------------------------------------------------
# private
# -------------------------------------------------------
__pkg = ""
__categoryCode = "B00"
__publisherOrgCode = "A21010000I"
__publisherOID = "2.16.886.101.20003.20065.20021"
__organization = u'衛生福利部疾病管制署'
__publisher = u'衛生福利部疾病管制署'
__license = u'政府資料開放授權條款-第1版'
__licenseURL = '/license'
__spatial = u'臺灣'
__dbID = ''
#
# desc : translate content
#
def __getLangContent(self, option, value):
if option == "cost":
if value == u"free":
return u'免費'
else:
return u'付費'
elif option == "freq":
if value == u"day":
return u'每日'
elif value == u"month":
return u'每月'
elif value == u"year":
return u'每年'
elif value == u"once":
return u'不更新'
elif value == u"non-scheduled":
return u'不定期'
#
# desc : transform datetime
#
def __transformTime(self, option, getStr):
if option == "issued":
return datetime.datetime((int)(getStr[0:4]), (int)(getStr[5:7]), (int)(getStr[8:10]))
elif option == "modified":
return datetime.datetime((int)(getStr[0:4]), (int)(getStr[5:7]), (int)(getStr[8:10]), (int)(getStr[11:13]), (int)(getStr[14:16]), (int)(getStr[17:19]))
#
# desc : find modified or created time from resources
#
def __findModifiedTime(self):
lastModified = ""
tmpTime = ""
for items in self.__pkg[u'resources']:
tmpTime = items['last_modified'] or items['created']
if tmpTime > lastModified:
lastModified = tmpTime
return lastModified
#
# desc : prepare tags
#
def __prepareTags(self):
allKeyList = []
for item in self.__pkg[u'tags']:
if item[u'display_name'] not in allKeyList:
allKeyList.append(item[u'display_name'])
return allKeyList
#
# desc : prepare resources
#
def __prepareRSC(self):
allResourceList = []
tmpRSC = {}
# for count resources
index = 1
for item in self.__pkg[u'resources']:
# prepare count string YYY
tmpIndex = str(index)
for count in range(len(str(index)),3,1):
tmpIndex = '0' + tmpIndex
tmpRSC = {\
"resourceID": self.__publisherOrgCode + "-" + self.__dbID + "-" + tmpIndex,\
"resourceDescription": item[u'description'],\
"format": item[u'format'],\
"resourceModified": str(self.__transformTime("modified",item[u'last_modified'] or item[u'created'])),\
"downloadURL": item[u'url'],\
"metadataSourceOfData": "",\
"characterSetCode": "UTF-8"
}
allResourceList.append(tmpRSC)
index += 1
return allResourceList
#
# desc : get id of the package for the identifier
#
def __getPKGID(self, dbHost, dbPort, dbDB, dbTB, dbUser, dbPwd):
# connect to postgresql
p2l = py2psql(dbHost, dbPort, dbDB, dbTB, dbUser, dbPwd)
tmpID = ""
if method == "post":
# select conditions
#data = p2l.select({"cdcid":self.__pkg[u"id"]},["id"],asdict=True)
p2l.execsql("select max(ndcid) as crtid from ndcsync;", True, {})
# set id
#tmpID = str(data[0]["id"])
tmpID = str((int)(p2l.status()['data'][0]['crtid'].split('-')[1]) + 1)
elif method == "put":
# select conditions
#data = p2l.select({"cdcid":self.__pkg[u"id"]},["ndcid"],asdict=True)
p2l.execsql("select ndcid from ndcsync where cdcid = %(cid)s;", True, {'cid' : self.__pkg[u'id']})
# set id
#tmpID = str(data[0]["id"])
tmpID = str((int)(p2l.status()['data'][0]['ndcid'].split('-')[1]))
# prepare package id string to XXXXXX
for index in range(len(str(tmpID)),6,1):
#if index == 5:
# tmpID = '9' + tmpID
# continue
tmpID = '0' + tmpID
return tmpID
# -------------------------------------------------------
# public
# -------------------------------------------------------
# constructor
def __init__(self, dbHost, dbPort, dbDB, dbTB, dbUser, dbPwd, getPKG, method):
# constant
self.__categoryCode = "B00"
self.__publisherOrgCode = "A21010000I"
self.__publisherOID = "2.16.886.101.20003.20065.20021"
self.__organization = u'衛生福利部疾病管制署'
self.__publisher = u'衛生福利部疾病管制署'
self.__license = u'政府資料開放授權條款-第1版'
self.__licenseURL = '/license'
self.__spatial = u'臺灣'
# outer resource
self.__pkg = getPKG
# database id, must be after self.__pkg = getPKG
self.__dbID = self.__getPKGID(dbHost, dbPort, dbDB, dbTB, dbUser, dbPwd, method)
# assemble POST or PUT data
def assemblePOSTOrPUTData(self):
postOrPUTData = {}
postOrPUTData = {\
"categoryCode": self.__categoryCode,\
"identifier": self.__publisherOrgCode + "-" + self.__dbID,\
"title": self.__pkg[u'c_title'],\
"description": self.__pkg[u'cd_notes'],\
"fieldDescription": self.__pkg[u'cm_notes'],\
"type": self.__pkg[u'data_type'],\
"license": self.__license,\
"licenseURL": self.__licenseURL,\
"cost": self.__getLangContent("cost",self.__pkg[u'fee']),\
"costURL": "",\
"costLaw": "",\
"organization": self.__organization,\
"organizationContactName": self.__pkg[u'author'],\
"organizationContactPhone": self.__pkg[u'author_phone'],\
"organizationContactEmail": self.__pkg[u'author_email'],\
"publisher": self.__publisher,\
"publisherContactName": self.__pkg[u'author'],\
"publisherContactPhone": self.__pkg[u'author_phone'],\
"publisherContactEmail": self.__pkg[u'author_email'],\
"publisherOID": self.__publisherOID,\
"publisherOrgCode": self.__publisherOrgCode,\
"accrualPeriodicity": self.__getLangContent("freq",self.__pkg[u'updated_freq']),\
"temporalCoverageFrom": "",\
"temporalCoverageTo": "",\
"issued": str(self.__transformTime("issued", self.__pkg[u'pub_time'])),\
"modified": str(self.__transformTime("modified", self.__findModifiedTime())),\
"spatial": self.__spatial,\
"language": "",\
"landingPage": "",\
"keyword": self.__prepareTags(),\
"numberOfData": "",\
"notes": "",\
"distribution": self.__prepareRSC()\
}
return postOrPUTData
#
# desc : check dataset existing in the postgresql server
# retn : 0 (failure) or 1 (success : already existing or creating one)
#
def syncNDCInitDataset(dbHost, dbPort, dbDB, dbTB, dbUser, dbPwd, pkg):
# connect to postgresql
p2l = py2psql(dbHost, dbPort, dbDB, dbTB, dbUser, dbPwd)
# select conditions
data = p2l.select({"cdcid":pkg[u"id"]},[],asdict=True)
if len(data) > 0:
# already exisiting in the local postgresql database
return 1
else:
# not in local postgresql database
return p2l.insert({ "cdcid" : pkg[u"id"], "state": u"none", "operation": u"none", "beginning": datetime.datetime.now() })
# -----------------------------------------------------------------------------------
# html context
# show = {"success"|"failure"|"sync"|"submit"} would be button style in html page
# clicking = { "post"|"put"|"sync" }, means the action taken for the next step
#
# POST (create)
# |- http://data.gov.tw/api/v1/rest/dataset
# |- Method=POST
#
# PUT (update)
# |- http://data.gov.tw/api/v1/rest/dataset/{identifier}
# |- Method=PUT
# |- example : http://data.gov.tw/api/v1/rest/dataset/A41000000G-000001
#
# DELETE (delete)
# |- http://data.gov.tw/api/v1/rest/dataset/{identifier}
# |- Method=DELETE
# |- example : http://data.gov.tw/api/v1/rest/dataset/A41000000G-000001
#
# postgresql database
# TABLE ndcsync schema
# state = {"none"|"existing"|"deleted"} stands for ndc database
# operation = {"none"|"success"|"failure"|"syncing"} means current updating status
# -----------------------------------------------------------------------------------
#
# desc : define in helper function
# getStatus = SYNCNDC("127.0.0.1", "5432", "ckan_default", "public.ndcsync", "ckan_default", "ckan", pkg, "http://data.gov.tw/api/v1/rest/dataset", "check")
# retn :
# |- retState = {"show" : "failure" , "clicking" : "", "note" : ""}
# |- show : button show (not clicking)
# |- clicking : button show (after clicking)
# |- note : text on the button
# multiprocessing method:
# |- { "post"|"put"|"sync"|"deleted" }
#
def SYNCNDC(dbHost, dbPort, dbDB, dbTB, dbUser, dbPwd, getPKG, tgtSrc, tgtMtd, *args):
# dbHost : postgresql server host
# dbPort : postgresql server port
# dbDB : postgresql server database
# dbTB : postgresql server table
# dbUser : postgresql server user
# dbPwd : postgresql server password
# getPKG : source package
# tgtSrc : target source url
# tgtMtd : target operaiton method, {"check", "delete"}
# |- check : auto-check
# |- delete : delete operation
# first of all : initialize postgresql database
status = syncNDCInitDataset(dbHost, dbPort, dbDB, dbTB, dbUser, dbPwd, getPKG)
if status == 0:
# initial database went error, this would be preferred to do another try in the next time
return;
# POST Data preparation
if tgtMtd == "delete":
try:
# object to record each steps for syncing with NDC
p2l = py2psql(dbHost, dbPort, dbDB, dbTB, dbUser, dbPwd)
# write current state to NDC table in postgresql db server
p2l.update({\
"operation" : u"syncing".lower(), \
"progress" : u"50%", \
u"beginning" : datetime.datetime.now()\
},{"cdcid" : getPKG[u'id']})
# start delete from NDC
ndcid = p2l.select({"cdcid": getPKG[u'id']},["ndcid"],asdict=True)
delFromNDC = SENDREQUEST(\
tgtSrc + "/" + ndcid[0][u'ndcid'], \
{"Authorization" : "api-key"}, \
{},\
"DELETE"\
)
#time.sleep(60)
if json.loads(delFromNDC.response()["response"])['success']:
#if True:
# success POST
# write state to postgresql db server
p2l.update({\
"operation" : u"success".lower(), \
"state" : u"deleted", \
"code" : str(delFromNDC.response()["response"]), \
"progress" : u"100%", \
u"ending" : datetime.datetime.now()\
},{"cdcid" : getPKG[u'id'], "ndcid" : ndcid[0][u'ndcid']})
else:
# failure POST
p2l.update({\
"operation" : u"failure".lower(), \
"code" : str(delFromNDC.response()["response"]), \
"progress" : u"100%", \
u"ending" : datetime.datetime.now()\
},{"cdcid" : getPKG[u'id'], "ndcid" : ndcid[0][u'ndcid']})
except:
p2l.update({\
"operation" : u"failure".lower(), \
"code" : u'unexcepted failure in delete', \
"progress" : u"100%", \
u"ending" : datetime.datetime.now()\
},{"cdcid" : getPKG[u'id'], "ndcid" : ndcid[0][u'ndcid']})
elif tgtMtd == "check":
# get current state
getStatue = syncNDCState(dbHost, dbPort, dbDB, dbTB, dbUser, dbPwd, getPKG)
# object to record each steps for syncing with NDC
p2l = py2psql(dbHost, dbPort, dbDB, dbTB, dbUser, dbPwd)
# take action based on clicking
if getStatue["clicking"] == "post":
try:
# get post json data
postData = ASSEMBLEDATA(dbHost, dbPort, dbDB, dbTB, dbUser, dbPwd, getPKG, "post")
# write current state to NDC table in postgresql db server
p2l.update({\
"operation" : u"syncing".lower(), \
"progress" : u"50%", \
u"beginning" : datetime.datetime.now()\
},{"cdcid" : getPKG[u'id']})
# start post to NDC
post2NDC = SENDREQUEST(\
tgtSrc, \
{"Authorization" : "api-key"}, \
postData.assemblePOSTOrPUTData(),\
"POST"\
)
#time.sleep(3)
#if u'error' not in json.loads(post2NDC.response()["response"]) or u'錯誤' not in json.loads(post2NDC.response()["response"]) or json.loads(post2NDC.response()["response"])['success']:
if json.loads(post2NDC.response()["response"])['success']:
# success POST
# write state to postgresql db server
p2l.update({\
"operation" : u"success".lower(), \
#"ndcid" : postData.assemblePOSTOrPUTData()["identifier"], \
"ndcid" : json.loads(post2NDC.response()["response"])['result']['identifier'], \
"state" : u"existing", \
"code" : str(post2NDC.response()["response"]), \
"progress" : u"100%", \
u"ending" : datetime.datetime.now()\
},{"cdcid" : getPKG[u'id']})
else:
# failure POST
p2l.update({\
"operation" : u"failure".lower(), \
#"ndcid" : postData.assemblePOSTOrPUTData()["identifier"], \
"ndcid" : json.loads(post2NDC.response()["response"])['error']['identifier'], \
"code" : str(post2NDC.response()['response']), \
"progress" : u"100%", \
u"ending" : datetime.datetime.now()\
},{"cdcid" : getPKG[u'id']})
except:
# failure POST
p2l.update({\
"operation" : u"failure".lower(), \
#"ndcid" : postData.assemblePOSTOrPUTData()["identifier"], \
"ndcid" : u'', \
"code" : u'unexcepted failure in POST', \
"progress" : u"100%", \
u"ending" : datetime.datetime.now()\
},{"cdcid" : getPKG[u'id']})
elif getStatue["clicking"] == "put":
try:
# get put json data
putData = ASSEMBLEDATA(dbHost, dbPort, dbDB, dbTB, dbUser, dbPwd, getPKG, "put")
# write current state to NDC table in postgresql db server
p2l.update({\
"operation" : u"syncing".lower(), \
"progress" : u"50%", \
u"beginning" : datetime.datetime.now()\
},{"cdcid" : getPKG[u'id']})
# start put to NDC
ndcid = p2l.select({"cdcid": getPKG[u'id']},["ndcid"],asdict=True)
p2l.update({\
"operation" : u"syncing".lower(), \
"code" : u'prepare to NDC', \
"progress" : u"100%", \
u"ending" : datetime.datetime.now()\
},{"cdcid" : getPKG[u'id'], "ndcid" : ndcid[0][u'ndcid']})
put2NDC = SENDREQUEST(\
tgtSrc + "/" + ndcid[0][u'ndcid'], \
{"Authorization" : "api-key"}, \
putData.assemblePOSTOrPUTData(),\
"PUT"\
)
#time.sleep(60)
p2l.update({\
"operation" : u"syncing".lower(), \
"code" : u'syncing finishs execution, ready to write state', \
"progress" : u"100%", \
u"ending" : datetime.datetime.now()\
},{"cdcid" : getPKG[u'id'], "ndcid" : ndcid[0][u'ndcid']})
if json.loads(put2NDC.response()["response"])['success']:
#if True:
# success PUT
# write state to postgresql db server
p2l.update({\
"operation" : u"success".lower(), \
"state" : u"existing", \
"code" : str(put2NDC.response()["response"]), \
"progress" : u"100%", \
"ending" : datetime.datetime.now()\
},{"cdcid" : getPKG[u'id'], "ndcid" : ndcid[0][u'ndcid']})
else:
# failure PUT
p2l.update({\
"operation" : u"failure".lower(), \
"code" : str(put2NDC.response()["response"]), \
"progress" : u"100%", \
"ending" : datetime.datetime.now()\
},{"cdcid" : getPKG[u'id'], "ndcid" : ndcid[0][u'ndcid']})
except:
# failure PUT
p2l.update({\
"operation" : u"failure".lower(), \
"code" : u'PUT uncepted error', \
"progress" : u"100%", \
u"ending" : datetime.datetime.now()\
},{"cdcid" : getPKG[u'id'], "ndcid" : ndcid[0][u'ndcid']})
else:
# getStatue["clicking"] == "sync"
# this state is in syncing
# there is not necessary to take any further actions
return
# remove from locked object
link.acquire()
execThread.remove(getPKG[u'id'])
link.release()
#
# desc : activate syncing to NDC by clicking
# clicking beginning from here
# exam : actSYNC2NDC("127.0.0.1", "5432", "ckan_default", "public.ndcsync", "ckan_default", "ckan", pkg, "http://data.gov.tw/api/v1/rest/dataset", "check")
#
execThread = []
link = threading.Lock()
def actSYNC2NDC(dbHost, dbPort, dbDB, dbTB, dbUser, dbPwd, getPKG, tgtSrc, tgtMtd):
#thread.start_new_thread(SYNCNDC, (dbHost, dbPort, dbDB, dbTB, dbUser, dbPwd, getPKG, tgtSrc, tgtMtd))
#SYNCNDC(dbHost, dbPort, dbDB, dbTB, dbUser, dbPwd, getPKG, tgtSrc, tgtMtd)
global execThread, link
link.acquire()
if getPKG['id'] not in execThread:
execThread.append(getPKG['id'])
t = threading.Thread(target=SYNCNDC, args=(dbHost, dbPort, dbDB, dbTB, dbUser, dbPwd, getPKG, tgtSrc, tgtMtd))
t.start()
link.release()
# ...
__allowed_functions__ = [
# ...
'setUserState',
'getUserOrgan',
'getSysTime',
'transTime',
'syncNDCState',
'syncNDCInitDataset',
'SYNCNDC',
'actSYNC2NDC',
帳號申請與變更表單
#
# desc : get account info for account application
#
def getAccInfo(option, getReq):
if option == "fullName":
p2l = py2psql("127.0.0.1","5432","ckan_default","public.user","ckan_default","ckan")
data = p2l.select({"name" : getReq}, ["fullname"], asdict=True)
return unicode(data[0]["fullname"], 'utf-8')
elif option == "getDate":
return str(datetime.datetime.now())[0:10]
elif option == "email":
p2l = py2psql("127.0.0.1","5432","ckan_default","public.user","ckan_default","ckan")
data = p2l.select({"name" : getReq}, ["email"], asdict=True)
return unicode(data[0]["email"], 'utf-8')
elif option == "org":
p2l = py2psql("127.0.0.1","5432","ckan_default","public.group","ckan_default","ckan")
data = p2l.select({"name": getReq},["title"],asdict=True)
return unicode(data[0]["title"], 'utf-8')
# 加入允許清單
__allowed_functions__ = [
'getAccInfo',
]