--- a/__init__.py Tue Feb 14 11:34:53 2012 +0100
+++ b/__init__.py Tue Feb 14 15:16:42 2012 +0100
@@ -117,6 +117,7 @@
binary.write(chunk)
else:
binary.write(fobj.read())
+ binary.seek(0)
return binary
--- a/debian/control Tue Feb 14 11:34:53 2012 +0100
+++ b/debian/control Tue Feb 14 15:16:42 2012 +0100
@@ -127,7 +127,7 @@
Architecture: all
XB-Python-Version: ${python:Versions}
Depends: ${misc:Depends}, ${python:Depends}, cubicweb-server (= ${source:Version}), cubicweb-web (= ${source:Version}), python-pysqlite2
-Suggests: w3c-dtd-xhtml
+Suggests: w3c-dtd-xhtml, xvfb
Description: tests suite and development tools for the CubicWeb framework
CubicWeb is a semantic web application framework.
.
--- a/devtools/qunit.py Tue Feb 14 11:34:53 2012 +0100
+++ b/devtools/qunit.py Tue Feb 14 15:16:42 2012 +0100
@@ -70,13 +70,16 @@
fnull = open(os.devnull, 'w')
stdout = TemporaryFile()
stderr = TemporaryFile()
+ self.firefox_cmd = ['firefox', '-no-remote']
+ if os.name == 'posix':
+ self.firefox_cmd = ['xvfb-run', '-a'] + self.firefox_cmd
try:
home = osp.expanduser('~')
user = getlogin()
assert os.access(home, os.W_OK), \
'No write access to your home directory, Firefox will crash.'\
' Are you sure "%s" is a valid home for user "%s"' % (home, user)
- check_call(['firefox', '-no-remote', '-CreateProfile',
+ check_call(self.firefox_cmd + ['-CreateProfile',
'%s %s' % (self._profile_name, self._tmp_dir)],
stdout=stdout, stderr=stderr)
except CalledProcessError, cpe:
@@ -87,7 +90,7 @@
def start(self, url):
self.stop()
fnull = open(os.devnull, 'w')
- self._process = Popen(['firefox', '-no-remote', '-P', self._profile_name, url],
+ self._process = Popen(self.firefox_cmd + ['-P', self._profile_name, url],
stdout=fnull, stderr=fnull)
def stop(self):
--- a/hooks/notification.py Tue Feb 14 11:34:53 2012 +0100
+++ b/hooks/notification.py Tue Feb 14 15:16:42 2012 +0100
@@ -30,7 +30,7 @@
"""delay rendering of notification view until precommit"""
view = None # make pylint happy
- def precommit_event(self):
+ def postcommit_event(self):
view = self.view
if view.cw_rset is not None and not view.cw_rset:
return # entity added and deleted in the same transaction (cache effect)
--- a/i18n.py Tue Feb 14 11:34:53 2012 +0100
+++ b/i18n.py Tue Feb 14 15:16:42 2012 +0100
@@ -60,7 +60,9 @@
status != 0
"""
from subprocess import call
- print cmd.replace(os.getcwd() + os.sep, '')
+ # use getcwdu as cmd may be unicode and cwd may contains non-ascii
+ # characters
+ print cmd.replace(os.getcwdu() + os.sep, '')
status = call(cmd, shell=True)
if status != 0:
raise Exception('status = %s' % status)
--- a/server/migractions.py Tue Feb 14 11:34:53 2012 +0100
+++ b/server/migractions.py Tue Feb 14 15:16:42 2012 +0100
@@ -1352,7 +1352,7 @@
getattr(entity, attribute)
storage.migrate_entity(entity, attribute)
# remove from entity cache to avoid memory exhaustion
- del entity[attribute]
+ del entity.cw_attr_cache[attribute]
pb.update()
print
source.set_storage(etype, attribute, storage)
--- a/server/repository.py Tue Feb 14 11:34:53 2012 +0100
+++ b/server/repository.py Tue Feb 14 15:16:42 2012 +0100
@@ -509,6 +509,8 @@
results['%s_cache_hit' % title] = hits
results['%s_cache_miss' % title] = misses
results['%s_cache_hit_percent' % title] = (hits * 100) / (hits + misses)
+ results['type_source_cache_size'] = len(self._type_source_cache)
+ results['extid_cache_size'] = len(self._extid_cache)
results['sql_no_cache'] = self.system_source.no_cache
results['nb_open_sessions'] = len(self._sessions)
results['nb_active_threads'] = threading.activeCount()
@@ -517,6 +519,43 @@
results['threads'] = ', '.join(sorted(str(t) for t in threading.enumerate()))
return results
+ def gc_stats(self, nmax=20):
+ """Return a dictionary containing some statistics about the repository
+ memory usage.
+
+ This is a public method, not requiring a session id.
+
+ nmax is the max number of (most) referenced object returned as
+ the 'referenced' result
+ """
+
+ from cubicweb._gcdebug import gc_info
+ from cubicweb.appobject import AppObject
+ from cubicweb.rset import ResultSet
+ from cubicweb.dbapi import Connection, Cursor
+ from cubicweb.web.request import CubicWebRequestBase
+ from rql.stmts import Union
+
+ lookupclasses = (AppObject,
+ Union, ResultSet,
+ Connection, Cursor,
+ CubicWebRequestBase)
+ try:
+ from cubicweb.server.session import Session, InternalSession
+ lookupclasses += (InternalSession, Session)
+ except ImportError:
+ pass # no server part installed
+
+ results = {}
+ counters, ocounters, garbage = gc_info(lookupclasses,
+ viewreferrersclasses=())
+ values = sorted(counters.iteritems(), key=lambda x: x[1], reverse=True)
+ results['lookupclasses'] = values
+ values = sorted(ocounters.iteritems(), key=lambda x: x[1], reverse=True)[:nmax]
+ results['referenced'] = values
+ results['unreachable'] = len(garbage)
+ return results
+
def get_schema(self):
"""Return the instance schema.
--- a/server/serverctl.py Tue Feb 14 11:34:53 2012 +0100
+++ b/server/serverctl.py Tue Feb 14 15:16:42 2012 +0100
@@ -25,6 +25,7 @@
import sys
import os
import logging
+import subprocess
from logilab.common import nullobject
from logilab.common.configuration import Configuration
@@ -258,12 +259,13 @@
cfgname = 'repository'
def start_server(self, config):
- command = ['cubicweb-ctl start-repository ']
+ command = ['cubicweb-ctl', 'start-repository']
if config.debugmode:
command.append('--debug')
- command.append('--loglevel %s' % config['log-threshold'].lower())
+ command.append('--loglevel')
+ command.append(config['log-threshold'].lower())
command.append(config.appid)
- os.system(' '.join(command))
+ subprocess.call(command)
return 1
--- a/server/sources/__init__.py Tue Feb 14 11:34:53 2012 +0100
+++ b/server/sources/__init__.py Tue Feb 14 15:16:42 2012 +0100
@@ -135,7 +135,8 @@
source_config.pop('type')
def __repr__(self):
- return '<%s source %s @%#x>' % (self.uri, self.eid, id(self))
+ return '<%s %s source %s @%#x>' % (self.uri, self.__class__.__name__,
+ self.eid, id(self))
def __cmp__(self, other):
"""simple comparison function to get predictable source order, with the
--- a/server/sources/native.py Tue Feb 14 11:34:53 2012 +0100
+++ b/server/sources/native.py Tue Feb 14 15:16:42 2012 +0100
@@ -1586,9 +1586,11 @@
pwd = rset[0][0]
except IndexError:
raise AuthenticationError('bad login')
+ if pwd is None:
+ # if pwd is None but a password is provided, something is wrong
+ raise AuthenticationError('bad password')
# passwords are stored using the Bytes type, so we get a StringIO
- if pwd is not None:
- args['pwd'] = Binary(crypt_password(password, pwd.getvalue()[:2]))
+ args['pwd'] = Binary(crypt_password(password, pwd.getvalue()[:2]))
# get eid from login and (crypted) password
rset = self.source.syntax_tree_search(session, self._auth_rqlst, args)
try: