Permalink
Browse files

Merge branch 'master' of github.com:lucjon/Py-StackExchange

  • Loading branch information...
2 parents 15a3cb9 + 3b312c5 commit 63cb3b3c318fed5fc34a2f5a63c380593c51b4d4 @lucjon committed Jun 14, 2011
Showing with 153 additions and 105 deletions.
  1. +5 −2 _genconsts.py
  2. +1 −1 release.sh
  3. +16 −8 stackexchange/__init__.py
  4. +15 −0 stackexchange/core.py
  5. +115 −93 stackexchange/sites.py
  6. +1 −1 stackexchange/web.py
View
@@ -1,12 +1,15 @@
import stackauth
sites = stackauth.StackAuth().sites()
-source = []
+source = ['''import stackexchange
+class __SEAPI(str):
+ def __call__(self):
+ return stackexchange.Site(self)''']
for site in sites:
name = site.name
name = name.replace(' ', '')
name = name.replace('-', '')
- source.append('%s = \'%s\'' % (name, site.api_endpoint[7:]))
+ source.append('%s = __SEAPI(\'%s\')' % (name, site.api_endpoint[7:]))
print ('\n'.join(source))
View
@@ -11,6 +11,6 @@ fi
# Clear old distutils stuff
rm -rf build dist MANIFEST &> /dev/null
# Re-generate site constants
-python _genconsts.py > stacksites.py
+python _genconsts.py > stackexchange/sites.py
# Build installers, etc. and upload to PyPI
python setup.py register sdist bdist_wininst upload
View
@@ -34,7 +34,7 @@ def _extend(self, json, site):
self.owner_id = json.owner['user_id']
self.owner_info = tuple(json.owner.values())
- self.creation_date = datetime.date.fromtimestamp(json.creation_date)
+ self.creation_date = datetime.datetime.fromtimestamp(json.creation_date)
if hasattr(json, 'last_edit_date'):
self.last_edit_date = datetime.date.fromtimestamp(json.last_edit_date)
@@ -126,7 +126,7 @@ class Comment(JSONModel):
def _extend(self, json, site):
self.id = json.comment_id
- self.creation_date = datetime.date.fromtimestamp(json.creation_date)
+ self.creation_date = datetime.datetime.fromtimestamp(json.creation_date)
if hasattr(json, 'owner'):
self.owner_id = json.owner['owner_id'] if 'owner_id' in json.owner else json.owner['user_id']
@@ -175,7 +175,7 @@ class PostRevision(JSONModel):
'revision_number', 'title', 'set_community_wiki', 'post_id', 'last_tags', 'tags')
def _extend(self, json, site):
- self.creation_date = datetime.date.fromtimestamp(json.creation_date)
+ self.creation_date = datetime.datetime.fromtimestamp(json.creation_date)
self.revision_type = RevisionType.from_string(json.revision_type)
part = json.user
@@ -207,7 +207,7 @@ class TagSynonym(JSONModel):
transfer = ('from_tag', 'to_tag', 'applied_count')
def _extend(self, json, site):
- self.creation_date = datetime.date.fromtimestamp(json.creation_date)
+ self.creation_date = datetime.datetime.fromtimestamp(json.creation_date)
self.last_applied_date = datetime.date.fromtimestamp(json.last_applied_date)
def __repr__(self):
@@ -308,7 +308,7 @@ def _extend(self, json, site):
if self.timeline_type in self._post_related:
self.post_type = PostType.from_string(json.post_type)
- self.creation_date = datetime.date.fromtimestamp(json.creation_date)
+ self.creation_date = datetime.datetime.fromtimestamp(json.creation_date)
def _get_post(self):
if self.timeline_type in self._post_related:
@@ -377,7 +377,7 @@ class User(JSONModel):
def _extend(self, json, site):
self.id = json.user_id
self.type = Enumeration.from_string(json.user_type, UserType)
- self.creation_date = datetime.date.fromtimestamp(json.creation_date)
+ self.creation_date = datetime.datetime.fromtimestamp(json.creation_date)
self.last_access_date = datetime.date.fromtimestamp(json.last_access_date)
self.reputation = FormattedReputation(json.reputation)
@@ -553,7 +553,11 @@ def _request(self, to, params):
new_params = {}
for k, v in params.iteritems():
- new_params[k] = self._kw_to_str(v)
+ if k in ('fromdate', 'todate'):
+ # bit of a HACKish workaround for a reported issue; force to an integer
+ new_params[k] = str(int(v))
+ else:
+ new_params[k] = self._kw_to_str(v)
if self.app_key != None:
new_params['key'] = self.app_key
@@ -620,9 +624,13 @@ def user(self, nid, **kw):
u, = self.users((nid,), **kw)
return u
- def users(self, ids, **kw):
+ def users(self, ids=[], **kw):
"""Retrieves a list of the users with the IDs specified in the `ids' parameter."""
return self._get(User, ids, 'users', kw)
+
+ def users_by_name(self, name, **kw):
+ kw['filter'] = name
+ return self.users(**kw)
def moderators(self, **kw):
"""Retrieves a list of the moderators on the site."""
View
@@ -91,6 +91,7 @@ class StackExchangeResultset(tuple):
def __new__(cls, items, page, pagesize, build_info):
instance = tuple.__new__(cls, items)
instance.page, instance.pagesize, instance.build_info = page, pagesize, build_info
+ instance.items = items
return instance
def reload(self):
@@ -127,6 +128,20 @@ def fetch(self):
# Do nothing, but allow multiple fetch calls
return self
+ def __iter__(self):
+ return self.next()
+
+ def next(self):
+ current = self
+ while not current.done:
+ for obj in current.items:
+ yield obj
+
+ try:
+ current = current.fetch_next()
+ except urllib2.HTTPError:
+ return
+
done = property(lambda s: len(s) == s.total)
class NeedsAwokenError(Exception):
View
@@ -1,93 +1,115 @@
-StackOverflow = 'api.stackoverflow.com'
-ServerFault = 'api.serverfault.com'
-SuperUser = 'api.superuser.com'
-MetaStackOverflow = 'api.meta.stackoverflow.com'
-WebApplications = 'api.webapps.stackexchange.com'
-WebApplicationsMeta = 'api.meta.webapps.stackexchange.com'
-Gaming = 'api.gaming.stackexchange.com'
-GamingMeta = 'api.meta.gaming.stackexchange.com'
-Webmasters = 'api.webmasters.stackexchange.com'
-WebmastersMeta = 'api.meta.webmasters.stackexchange.com'
-Cooking = 'api.cooking.stackexchange.com'
-CookingMeta = 'api.meta.cooking.stackexchange.com'
-GameDevelopment = 'api.gamedev.stackexchange.com'
-GameDevelopmentMeta = 'api.meta.gamedev.stackexchange.com'
-Photography = 'api.photo.stackexchange.com'
-PhotographyMeta = 'api.meta.photo.stackexchange.com'
-StatisticalAnalysis = 'api.stats.stackexchange.com'
-StatisticalAnalysisMeta = 'api.meta.stats.stackexchange.com'
-Mathematics = 'api.math.stackexchange.com'
-MathematicsMeta = 'api.meta.math.stackexchange.com'
-HomeImprovement = 'api.diy.stackexchange.com'
-HomeImprovementMeta = 'api.meta.diy.stackexchange.com'
-MetaSuperUser = 'api.meta.superuser.com'
-MetaServerFault = 'api.meta.serverfault.com'
-GIS = 'api.gis.stackexchange.com'
-GISMeta = 'api.meta.gis.stackexchange.com'
-TeXLaTeX = 'api.tex.stackexchange.com'
-TeXLaTeXMeta = 'api.meta.tex.stackexchange.com'
-AskUbuntu = 'api.askubuntu.com'
-AskUbuntuMeta = 'api.meta.askubuntu.com'
-PersonalFinanceandMoney = 'api.money.stackexchange.com'
-PersonalFinanceandMoneyMeta = 'api.meta.money.stackexchange.com'
-EnglishLanguageandUsage = 'api.english.stackexchange.com'
-EnglishLanguageandUsageMeta = 'api.meta.english.stackexchange.com'
-StackApps = 'api.stackapps.com'
-UserInterface = 'api.ui.stackexchange.com'
-UserInterfaceMeta = 'api.meta.ui.stackexchange.com'
-UnixandLinux = 'api.unix.stackexchange.com'
-UnixandLinuxMeta = 'api.meta.unix.stackexchange.com'
-WordPress = 'api.wordpress.stackexchange.com'
-WordPressMeta = 'api.meta.wordpress.stackexchange.com'
-TheoreticalComputerScience = 'api.cstheory.stackexchange.com'
-TheoreticalComputerScienceMeta = 'api.meta.cstheory.stackexchange.com'
-Apple = 'api.apple.stackexchange.com'
-AppleMeta = 'api.meta.apple.stackexchange.com'
-RoleplayingGames = 'api.rpg.stackexchange.com'
-RoleplayingGamesMeta = 'api.meta.rpg.stackexchange.com'
-Bicycles = 'api.bicycles.stackexchange.com'
-BicyclesMeta = 'api.meta.bicycles.stackexchange.com'
-Programmers = 'api.programmers.stackexchange.com'
-ProgrammersMeta = 'api.meta.programmers.stackexchange.com'
-ElectronicsandRobotics = 'api.electronics.stackexchange.com'
-ElectronicsandRoboticsMeta = 'api.meta.electronics.stackexchange.com'
-AndroidEnthusiasts = 'api.android.stackexchange.com'
-AndroidEnthusiastsMeta = 'api.meta.android.stackexchange.com'
-OnStartups = 'api.onstartups.stackexchange.com'
-OnStartupsMeta = 'api.meta.onstartups.stackexchange.com'
-BoardandCardGames = 'api.boardgames.stackexchange.com'
-BoardandCardGamesMeta = 'api.meta.boardgames.stackexchange.com'
-Physics = 'api.physics.stackexchange.com'
-PhysicsMeta = 'api.meta.physics.stackexchange.com'
-Homebrew = 'api.homebrew.stackexchange.com'
-HomebrewMeta = 'api.meta.homebrew.stackexchange.com'
-ITSecurity = 'api.security.stackexchange.com'
-ITSecurityMeta = 'api.meta.security.stackexchange.com'
-Writers = 'api.writers.stackexchange.com'
-WritersMeta = 'api.meta.writers.stackexchange.com'
-AudioRecordingandProduction = 'api.audio.stackexchange.com'
-AudioRecordingandProductionMeta = 'api.meta.audio.stackexchange.com'
-GraphicDesign = 'api.graphicdesign.stackexchange.com'
-GraphicDesignMeta = 'api.meta.graphicdesign.stackexchange.com'
-Atheism = 'api.atheism.stackexchange.com'
-AtheismMeta = 'api.meta.atheism.stackexchange.com'
-DatabaseAdministrators = 'api.dba.stackexchange.com'
-DatabaseAdministratorsMeta = 'api.meta.dba.stackexchange.com'
-ScienceFictionandFantasy = 'api.scifi.stackexchange.com'
-ScienceFictionandFantasyMeta = 'api.meta.scifi.stackexchange.com'
-Guitars = 'api.guitars.stackexchange.com'
-GuitarsMeta = 'api.meta.guitars.stackexchange.com'
-CodeReview = 'api.codereview.stackexchange.com'
-CodeReviewMeta = 'api.meta.codereview.stackexchange.com'
-CodeGolf = 'api.codegolf.stackexchange.com'
-CodeGolfMeta = 'api.meta.codegolf.stackexchange.com'
-QuantitativeFinance = 'api.quant.stackexchange.com'
-QuantitativeFinanceMeta = 'api.meta.quant.stackexchange.com'
-ProjectManagement = 'api.pm.stackexchange.com'
-ProjectManagementMeta = 'api.meta.pm.stackexchange.com'
-Skeptics = 'api.skeptics.stackexchange.com'
-SkepticsMeta = 'api.meta.skeptics.stackexchange.com'
-FitnessandNutrition = 'api.fitness.stackexchange.com'
-FitnessandNutritionMeta = 'api.meta.fitness.stackexchange.com'
-DrupalAnswers = 'api.drupal.stackexchange.com'
-DrupalAnswersMeta = 'api.meta.drupal.stackexchange.com'
+import stackexchange
+class __SEAPI(str):
+ def __call__(self):
+ return stackexchange.Site(self)
+StackOverflow = __SEAPI('api.stackoverflow.com')
+ServerFault = __SEAPI('api.serverfault.com')
+SuperUser = __SEAPI('api.superuser.com')
+MetaStackOverflow = __SEAPI('api.meta.stackoverflow.com')
+WebApplications = __SEAPI('api.webapps.stackexchange.com')
+WebApplicationsMeta = __SEAPI('api.meta.webapps.stackexchange.com')
+Gaming = __SEAPI('api.gaming.stackexchange.com')
+GamingMeta = __SEAPI('api.meta.gaming.stackexchange.com')
+Webmasters = __SEAPI('api.webmasters.stackexchange.com')
+WebmastersMeta = __SEAPI('api.meta.webmasters.stackexchange.com')
+Cooking = __SEAPI('api.cooking.stackexchange.com')
+CookingMeta = __SEAPI('api.meta.cooking.stackexchange.com')
+GameDevelopment = __SEAPI('api.gamedev.stackexchange.com')
+GameDevelopmentMeta = __SEAPI('api.meta.gamedev.stackexchange.com')
+Photography = __SEAPI('api.photo.stackexchange.com')
+PhotographyMeta = __SEAPI('api.meta.photo.stackexchange.com')
+StatisticalAnalysis = __SEAPI('api.stats.stackexchange.com')
+StatisticalAnalysisMeta = __SEAPI('api.meta.stats.stackexchange.com')
+Mathematics = __SEAPI('api.math.stackexchange.com')
+MathematicsMeta = __SEAPI('api.meta.math.stackexchange.com')
+HomeImprovement = __SEAPI('api.diy.stackexchange.com')
+HomeImprovementMeta = __SEAPI('api.meta.diy.stackexchange.com')
+MetaSuperUser = __SEAPI('api.meta.superuser.com')
+MetaServerFault = __SEAPI('api.meta.serverfault.com')
+GIS = __SEAPI('api.gis.stackexchange.com')
+GISMeta = __SEAPI('api.meta.gis.stackexchange.com')
+TeXLaTeX = __SEAPI('api.tex.stackexchange.com')
+TeXLaTeXMeta = __SEAPI('api.meta.tex.stackexchange.com')
+AskUbuntu = __SEAPI('api.askubuntu.com')
+AskUbuntuMeta = __SEAPI('api.meta.askubuntu.com')
+PersonalFinanceandMoney = __SEAPI('api.money.stackexchange.com')
+PersonalFinanceandMoneyMeta = __SEAPI('api.meta.money.stackexchange.com')
+EnglishLanguageandUsage = __SEAPI('api.english.stackexchange.com')
+EnglishLanguageandUsageMeta = __SEAPI('api.meta.english.stackexchange.com')
+StackApps = __SEAPI('api.stackapps.com')
+UserExperience = __SEAPI('api.ux.stackexchange.com')
+UserExperienceMeta = __SEAPI('api.meta.ux.stackexchange.com')
+UnixandLinux = __SEAPI('api.unix.stackexchange.com')
+UnixandLinuxMeta = __SEAPI('api.meta.unix.stackexchange.com')
+WordPress = __SEAPI('api.wordpress.stackexchange.com')
+WordPressMeta = __SEAPI('api.meta.wordpress.stackexchange.com')
+TheoreticalComputerScience = __SEAPI('api.cstheory.stackexchange.com')
+TheoreticalComputerScienceMeta = __SEAPI('api.meta.cstheory.stackexchange.com')
+Apple = __SEAPI('api.apple.stackexchange.com')
+AppleMeta = __SEAPI('api.meta.apple.stackexchange.com')
+RoleplayingGames = __SEAPI('api.rpg.stackexchange.com')
+RoleplayingGamesMeta = __SEAPI('api.meta.rpg.stackexchange.com')
+Bicycles = __SEAPI('api.bicycles.stackexchange.com')
+BicyclesMeta = __SEAPI('api.meta.bicycles.stackexchange.com')
+Programmers = __SEAPI('api.programmers.stackexchange.com')
+ProgrammersMeta = __SEAPI('api.meta.programmers.stackexchange.com')
+ElectricalEngineering = __SEAPI('api.electronics.stackexchange.com')
+ElectricalEngineeringMeta = __SEAPI('api.meta.electronics.stackexchange.com')
+AndroidEnthusiasts = __SEAPI('api.android.stackexchange.com')
+AndroidEnthusiastsMeta = __SEAPI('api.meta.android.stackexchange.com')
+OnStartups = __SEAPI('api.onstartups.stackexchange.com')
+OnStartupsMeta = __SEAPI('api.meta.onstartups.stackexchange.com')
+BoardandCardGames = __SEAPI('api.boardgames.stackexchange.com')
+BoardandCardGamesMeta = __SEAPI('api.meta.boardgames.stackexchange.com')
+Physics = __SEAPI('api.physics.stackexchange.com')
+PhysicsMeta = __SEAPI('api.meta.physics.stackexchange.com')
+Homebrew = __SEAPI('api.homebrew.stackexchange.com')
+HomebrewMeta = __SEAPI('api.meta.homebrew.stackexchange.com')
+ITSecurity = __SEAPI('api.security.stackexchange.com')
+ITSecurityMeta = __SEAPI('api.meta.security.stackexchange.com')
+Writers = __SEAPI('api.writers.stackexchange.com')
+WritersMeta = __SEAPI('api.meta.writers.stackexchange.com')
+AudioRecordingandProduction = __SEAPI('api.audio.stackexchange.com')
+AudioRecordingandProductionMeta = __SEAPI('api.meta.audio.stackexchange.com')
+GraphicDesign = __SEAPI('api.graphicdesign.stackexchange.com')
+GraphicDesignMeta = __SEAPI('api.meta.graphicdesign.stackexchange.com')
+DatabaseAdministrators = __SEAPI('api.dba.stackexchange.com')
+DatabaseAdministratorsMeta = __SEAPI('api.meta.dba.stackexchange.com')
+ScienceFictionandFantasy = __SEAPI('api.scifi.stackexchange.com')
+ScienceFictionandFantasyMeta = __SEAPI('api.meta.scifi.stackexchange.com')
+CodeReview = __SEAPI('api.codereview.stackexchange.com')
+CodeReviewMeta = __SEAPI('api.meta.codereview.stackexchange.com')
+CodeGolf = __SEAPI('api.codegolf.stackexchange.com')
+CodeGolfMeta = __SEAPI('api.meta.codegolf.stackexchange.com')
+QuantitativeFinance = __SEAPI('api.quant.stackexchange.com')
+QuantitativeFinanceMeta = __SEAPI('api.meta.quant.stackexchange.com')
+ProjectManagement = __SEAPI('api.pm.stackexchange.com')
+ProjectManagementMeta = __SEAPI('api.meta.pm.stackexchange.com')
+Skeptics = __SEAPI('api.skeptics.stackexchange.com')
+SkepticsMeta = __SEAPI('api.meta.skeptics.stackexchange.com')
+FitnessandNutrition = __SEAPI('api.fitness.stackexchange.com')
+FitnessandNutritionMeta = __SEAPI('api.meta.fitness.stackexchange.com')
+DrupalAnswers = __SEAPI('api.drupal.stackexchange.com')
+DrupalAnswersMeta = __SEAPI('api.meta.drupal.stackexchange.com')
+MotorVehicleMaintenanceandRepair = __SEAPI('api.mechanics.stackexchange.com')
+MotorVehicleMaintenanceandRepairMeta = __SEAPI('api.meta.mechanics.stackexchange.com')
+Parenting = __SEAPI('api.parenting.stackexchange.com')
+ParentingMeta = __SEAPI('api.meta.parenting.stackexchange.com')
+SharePoint = __SEAPI('api.sharepoint.stackexchange.com')
+SharePointMeta = __SEAPI('api.meta.sharepoint.stackexchange.com')
+MusicalPracticeandPerformance = __SEAPI('api.music.stackexchange.com')
+MusicalPracticeandPerformanceMeta = __SEAPI('api.meta.music.stackexchange.com')
+SoftwareQualityAssuranceandTesting = __SEAPI('api.sqa.stackexchange.com')
+SoftwareQualityAssuranceandTestingMeta = __SEAPI('api.meta.sqa.stackexchange.com')
+JewishLifeandLearning = __SEAPI('api.judaism.stackexchange.com')
+JewishLifeandLearningMeta = __SEAPI('api.meta.judaism.stackexchange.com')
+GermanLanguageandUsage = __SEAPI('api.german.stackexchange.com')
+GermanLanguageandUsageMeta = __SEAPI('api.meta.german.stackexchange.com')
+JapaneseLanguageandUsage = __SEAPI('api.japanese.stackexchange.com')
+JapaneseLanguageandUsageMeta = __SEAPI('api.meta.japanese.stackexchange.com')
+Astronomy = __SEAPI('api.astronomy.stackexchange.com')
+AstronomyMeta = __SEAPI('api.meta.astronomy.stackexchange.com')
+Philosophy = __SEAPI('api.philosophy.stackexchange.com')
+PhilosophyMeta = __SEAPI('api.meta.philosophy.stackexchange.com')
+GardeningandLandscaping = __SEAPI('api.gardening.stackexchange.com')
+GardeningandLandscapingMeta = __SEAPI('api.meta.gardening.stackexchange.com')
View
@@ -58,7 +58,7 @@ def request(self, url, params):
done = True
else: url += '&'
- url += '%s=%s' % (k, urllib.quote(v))
+ url += '%s=%s' % (k, urllib.quote(v.encode('utf-8')))
# Now we have the `proper` URL, we can check the cache
if self.do_cache and url in self.cache:

0 comments on commit 63cb3b3

Please sign in to comment.