iPhone push 테스트

Posted at 2011/05/13 18:41// Posted in mobile

http://code.google.com/p/apns-python-wrapper/

pem 만들기

openssl pkcs12 -clcerts -nokeys -out cert.pem -in cert.p12
openssl pkcs12 -nocerts -out key.pem -in key.p12

# passphase 제거
openssl rsa -in key.pem -out key.unencrypted.pem

# pem 합치기
cat cert.pem key.unencrypted.pem > ck.pem




deviceToken = "~~~"

import binascii
deviceToken = binascii.unhexlify(deviceToken)
print deviceToken

from APNSWrapper import *

wrapper = APNSNotificationWrapper('ck.pem', True)

message = APNSNotification()
message.token(deviceToken)
message.alert("!!")

wrapper.append(message)
wrapper.notify()
이올린에 북마크하기
2011/05/13 18:41 2011/05/13 18:41

페이스북 억세스 토큰을 얻는 것은 트위터에 비해 조금 귀찮습니다.
브라우저를 사용해야 하기 때문입니다~
 

페이스북 억세스 토큰을 얻어내는 코드에 파이썬 브라우저 모듈인 mechanize 를 붙여보았습니다



# vi: set sw=4 sts=4 expandtab:
import os
import os.path
import json
import urllib2
import urllib
import urlparse
import BaseHTTPServer
import webbrowser
import mechanize
CODE_BEGIN = 'code='
CODE_END = '"'

APP_ID = '페이스북_앱_아이디'
APP_SECRET = '페이스북_앱_시크릿'
ENDPOINT = 'graph.facebook.com'
REDIRECT_URI = '콜백처리_URL'
ACCESS_TOKEN = None
LOCAL_FILE = '.fb_access_token'

STATUS_TEMPLATE = u"{name}\033[0m: {message}"

def get_url(path, args=None):
args = args or {}
if ACCESS_TOKEN:
args['access_token'] = ACCESS_TOKEN
if 'access_token' in args or 'client_secret' in args:
endpoint = "https://"+ENDPOINT
else:
endpoint = "http://"+ENDPOINT
return endpoint+path+'?'+urllib.urlencode(args)

def get(path, args=None):
return urllib2.urlopen(get_url(path, args=args)).read()


class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):

def do_GET(self):
global ACCESS_TOKEN
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()

code = urlparse.parse_qs(urlparse.urlparse(self.path).query).get('code')
code = code[0] if code else None
if code is None:
self.wfile.write("Sorry, authentication failed.")
sys.exit(1)
response = get('/oauth/access_token', {'client_id':APP_ID,
'redirect_uri':REDIRECT_URI,
'client_secret':APP_SECRET,
'code':code})
ACCESS_TOKEN = urlparse.parse_qs(response)['access_token'][0]
open(LOCAL_FILE,'w').write(ACCESS_TOKEN)
self.wfile.write("You have successfully logged in to facebook. "
"You can close this window now.")

def print_status(item, color=u'\033[1;35m'):
print color+STATUS_TEMPLATE.format(name=item['from']['name'],
message=item['message'].strip())


def main(email, password):
url = get_url('/oauth/authorize',
{'client_id':APP_ID,
'redirect_uri':REDIRECT_URI,
'scope':'read_stream'})

browser = mechanize.Browser()
browser.set_handle_refresh(False)
browser.set_handle_robots(False)
cookies = mechanize.CookieJar()
browser.set_cookiejar(cookies)
response = browser.open(url)
open("response.html", "wb").write(response.get_data())
browser.addheaders = [('User-agent', 'Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.7 (KHTML, like Gecko) Chrome/7.0.517.41 Safari/534.7')]


try:
browser.select_form(predicate=lambda f:"login.php" in f.action and f.method.lower() == "post")
except mechanize.FormNotFoundError:
print "WRONG_LOGIN_PAGE"
return -1

browser.form["email"] = email
browser.form["pass"] = password

response = browser.submit()
responseData = response.read()
relocationPos = responseData.find("window.location.replace")
open("response2.html", "wb").write(responseData)

if relocationPos < 0:
try:
browser.select_form(predicate=lambda f:f.action.endswith("uiserver.php") and f.method.lower() == "post")
except mechanize.FormNotFoundError:
print "RETRY_LOGIN_LATER"
return -2

response = browser.submit(name="grant_clicked")
responseData = response.read()
relocationPos = responseData.find("window.location.replace")
open("response3.html", "wb").write(responseData)


if relocationPos > 0:
tagBeginPos = responseData.find(CODE_BEGIN, relocationPos)
if tagBeginPos > 0:
tagEndPos = responseData.find(CODE_END, tagBeginPos)

code = responseData[tagBeginPos+len(CODE_BEGIN):tagEndPos].decode("unicode-escape")

response = get('/oauth/access_token', {'client_id':APP_ID,
'redirect_uri':REDIRECT_URI,
'client_secret':APP_SECRET,
'code':code})
ACCESS_TOKEN = urlparse.parse_qs(response)['access_token'][0]
open(LOCAL_FILE,'w').write(ACCESS_TOKEN)
print "LOGIN_SUCCESS"
return 0
else:
print "UNKNOWN_REDIRECT"
return -4
else:
print "INVALID_CODE"
return -3

if __name__ == '__main__':
import sys
if len(sys.argv) >= 3:
sys.exit(main(sys.argv[1], sys.argv[2]))
else:
print "USAGE:"
print "\t%s [email] [password]" % os.path.split(sys.argv[0])[1]


UNKNOWN_REDIRECT 는 뭔가 페이스 북이 특수 기능 - 이메일 친구 스캔 하기 - 을 처리하기 위해

로그인 절차와는 상관없는 페이지를 보여주는 경우가 있습니다. 이 때는 진짜 웹 브라우저를 띄워서 처리해주는 수밖에 없을 듯 합니다.

끝 ~(-_-)~

이올린에 북마크하기(0) 이올린에 추천하기(0)
2011/03/31 17:26 2011/03/31 17:26

파이썬에서 트위터 날리기 tweepy

Posted at 2011/03/31 17:11// Posted in python/py-sns

tweepy 를 사용해서 트위터 OAuth 로그인을 한 다음 타임 라인을 보는 예제입니다~


USERNAME = "아이디"
PASSWORD = "비밀번호"

import tweepy

import re
roToken = re.compile("<\w+|>|/>|</\w+>|\w+|=|\"[^\"]+\"")

def GetTagAttrd(tokens, beginTag, endTag, curIndex, endIndex):
itokens = []
try:
curIndex = tokens.index(beginTag, curIndex)
except ValueError:
return curIndex, None

if curIndex >= endIndex:
return endIndex, None

while tokens[curIndex] != endTag:
itokens.append(tokens[curIndex])
curIndex += 1

return curIndex, dict(zip(itokens[1::3], [val[1:-1] for val in itokens[3::3]]))

from urllib import *
from urllib2 import *

def Main():
CONSUMER_KEY = '트위터_앱_키'
CONSUMER_SECRET = '트위터_앱_시크릿'

auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
aurl = auth.get_authorization_url()
data = urlopen(aurl).read()
lines = data.splitlines()
tokens = []
for line in lines:
tokens += roToken.findall(line)

curIndex, formd = GetTagAttrd(tokens, "<form", ">", 0, len(tokens))
endIndex = tokens.index("</form>", curIndex)
actionURL = formd["action"]

valued = {}
while True:
curIndex, inputd = GetTagAttrd(tokens, "<input", "/>", curIndex, endIndex)
if inputd:
if inputd["type"] == "hidden":
valued[inputd["name"]] = inputd["value"]
elif inputd["type"] == "text":
valued[inputd["name"]] = USERNAME
elif inputd["type"] == "password":
valued[inputd["name"]] = PASSWORD
elif inputd["type"] == "submit":
valued["submit"] = inputd["value"]
else:
print inputd
else:
break

params = urlencode(valued)
req = Request(actionURL, params)
res = urlopen(req)
data = res.read()
lines = data.splitlines()
tokens = []
for index, line in enumerate(lines):
if "div" in line and "oauth_pin" in line:
index += 1
break

verifier = lines[index].strip()
auth.get_access_token(verifier)

api = tweepy.API(auth)

if 0:
api.update_status(u"~tweepy test")
else:
for s in api.user_timeline():
print s.text.encode("utf8")

Main()
이올린에 북마크하기(0) 이올린에 추천하기(0)
2011/03/31 17:11 2011/03/31 17:11

IronPython-2.6.1

Posted at 2010/06/10 18:10// Posted in IronPython

http://ironpython.net/

오오 -ㅁ-; iron python 1.x 의 허접함에 실망해서 거의 신경 쓰지 않고 있었는데...


엄청나게 강한 모습으로 다시 돌아왔습니다.

최근 앞으로 변화되는 플랫폼에 대응하기 위해 아래 3가지로 고민하고 있었는데...

1. HTML5 + JavaScript

2. FLASH + Action Script

3. Unity3D + JavaScript, CLR 언어

4. nebula3 + C++



사실 마음에 내키는게 별로 없었거든요.

HTML5 는 핵심인 canvas 기능에 대해 MS 가 딴청부리는 중인데다;
JavaScript 무조건 소스 공개 스타일이 게임에는 적합하지 않아보였고


FLASH 는 애플에서 노골적으로 거부를 하는 상황이죠;

Unity3D 는 과연 커스터마이징이 어느정도 될 것인가... 문제 발생시 대처가 어느정도나 가능할까...
(무엇보다 설치 후 툴이 실행 안되는 모습에 신뢰도가 -ㅅ-;; DEP 문제라는 것 같은데... )

nebula3 는 코어는 맘에드는데 최근 업데이트가 거의 없는데다가;
과연 다른 플랫폼에 대응하려면 엄청난 노력이 필요할것 같더군요.




제가 생각하는 프로그램을 만드는 가장 좋은 방법은

일단 스크립트 언어로 편하게 프로토 타입을 만든 다음
필요한 부분만 저수준 언어로 확장 모듈을 만드는 방법이거든요.


그런데 c 나 c++ 만 10년 정도 하신 분들은 새로운 언어에 대한 두려움아 꽤 많은 것 같더라구요.
더군다나 통합 디버깅 환경도 지원이 안되면... 모르겠다 -ㅁ-)~ 이런 결과가...;

이런 점에서 IronPython-2.6.1 버전은 꽤 괜찮은 솔류션으로 보입니다.

홈페이지 첫화면에 떠있는 대형 문구!

IronPython Tools


for Visual Studio 2010


오오 -ㅁ-);

다운로드 받아서 돌려보니

단독 실행 파일 생성 을 지원하더군요!!



ipy.exe Tools\Scripts\pyc.py /out:test /target:exe /main:test.py /platform:x86


Windows 뿐만 아니라 Mono 가 지원되는 유닉스 계열 운영 체제나 모바일 운영체제도 지원되죠
동일한 바이너리로 말이죠! -ㅁ-)! 오오;


파이썬 모듈은 ctypes 도 가능!


IronPython 2.6.1 (2.6.10920.0) on .NET 2.0.50727.4927
Type "help", "copyright", "credits" or "license" for more information.
>>> import ctypes
>>> ctypes.cdll.msvcrt.puts(b"HAHA")
HAHA
0
>>>


ctypes 가 된다는 말은 .NET 안쓰고
기존에 c/c++ 로 작성된 dll 을 그냥 불러와서 사용할 수 있다는 이야기거든요! 확장 모듈 만들기가 쉽다는 말이죠

>ㅁ<) 와하하~



멀티 코어 시대에 GIL 때문에 난감한 CPython 과는 달리


멀티 쓰레딩도 어느정도 지원한다는 것 같고요~



다만 몇가지 문제가 있긴 한데...

그중 하나가 성능입니다.

2008 년 성능 비교 (음... ;; )
http://ironpython.codeplex.com/wikipage?title=IP20VsCPy25Perf&referringTitle=IronPython%20Performance&ProjectName=ironpython


2010 년 성능 비교 ( 아아-_-;; )
http://ironpython.codeplex.com/wikipage?title=IP261Net20VsCPy26Perf&referringTitle=IronPython%20Performance

2년이 지난 결과가 오히려 더 안 좋다는건 그만큼 CPython 성능이 좋아진걸로 받아드리도록 하죠. 흠흠;;


개별 성능 비교를 보면 극단적인 결과를 찾아볼 수 있습니다.

빠른건 2배 가까이 빠른데

느린건 (구체적으로 말하면 문자열 처리-_-) 2배 이상 느리네요;;


열심히 최적화하다보면 언젠가는 빨라지지 않을까 기대해 봅니다.
(왜 이렇게 느린지는 소스를 한번 뜯어 봐야 할 듯 합니다)



두번째 모듈은 아직까지 Python 모듈 포팅이 완벽하지 않습니다.
자주 사용되는 모듈 중심으로 70% 정도 진행된것 같은데...

신기하게도 제가 자주 사용하는 expat 이 빠졌더군요 T_T)~


덕분에 xml.dom.minidom 을 사용 못하고 있습니다 orz;


스크립트 언어를 쓰는 이상 느리거나 없는 건 만들어 쓰는게 당연하니
큰 문제는 없으리라고 생각됩니다~

이런 이유로 오늘부터 저는 IronPython 의 세계로 들어가겠습니다. 햐햐 -ㅂ-)~
이올린에 북마크하기(0) 이올린에 추천하기(0)
2010/06/10 18:10 2010/06/10 18:10

파이썬 설치 경로 알아내기

Posted at 2010/05/31 15:50// Posted in python/pyutils
작년부터 자동화된 빌드를 위해 파이썬 대신 파이널 빌더를 사용하고 있습니다.

cpascal 님 추천으로 사용하기 시작했는데, 스케쥴러를 사용해서 데일리 빌드도 할 수 있고

트레이에서 명령을 내릴 수도 있어서 꽤나 유용하게 사용하고 있습니다.


그런데 파이썬으로 만든 도구들을 실행할때가 문제더군요.

파이널 빌더에서도 파이썬 스크립트를 지원하긴 하는데,

임베딩 느낌인데다 사용 방법이 불편해서

지금까지는 그냥  "c:\python26 에 무조건 설치해라!" 라고 강요했었는데...;

요즘들어 cpascal 님을 비롯해서 여러 분들이 지나친 강요는 반발을 불러일으킨다라는 조언을 해주셔서

왼손잡이를 위한 방법을 찾아보기로 했습니다.


Modifying the module search path can also be done through the Windows registry under the keyHKLM\SOFTWARE\Python\PythonCore\version\PythonPath. Subkeys which have semicolon-delimited path strings as their default value will cause each path to be searched. Multiple subkeys can be created and are appended to the path in alphabetical order. A convenient registry editor is regedit (start it by typing “regedit” into Start ‣ Run).

메뉴얼 상에는 HKLM\SOFTWARE\Python\PythonCore\version\PythonPath 로 나와있지만, 이곳에는 다양한 모듈 경로가 들어있기 때문에

C:\Python\Python26\Lib;C:\Python\Python26\DLLs;C:\Python\Python26\Lib\lib-tk

HKLM\SOFTWARE\Python\PythonCore\version\InstallPath 를 사용하는 편이 더 좋아 보입니다~

C:\Python\Python26\

파이썬은 여러개 설치될 수 있기 때문에 어느 것이 디폴트 버전인가도 중요한 이슈입니다만


윈도우 버전은 확장자-아이콘 연결을 통해 알아내는 방법밖에 안 나오는군요.


일단 파이널 빌더에서는 지정한 버전을 실행하면 되니까 윈도우에서

정확한 파이썬 디폴트 버전을 알아내는 방법은 어물쩡 넘어가도록 하겠습니다 ㅋㅋ ~(-_-)~
이올린에 북마크하기(0) 이올린에 추천하기(0)
2010/05/31 15:50 2010/05/31 15:50

wxPython PathTreeCtrl

Posted at 2010/05/26 13:26// Posted in wxPython/wxTreeCtrl
트리 컨트롤은 디렉토리 구조를 표현할때 편리합니다.

사용자 삽입 이미지
















그런데 경로를 파싱해서 디렉토리를 만드는건 의외로 귀찮은 일이더라구요 = =)~

그래서 만들어본 예제입니다



# vi: set sw=4 sts=4 expandtab:
import wx
import os

class wxPathTreeCtrl(wx.TreeCtrl):
def __init__(self, *args, **kwargs):
wx.TreeCtrl.__init__(self, *args, **kwargs)

def InitRoot(self, rootPath):
self.branchd = {}
self.DeleteAllItems()
self.root = self.AddRoot(rootPath)
self.SetPyData(self.root, ("ROOT", rootPath))
return self.root

def AppendPath(self, path):
branch = path

branches = []
while branch:
branch, leaf = os.path.split(branch)
if branch in self.branchd:
break
elif branch:
branches.append(branch)

branches.reverse()

last = self.branchd.get(branch, self.root)
for branch in branches:
last = self.AppendItem(last, os.path.split(branch)[1])
self.SetPyData(last, ("DIR", branch))
self.branchd[branch] = last

item = self.AppendItem(last, os.path.split(path)[1])
self.SetPyData(item, ("FILE", path))
return item

def ExpandAllDirs(self):
self.ExpandDirs(self.root)

def ExpandDirs(self, node):
if self.GetPyData(node)[0] == "FILE":
pass
else:
children = list(self.GenChildren(node))
fileCount = len([child for child in children if self.GetPyData(child)[0] == "FILE"])
if 0 == fileCount:
self.Expand(node)

for child in children:
self.ExpandDirs(child)

def GetBranchd(self):
return self.branchd

def GenChildren(self, node):
child = self.GetFirstChild(node)[0]
while child:
yield child
child = self.GetNextSibling(child)

if __name__ == "__main__":

class TestFrame(wx.Frame):
def __init__(self, parent, title, size=(800, 600)):
wx.Frame.__init__(self, parent, -1, title, pos=(0, 0), size=size)
self.CentreOnScreen(wx.BOTH)

self.pathTreeCtrl = wxPathTreeCtrl(self)
self.pathTreeCtrl.InitRoot("root")
self.pathTreeCtrl.AppendPath("bin/main.exe")
self.pathTreeCtrl.AppendPath("data/char/pc/warrior/warriror.png")
self.pathTreeCtrl.AppendPath("data/char/pc/warrior/warriror2.png")
self.pathTreeCtrl.ExpandAllDirs()

class TestApp(wx.App):
def OnInit(self):
toolFrame = TestFrame(None, "TEST")
toolFrame.Show()
self.SetTopWindow(toolFrame)
return True

TestApp(redirect=False).MainLoop()


이올린에 북마크하기(0) 이올린에 추천하기(0)
2010/05/26 13:26 2010/05/26 13:26
사내에서 urlimport 를 perforce 와 연계해서 사용하고 있는 중 입니다.

문제는 프로그래머가 아닌 사용자가 urlimport 랑 p4python 을 설치하는 것은 꽤나 귀찮은 일이더군요.

urlimport 의 경우는 python site-packages 디렉토리를 찾아 복사해줘야 하고
p4python 은  커맨드라인에서 setup.py install 을 실행해야하는데...;
... orz;;

가만히 생각해보니 파이썬 모듈들은 전부 msi 로 배포된다는 사실이 떠오르더군요.

게다가 촌스러운 모양도 거의 동일하기 때문에;
아무래도 파이썬에서 제공해주는 기능이 아닐까 생각되더라구요.

열심히 검색해 본 결과!

setup.py bdist_wininst


이렇게 실행하면 윈도우즈용 인스톨러가 만들어지더군요 -ㅁ-; 오오오;




이올린에 북마크하기(0) 이올린에 추천하기(0)
2010/04/14 17:58 2010/04/14 17:58
http://dev.naver.com/projects/urlimport/

SVN
  • svn checkout --username anonsvn https://dev.naver.com/svn/urlimport
  • The password is 'anonsvn'

이올린에 북마크하기(0) 이올린에 추천하기(0)
2010/03/26 17:48 2010/03/26 17:48

python urlimport 0.55m

Posted at 2010/03/21 19:00// Posted in python/py-urlimport
회사 업무에 쫓겨서 퍼포스 테스트만 했더니 T_T)~

수정한 사항에 버그가 있었네요

다행히 방명록에 split_url 버그를 알려주신 분이 있어서 바로 수정본 올립니다.

http://www.imp17.com/python/urlimport-0.55m.py (myevan version)

테스트 스크립트를 하나 만들어 봐야겠습니다~


오늘 답장이~

"\\컴퓨터\경로" 로 사용하는윈도우 파일 공유 프로토콜이
일부 구현에서 "//컴퓨터/경로" 식으로 접근하기 때문에 perforce 주소 형식과 충돌이 생길 수 있다는 군요.

아래는 alex 님이 퍼포스 주소 사용시에는 "p4://depot/path" 식으로 수정한 버전입니다.

http://www.imp17.com/python/urlimport.py (alex version)
http://www.imp17.com/python/urlimport-0.53n.py (alex version)

심심할때 svn+ssh 연동도 시켜봐야겠어요~

이올린에 북마크하기(0) 이올린에 추천하기(0)
2010/03/21 19:00 2010/03/21 19:00

python urlimport 0.54m

Posted at 2010/03/19 13:36// Posted in python/py-urlimport
얼마전 방명록을 통해 만난 alex 님으로부터 urlimport 향상 버전을 받았습니다.

아무 생각 없이 붙였던 캐슁 기능과 퍼포스 연동 기능을 깔끔하게 정리해주셨더라구요 -_-)b

http://www.imp17.com/python/urlimport-0.53n.py (from alex)

alex 님 요청에 따라 퍼포스 관련 테스트 결과 생긴 자잘한 버그만 수정해봤습니다.

http://www.imp17.com/python/urlimport-0.54m.py (from myevan)

아... 몇천 km 떨어진 곳에 계신 분과 작업하니까 재밌네요 >ㅁ<)~

정말 바램대로 기본 모듈로 들어가면 좋겠어요. 햐햐



이올린에 북마크하기(0) 이올린에 추천하기(0)
2010/03/19 13:36 2010/03/19 13:36
1 2 3 4 5 ... 11