allow python-bundled json

This commit is contained in:
Damien Elmes 2012-04-28 17:41:56 +09:00
parent 491596096a
commit 461e240d53
14 changed files with 70 additions and 61 deletions

View file

@ -2,7 +2,7 @@
# Copyright: Damien Elmes <anki@ichi2.net> # Copyright: Damien Elmes <anki@ichi2.net>
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import sys as _sys, simplejson as _simplejson, httplib2 as _httplib2, \ import sys as _sys, httplib2 as _httplib2, \
BeautifulSoup as _bs BeautifulSoup as _bs
if _sys.version_info[0] > 2: if _sys.version_info[0] > 2:
@ -11,12 +11,17 @@ elif _sys.version_info[1] < 5:
raise Exception("Anki requires Python 2.5+") raise Exception("Anki requires Python 2.5+")
elif _sys.getfilesystemencoding().lower() in ("ascii", "ansi_x3.4-1968"): elif _sys.getfilesystemencoding().lower() in ("ascii", "ansi_x3.4-1968"):
raise Exception("Anki requires a UTF-8 locale.") raise Exception("Anki requires a UTF-8 locale.")
elif _simplejson.__version__ < "1.7.3":
raise Exception("SimpleJSON must be 1.7.3 or later.")
elif _httplib2.__version__ < "0.7.0": elif _httplib2.__version__ < "0.7.0":
raise Exception("Httplib2 must be 0.7.0 or later.") raise Exception("Httplib2 must be 0.7.0 or later.")
elif _bs.__version__ < "3.2": elif _bs.__version__ < "3.2":
raise Exception("Please install BeautifulSoup 3.2+") raise Exception("Please install BeautifulSoup 3.2+")
try:
import simplejson as _json
except:
import json as _json
if _json.__version__ < "1.7.3":
raise Exception("SimpleJSON must be 1.7.3 or later.")
version = "1.99" version = "1.99"
from anki.storage import Collection from anki.storage import Collection

View file

@ -2,10 +2,10 @@
# Copyright: Damien Elmes <anki@ichi2.net> # Copyright: Damien Elmes <anki@ichi2.net>
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import time, os, random, re, stat, simplejson, datetime, copy, shutil, sys import time, os, random, re, stat, datetime, copy, shutil, sys
from anki.lang import _, ngettext from anki.lang import _, ngettext
from anki.utils import ids2str, hexifyID, checksum, fieldChecksum, stripHTML, \ from anki.utils import ids2str, hexifyID, checksum, fieldChecksum, stripHTML, \
intTime, splitFields, joinFields, maxID intTime, splitFields, joinFields, maxID, json
from anki.hooks import runHook, runFilter from anki.hooks import runHook, runFilter
from anki.sched import Scheduler from anki.sched import Scheduler
from anki.models import ModelManager from anki.models import ModelManager
@ -81,7 +81,7 @@ class _Collection(object):
tags) = self.db.first(""" tags) = self.db.first("""
select crt, mod, scm, dty, usn, ls, select crt, mod, scm, dty, usn, ls,
conf, models, decks, dconf, tags from col""") conf, models, decks, dconf, tags from col""")
self.conf = simplejson.loads(self.conf) self.conf = json.loads(self.conf)
self.models.load(models) self.models.load(models)
self.decks.load(decks, dconf) self.decks.load(decks, dconf)
self.tags.load(tags) self.tags.load(tags)
@ -100,7 +100,7 @@ is only necessary if you modify properties of this object or the conf dict."""
"""update col set """update col set
crt=?, mod=?, scm=?, dty=?, usn=?, ls=?, conf=?""", crt=?, mod=?, scm=?, dty=?, usn=?, ls=?, conf=?""",
self.crt, self.mod, self.scm, self.dty, self.crt, self.mod, self.scm, self.dty,
self._usn, self.ls, simplejson.dumps(self.conf)) self._usn, self.ls, json.dumps(self.conf))
def save(self, name=None, mod=None): def save(self, name=None, mod=None):
"Flush, commit DB, and take out another write lock." "Flush, commit DB, and take out another write lock."

View file

@ -2,8 +2,8 @@
# Copyright: Damien Elmes <anki@ichi2.net> # Copyright: Damien Elmes <anki@ichi2.net>
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import simplejson, copy import copy
from anki.utils import intTime, ids2str from anki.utils import intTime, ids2str, json
from anki.consts import * from anki.consts import *
from anki.lang import _ from anki.lang import _
from anki.errors import DeckRenameError from anki.errors import DeckRenameError
@ -83,8 +83,8 @@ class DeckManager(object):
self.col = col self.col = col
def load(self, decks, dconf): def load(self, decks, dconf):
self.decks = simplejson.loads(decks) self.decks = json.loads(decks)
self.dconf = simplejson.loads(dconf) self.dconf = json.loads(dconf)
self.changed = False self.changed = False
def save(self, g=None): def save(self, g=None):
@ -97,8 +97,8 @@ class DeckManager(object):
def flush(self): def flush(self):
if self.changed: if self.changed:
self.col.db.execute("update col set decks=?, dconf=?", self.col.db.execute("update col set decks=?, dconf=?",
simplejson.dumps(self.decks), json.dumps(self.decks),
simplejson.dumps(self.dconf)) json.dumps(self.dconf))
self.changed = False self.changed = False
# Deck save/load # Deck save/load

View file

@ -2,11 +2,11 @@
# Copyright: Damien Elmes <anki@ichi2.net> # Copyright: Damien Elmes <anki@ichi2.net>
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import itertools, time, re, os, HTMLParser, zipfile, simplejson import itertools, time, re, os, HTMLParser, zipfile
from operator import itemgetter from operator import itemgetter
from anki.cards import Card from anki.cards import Card
from anki.lang import _ from anki.lang import _
from anki.utils import stripHTML, ids2str, splitFields from anki.utils import stripHTML, ids2str, splitFields, json
from anki import Collection from anki import Collection
class Exporter(object): class Exporter(object):
@ -225,7 +225,7 @@ class AnkiPackageExporter(AnkiExporter):
z.write(file, c) z.write(file, c)
media[c] = file media[c] = file
# media map # media map
z.writestr("media", simplejson.dumps(media)) z.writestr("media", json.dumps(media))
z.close() z.close()
# tidy up intermediate files # tidy up intermediate files
os.unlink(colfile) os.unlink(colfile)

View file

@ -2,8 +2,8 @@
# Copyright: Damien Elmes <anki@ichi2.net> # Copyright: Damien Elmes <anki@ichi2.net>
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import zipfile, simplejson, os import zipfile, os
from anki.utils import tmpfile from anki.utils import tmpfile, json
from anki.importing.anki2 import Anki2Importer from anki.importing.anki2 import Anki2Importer
class AnkiPackageImporter(Anki2Importer): class AnkiPackageImporter(Anki2Importer):
@ -18,7 +18,7 @@ class AnkiPackageImporter(Anki2Importer):
self.file = colpath self.file = colpath
Anki2Importer.run(self) Anki2Importer.run(self)
# import media # import media
media = simplejson.loads(z.read("media")) media = json.loads(z.read("media"))
for c, file in media.items(): for c, file in media.items():
path = os.path.join(self.col.media.dir(), file) path = os.path.join(self.col.media.dir(), file)
if not os.path.exists(path): if not os.path.exists(path):

View file

@ -3,9 +3,9 @@
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import os, shutil, re, urllib, urllib2, time, unicodedata, \ import os, shutil, re, urllib, urllib2, time, unicodedata, \
urllib, sys, simplejson, zipfile urllib, sys, zipfile
from cStringIO import StringIO from cStringIO import StringIO
from anki.utils import checksum, intTime, namedtmp, isWin, isMac from anki.utils import checksum, intTime, namedtmp, isWin, isMac, json
from anki.lang import _ from anki.lang import _
from anki.db import DB from anki.db import DB
from anki.consts import * from anki.consts import *
@ -229,7 +229,7 @@ If the same name exists, compare checksums."""
sizecnt = 0 sizecnt = 0
# get meta info first # get meta info first
assert z.getinfo("_meta").file_size < 100000 assert z.getinfo("_meta").file_size < 100000
meta = simplejson.loads(z.read("_meta")) meta = json.loads(z.read("_meta"))
nextUsn = int(z.read("_usn")) nextUsn = int(z.read("_usn"))
# then loop through all files # then loop through all files
for i in z.infolist(): for i in z.infolist():
@ -306,7 +306,7 @@ If the same name exists, compare checksums."""
if sz > SYNC_ZIP_SIZE: if sz > SYNC_ZIP_SIZE:
break break
cnt += 1 cnt += 1
z.writestr("_meta", simplejson.dumps(files)) z.writestr("_meta", json.dumps(files))
z.close() z.close()
return f.getvalue(), fnames return f.getvalue(), fnames

View file

@ -2,9 +2,9 @@
# Copyright: Damien Elmes <anki@ichi2.net> # Copyright: Damien Elmes <anki@ichi2.net>
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import simplejson, copy, re import copy, re
from anki.utils import intTime, hexifyID, joinFields, splitFields, ids2str, \ from anki.utils import intTime, hexifyID, joinFields, splitFields, ids2str, \
timestampID, fieldChecksum timestampID, fieldChecksum, json
from anki.lang import _ from anki.lang import _
from anki.consts import * from anki.consts import *
@ -69,10 +69,10 @@ class ModelManager(object):
def __init__(self, col): def __init__(self, col):
self.col = col self.col = col
def load(self, json): def load(self, json_):
"Load registry from JSON." "Load registry from JSON."
self.changed = False self.changed = False
self.models = simplejson.loads(json) self.models = json.loads(json_)
def save(self, m=None, templates=False): def save(self, m=None, templates=False):
"Mark M modified if provided, and schedule registry flush." "Mark M modified if provided, and schedule registry flush."
@ -88,7 +88,7 @@ class ModelManager(object):
"Flush the registry if any models were changed." "Flush the registry if any models were changed."
if self.changed: if self.changed:
self.col.db.execute("update col set models = ?", self.col.db.execute("update col set models = ?",
simplejson.dumps(self.models)) json.dumps(self.models))
self.changed = False self.changed = False
# Retrieving and creating models # Retrieving and creating models

View file

@ -2,7 +2,7 @@
# Copyright: Damien Elmes <anki@ichi2.net> # Copyright: Damien Elmes <anki@ichi2.net>
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import time, datetime, simplejson, random, itertools, math import time, datetime, random, itertools, math
from operator import itemgetter from operator import itemgetter
from heapq import * from heapq import *
#from anki.cards import Card #from anki.cards import Card

View file

@ -2,7 +2,7 @@
# Copyright: Damien Elmes <anki@ichi2.net> # Copyright: Damien Elmes <anki@ichi2.net>
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import time, sys, os, datetime, simplejson import time, sys, os, datetime, json
import anki.js import anki.js
from anki.utils import fmtTimeSpan, fmtFloat, ids2str from anki.utils import fmtTimeSpan, fmtFloat, ids2str
from anki.consts import * from anki.consts import *
@ -670,7 +670,7 @@ $(function () {
</script>""" % dict( </script>""" % dict(
id=id, w=width, h=height, id=id, w=width, h=height,
ylab=ylabel, ylab=ylabel,
data=simplejson.dumps(data), conf=simplejson.dumps(conf))) data=json.dumps(data), conf=json.dumps(conf)))
def _limit(self): def _limit(self):
if self.wholeCollection: if self.wholeCollection:

View file

@ -2,9 +2,9 @@
# Copyright: Damien Elmes <anki@ichi2.net> # Copyright: Damien Elmes <anki@ichi2.net>
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import os, simplejson, copy, re import os, copy, re
from anki.lang import _ from anki.lang import _
from anki.utils import intTime, ids2str from anki.utils import intTime, ids2str, json
from anki.db import DB from anki.db import DB
from anki.collection import _Collection from anki.collection import _Collection
from anki.consts import * from anki.consts import *
@ -218,9 +218,9 @@ def _getColVars(db):
def _addColVars(db, g, gc, c): def _addColVars(db, g, gc, c):
db.execute(""" db.execute("""
update col set conf = ?, decks = ?, dconf = ?""", update col set conf = ?, decks = ?, dconf = ?""",
simplejson.dumps(c), json.dumps(c),
simplejson.dumps({'1': g}), json.dumps({'1': g}),
simplejson.dumps({'1': gc})) json.dumps({'1': gc}))
def _updateIndices(db): def _updateIndices(db):
"Add indices to the DB." "Add indices to the DB."

View file

@ -2,12 +2,12 @@
# Copyright: Damien Elmes <anki@ichi2.net> # Copyright: Damien Elmes <anki@ichi2.net>
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import urllib, simplejson, os, sys, httplib2, gzip import urllib, os, sys, httplib2, gzip
from cStringIO import StringIO from cStringIO import StringIO
from datetime import date from datetime import date
from anki.db import DB from anki.db import DB
from anki.errors import * from anki.errors import *
from anki.utils import ids2str, checksum, intTime from anki.utils import ids2str, checksum, intTime, json
from anki.consts import * from anki.consts import *
from anki.lang import _ from anki.lang import _
from hooks import runHook from hooks import runHook
@ -393,7 +393,7 @@ class LocalServer(Syncer):
# serialize/deserialize payload, so we don't end up sharing objects # serialize/deserialize payload, so we don't end up sharing objects
# between cols # between cols
def applyChanges(self, changes): def applyChanges(self, changes):
l = simplejson.loads; d = simplejson.dumps l = json.loads; d = json.dumps
return l(d(Syncer.applyChanges(self, l(d(changes))))) return l(d(Syncer.applyChanges(self, l(d(changes)))))
# HTTP syncing tools # HTTP syncing tools
@ -483,22 +483,22 @@ class RemoteServer(HttpSyncer):
def hostKey(self, user, pw): def hostKey(self, user, pw):
"Returns hkey or none if user/pw incorrect." "Returns hkey or none if user/pw incorrect."
ret = self.req( ret = self.req(
"hostKey", StringIO(simplejson.dumps(dict(u=user, p=pw))), "hostKey", StringIO(json.dumps(dict(u=user, p=pw))),
badAuthRaises=False, hkey=False) badAuthRaises=False, hkey=False)
if not ret: if not ret:
# invalid auth # invalid auth
return return
self.hkey = simplejson.loads(ret)['key'] self.hkey = json.loads(ret)['key']
return self.hkey return self.hkey
def meta(self): def meta(self):
ret = self.req( ret = self.req(
"meta", StringIO(simplejson.dumps(dict(v=SYNC_VER))), "meta", StringIO(json.dumps(dict(v=SYNC_VER))),
badAuthRaises=False) badAuthRaises=False)
if not ret: if not ret:
# invalid auth # invalid auth
return return
return simplejson.loads(ret) return json.loads(ret)
def applyChanges(self, **kw): def applyChanges(self, **kw):
return self._run("applyChanges", kw) return self._run("applyChanges", kw)
@ -519,8 +519,8 @@ class RemoteServer(HttpSyncer):
return self._run("finish", kw) return self._run("finish", kw)
def _run(self, cmd, data): def _run(self, cmd, data):
return simplejson.loads( return json.loads(
self.req(cmd, StringIO(simplejson.dumps(data)))) self.req(cmd, StringIO(json.dumps(data))))
# Full syncing # Full syncing
########################################################################## ##########################################################################
@ -635,23 +635,23 @@ class RemoteMediaServer(HttpSyncer):
HttpSyncer.__init__(self, hkey, con) HttpSyncer.__init__(self, hkey, con)
def remove(self, **kw): def remove(self, **kw):
return simplejson.loads( return json.loads(
self.req("remove", StringIO(simplejson.dumps(kw)))) self.req("remove", StringIO(json.dumps(kw))))
def files(self, **kw): def files(self, **kw):
return self.req("files", StringIO(simplejson.dumps(kw))) return self.req("files", StringIO(json.dumps(kw)))
def addFiles(self, zip): def addFiles(self, zip):
# no compression, as we compress the zip file instead # no compression, as we compress the zip file instead
return simplejson.loads( return json.loads(
self.req("addFiles", StringIO(zip), comp=0)) self.req("addFiles", StringIO(zip), comp=0))
def mediaSanity(self): def mediaSanity(self):
return simplejson.loads( return json.loads(
self.req("mediaSanity")) self.req("mediaSanity"))
# only for unit tests # only for unit tests
def mediatest(self, n): def mediatest(self, n):
return simplejson.loads( return json.loads(
self.req("mediatest", StringIO( self.req("mediatest", StringIO(
simplejson.dumps(dict(n=n))))) json.dumps(dict(n=n)))))

View file

@ -2,8 +2,7 @@
# Copyright: Damien Elmes <anki@ichi2.net> # Copyright: Damien Elmes <anki@ichi2.net>
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import simplejson from anki.utils import intTime, ids2str, json
from anki.utils import intTime, ids2str
from anki.hooks import runHook from anki.hooks import runHook
""" """
@ -22,14 +21,14 @@ class TagManager(object):
def __init__(self, col): def __init__(self, col):
self.col = col self.col = col
def load(self, json): def load(self, json_):
self.tags = simplejson.loads(json) self.tags = json.loads(json_)
self.changed = False self.changed = False
def flush(self): def flush(self):
if self.changed: if self.changed:
self.col.db.execute("update col set tags=?", self.col.db.execute("update col set tags=?",
simplejson.dumps(self.tags)) json.dumps(self.tags))
self.changed = False self.changed = False
# Registering and fetching tags # Registering and fetching tags

View file

@ -2,9 +2,9 @@
# Copyright: Damien Elmes <anki@ichi2.net> # Copyright: Damien Elmes <anki@ichi2.net>
# License: GNU AGPL, version 3 or later; http://www.gnu.org/copyleft/agpl.html # License: GNU AGPL, version 3 or later; http://www.gnu.org/copyleft/agpl.html
import os, time, simplejson, re, datetime, shutil import os, time, re, datetime, shutil
from anki.lang import _ from anki.lang import _
from anki.utils import intTime, tmpfile, ids2str, splitFields, base91 from anki.utils import intTime, tmpfile, ids2str, splitFields, base91, json
from anki.db import DB from anki.db import DB
from anki.collection import _Collection from anki.collection import _Collection
from anki.consts import * from anki.consts import *
@ -280,7 +280,7 @@ yesCount from reviewHistory"""):
tags = {} tags = {}
for t in db.list("select tag from tags"): for t in db.list("select tag from tags"):
tags[t] = intTime() tags[t] = intTime()
db.execute("update col set tags = ?", simplejson.dumps(tags)) db.execute("update col set tags = ?", json.dumps(tags))
db.execute("drop table tags") db.execute("drop table tags")
db.execute("drop table cardTags") db.execute("drop table cardTags")
@ -346,7 +346,7 @@ insert or replace into col select id, cast(created as int), :t,
mods[m['id']] = m mods[m['id']] = m
db.execute("update notes set mid = ? where mid = ?", t, row[0]) db.execute("update notes set mid = ? where mid = ?", t, row[0])
# save and clean up # save and clean up
db.execute("update col set models = ?", simplejson.dumps(mods)) db.execute("update col set models = ?", json.dumps(mods))
db.execute("drop table fieldModels") db.execute("drop table fieldModels")
db.execute("drop table cardModels") db.execute("drop table cardModels")
db.execute("drop table models") db.execute("drop table models")

View file

@ -14,6 +14,11 @@ if sys.version_info[1] < 5:
return a % b return a % b
locale.format_string = format_string locale.format_string = format_string
try:
import simplejson as json
except ImportError:
import json
# Time handling # Time handling
############################################################################## ##############################################################################