This file is indexed.

/usr/share/pyshared/PyritePublisher/dbprotocol.py is in pyrite-publisher 2.1.1-8.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
#
#  $Id: dbprotocol.py,v 1.1 2002/03/26 12:56:06 rob Exp $
#
#  Copyright 2001 Rob Tillotson <rob@pyrite.org>
#  All Rights Reserved
#
#  Permission to use, copy, modify, and distribute this software and
#  its documentation for any purpose and without fee or royalty is
#  hereby granted, provided that the above copyright notice appear in
#  all copies and that both the copyright notice and this permission
#  notice appear in supporting documentation or portions thereof,
#  including modifications, that you you make.
#
#  THE AUTHOR ROB TILLOTSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
#  THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
#  AND FITNESS.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
#  SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
#  RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
#  CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
#  CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE!
#
"""Pyrite Publisher Database Protocol Support

This module provides support for the Pyrite Publisher protocol
'columnar-database', which is used for simple flat-file databases like
those found in CSV files and Palm applications like JFile, MobileDB,
and Handbase.  Primarily, it provides classes for handling metadata
about the columns in the database.

The field types supported by this module, their identifiers (defined in
this module as constants), and their internal representations are as
follows:

  FLD_STRING  - a string
    Represented internally by a string.
  FLD_INT     - an integer
    Represented internally by an integer.
  FLD_FLOAT   - a floating-point number
    Represented internally by a float.
  FLD_BOOLEAN - a true or false value
    Represented internally by an integer 0 or 1.
  FLD_DATE    - a date (without time)
    Represented internally by a string.
  FLD_TIME    - a time (without date)
    Represented internally by a string.

Objects implementing the columnar-database protocol have the following
methods:

  define_fields(speclist)
    REQUIRED.  Called by the upstream plugin before any records are
    fed downstream.  The parameter is a list of FieldSpec objects which
    describe the columns in the database.

  feed_record(list)
    REQUIRED.  Called by the upstream plugin once for each record.  The
    parameter is a list of values contained in that record, in their
    internal representation.
"""

__version__ = '$Id: dbprotocol.py,v 1.1 2002/03/26 12:56:06 rob Exp $'

__author__ = 'Rob Tillotson <rob@pyrite.org>'

__copyright__ = 'Copyright 2001 Rob Tillotson <rob@pyrite.org>'

import os

import config

FLD_STRING = 'string'
FLD_INT = 'int'
FLD_FLOAT = 'float'
FLD_BOOLEAN = 'boolean'
FLD_DATE = 'date'
FLD_TIME = 'time'

class FieldSpec:
    """Columnar database field specification.
    """
    def __init__(self, name, type=FLD_STRING, **kw):
        self.name = name
        self.type = type
        self.max_length = 0
        
        for k,v in kw.items():
            setattr(self, k, v)

    def __str__(self):
        s = '<Field: %s [%s]' % (self.name, self.type)
        l = []
        for k,v in self.__dict__.items():
            if k not in ('name','type'):
                l.append('%s=%s' % (k, repr(v)))
        if l: s = s + ' (%s)' % ' '.join(l)
        s = s + '>'
        return s

    def __repr__(self):
        return self.__str__()
    
    def setFromConfig(self, k, v):
        setattr(self, k, v)

    def __getattr__(self, k, v):
        return None
    
# field "name" type <flags>;
# values "name" <value> ... ;


_type_names = {
    'string' : FLD_STRING,
    'str': FLD_STRING,
    'int': FLD_INT,
    'integer': FLD_INT,
    'float': FLD_FLOAT,
    'bool': FLD_BOOLEAN,
    'boolean': FLD_BOOLEAN,
    'checkbox': FLD_BOOLEAN,
    'check': FLD_BOOLEAN,
    'toggle': FLD_BOOLEAN,
    }

class DBSpecCmdProc(config.CommandProcessor):
    def __init__(self):
        self.fields = {}
        self.field_order = []
        
    def load(self, fn):
        if os.path.isfile(fn): config.read_config(fn, self)

    def cmd_field(self, argv):
        argv = argv[1:]
        if len(argv) < 1: raise config.Error, 'field syntax error'
        
        name = config.maybe_unquote(argv[0])
        argv = argv[1:]
        fspec = FieldSpec(name)

        if not argv:
            fspec.setFromConfig("type", FLD_STRING)
        else:
            t = config.maybe_unquote(argv[0])
            if not _type_names.has_key(t):
                raise config.Error, 'unknown field type %s' % t
            fspec.setFromConfig("type", _type_names[t])
            argv = argv[1:]

            while argv:
                a = config.maybe_unquote(argv[0])
                argv = argv[1:]
                if not argv: fspec.setFromConfig(a, 1)
                else:
                    v = config.maybe_unquote(argv[0])
                    argv = argv[1:]
                    fspec.setFromConfig(a, v)
                    
        self.fields[name] = fspec
        self.field_order.append(fspec)

    def cmd_values(self, argv): # values for popup list
        argv = argv[1:]
        if not argv: raise config.Error, "not enough arguments for 'values'"
        
        try:
            fnum = int(argv[0])
            fspec = self.field_order[fnum]
        except:
            fspec = self.fields[config.maybe_unquote(argv[0])]

        fspec.setFromConfig('values', map(config.maybe_unquote, argv[1:]))



class TypeGuesser:
    """Type guesser for the columnar database protocol.
    This class implements a simple type-guesser which takes a series of
    records with string values and tries to guess what type the values
    *should* be.  To accomplish this, it uses a set of regular expressions
    which match the string representations of other data types, and a set
    of type-inclusion rules.  (These rules are used to handle situations
    where more than one regular expression might match a particular value
    -- for example, an integer is also a valid floating point value.) As
    records are fed to it, it updates its guesses as to the type of each
    column.  If the values in a column don't consistently match any
    particular type, it will be declared to be a string.

    At the same time, it keeps track of field lengths to determine the
    largest required field size, and will in the future be expanded to
    collect even more information about the data passing through it.
    """


    def __init__(self, fields=[], rx_types=[], included_types={},
                 converters={}):
        self.fieldspecs = fields
        self.rx_types = rx_types
        self.included_types = included_types
        self.converters = converters
        
    def guess(self, s):
        for rx, typ in self.rx_types:
            if rx.match(s): return typ
        return FLD_STRING

    def __call__(self, fields):
        if not self.fieldspecs:
            self.fieldspecs = FieldSpec('', None)
            
        # now try to guess types
        for x in range(len(fields)):
            f = fields[x]
            t = self.fieldspecs[x]
            
            if t.type != FLD_STRING:
                t0 = self.guess(f)
                if t.type is None:
                    print t, t0, f
                    t.type = t0
                elif t.type != t0:
                    print t, t0, f
                    if self.included_types.has_key((t.type,t0)):
                        t.type = t0
                    else:
                        t.type = FLD_STRING

            if len(f) > self.fieldspecs[x].max_length: self.fieldspecs[x].max_length = len(f)

    def convert_rec(self, rec):
        ret = []
        for x in range(len(rec)):
            conv = self.converters.get(self.fieldspecs[x].type)
            if conv: ret.append(conv(rec[x]))
            else: ret.append(rec[x])
        return ret

if __name__ == '__main__':
    import sys
    from pprint import pprint
    
    c = DBSpecCmdProc()
    c.load(sys.argv[1])
    pprint(c.field_order)