Skip to content

Commit 605bda2

Browse files
author
Richard Jones
committed
use the upload-supplied content-type if there is one
1 parent 6d5523e commit 605bda2

File tree

7 files changed

+110
-19
lines changed

7 files changed

+110
-19
lines changed

CHANGES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ Fixed:
5050
- the mail gateway now searches recursively for the text/plain and the
5151
attachments of a message (sf bug 841241).
5252
- fixed display of feedback messages in some situations (sf bug 739545)
53+
- use supplied content-type on file uploads before trying filename)
5354

5455
Cleanup:
5556
- replace curuserid attribute on Database with the extended getuid() method.

TODO.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
This file has been re-purposed to contain specifically the items that need
22
doing before the next release:
33

4+
- add tests for group-by-multilink so I finally implement it for the RDBMSes
45
- full coverage analysis for unit tests
56
- migrate to numeric ID values (fixes bug 817217)
67

roundup/backends/back_mysql.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,92 @@ def filter(self, search_matches, filterspec, sort=(None,None),
411411
# return the IDs (the first column)
412412
return [row[0] for row in l]
413413

414+
# mysql doesn't implement INTERSECT
415+
def find(self, **propspec):
416+
'''Get the ids of nodes in this class which link to the given nodes.
417+
418+
'propspec' consists of keyword args propname=nodeid or
419+
propname={nodeid:1, }
420+
'propname' must be the name of a property in this class, or a
421+
KeyError is raised. That property must be a Link or
422+
Multilink property, or a TypeError is raised.
423+
424+
Any node in this class whose 'propname' property links to any of the
425+
nodeids will be returned. Used by the full text indexing, which knows
426+
that "foo" occurs in msg1, msg3 and file7, so we have hits on these
427+
issues:
428+
429+
db.issue.find(messages={'1':1,'3':1}, files={'7':1})
430+
'''
431+
if __debug__:
432+
print >>hyperdb.DEBUG, 'find', (self, propspec)
433+
434+
# shortcut
435+
if not propspec:
436+
return []
437+
438+
# validate the args
439+
props = self.getprops()
440+
propspec = propspec.items()
441+
for propname, nodeids in propspec:
442+
# check the prop is OK
443+
prop = props[propname]
444+
if not isinstance(prop, Link) and not isinstance(prop, Multilink):
445+
raise TypeError, "'%s' not a Link/Multilink property"%propname
446+
447+
# first, links
448+
a = self.db.arg
449+
where = ['__retired__ <> %s'%a]
450+
allvalues = (1,)
451+
for prop, values in propspec:
452+
if not isinstance(props[prop], hyperdb.Link):
453+
continue
454+
if type(values) is type({}) and len(values) == 1:
455+
values = values.keys()[0]
456+
if type(values) is type(''):
457+
allvalues += (values,)
458+
where.append('_%s = %s'%(prop, a))
459+
elif values is None:
460+
where.append('_%s is NULL'%prop)
461+
else:
462+
allvalues += tuple(values.keys())
463+
where.append('_%s in (%s)'%(prop, ','.join([a]*len(values))))
464+
tables = []
465+
if where:
466+
tables.append('select id as nodeid from _%s where %s'%(
467+
self.classname, ' and '.join(where)))
468+
469+
# now multilinks
470+
for prop, values in propspec:
471+
if not isinstance(props[prop], hyperdb.Multilink):
472+
continue
473+
if type(values) is type(''):
474+
allvalues += (values,)
475+
s = a
476+
else:
477+
allvalues += tuple(values.keys())
478+
s = ','.join([a]*len(values))
479+
tables.append('select nodeid from %s_%s where linkid in (%s)'%(
480+
self.classname, prop, s))
481+
482+
raise NotImplemented, "XXX this code's farked"
483+
d = {}
484+
self.db.sql(sql, allvalues)
485+
for result in self.db.sql_fetchall():
486+
d[result[0]] = 1
487+
488+
for query in tables[1:]:
489+
self.db.sql(sql, allvalues)
490+
for result in self.db.sql_fetchall():
491+
if not d.has_key(result[0]):
492+
continue
493+
494+
if __debug__:
495+
print >>hyperdb.DEBUG, 'find ... ', l
496+
l = d.keys()
497+
l.sort()
498+
return l
499+
414500
class Class(MysqlClass, rdbms_common.Class):
415501
pass
416502
class IssueClass(MysqlClass, rdbms_common.IssueClass):

roundup/backends/rdbms_common.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# $Id: rdbms_common.py,v 1.72 2003-12-05 09:47:46 richard Exp $
1+
# $Id: rdbms_common.py,v 1.73 2004-01-20 03:58:38 richard Exp $
22
''' Relational database (SQL) backend common code.
33
44
Basics:
@@ -1788,9 +1788,9 @@ def find(self, **propspec):
17881788
raise TypeError, "'%s' not a Link/Multilink property"%propname
17891789

17901790
# first, links
1791-
where = ['__retired__ = %s']
1792-
allvalues = (0,)
17931791
a = self.db.arg
1792+
where = ['__retired__ <> %s'%a]
1793+
allvalues = (1,)
17941794
for prop, values in propspec:
17951795
if not isinstance(props[prop], hyperdb.Link):
17961796
continue
@@ -1821,7 +1821,8 @@ def find(self, **propspec):
18211821
s = ','.join([a]*len(values))
18221822
tables.append('select nodeid from %s_%s where linkid in (%s)'%(
18231823
self.classname, prop, s))
1824-
sql = '\nunion\n'.join(tables)
1824+
1825+
sql = '\nintersect\n'.join(tables)
18251826
self.db.sql(sql, allvalues)
18261827
l = [x[0] for x in self.db.sql_fetchall()]
18271828
if __debug__:

roundup/cgi/client.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# $Id: client.py,v 1.152 2004-01-19 23:56:07 richard Exp $
1+
# $Id: client.py,v 1.153 2004-01-20 03:58:38 richard Exp $
22

33
__doc__ = """
44
WWW request handler (also used in the stand-alone server).
@@ -1778,8 +1778,11 @@ def parsePropsFromForm(self, num_re=re.compile('^\d+$')):
17781778
props['name'] = fn
17791779
# use this info as the type/filename properties
17801780
if propdef.has_key('type'):
1781-
props['type'] = mimetypes.guess_type(fn)[0]
1782-
if not props['type']:
1781+
if hasattr(value, 'type'):
1782+
props['type'] = value.type
1783+
elif mimetypes.guess_type(fn)[0]:
1784+
props['type'] = mimetypes.guess_type(fn)[0]
1785+
else:
17831786
props['type'] = "application/octet-stream"
17841787
# finally, read the content RAW
17851788
value = value.value

roundup/indexer.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
# that promote freedom, but obviously am giving up any rights
1515
# to compel such.
1616
#
17-
#$Id: indexer.py,v 1.16 2003-01-14 03:56:44 richard Exp $
17+
#$Id: indexer.py,v 1.17 2004-01-20 03:58:38 richard Exp $
1818
'''
1919
This module provides an indexer class, RoundupIndexer, that stores text
2020
indices in a roundup instance. This class makes searching the content of
@@ -146,15 +146,14 @@ def search(self, search_terms, klass, ignore={},
146146
if not hits:
147147
return {}
148148

149-
#designator_propname = {'msg': 'messages', 'file': 'files'}
150149
designator_propname = {}
151150
for nm, propclass in klass.getprops().items():
152151
if isinstance(propclass, Link) or isinstance(propclass, Multilink):
153152
designator_propname[propclass.classname] = nm
154153

155154
# build a dictionary of nodes and their associated messages
156155
# and files
157-
nodeids = {} # this is the answer
156+
nodeids = {} # this is the answer
158157
propspec = {} # used to do the klass.find
159158
for propname in designator_propname.values():
160159
propspec[propname] = {} # used as a set (value doesn't matter)

test/db_test_base.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
1616
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
1717
#
18-
# $Id: db_test_base.py,v 1.12 2003-12-10 01:40:51 richard Exp $
18+
# $Id: db_test_base.py,v 1.13 2004-01-20 03:58:38 richard Exp $
1919

2020
import unittest, os, shutil, errno, imp, sys, time, pprint
2121

@@ -580,20 +580,20 @@ def testPack(self):
580580
# we should have the create and last set entries now
581581
self.assertEqual(jlen-1, len(self.db.getjournal('issue', id)))
582582

583-
def testSearching(self):
584-
self.db.file.create(content='hello', type="text/plain")
585-
self.db.file.create(content='world', type="text/frozz",
583+
def testIndexerSearching(self):
584+
f1 = self.db.file.create(content='hello', type="text/plain")
585+
f2 = self.db.file.create(content='world', type="text/frozz",
586586
comment='blah blah')
587-
self.db.issue.create(files=['1', '2'], title="flebble plop")
588-
self.db.issue.create(title="flebble frooz")
587+
i1 = self.db.issue.create(files=[f1, f2], title="flebble plop")
588+
i2 = self.db.issue.create(title="flebble frooz")
589589
self.db.commit()
590590
self.assertEquals(self.db.indexer.search(['hello'], self.db.issue),
591-
{'1': {'files': ['1']}})
591+
{i1: {'files': [f1]}})
592592
self.assertEquals(self.db.indexer.search(['world'], self.db.issue), {})
593593
self.assertEquals(self.db.indexer.search(['frooz'], self.db.issue),
594-
{'2': {}})
594+
{i2: {}})
595595
self.assertEquals(self.db.indexer.search(['flebble'], self.db.issue),
596-
{'2': {}, '1': {}})
596+
{i1: {}, i2: {}})
597597

598598
def testReindexing(self):
599599
self.db.issue.create(title="frooz")

0 commit comments

Comments
 (0)