X Tutup
Skip to content

Commit 66a3564

Browse files
committed
Breaking all twitter classes out into their own package.
This is done without breaking exsiting functionality or imports by doing imports in the twitter/__init__.py file. user.py imports Status and status.py import User In order to prevent cyclic import errors, they are imported only if they are actually used. Also, sys was not imported in the setup.py file, causing setup.py to fail if setuptools can't be imported.
1 parent e716410 commit 66a3564

File tree

13 files changed

+2471
-2362
lines changed

13 files changed

+2471
-2362
lines changed

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ def Main():
6565
METADATA.update(SETUPTOOLS_METADATA)
6666
setuptools.setup(**METADATA)
6767
except ImportError:
68+
import sys
6869
sys.stderr.write("Could not import setuptools, using distutils")
6970
sys.stderr.write("NOTE: You will need to install dependencies manualy")
7071
import distutils.core

twitter/__init__.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#!/usr/bin/env python
2+
#
3+
# vim: sw=2 ts=2 sts=2
4+
#
5+
# Copyright 2007 The Python-Twitter Developers
6+
#
7+
# Licensed under the Apache License, Version 2.0 (the "License");
8+
# you may not use this file except in compliance with the License.
9+
# You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing, software
14+
# distributed under the License is distributed on an "AS IS" BASIS,
15+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
# See the License for the specific language governing permissions and
17+
# limitations under the License.
18+
19+
'''A library that provides a Python interface to the Twitter API'''
20+
21+
__author__ = 'python-twitter@googlegroups.com'
22+
__version__ = '1.2'
23+
24+
try:
25+
# Python >= 2.6
26+
import json as simplejson
27+
except ImportError:
28+
try:
29+
# Python < 2.6
30+
import simplejson
31+
except ImportError:
32+
try:
33+
# Google App Engine
34+
from django.utils import simplejson
35+
except ImportError:
36+
raise ImportError, "Unable to load a json library"
37+
# parse_qsl moved to urlparse module in v2.6
38+
try:
39+
from urlparse import parse_qsl, parse_qs
40+
except ImportError:
41+
from cgi import parse_qsl, parse_qs
42+
43+
try:
44+
from hashlib import md5
45+
except ImportError:
46+
from md5 import md5
47+
48+
from _file_cache import _FileCache
49+
from error import TwitterError
50+
from direct_message import DirectMessage
51+
from hashtag import Hashtag
52+
from parse_tweet import ParseTweet
53+
from trend import Trend
54+
from url import Url
55+
from status import Status
56+
from user import User
57+
from list import List
58+
from api import Api

twitter/_file_cache.py

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
#!/usr/bin/python
2+
import md5
3+
import os
4+
import re
5+
import tempfile
6+
7+
class _FileCacheError(Exception):
8+
'''Base exception class for FileCache related errors'''
9+
10+
class _FileCache(object):
11+
12+
DEPTH = 3
13+
14+
def __init__(self,root_directory=None):
15+
self._InitializeRootDirectory(root_directory)
16+
17+
def Get(self, key):
18+
path = self._GetPath(key)
19+
if os.path.exists(path):
20+
return open(path).read()
21+
else:
22+
return None
23+
24+
def Set(self, key, data):
25+
path = self._GetPath(key)
26+
directory = os.path.dirname(path)
27+
if not os.path.exists(directory):
28+
os.makedirs(directory)
29+
if not os.path.isdir(directory):
30+
raise _FileCacheError('%s exists but is not a directory' % directory)
31+
temp_fd, temp_path = tempfile.mkstemp()
32+
temp_fp = os.fdopen(temp_fd, 'w')
33+
temp_fp.write(data)
34+
temp_fp.close()
35+
if not path.startswith(self._root_directory):
36+
raise _FileCacheError('%s does not appear to live under %s' %
37+
(path, self._root_directory))
38+
if os.path.exists(path):
39+
os.remove(path)
40+
os.rename(temp_path, path)
41+
42+
def Remove(self, key):
43+
path = self._GetPath(key)
44+
if not path.startswith(self._root_directory):
45+
raise _FileCacheError('%s does not appear to live under %s' %
46+
(path, self._root_directory ))
47+
if os.path.exists(path):
48+
os.remove(path)
49+
50+
def GetCachedTime(self, key):
51+
path = self._GetPath(key)
52+
if os.path.exists(path):
53+
return os.path.getmtime(path)
54+
else:
55+
return None
56+
57+
def _GetUsername(self):
58+
'''Attempt to find the username in a cross-platform fashion.'''
59+
try:
60+
return os.getenv('USER') or \
61+
os.getenv('LOGNAME') or \
62+
os.getenv('USERNAME') or \
63+
os.getlogin() or \
64+
'nobody'
65+
except (AttributeError, IOError, OSError), e:
66+
return 'nobody'
67+
68+
def _GetTmpCachePath(self):
69+
username = self._GetUsername()
70+
cache_directory = 'python.cache_' + username
71+
return os.path.join(tempfile.gettempdir(), cache_directory)
72+
73+
def _InitializeRootDirectory(self, root_directory):
74+
if not root_directory:
75+
root_directory = self._GetTmpCachePath()
76+
root_directory = os.path.abspath(root_directory)
77+
if not os.path.exists(root_directory):
78+
os.mkdir(root_directory)
79+
if not os.path.isdir(root_directory):
80+
raise _FileCacheError('%s exists but is not a directory' %
81+
root_directory)
82+
self._root_directory = root_directory
83+
84+
def _GetPath(self, key):
85+
try:
86+
hashed_key = md5(key).hexdigest()
87+
except TypeError:
88+
hashed_key = md5.new(key).hexdigest()
89+
90+
return os.path.join(self._root_directory,
91+
self._GetPrefix(hashed_key),
92+
hashed_key)
93+
94+
def _GetPrefix(self, hashed_key):
95+
return os.path.sep.join(hashed_key[0:_FileCache.DEPTH])
96+
97+
class ParseTweet:
98+
# compile once on import
99+
regexp = { "RT": "^RT", "MT":r"^MT", "ALNUM": r"(@[a-zA-Z0-9_]+)",
100+
"HASHTAG": r"(#[\w\d]+)", "URL": r"([http://]?[a-zA-Z\d\/]+[\.]+[a-zA-Z\d\/\.]+)" }
101+
regexp = dict((key,re.compile(value)) for key,value in regexp.items())
102+
103+
def __init__(self,timeline_owner,tweet):
104+
''' timeline_owner : twitter handle of user account. tweet - 140 chars from feed; object does all computation on construction
105+
properties:
106+
RT, MT - boolean
107+
URLs - list of URL
108+
Hashtags - list of tags
109+
'''
110+
self.Owner = timeline_owner
111+
self.tweet = tweet
112+
self.UserHandles = ParseTweet.getUserHandles(tweet)
113+
self.Hashtags = ParseTweet.getHashtags(tweet)
114+
self.URLs = ParseTweet.getURLs(tweet)
115+
self.RT = ParseTweet.getAttributeRT(tweet)
116+
self.MT = ParseTweet.getAttributeMT(tweet)
117+
118+
# additional intelligence
119+
if ( self.RT and len(self.UserHandles) > 0 ): #change the owner of tweet?
120+
self.Owner = self.UserHandles[0]
121+
return
122+
123+
def __str__(self):
124+
''' for display method '''
125+
return "owner %s, urls: %d, hashtags %d, user_handles %d, len_tweet %d, RT = %s, MT = %s"%(self.Owner,len(self.URLs),len(self.Hashtags),len(self.UserHandles), len(self.tweet), self.RT,self.MT)
126+
127+
@staticmethod
128+
def getAttributeRT( tweet ):
129+
""" see if tweet is a RT """
130+
return re.search(ParseTweet.regexp["RT"],tweet.strip()) != None
131+
132+
@staticmethod
133+
def getAttributeMT( tweet ):
134+
""" see if tweet is a MT """
135+
return re.search(ParseTweet.regexp["MT"],tweet.strip()) != None
136+
137+
@staticmethod
138+
def getUserHandles( tweet ):
139+
""" given a tweet we try and extract all user handles in order of occurrence"""
140+
return re.findall(ParseTweet.regexp["ALNUM"],tweet)
141+
142+
@staticmethod
143+
def getHashtags( tweet ):
144+
""" return all hashtags"""
145+
return re.findall(ParseTweet.regexp["HASHTAG"],tweet)
146+
147+
@staticmethod
148+
def getURLs( tweet ):
149+
""" URL : [http://]?[\w\.?/]+"""
150+
return re.findall(ParseTweet.regexp["URL"],tweet)

0 commit comments

Comments
 (0)
X Tutup