Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Aguiar <alanjas@hotmail.com>2013-11-11 21:16:05 (GMT)
committer Alan Aguiar <alanjas@hotmail.com>2013-11-11 21:16:05 (GMT)
commitdbf6e8060b9d91b0c92a13473a12474eee5a63f2 (patch)
treedbd6d9b51807eb411697dcdc201ba2b8fafc9181
parent7ef87a3de795d15ea14e13668756b43c42b84567 (diff)
sugar not work
-rw-r--r--Gambiarra/__init__.py22
-rw-r--r--Gambiarra/gambiarra.py201
-rw-r--r--Gambiarra/objects/__init__.py16
-rw-r--r--activity.py12
-rw-r--r--activity/activity.info2
-rw-r--r--activity/gambiarra.svg (renamed from activity/activity-gambiarra.svg)0
-rw-r--r--command.py (renamed from Gambiarra/command.py)0
-rwxr-xr-x[-rw-r--r--]gambiarra.py211
-rw-r--r--gamemenu.py (renamed from Gambiarra/gamemenu.py)0
-rw-r--r--levels.py (renamed from Gambiarra/levels.py)7
-rw-r--r--objects/__init__.py16
-rw-r--r--objects/animals.py (renamed from Gambiarra/objects/animals.py)0
-rw-r--r--objects/balls.py (renamed from Gambiarra/objects/balls.py)0
-rw-r--r--objects/elastica.py (renamed from Gambiarra/objects/elastica.py)0
-rw-r--r--objects/esteira.py (renamed from Gambiarra/objects/esteira.py)0
-rw-r--r--objects/target.py (renamed from Gambiarra/objects/target.py)0
-rw-r--r--objects/things.py (renamed from Gambiarra/objects/things.py)0
-rw-r--r--objects/wall.py (renamed from Gambiarra/objects/wall.py)0
-rw-r--r--simplejson/__init__.py389
-rw-r--r--simplejson/decoder.py322
-rw-r--r--simplejson/encoder.py376
-rw-r--r--simplejson/jsonfilter.py40
-rw-r--r--simplejson/scanner.py64
23 files changed, 208 insertions, 1470 deletions
diff --git a/Gambiarra/__init__.py b/Gambiarra/__init__.py
deleted file mode 100644
index 424bcbd..0000000
--- a/Gambiarra/__init__.py
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: UTF-8 -*-
-#
-# Copyright (C) 2007 by ULPM: Alexandre Yukio Harano
-# Fábio Cassarotti Parronchi Navarro
-# Gabriel Geraldo França Marcondes
-# Luiz Carlos Irber Júnior
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
diff --git a/Gambiarra/gambiarra.py b/Gambiarra/gambiarra.py
deleted file mode 100644
index 0daeee2..0000000
--- a/Gambiarra/gambiarra.py
+++ /dev/null
@@ -1,201 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: UTF-8 -*-
-#
-# Copyright (C) 2007 by ULPM: Alexandre Yukio Harano
-# Fábio Cassarotti Parronchi Navarro
-# Gabriel Geraldo França Marcondes
-# Luiz Carlos Irber Júnior
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-import sys
-import os
-import gtk
-import pygame
-
-from Gambiarra.command import Play, Help, Quit
-from Gambiarra.gamemenu import GameMenu
-import Gambiarra.levels as Levels
-
-from Gambiarra.objects import Esteira, check_collision
-
-class Game(object):
- # controle do jogo
- fps = 30
- playing = None
- running = None
- clock = None
- level = 0
- levels = []
- selected_element = None
- _showed_help = None
- count = None
- play_sounds = None
-
- # elementos do jogo
- screen = None
- menu = None
- congrats = None
- congrats_snd = None
-
- def __init__(self, play_sounds=True):
- self.play_sounds = play_sounds
- self.running = True
- self.playing = False
- self._showed_help = False
- self.count = 0
-
- def load_all(self):
- pygame.init()
- if self.play_sounds:
- pygame.mixer.init()
- #self.screen = pygame.display.set_mode((1200, 900))
- self.screen = pygame.display.get_surface()
- pygame.display.flip()
- pygame.display.set_caption("Gambiarra")
- self.clock = pygame.time.Clock()
- self.levels = Levels.init_levels()
- self.menu = GameMenu()
- self.congrats = pygame.image.load(os.path.join("data","images",
- "fim_fase.png"))
- if self.play_sounds:
- snd_file = os.path.join("data", "snd", "Congrats.wav")
- self.congrats_snd = pygame.mixer.Sound(snd_file)
-
- def run(self):
- self.load_all()
- #inicia o loop
- self.main_loop()
-
- def event_handler(self):
- #GTK events
- while gtk.events_pending():
- gtk.main_iteration()
- for event in pygame.event.get():
- if event.type == pygame.MOUSEBUTTONDOWN:
- self.mouse_event( pygame.mouse.get_pos() )
-
- def update_screen(self, fps):
- #update dos elementos da tela
- if self.playing:
-
- # executa a simulacao
- objs = check_collision(self.levels[self.level].simulator.objects,
- self.levels[self.level].simulator.static_objs)
- self.levels[self.level].simulator.objects = objs
- for obj in self.levels[self.level].simulator.objects:
- obj.update()
- else:
- if self.selected_element:
- if self.selected_element.editable:
- self.selected_element.rect.center = pygame.mouse.get_pos()
-
- def mouse_event(self, mouse_pos):
- if not self.selected_element:
- mouse_move = (0, 0)
- mouse_move = pygame.mouse.get_rel()
-
- for element in self.levels[self.level].simulator.objects:
- if element.rect.collidepoint(mouse_pos):
- self.selected_element = element
- break
-
- if not self.selected_element:
- for element in self.levels[self.level].simulator.static_objs:
- if element.rect.collidepoint(mouse_pos):
- self.selected_element = element
-
- if isinstance(element, Esteira) and element.editable:
- self.count += 1
- if self.count == 1:
- element.sentido = -element.sentido
- self.count = 0
- break
-
- if not self.selected_element: #se nao encontrou no for anterior
- for element in self.levels[self.level].objbar.objects:
- if element.rect.collidepoint(mouse_pos):
- element.remove(self.levels[self.level].objbar.objects)
- self.levels[self.level].simulator.add(element)
- self.selected_element = element
- break
-
- if not self.selected_element: #se nao encontrou no for anterior
- for element in self.levels[self.level].cmdbar.commands:
- if element.rect.collidepoint(mouse_pos):
- if isinstance(element, Play):
- element.image = pygame.transform.flip(element.image,
- True, False)
- self.playing = not self.playing
- if not self.playing:
- objs = self.levels[self.level].simulator.objects
- for obj in objs:
- obj.speed = [0, 0]
- obj.rect.topleft = obj.initial_pos
- elif isinstance(element, Help):
- self.levels[self.level].show_help(self.screen)
- elif isinstance(element, Quit):
- sys.exit()
- break
-
- else:
- if self.selected_element.editable and not self.playing:
- mouse_move = pygame.mouse.get_rel()
- if mouse_move != (0, 0):
- self.count -= 1
- self.selected_element.rect.center = pygame.mouse.get_pos()
- new_pos = self.selected_element.rect.topleft
- self.selected_element.initial_pos = new_pos
- self.selected_element = None
-
- def show_congratulations(self):
- if self.play_sounds:
- pygame.mixer.stop()
- self.congrats_snd.play()
-
- self.screen.blit(self.congrats, (600 - self.congrats.get_width()/2,
- 450 - self.congrats.get_height()/2) )
- pygame.display.flip()
-
- while True:
- #GTK events
- while gtk.events_pending():
- gtk.main_iteration()
- for event in pygame.event.get():
- if event.type == pygame.MOUSEBUTTONDOWN:
- return
-
- def main_loop(self):
- self.menu.run()
- while self.running and self.level < len(self.levels):
- while not self.levels[self.level].goal_reached():
- self.event_handler()
- self.clock.tick(self.fps)
- self.update_screen(self.fps)
- self.levels[self.level].draw()
-
- if not self._showed_help:
- self.levels[self.level].show_help(self.screen)
- self._showed_help = True
-
- pygame.display.flip()
-
- self.playing = False
- self._showed_help = False
- self.level += 1
- self.show_congratulations()
- if (len(self.levels) == self.level) :
- self.running = False
-
diff --git a/Gambiarra/objects/__init__.py b/Gambiarra/objects/__init__.py
deleted file mode 100644
index f4e303c..0000000
--- a/Gambiarra/objects/__init__.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from Gambiarra.objects.animals import Penguin
-from Gambiarra.objects.balls import SoccerBall, BowlingBall, BeachBall
-from Gambiarra.objects.elastica import Elastica
-from Gambiarra.objects.esteira import Esteira
-from Gambiarra.objects.target import Target
-from Gambiarra.objects.things import Thing, check_collision
-from Gambiarra.objects.wall import UpWall, DownWall, LeftWall, RightWall
-
-# namespace cleanup
-del animals
-del balls
-del elastica
-del esteira
-del target
-del things
-del wall
diff --git a/activity.py b/activity.py
index 5134d06..3089696 100644
--- a/activity.py
+++ b/activity.py
@@ -29,26 +29,20 @@ from sugar.graphics.toolbarbox import ToolbarBox
from sugar.activity.widgets import ActivityToolbarButton
from sugar.graphics.toolbutton import ToolButton
from sugar.activity.widgets import StopButton
-
import sugargame.canvas
from gettext import gettext as _
-# add the libs subdir to the path
-basedir = os.path.abspath(os.curdir)
-libdir = os.path.join(basedir, "libs")
-
-sys.path.insert(0, libdir)
-
-from Gambiarra.gambiarra import Game
+from gambiarra import Game
class GambiarraActivity(activity.Activity):
def __init__(self, handle):
activity.Activity.__init__(self, handle)
+ self.max_participants = 1
self.game = Game()
- self.build_toolbar()
+ #self.build_toolbar()
self._pygamecanvas = sugargame.canvas.PygameCanvas(self)
self.set_canvas(self._pygamecanvas)
self._pygamecanvas.grab_focus()
diff --git a/activity/activity.info b/activity/activity.info
index 8486357..5638b0d 100644
--- a/activity/activity.info
+++ b/activity/activity.info
@@ -2,6 +2,6 @@
name = Gambiarra
activity_version = 1
bundle_id = org.laptop.community.Gambiarra
-icon = activity-gambiarra
+icon = gambiarra
exec = sugar-activity activity.GambiarraActivity
diff --git a/activity/activity-gambiarra.svg b/activity/gambiarra.svg
index e8528dd..e8528dd 100644
--- a/activity/activity-gambiarra.svg
+++ b/activity/gambiarra.svg
diff --git a/Gambiarra/command.py b/command.py
index b2db177..b2db177 100644
--- a/Gambiarra/command.py
+++ b/command.py
diff --git a/gambiarra.py b/gambiarra.py
index 8996dc1..2c23a36 100644..100755
--- a/gambiarra.py
+++ b/gambiarra.py
@@ -2,9 +2,9 @@
# -*- coding: UTF-8 -*-
#
# Copyright (C) 2007 by ULPM: Alexandre Yukio Harano
-# Fábio Cassarotti Parronchi Navarro
-# Gabriel Geraldo França Marcondes
-# Luiz Carlos Irber Júnior
+# Fábio Cassarotti Parronchi Navarro
+# Gabriel Geraldo França Marcondes
+# Luiz Carlos Irber Júnior
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@@ -21,34 +21,189 @@
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
import sys
-import os.path
-from optparse import OptionParser
+import os
+import gtk
+import pygame
-# add the libs subdir to the path
-basedir = os.path.abspath(os.curdir)
-libdir = os.path.join(basedir, "libs")
+from command import Play, Help, Quit
+from gamemenu import GameMenu
+import levels as Levels
-if not libdir in sys.path:
- sys.path.insert(0, libdir)
+from objects import Esteira, check_collision
-from Gambiarra.gambiarra import Game
+class Game(object):
+ # controle do jogo
+ fps = 30
+ playing = None
+ running = None
+ clock = None
+ level = 0
+ levels = []
+ selected_element = None
+ _showed_help = None
+ count = None
+ play_sounds = None
-def main(play_sounds=True):
- game = Game(play_sounds)
- game.run()
+ # elementos do jogo
+ screen = None
+ menu = None
+ congrats = None
+ congrats_snd = None
+
+ def __init__(self, play_sounds=True, running_sugar=True):
+ self.play_sounds = play_sounds
+ self.running_sugar = running_sugar
+ self.running = True
+ self.playing = False
+ self._showed_help = False
+ self.count = 0
+
+ def load_all(self):
+ pygame.init()
+ if self.play_sounds:
+ pygame.mixer.init()
+ self.screen = pygame.display.get_surface()
+ if self.screen is None:
+ self.screen = pygame.display.set_mode((1200, 900))
+ pygame.display.flip()
+ pygame.display.set_caption("Gambiarra")
+ self.clock = pygame.time.Clock()
+ self.levels = Levels.init_levels()
+ self.menu = GameMenu()
+ self.congrats = pygame.image.load(os.path.join("data","images",
+ "fim_fase.png"))
+ if self.play_sounds:
+ snd_file = os.path.join("data", "snd", "Congrats.wav")
+ self.congrats_snd = pygame.mixer.Sound(snd_file)
+
+ def run(self):
+ self.load_all()
+ self.main_loop()
+
+ def event_handler(self):
+ #GTK events
+ while gtk.events_pending():
+ gtk.main_iteration()
+ for event in pygame.event.get():
+ if event.type == pygame.MOUSEBUTTONDOWN:
+ self.mouse_event( pygame.mouse.get_pos() )
+ elif (event.type == pygame.QUIT) and not self.running_sugar:
+ self.running = False
+
+ def update_screen(self, fps):
+ #update dos elementos da tela
+ if self.playing:
+
+ # executa a simulacao
+ objs = check_collision(self.levels[self.level].simulator.objects,
+ self.levels[self.level].simulator.static_objs)
+ self.levels[self.level].simulator.objects = objs
+ for obj in self.levels[self.level].simulator.objects:
+ obj.update()
+ else:
+ if self.selected_element:
+ if self.selected_element.editable:
+ self.selected_element.rect.center = pygame.mouse.get_pos()
+
+ def mouse_event(self, mouse_pos):
+ if not self.selected_element:
+ mouse_move = (0, 0)
+ mouse_move = pygame.mouse.get_rel()
+
+ for element in self.levels[self.level].simulator.objects:
+ if element.rect.collidepoint(mouse_pos):
+ self.selected_element = element
+ break
+
+ if not self.selected_element:
+ for element in self.levels[self.level].simulator.static_objs:
+ if element.rect.collidepoint(mouse_pos):
+ self.selected_element = element
+
+ if isinstance(element, Esteira) and element.editable:
+ self.count += 1
+ if self.count == 1:
+ element.sentido = -element.sentido
+ self.count = 0
+ break
+
+ if not self.selected_element: #se nao encontrou no for anterior
+ for element in self.levels[self.level].objbar.objects:
+ if element.rect.collidepoint(mouse_pos):
+ element.remove(self.levels[self.level].objbar.objects)
+ self.levels[self.level].simulator.add(element)
+ self.selected_element = element
+ break
+
+ if not self.selected_element: #se nao encontrou no for anterior
+ for element in self.levels[self.level].cmdbar.commands:
+ if element.rect.collidepoint(mouse_pos):
+ if isinstance(element, Play):
+ element.image = pygame.transform.flip(element.image,
+ True, False)
+ self.playing = not self.playing
+ if not self.playing:
+ objs = self.levels[self.level].simulator.objects
+ for obj in objs:
+ obj.speed = [0, 0]
+ obj.rect.topleft = obj.initial_pos
+ elif isinstance(element, Help):
+ self.levels[self.level].show_help(self.screen)
+ elif isinstance(element, Quit):
+ sys.exit()
+ break
+
+ else:
+ if self.selected_element.editable and not self.playing:
+ mouse_move = pygame.mouse.get_rel()
+ if mouse_move != (0, 0):
+ self.count -= 1
+ self.selected_element.rect.center = pygame.mouse.get_pos()
+ new_pos = self.selected_element.rect.topleft
+ self.selected_element.initial_pos = new_pos
+ self.selected_element = None
+
+ def show_congratulations(self):
+ if self.play_sounds:
+ pygame.mixer.stop()
+ self.congrats_snd.play()
+
+ self.screen.blit(self.congrats, (600 - self.congrats.get_width()/2,
+ 450 - self.congrats.get_height()/2) )
+ pygame.display.flip()
+
+ while True:
+ #GTK events
+ while gtk.events_pending():
+ gtk.main_iteration()
+ for event in pygame.event.get():
+ if event.type == pygame.MOUSEBUTTONDOWN:
+ return
+
+ def main_loop(self):
+ self.menu.run()
+ while self.running and self.level < len(self.levels):
+ while not self.levels[self.level].goal_reached() and self.running:
+ self.event_handler()
+ self.clock.tick(self.fps)
+ self.update_screen(self.fps)
+ self.levels[self.level].draw()
+
+ if not self._showed_help:
+ self.levels[self.level].show_help(self.screen)
+ self._showed_help = True
+
+ pygame.display.flip()
+
+ if self.running:
+ self.playing = False
+ self._showed_help = False
+ self.level += 1
+ self.show_congratulations()
+ if (len(self.levels) == self.level) :
+ self.running = False
if __name__ == "__main__":
- parser = OptionParser()
- parser.add_option('-p', '--profile', action='store_true',
- dest='profile', default=False,
- help='run in profiling mode [default: %default]')
- parser.add_option('-s', '--no-sound', action='store_true',
- dest='sound', default=False,
- help='disable sounds [default: %default]')
- options, args = parser.parse_args()
-
- if options.profile:
- import cProfile
- cProfile.run('main()', filename='gambiarra.cprof')
- else:
- main(options.sound)
+ g = Game(running_sugar=False)
+ g.run()
+
diff --git a/Gambiarra/gamemenu.py b/gamemenu.py
index 55d838e..55d838e 100644
--- a/Gambiarra/gamemenu.py
+++ b/gamemenu.py
diff --git a/Gambiarra/levels.py b/levels.py
index 9d16bd2..79bf675 100644
--- a/Gambiarra/levels.py
+++ b/levels.py
@@ -25,9 +25,9 @@ import os
import simplejson as json
-from Gambiarra.objects import *
+from objects import *
-from Gambiarra.command import Play, Help, Quit
+from command import Play, Help, Quit
class SimulationView(object):
""" This widget holds the objects being simulated. """
@@ -149,6 +149,9 @@ class Level(object):
450 - self.help_img.get_height()/2) )
pygame.display.flip()
while True:
+ #GTK events
+ while gtk.events_pending():
+ gtk.main_iteration()
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
return
diff --git a/objects/__init__.py b/objects/__init__.py
new file mode 100644
index 0000000..f10dcdb
--- /dev/null
+++ b/objects/__init__.py
@@ -0,0 +1,16 @@
+from objects.animals import Penguin
+from objects.balls import SoccerBall, BowlingBall, BeachBall
+from objects.elastica import Elastica
+from objects.esteira import Esteira
+from objects.target import Target
+from objects.things import Thing, check_collision
+from objects.wall import UpWall, DownWall, LeftWall, RightWall
+
+# namespace cleanup
+del animals
+del balls
+del elastica
+del esteira
+del target
+del things
+del wall
diff --git a/Gambiarra/objects/animals.py b/objects/animals.py
index 9b3114a..9b3114a 100644
--- a/Gambiarra/objects/animals.py
+++ b/objects/animals.py
diff --git a/Gambiarra/objects/balls.py b/objects/balls.py
index 3546d34..3546d34 100644
--- a/Gambiarra/objects/balls.py
+++ b/objects/balls.py
diff --git a/Gambiarra/objects/elastica.py b/objects/elastica.py
index 01dd9d8..01dd9d8 100644
--- a/Gambiarra/objects/elastica.py
+++ b/objects/elastica.py
diff --git a/Gambiarra/objects/esteira.py b/objects/esteira.py
index f17fe59..f17fe59 100644
--- a/Gambiarra/objects/esteira.py
+++ b/objects/esteira.py
diff --git a/Gambiarra/objects/target.py b/objects/target.py
index 69bbca5..69bbca5 100644
--- a/Gambiarra/objects/target.py
+++ b/objects/target.py
diff --git a/Gambiarra/objects/things.py b/objects/things.py
index 7d8ac79..7d8ac79 100644
--- a/Gambiarra/objects/things.py
+++ b/objects/things.py
diff --git a/Gambiarra/objects/wall.py b/objects/wall.py
index ec6c1de..ec6c1de 100644
--- a/Gambiarra/objects/wall.py
+++ b/objects/wall.py
diff --git a/simplejson/__init__.py b/simplejson/__init__.py
deleted file mode 100644
index be9e87a..0000000
--- a/simplejson/__init__.py
+++ /dev/null
@@ -1,389 +0,0 @@
-r"""
-A simple, fast, extensible JSON encoder and decoder
-
-JSON (JavaScript Object Notation) <http://json.org> is a subset of
-JavaScript syntax (ECMA-262 3rd edition) used as a lightweight data
-interchange format.
-
-simplejson exposes an API familiar to uses of the standard library
-marshal and pickle modules.
-
-Encoding basic Python object hierarchies::
-
- >>> import simplejson
- >>> simplejson.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}])
- '["foo", {"bar": ["baz", null, 1.0, 2]}]'
- >>> print simplejson.dumps("\"foo\bar")
- "\"foo\bar"
- >>> print simplejson.dumps(u'\u1234')
- "\u1234"
- >>> print simplejson.dumps('\\')
- "\\"
- >>> print simplejson.dumps({"c": 0, "b": 0, "a": 0}, sort_keys=True)
- {"a": 0, "b": 0, "c": 0}
- >>> from StringIO import StringIO
- >>> io = StringIO()
- >>> simplejson.dump(['streaming API'], io)
- >>> io.getvalue()
- '["streaming API"]'
-
-Compact encoding::
-
- >>> import simplejson
- >>> simplejson.dumps([1,2,3,{'4': 5, '6': 7}], separators=(',',':'))
- '[1,2,3,{"4":5,"6":7}]'
-
-Pretty printing::
-
- >>> import simplejson
- >>> print simplejson.dumps({'4': 5, '6': 7}, sort_keys=True, indent=4)
- {
- "4": 5,
- "6": 7
- }
-
-Decoding JSON::
-
- >>> import simplejson
- >>> simplejson.loads('["foo", {"bar":["baz", null, 1.0, 2]}]')
- [u'foo', {u'bar': [u'baz', None, 1.0, 2]}]
- >>> simplejson.loads('"\\"foo\\bar"')
- u'"foo\x08ar'
- >>> from StringIO import StringIO
- >>> io = StringIO('["streaming API"]')
- >>> simplejson.load(io)
- [u'streaming API']
-
-Specializing JSON object decoding::
-
- >>> import simplejson
- >>> def as_complex(dct):
- ... if '__complex__' in dct:
- ... return complex(dct['real'], dct['imag'])
- ... return dct
- ...
- >>> simplejson.loads('{"__complex__": true, "real": 1, "imag": 2}',
- ... object_hook=as_complex)
- (1+2j)
- >>> import decimal
- >>> simplejson.loads('1.1', parse_float=decimal.Decimal)
- decimal.Decimal(1.1)
-
-Extending JSONEncoder::
-
- >>> import simplejson
- >>> class ComplexEncoder(simplejson.JSONEncoder):
- ... def default(self, obj):
- ... if isinstance(obj, complex):
- ... return [obj.real, obj.imag]
- ... return simplejson.JSONEncoder.default(self, obj)
- ...
- >>> dumps(2 + 1j, cls=ComplexEncoder)
- '[2.0, 1.0]'
- >>> ComplexEncoder().encode(2 + 1j)
- '[2.0, 1.0]'
- >>> list(ComplexEncoder().iterencode(2 + 1j))
- ['[', '2.0', ', ', '1.0', ']']
-
-
-Using simplejson from the shell to validate and
-pretty-print::
-
- $ echo '{"json":"obj"}' | python -msimplejson
- {
- "json": "obj"
- }
- $ echo '{ 1.2:3.4}' | python -msimplejson
- Expecting property name: line 1 column 2 (char 2)
-
-Note that the JSON produced by this module's default settings
-is a subset of YAML, so it may be used as a serializer for that as well.
-"""
-__version__ = '1.8.1'
-__all__ = [
- 'dump', 'dumps', 'load', 'loads',
- 'JSONDecoder', 'JSONEncoder',
-]
-
-if __name__ == '__main__':
- from simplejson.decoder import JSONDecoder
- from simplejson.encoder import JSONEncoder
-else:
- from decoder import JSONDecoder
- from encoder import JSONEncoder
-
-_default_encoder = JSONEncoder(
- skipkeys=False,
- ensure_ascii=True,
- check_circular=True,
- allow_nan=True,
- indent=None,
- separators=None,
- encoding='utf-8',
- default=None,
-)
-
-def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True,
- allow_nan=True, cls=None, indent=None, separators=None,
- encoding='utf-8', default=None, **kw):
- """
- Serialize ``obj`` as a JSON formatted stream to ``fp`` (a
- ``.write()``-supporting file-like object).
-
- If ``skipkeys`` is ``True`` then ``dict`` keys that are not basic types
- (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``)
- will be skipped instead of raising a ``TypeError``.
-
- If ``ensure_ascii`` is ``False``, then the some chunks written to ``fp``
- may be ``unicode`` instances, subject to normal Python ``str`` to
- ``unicode`` coercion rules. Unless ``fp.write()`` explicitly
- understands ``unicode`` (as in ``codecs.getwriter()``) this is likely
- to cause an error.
-
- If ``check_circular`` is ``False``, then the circular reference check
- for container types will be skipped and a circular reference will
- result in an ``OverflowError`` (or worse).
-
- If ``allow_nan`` is ``False``, then it will be a ``ValueError`` to
- serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``)
- in strict compliance of the JSON specification, instead of using the
- JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).
-
- If ``indent`` is a non-negative integer, then JSON array elements and object
- members will be pretty-printed with that indent level. An indent level
- of 0 will only insert newlines. ``None`` is the most compact representation.
-
- If ``separators`` is an ``(item_separator, dict_separator)`` tuple
- then it will be used instead of the default ``(', ', ': ')`` separators.
- ``(',', ':')`` is the most compact JSON representation.
-
- ``encoding`` is the character encoding for str instances, default is UTF-8.
-
- ``default(obj)`` is a function that should return a serializable version
- of obj or raise TypeError. The default simply raises TypeError.
-
- To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
- ``.default()`` method to serialize additional types), specify it with
- the ``cls`` kwarg.
- """
- # cached encoder
- if (skipkeys is False and ensure_ascii is True and
- check_circular is True and allow_nan is True and
- cls is None and indent is None and separators is None and
- encoding == 'utf-8' and default is None and not kw):
- iterable = _default_encoder.iterencode(obj)
- else:
- if cls is None:
- cls = JSONEncoder
- iterable = cls(skipkeys=skipkeys, ensure_ascii=ensure_ascii,
- check_circular=check_circular, allow_nan=allow_nan, indent=indent,
- separators=separators, encoding=encoding,
- default=default, **kw).iterencode(obj)
- # could accelerate with writelines in some versions of Python, at
- # a debuggability cost
- for chunk in iterable:
- fp.write(chunk)
-
-
-def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True,
- allow_nan=True, cls=None, indent=None, separators=None,
- encoding='utf-8', default=None, **kw):
- """
- Serialize ``obj`` to a JSON formatted ``str``.
-
- If ``skipkeys`` is ``True`` then ``dict`` keys that are not basic types
- (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``)
- will be skipped instead of raising a ``TypeError``.
-
- If ``ensure_ascii`` is ``False``, then the return value will be a
- ``unicode`` instance subject to normal Python ``str`` to ``unicode``
- coercion rules instead of being escaped to an ASCII ``str``.
-
- If ``check_circular`` is ``False``, then the circular reference check
- for container types will be skipped and a circular reference will
- result in an ``OverflowError`` (or worse).
-
- If ``allow_nan`` is ``False``, then it will be a ``ValueError`` to
- serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) in
- strict compliance of the JSON specification, instead of using the
- JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).
-
- If ``indent`` is a non-negative integer, then JSON array elements and
- object members will be pretty-printed with that indent level. An indent
- level of 0 will only insert newlines. ``None`` is the most compact
- representation.
-
- If ``separators`` is an ``(item_separator, dict_separator)`` tuple
- then it will be used instead of the default ``(', ', ': ')`` separators.
- ``(',', ':')`` is the most compact JSON representation.
-
- ``encoding`` is the character encoding for str instances, default is UTF-8.
-
- ``default(obj)`` is a function that should return a serializable version
- of obj or raise TypeError. The default simply raises TypeError.
-
- To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
- ``.default()`` method to serialize additional types), specify it with
- the ``cls`` kwarg.
- """
- # cached encoder
- if (skipkeys is False and ensure_ascii is True and
- check_circular is True and allow_nan is True and
- cls is None and indent is None and separators is None and
- encoding == 'utf-8' and default is None and not kw):
- return _default_encoder.encode(obj)
- if cls is None:
- cls = JSONEncoder
- return cls(
- skipkeys=skipkeys, ensure_ascii=ensure_ascii,
- check_circular=check_circular, allow_nan=allow_nan, indent=indent,
- separators=separators, encoding=encoding, default=default,
- **kw).encode(obj)
-
-_default_decoder = JSONDecoder(encoding=None, object_hook=None)
-
-def load(fp, encoding=None, cls=None, object_hook=None, parse_float=None,
- parse_int=None, parse_constant=None, **kw):
- """
- Deserialize ``fp`` (a ``.read()``-supporting file-like object containing
- a JSON document) to a Python object.
-
- If the contents of ``fp`` is encoded with an ASCII based encoding other
- than utf-8 (e.g. latin-1), then an appropriate ``encoding`` name must
- be specified. Encodings that are not ASCII based (such as UCS-2) are
- not allowed, and should be wrapped with
- ``codecs.getreader(fp)(encoding)``, or simply decoded to a ``unicode``
- object and passed to ``loads()``
-
- ``object_hook`` is an optional function that will be called with the
- result of any object literal decode (a ``dict``). The return value of
- ``object_hook`` will be used instead of the ``dict``. This feature
- can be used to implement custom decoders (e.g. JSON-RPC class hinting).
-
- To use a custom ``JSONDecoder`` subclass, specify it with the ``cls``
- kwarg.
- """
- return loads(fp.read(),
- encoding=encoding, cls=cls, object_hook=object_hook,
- parse_float=parse_float, parse_int=parse_int,
- parse_constant=parse_constant, **kw)
-
-def loads(s, encoding=None, cls=None, object_hook=None, parse_float=None,
- parse_int=None, parse_constant=None, **kw):
- """
- Deserialize ``s`` (a ``str`` or ``unicode`` instance containing a JSON
- document) to a Python object.
-
- If ``s`` is a ``str`` instance and is encoded with an ASCII based encoding
- other than utf-8 (e.g. latin-1) then an appropriate ``encoding`` name
- must be specified. Encodings that are not ASCII based (such as UCS-2)
- are not allowed and should be decoded to ``unicode`` first.
-
- ``object_hook`` is an optional function that will be called with the
- result of any object literal decode (a ``dict``). The return value of
- ``object_hook`` will be used instead of the ``dict``. This feature
- can be used to implement custom decoders (e.g. JSON-RPC class hinting).
-
- ``parse_float``, if specified, will be called with the string
- of every JSON float to be decoded. By default this is equivalent to
- float(num_str). This can be used to use another datatype or parser
- for JSON floats (e.g. decimal.Decimal).
-
- ``parse_int``, if specified, will be called with the string
- of every JSON int to be decoded. By default this is equivalent to
- int(num_str). This can be used to use another datatype or parser
- for JSON integers (e.g. float).
-
- ``parse_constant``, if specified, will be called with one of the
- following strings: -Infinity, Infinity, NaN, null, true, false.
- This can be used to raise an exception if invalid JSON numbers
- are encountered.
-
- To use a custom ``JSONDecoder`` subclass, specify it with the ``cls``
- kwarg.
- """
- if (cls is None and encoding is None and object_hook is None and
- parse_int is None and parse_float is None and
- parse_constant is None and not kw):
- return _default_decoder.decode(s)
- if cls is None:
- cls = JSONDecoder
- if object_hook is not None:
- kw['object_hook'] = object_hook
- if parse_float is not None:
- kw['parse_float'] = parse_float
- if parse_int is not None:
- kw['parse_int'] = parse_int
- if parse_constant is not None:
- kw['parse_constant'] = parse_constant
- return cls(encoding=encoding, **kw).decode(s)
-
-#
-# Compatibility cruft from other libraries
-#
-
-def decode(s):
- """
- demjson, python-cjson API compatibility hook. Use loads(s) instead.
- """
- import warnings
- warnings.warn("simplejson.loads(s) should be used instead of decode(s)",
- DeprecationWarning)
- return loads(s)
-
-def encode(obj):
- """
- demjson, python-cjson compatibility hook. Use dumps(s) instead.
- """
- import warnings
- warnings.warn("simplejson.dumps(s) should be used instead of encode(s)",
- DeprecationWarning)
- return dumps(obj)
-
-def read(s):
- """
- jsonlib, JsonUtils, python-json, json-py API compatibility hook.
- Use loads(s) instead.
- """
- import warnings
- warnings.warn("simplejson.loads(s) should be used instead of read(s)",
- DeprecationWarning)
- return loads(s)
-
-def write(obj):
- """
- jsonlib, JsonUtils, python-json, json-py API compatibility hook.
- Use dumps(s) instead.
- """
- import warnings
- warnings.warn("simplejson.dumps(s) should be used instead of write(s)",
- DeprecationWarning)
- return dumps(obj)
-
-#
-# Pretty printer:
-# curl http://mochikit.com/examples/ajax_tables/domains.json | python -msimplejson
-#
-
-def main():
- import sys
- if len(sys.argv) == 1:
- infile = sys.stdin
- outfile = sys.stdout
- elif len(sys.argv) == 2:
- infile = open(sys.argv[1], 'rb')
- outfile = sys.stdout
- elif len(sys.argv) == 3:
- infile = open(sys.argv[1], 'rb')
- outfile = open(sys.argv[2], 'wb')
- else:
- raise SystemExit("%s [infile [outfile]]" % (sys.argv[0],))
- try:
- obj = load(infile)
- except ValueError, e:
- raise SystemExit(e)
- dump(obj, outfile, sort_keys=True, indent=4)
- outfile.write('\n')
-
-if __name__ == '__main__':
- main()
diff --git a/simplejson/decoder.py b/simplejson/decoder.py
deleted file mode 100644
index 6a73e9a..0000000
--- a/simplejson/decoder.py
+++ /dev/null
@@ -1,322 +0,0 @@
-"""
-Implementation of JSONDecoder
-"""
-import re
-import sys
-
-from simplejson.scanner import Scanner, pattern
-try:
- from simplejson import _speedups
-except:
- _speedups = None
-
-FLAGS = re.VERBOSE | re.MULTILINE | re.DOTALL
-
-def _floatconstants():
- import struct
- import sys
- _BYTES = '7FF80000000000007FF0000000000000'.decode('hex')
- if sys.byteorder != 'big':
- _BYTES = _BYTES[:8][::-1] + _BYTES[8:][::-1]
- nan, inf = struct.unpack('dd', _BYTES)
- return nan, inf, -inf
-
-NaN, PosInf, NegInf = _floatconstants()
-
-def linecol(doc, pos):
- lineno = doc.count('\n', 0, pos) + 1
- if lineno == 1:
- colno = pos
- else:
- colno = pos - doc.rindex('\n', 0, pos)
- return lineno, colno
-
-def errmsg(msg, doc, pos, end=None):
- lineno, colno = linecol(doc, pos)
- if end is None:
- return '%s: line %d column %d (char %d)' % (msg, lineno, colno, pos)
- endlineno, endcolno = linecol(doc, end)
- return '%s: line %d column %d - line %d column %d (char %d - %d)' % (
- msg, lineno, colno, endlineno, endcolno, pos, end)
-
-_CONSTANTS = {
- '-Infinity': NegInf,
- 'Infinity': PosInf,
- 'NaN': NaN,
- 'true': True,
- 'false': False,
- 'null': None,
-}
-
-def JSONConstant(match, context, c=_CONSTANTS):
- s = match.group(0)
- fn = getattr(context, 'parse_constant', None)
- if fn is None:
- rval = c[s]
- else:
- rval = fn(s)
- return rval, None
-pattern('(-?Infinity|NaN|true|false|null)')(JSONConstant)
-
-def JSONNumber(match, context):
- match = JSONNumber.regex.match(match.string, *match.span())
- integer, frac, exp = match.groups()
- if frac or exp:
- fn = getattr(context, 'parse_float', None) or float
- res = fn(integer + (frac or '') + (exp or ''))
- else:
- fn = getattr(context, 'parse_int', None) or int
- res = fn(integer)
- return res, None
-pattern(r'(-?(?:0|[1-9]\d*))(\.\d+)?([eE][-+]?\d+)?')(JSONNumber)
-
-STRINGCHUNK = re.compile(r'(.*?)(["\\])', FLAGS)
-BACKSLASH = {
- '"': u'"', '\\': u'\\', '/': u'/',
- 'b': u'\b', 'f': u'\f', 'n': u'\n', 'r': u'\r', 't': u'\t',
-}
-
-DEFAULT_ENCODING = "utf-8"
-
-def scanstring(s, end, encoding=None, _b=BACKSLASH, _m=STRINGCHUNK.match):
- if encoding is None:
- encoding = DEFAULT_ENCODING
- chunks = []
- _append = chunks.append
- begin = end - 1
- while 1:
- chunk = _m(s, end)
- if chunk is None:
- raise ValueError(
- errmsg("Unterminated string starting at", s, begin))
- end = chunk.end()
- content, terminator = chunk.groups()
- if content:
- if not isinstance(content, unicode):
- content = unicode(content, encoding)
- _append(content)
- if terminator == '"':
- break
- try:
- esc = s[end]
- except IndexError:
- raise ValueError(
- errmsg("Unterminated string starting at", s, begin))
- if esc != 'u':
- try:
- m = _b[esc]
- except KeyError:
- raise ValueError(
- errmsg("Invalid \\escape: %r" % (esc,), s, end))
- end += 1
- else:
- esc = s[end + 1:end + 5]
- next_end = end + 5
- msg = "Invalid \\uXXXX escape"
- try:
- if len(esc) != 4:
- raise ValueError
- uni = int(esc, 16)
- if 0xd800 <= uni <= 0xdbff and sys.maxunicode > 65535:
- msg = "Invalid \\uXXXX\\uXXXX surrogate pair"
- if not s[end + 5:end + 7] == '\\u':
- raise ValueError
- esc2 = s[end + 7:end + 11]
- if len(esc2) != 4:
- raise ValueError
- uni2 = int(esc2, 16)
- uni = 0x10000 + (((uni - 0xd800) << 10) | (uni2 - 0xdc00))
- next_end += 6
- m = unichr(uni)
- except ValueError:
- raise ValueError(errmsg(msg, s, end))
- end = next_end
- _append(m)
- return u''.join(chunks), end
-
-# Use speedup
-if _speedups is not None:
- scanstring = _speedups.scanstring
-
-def JSONString(match, context):
- encoding = getattr(context, 'encoding', None)
- return scanstring(match.string, match.end(), encoding)
-pattern(r'"')(JSONString)
-
-WHITESPACE = re.compile(r'\s*', FLAGS)
-
-def JSONObject(match, context, _w=WHITESPACE.match):
- pairs = {}
- s = match.string
- end = _w(s, match.end()).end()
- nextchar = s[end:end + 1]
- # trivial empty object
- if nextchar == '}':
- return pairs, end + 1
- if nextchar != '"':
- raise ValueError(errmsg("Expecting property name", s, end))
- end += 1
- encoding = getattr(context, 'encoding', None)
- iterscan = JSONScanner.iterscan
- while True:
- key, end = scanstring(s, end, encoding)
- end = _w(s, end).end()
- if s[end:end + 1] != ':':
- raise ValueError(errmsg("Expecting : delimiter", s, end))
- end = _w(s, end + 1).end()
- try:
- value, end = iterscan(s, idx=end, context=context).next()
- except StopIteration:
- raise ValueError(errmsg("Expecting object", s, end))
- pairs[key] = value
- end = _w(s, end).end()
- nextchar = s[end:end + 1]
- end += 1
- if nextchar == '}':
- break
- if nextchar != ',':
- raise ValueError(errmsg("Expecting , delimiter", s, end - 1))
- end = _w(s, end).end()
- nextchar = s[end:end + 1]
- end += 1
- if nextchar != '"':
- raise ValueError(errmsg("Expecting property name", s, end - 1))
- object_hook = getattr(context, 'object_hook', None)
- if object_hook is not None:
- pairs = object_hook(pairs)
- return pairs, end
-pattern(r'{')(JSONObject)
-
-def JSONArray(match, context, _w=WHITESPACE.match):
- values = []
- s = match.string
- end = _w(s, match.end()).end()
- # look-ahead for trivial empty array
- nextchar = s[end:end + 1]
- if nextchar == ']':
- return values, end + 1
- iterscan = JSONScanner.iterscan
- while True:
- try:
- value, end = iterscan(s, idx=end, context=context).next()
- except StopIteration:
- raise ValueError(errmsg("Expecting object", s, end))
- values.append(value)
- end = _w(s, end).end()
- nextchar = s[end:end + 1]
- end += 1
- if nextchar == ']':
- break
- if nextchar != ',':
- raise ValueError(errmsg("Expecting , delimiter", s, end))
- end = _w(s, end).end()
- return values, end
-pattern(r'\[')(JSONArray)
-
-ANYTHING = [
- JSONObject,
- JSONArray,
- JSONString,
- JSONConstant,
- JSONNumber,
-]
-
-JSONScanner = Scanner(ANYTHING)
-
-class JSONDecoder(object):
- """
- Simple JSON <http://json.org> decoder
-
- Performs the following translations in decoding by default:
-
- +---------------+-------------------+
- | JSON | Python |
- +===============+===================+
- | object | dict |
- +---------------+-------------------+
- | array | list |
- +---------------+-------------------+
- | string | unicode |
- +---------------+-------------------+
- | number (int) | int, long |
- +---------------+-------------------+
- | number (real) | float |
- +---------------+-------------------+
- | true | True |
- +---------------+-------------------+
- | false | False |
- +---------------+-------------------+
- | null | None |
- +---------------+-------------------+
-
- It also understands ``NaN``, ``Infinity``, and ``-Infinity`` as
- their corresponding ``float`` values, which is outside the JSON spec.
- """
-
- _scanner = Scanner(ANYTHING)
- __all__ = ['__init__', 'decode', 'raw_decode']
-
- def __init__(self, encoding=None, object_hook=None, parse_float=None,
- parse_int=None, parse_constant=None):
- """
- ``encoding`` determines the encoding used to interpret any ``str``
- objects decoded by this instance (utf-8 by default). It has no
- effect when decoding ``unicode`` objects.
-
- Note that currently only encodings that are a superset of ASCII work,
- strings of other encodings should be passed in as ``unicode``.
-
- ``object_hook``, if specified, will be called with the result
- of every JSON object decoded and its return value will be used in
- place of the given ``dict``. This can be used to provide custom
- deserializations (e.g. to support JSON-RPC class hinting).
-
- ``parse_float``, if specified, will be called with the string
- of every JSON float to be decoded. By default this is equivalent to
- float(num_str). This can be used to use another datatype or parser
- for JSON floats (e.g. decimal.Decimal).
-
- ``parse_int``, if specified, will be called with the string
- of every JSON int to be decoded. By default this is equivalent to
- int(num_str). This can be used to use another datatype or parser
- for JSON integers (e.g. float).
-
- ``parse_constant``, if specified, will be called with one of the
- following strings: -Infinity, Infinity, NaN, null, true, false.
- This can be used to raise an exception if invalid JSON numbers
- are encountered.
- """
- self.encoding = encoding
- self.object_hook = object_hook
- self.parse_float = parse_float
- self.parse_int = parse_int
- self.parse_constant = parse_constant
-
- def decode(self, s, _w=WHITESPACE.match):
- """
- Return the Python representation of ``s`` (a ``str`` or ``unicode``
- instance containing a JSON document)
- """
- obj, end = self.raw_decode(s, idx=_w(s, 0).end())
- end = _w(s, end).end()
- if end != len(s):
- raise ValueError(errmsg("Extra data", s, end, len(s)))
- return obj
-
- def raw_decode(self, s, **kw):
- """
- Decode a JSON document from ``s`` (a ``str`` or ``unicode`` beginning
- with a JSON document) and return a 2-tuple of the Python
- representation and the index in ``s`` where the document ended.
-
- This can be used to decode a JSON document from a string that may
- have extraneous data at the end.
- """
- kw.setdefault('context', self)
- try:
- obj, end = self._scanner.iterscan(s, **kw).next()
- except StopIteration:
- raise ValueError("No JSON object could be decoded")
- return obj, end
-
-__all__ = ['JSONDecoder']
diff --git a/simplejson/encoder.py b/simplejson/encoder.py
deleted file mode 100644
index 1c69b02..0000000
--- a/simplejson/encoder.py
+++ /dev/null
@@ -1,376 +0,0 @@
-"""
-Implementation of JSONEncoder
-"""
-import re
-try:
- from simplejson import _speedups
-except ImportError:
- _speedups = None
-
-ESCAPE = re.compile(r'[\x00-\x1f\\"\b\f\n\r\t]')
-ESCAPE_ASCII = re.compile(r'([\\"/]|[^\ -~])')
-ESCAPE_DCT = {
- '\\': '\\\\',
- '"': '\\"',
- '\b': '\\b',
- '\f': '\\f',
- '\n': '\\n',
- '\r': '\\r',
- '\t': '\\t',
-}
-for i in range(0x20):
- ESCAPE_DCT.setdefault(chr(i), '\\u%04x' % (i,))
-
-# assume this produces an infinity on all machines (probably not guaranteed)
-INFINITY = float('1e66666')
-FLOAT_REPR = repr
-
-def floatstr(o, allow_nan=True):
- # Check for specials. Note that this type of test is processor- and/or
- # platform-specific, so do tests which don't depend on the internals.
-
- if o != o:
- text = 'NaN'
- elif o == INFINITY:
- text = 'Infinity'
- elif o == -INFINITY:
- text = '-Infinity'
- else:
- return FLOAT_REPR(o)
-
- if not allow_nan:
- raise ValueError("Out of range float values are not JSON compliant: %r"
- % (o,))
-
- return text
-
-
-def encode_basestring(s):
- """
- Return a JSON representation of a Python string
- """
- def replace(match):
- return ESCAPE_DCT[match.group(0)]
- return '"' + ESCAPE.sub(replace, s) + '"'
-
-def encode_basestring_ascii(s):
- def replace(match):
- s = match.group(0)
- try:
- return ESCAPE_DCT[s]
- except KeyError:
- n = ord(s)
- if n < 0x10000:
- return '\\u%04x' % (n,)
- else:
- # surrogate pair
- n -= 0x10000
- s1 = 0xd800 | ((n >> 10) & 0x3ff)
- s2 = 0xdc00 | (n & 0x3ff)
- return '\\u%04x\\u%04x' % (s1, s2)
- return '"' + str(ESCAPE_ASCII.sub(replace, s)) + '"'
-
-try:
- encode_basestring_ascii = _speedups.encode_basestring_ascii
- _need_utf8 = True
-except AttributeError:
- _need_utf8 = False
-
-class JSONEncoder(object):
- """
- Extensible JSON <http://json.org> encoder for Python data structures.
-
- Supports the following objects and types by default:
-
- +-------------------+---------------+
- | Python | JSON |
- +===================+===============+
- | dict | object |
- +-------------------+---------------+
- | list, tuple | array |
- +-------------------+---------------+
- | str, unicode | string |
- +-------------------+---------------+
- | int, long, float | number |
- +-------------------+---------------+
- | True | true |
- +-------------------+---------------+
- | False | false |
- +-------------------+---------------+
- | None | null |
- +-------------------+---------------+
-
- To extend this to recognize other objects, subclass and implement a
- ``.default()`` method with another method that returns a serializable
- object for ``o`` if possible, otherwise it should call the superclass
- implementation (to raise ``TypeError``).
- """
- __all__ = ['__init__', 'default', 'encode', 'iterencode']
- item_separator = ', '
- key_separator = ': '
- def __init__(self, skipkeys=False, ensure_ascii=True,
- check_circular=True, allow_nan=True, sort_keys=False,
- indent=None, separators=None, encoding='utf-8', default=None):
- """
- Constructor for JSONEncoder, with sensible defaults.
-
- If skipkeys is False, then it is a TypeError to attempt
- encoding of keys that are not str, int, long, float or None. If
- skipkeys is True, such items are simply skipped.
-
- If ensure_ascii is True, the output is guaranteed to be str
- objects with all incoming unicode characters escaped. If
- ensure_ascii is false, the output will be unicode object.
-
- If check_circular is True, then lists, dicts, and custom encoded
- objects will be checked for circular references during encoding to
- prevent an infinite recursion (which would cause an OverflowError).
- Otherwise, no such check takes place.
-
- If allow_nan is True, then NaN, Infinity, and -Infinity will be
- encoded as such. This behavior is not JSON specification compliant,
- but is consistent with most JavaScript based encoders and decoders.
- Otherwise, it will be a ValueError to encode such floats.
-
- If sort_keys is True, then the output of dictionaries will be
- sorted by key; this is useful for regression tests to ensure
- that JSON serializations can be compared on a day-to-day basis.
-
- If indent is a non-negative integer, then JSON array
- elements and object members will be pretty-printed with that
- indent level. An indent level of 0 will only insert newlines.
- None is the most compact representation.
-
- If specified, separators should be a (item_separator, key_separator)
- tuple. The default is (', ', ': '). To get the most compact JSON
- representation you should specify (',', ':') to eliminate whitespace.
-
- If specified, default is a function that gets called for objects
- that can't otherwise be serialized. It should return a JSON encodable
- version of the object or raise a ``TypeError``.
-
- If encoding is not None, then all input strings will be
- transformed into unicode using that encoding prior to JSON-encoding.
- The default is UTF-8.
- """
-
- self.skipkeys = skipkeys
- self.ensure_ascii = ensure_ascii
- self.check_circular = check_circular
- self.allow_nan = allow_nan
- self.sort_keys = sort_keys
- self.indent = indent
- self.current_indent_level = 0
- if separators is not None:
- self.item_separator, self.key_separator = separators
- if default is not None:
- self.default = default
- self.encoding = encoding
-
- def _newline_indent(self):
- return '\n' + (' ' * (self.indent * self.current_indent_level))
-
- def _iterencode_list(self, lst, markers=None):
- if not lst:
- yield '[]'
- return
- if markers is not None:
- markerid = id(lst)
- if markerid in markers:
- raise ValueError("Circular reference detected")
- markers[markerid] = lst
- yield '['
- if self.indent is not None:
- self.current_indent_level += 1
- newline_indent = self._newline_indent()
- separator = self.item_separator + newline_indent
- yield newline_indent
- else:
- newline_indent = None
- separator = self.item_separator
- first = True
- for value in lst:
- if first:
- first = False
- else:
- yield separator
- for chunk in self._iterencode(value, markers):
- yield chunk
- if newline_indent is not None:
- self.current_indent_level -= 1
- yield self._newline_indent()
- yield ']'
- if markers is not None:
- del markers[markerid]
-
- def _iterencode_dict(self, dct, markers=None):
- if not dct:
- yield '{}'
- return
- if markers is not None:
- markerid = id(dct)
- if markerid in markers:
- raise ValueError("Circular reference detected")
- markers[markerid] = dct
- yield '{'
- key_separator = self.key_separator
- if self.indent is not None:
- self.current_indent_level += 1
- newline_indent = self._newline_indent()
- item_separator = self.item_separator + newline_indent
- yield newline_indent
- else:
- newline_indent = None
- item_separator = self.item_separator
- first = True
- if self.ensure_ascii:
- encoder = encode_basestring_ascii
- else:
- encoder = encode_basestring
- allow_nan = self.allow_nan
- if self.sort_keys:
- keys = dct.keys()
- keys.sort()
- items = [(k, dct[k]) for k in keys]
- else:
- items = dct.iteritems()
- _encoding = self.encoding
- _do_decode = (_encoding is not None
- and not (_need_utf8 and _encoding == 'utf-8'))
- for key, value in items:
- if isinstance(key, str):
- if _do_decode:
- key = key.decode(_encoding)
- elif isinstance(key, basestring):
- pass
- # JavaScript is weakly typed for these, so it makes sense to
- # also allow them. Many encoders seem to do something like this.
- elif isinstance(key, float):
- key = floatstr(key, allow_nan)
- elif isinstance(key, (int, long)):
- key = str(key)
- elif key is True:
- key = 'true'
- elif key is False:
- key = 'false'
- elif key is None:
- key = 'null'
- elif self.skipkeys:
- continue
- else:
- raise TypeError("key %r is not a string" % (key,))
- if first:
- first = False
- else:
- yield item_separator
- yield encoder(key)
- yield key_separator
- for chunk in self._iterencode(value, markers):
- yield chunk
- if newline_indent is not None:
- self.current_indent_level -= 1
- yield self._newline_indent()
- yield '}'
- if markers is not None:
- del markers[markerid]
-
- def _iterencode(self, o, markers=None):
- if isinstance(o, basestring):
- if self.ensure_ascii:
- encoder = encode_basestring_ascii
- else:
- encoder = encode_basestring
- _encoding = self.encoding
- if (_encoding is not None and isinstance(o, str)
- and not (_need_utf8 and _encoding == 'utf-8')):
- o = o.decode(_encoding)
- yield encoder(o)
- elif o is None:
- yield 'null'
- elif o is True:
- yield 'true'
- elif o is False:
- yield 'false'
- elif isinstance(o, (int, long)):
- yield str(o)
- elif isinstance(o, float):
- yield floatstr(o, self.allow_nan)
- elif isinstance(o, (list, tuple)):
- for chunk in self._iterencode_list(o, markers):
- yield chunk
- elif isinstance(o, dict):
- for chunk in self._iterencode_dict(o, markers):
- yield chunk
- else:
- if markers is not None:
- markerid = id(o)
- if markerid in markers:
- raise ValueError("Circular reference detected")
- markers[markerid] = o
- for chunk in self._iterencode_default(o, markers):
- yield chunk
- if markers is not None:
- del markers[markerid]
-
- def _iterencode_default(self, o, markers=None):
- newobj = self.default(o)
- return self._iterencode(newobj, markers)
-
- def default(self, o):
- """
- Implement this method in a subclass such that it returns
- a serializable object for ``o``, or calls the base implementation
- (to raise a ``TypeError``).
-
- For example, to support arbitrary iterators, you could
- implement default like this::
-
- def default(self, o):
- try:
- iterable = iter(o)
- except TypeError:
- pass
- else:
- return list(iterable)
- return JSONEncoder.default(self, o)
- """
- raise TypeError("%r is not JSON serializable" % (o,))
-
- def encode(self, o):
- """
- Return a JSON string representation of a Python data structure.
-
- >>> JSONEncoder().encode({"foo": ["bar", "baz"]})
- '{"foo":["bar", "baz"]}'
- """
- # This is for extremely simple cases and benchmarks...
- if isinstance(o, basestring):
- if isinstance(o, str):
- _encoding = self.encoding
- if (_encoding is not None
- and not (_encoding == 'utf-8' and _need_utf8)):
- o = o.decode(_encoding)
- return encode_basestring_ascii(o)
- # This doesn't pass the iterator directly to ''.join() because it
- # sucks at reporting exceptions. It's going to do this internally
- # anyway because it uses PySequence_Fast or similar.
- chunks = list(self.iterencode(o))
- return ''.join(chunks)
-
- def iterencode(self, o):
- """
- Encode the given object and yield each string
- representation as available.
-
- For example::
-
- for chunk in JSONEncoder().iterencode(bigobject):
- mysocket.write(chunk)
- """
- if self.check_circular:
- markers = {}
- else:
- markers = None
- return self._iterencode(o, markers)
-
-__all__ = ['JSONEncoder']
diff --git a/simplejson/jsonfilter.py b/simplejson/jsonfilter.py
deleted file mode 100644
index 01ca21d..0000000
--- a/simplejson/jsonfilter.py
+++ /dev/null
@@ -1,40 +0,0 @@
-import simplejson
-import cgi
-
-class JSONFilter(object):
- def __init__(self, app, mime_type='text/x-json'):
- self.app = app
- self.mime_type = mime_type
-
- def __call__(self, environ, start_response):
- # Read JSON POST input to jsonfilter.json if matching mime type
- response = {'status': '200 OK', 'headers': []}
- def json_start_response(status, headers):
- response['status'] = status
- response['headers'].extend(headers)
- environ['jsonfilter.mime_type'] = self.mime_type
- if environ.get('REQUEST_METHOD', '') == 'POST':
- if environ.get('CONTENT_TYPE', '') == self.mime_type:
- args = [_ for _ in [environ.get('CONTENT_LENGTH')] if _]
- data = environ['wsgi.input'].read(*map(int, args))
- environ['jsonfilter.json'] = simplejson.loads(data)
- res = simplejson.dumps(self.app(environ, json_start_response))
- jsonp = cgi.parse_qs(environ.get('QUERY_STRING', '')).get('jsonp')
- if jsonp:
- content_type = 'text/javascript'
- res = ''.join(jsonp + ['(', res, ')'])
- elif 'Opera' in environ.get('HTTP_USER_AGENT', ''):
- # Opera has bunk XMLHttpRequest support for most mime types
- content_type = 'text/plain'
- else:
- content_type = self.mime_type
- headers = [
- ('Content-type', content_type),
- ('Content-length', len(res)),
- ]
- headers.extend(response['headers'])
- start_response(response['status'], headers)
- return [res]
-
-def factory(app, global_conf, **kw):
- return JSONFilter(app, **kw)
diff --git a/simplejson/scanner.py b/simplejson/scanner.py
deleted file mode 100644
index 0f4be10..0000000
--- a/simplejson/scanner.py
+++ /dev/null
@@ -1,64 +0,0 @@
-"""
-Iterator based sre token scanner
-"""
-import sre_parse, sre_compile, sre_constants
-from sre_constants import BRANCH, SUBPATTERN
-from re import VERBOSE, MULTILINE, DOTALL
-import re
-
-__all__ = ['Scanner', 'pattern']
-
-FLAGS = (VERBOSE | MULTILINE | DOTALL)
-class Scanner(object):
- def __init__(self, lexicon, flags=FLAGS):
- self.actions = [None]
- # combine phrases into a compound pattern
- s = sre_parse.Pattern()
- s.flags = flags
- p = []
- for idx, token in enumerate(lexicon):
- phrase = token.pattern
- try:
- subpattern = sre_parse.SubPattern(s,
- [(SUBPATTERN, (idx + 1, sre_parse.parse(phrase, flags)))])
- except sre_constants.error:
- raise
- p.append(subpattern)
- self.actions.append(token)
-
- s.groups = len(p)+1 # NOTE(guido): Added to make SRE validation work
- p = sre_parse.SubPattern(s, [(BRANCH, (None, p))])
- self.scanner = sre_compile.compile(p)
-
-
- def iterscan(self, string, idx=0, context=None):
- """
- Yield match, end_idx for each match
- """
- match = self.scanner.scanner(string, idx).match
- actions = self.actions
- lastend = idx
- end = len(string)
- while True:
- m = match()
- if m is None:
- break
- matchbegin, matchend = m.span()
- if lastend == matchend:
- break
- action = actions[m.lastindex]
- if action is not None:
- rval, next_pos = action(m, context)
- if next_pos is not None and next_pos != matchend:
- # "fast forward" the scanner
- matchend = next_pos
- match = self.scanner.scanner(string, matchend).match
- yield rval, matchend
- lastend = matchend
-
-def pattern(pattern, flags=FLAGS):
- def decorator(fn):
- fn.pattern = pattern
- fn.regex = re.compile(pattern, flags)
- return fn
- return decorator