~ubuntu-branches/ubuntu/wily/opencollada/wily-proposed

« back to all changes in this revision

Viewing changes to Externals/LibXML/doc/index.py

  • Committer: Package Import Robot
  • Author(s): Matteo F. Vescovi
  • Date: 2015-05-14 17:23:27 UTC
  • Revision ID: package-import@ubuntu.com-20150514172327-f862u8envms01fra
Tags: upstream-0.1.0~20140703.ddf8f47+dfsg1
ImportĀ upstreamĀ versionĀ 0.1.0~20140703.ddf8f47+dfsg1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/python -u
 
2
#
 
3
# imports the API description and fills up a database with
 
4
# name relevance to modules, functions or web pages
 
5
#
 
6
# Operation needed:
 
7
# =================
 
8
#
 
9
# install mysqld, the python wrappers for mysql and libxml2, start mysqld
 
10
# Change the root passwd of mysql:
 
11
#    mysqladmin -u root password new_password
 
12
# Create the new database xmlsoft
 
13
#    mysqladmin -p create xmlsoft
 
14
# Create a database user 'veillard' and give him passord access
 
15
# change veillard and abcde with the right user name and passwd
 
16
#    mysql -p
 
17
#    password:
 
18
#    mysql> GRANT ALL PRIVILEGES ON xmlsoft TO veillard@localhost
 
19
#           IDENTIFIED BY 'abcde' WITH GRANT OPTION;
 
20
#
 
21
# As the user check the access:
 
22
#    mysql -p xmlsoft
 
23
#    Enter password:
 
24
#    Welcome to the MySQL monitor....
 
25
#    mysql> use xmlsoft
 
26
#    Database changed
 
27
#    mysql> quit
 
28
#    Bye
 
29
#
 
30
# Then run the script in the doc subdir, it will create the symbols and
 
31
# word tables and populate them with informations extracted from 
 
32
# the libxml2-api.xml API description, and make then accessible read-only
 
33
# by nobody@loaclhost the user expected to be Apache's one
 
34
#
 
35
# On the Apache configuration, make sure you have php support enabled
 
36
#
 
37
 
 
38
import MySQLdb
 
39
import libxml2
 
40
import sys
 
41
import string
 
42
import os
 
43
 
 
44
#
 
45
# We are not interested in parsing errors here
 
46
#
 
47
def callback(ctx, str):
 
48
    return
 
49
libxml2.registerErrorHandler(callback, None)
 
50
 
 
51
#
 
52
# The dictionnary of tables required and the SQL command needed
 
53
# to create them
 
54
#
 
55
TABLES={
 
56
  "symbols" : """CREATE TABLE symbols (
 
57
           name varchar(255) BINARY NOT NULL,
 
58
           module varchar(255) BINARY NOT NULL,
 
59
           type varchar(25) NOT NULL,
 
60
           descr varchar(255),
 
61
           UNIQUE KEY name (name),
 
62
           KEY module (module))""",
 
63
  "words" : """CREATE TABLE words (
 
64
           name varchar(50) BINARY NOT NULL,
 
65
           symbol varchar(255) BINARY NOT NULL,
 
66
           relevance int,
 
67
           KEY name (name),
 
68
           KEY symbol (symbol),
 
69
           UNIQUE KEY ID (name, symbol))""",
 
70
  "wordsHTML" : """CREATE TABLE wordsHTML (
 
71
           name varchar(50) BINARY NOT NULL,
 
72
           resource varchar(255) BINARY NOT NULL,
 
73
           section varchar(255),
 
74
           id varchar(50),
 
75
           relevance int,
 
76
           KEY name (name),
 
77
           KEY resource (resource),
 
78
           UNIQUE KEY ref (name, resource))""",
 
79
  "wordsArchive" : """CREATE TABLE wordsArchive (
 
80
           name varchar(50) BINARY NOT NULL,
 
81
           ID int(11) NOT NULL,
 
82
           relevance int,
 
83
           KEY name (name),
 
84
           UNIQUE KEY ref (name, ID))""",
 
85
  "pages" : """CREATE TABLE pages (
 
86
           resource varchar(255) BINARY NOT NULL,
 
87
           title varchar(255) BINARY NOT NULL,
 
88
           UNIQUE KEY name (resource))""",
 
89
  "archives" : """CREATE TABLE archives (
 
90
           ID int(11) NOT NULL auto_increment,
 
91
           resource varchar(255) BINARY NOT NULL,
 
92
           title varchar(255) BINARY NOT NULL,
 
93
           UNIQUE KEY id (ID,resource(255)),
 
94
           INDEX (ID),
 
95
           INDEX (resource))""",
 
96
  "Queries" : """CREATE TABLE Queries (
 
97
           ID int(11) NOT NULL auto_increment,
 
98
           Value varchar(50) NOT NULL,
 
99
           Count int(11) NOT NULL,
 
100
           UNIQUE KEY id (ID,Value(35)),
 
101
           INDEX (ID))""",
 
102
  "AllQueries" : """CREATE TABLE AllQueries (
 
103
           ID int(11) NOT NULL auto_increment,
 
104
           Value varchar(50) NOT NULL,
 
105
           Count int(11) NOT NULL,
 
106
           UNIQUE KEY id (ID,Value(35)),
 
107
           INDEX (ID))""",
 
108
}
 
109
 
 
110
#
 
111
# The XML API description file to parse
 
112
#
 
113
API="libxml2-api.xml"
 
114
DB=None
 
115
 
 
116
#########################################################################
 
117
#                                                                       #
 
118
#                  MySQL database interfaces                            #
 
119
#                                                                       #
 
120
#########################################################################
 
121
def createTable(db, name):
 
122
    global TABLES
 
123
 
 
124
    if db == None:
 
125
        return -1
 
126
    if name == None:
 
127
        return -1
 
128
    c = db.cursor()
 
129
 
 
130
    ret = c.execute("DROP TABLE IF EXISTS %s" % (name))
 
131
    if ret == 1:
 
132
        print "Removed table %s" % (name)
 
133
    print "Creating table %s" % (name)
 
134
    try:
 
135
        ret = c.execute(TABLES[name])
 
136
    except:
 
137
        print "Failed to create table %s" % (name)
 
138
        return -1
 
139
    return ret
 
140
 
 
141
def checkTables(db, verbose = 1):
 
142
    global TABLES
 
143
 
 
144
    if db == None:
 
145
        return -1
 
146
    c = db.cursor()
 
147
    nbtables = c.execute("show tables")
 
148
    if verbose:
 
149
        print "Found %d tables" % (nbtables)
 
150
    tables = {}
 
151
    i = 0
 
152
    while i < nbtables:
 
153
        l = c.fetchone()
 
154
        name = l[0]
 
155
        tables[name] = {}
 
156
        i = i + 1
 
157
 
 
158
    for table in TABLES.keys():
 
159
        if not tables.has_key(table):
 
160
            print "table %s missing" % (table)
 
161
            createTable(db, table)
 
162
        try:
 
163
            ret = c.execute("SELECT count(*) from %s" % table);
 
164
            row = c.fetchone()
 
165
            if verbose:
 
166
                print "Table %s contains %d records" % (table, row[0])
 
167
        except:
 
168
            print "Troubles with table %s : repairing" % (table)
 
169
            ret = c.execute("repair table %s" % table);
 
170
            print "repairing returned %d" % (ret)
 
171
            ret = c.execute("SELECT count(*) from %s" % table);
 
172
            row = c.fetchone()
 
173
            print "Table %s contains %d records" % (table, row[0])
 
174
    if verbose:
 
175
        print "checkTables finished"
 
176
 
 
177
    # make sure apache can access the tables read-only
 
178
    try:
 
179
        ret = c.execute("GRANT SELECT ON xmlsoft.* TO nobody@localhost")
 
180
        ret = c.execute("GRANT INSERT,SELECT,UPDATE  ON xmlsoft.Queries TO nobody@localhost")
 
181
    except:
 
182
        pass
 
183
    return 0
 
184
    
 
185
def openMySQL(db="xmlsoft", passwd=None, verbose = 1):
 
186
    global DB
 
187
 
 
188
    if passwd == None:
 
189
        try:
 
190
            passwd = os.environ["MySQL_PASS"]
 
191
        except:
 
192
            print "No password available, set environment MySQL_PASS"
 
193
            sys.exit(1)
 
194
 
 
195
    DB = MySQLdb.connect(passwd=passwd, db=db)
 
196
    if DB == None:
 
197
        return -1
 
198
    ret = checkTables(DB, verbose)
 
199
    return ret
 
200
 
 
201
def updateWord(name, symbol, relevance):
 
202
    global DB
 
203
 
 
204
    if DB == None:
 
205
        openMySQL()
 
206
    if DB == None:
 
207
        return -1
 
208
    if name == None:
 
209
        return -1
 
210
    if symbol == None:
 
211
        return -1
 
212
 
 
213
    c = DB.cursor()
 
214
    try:
 
215
        ret = c.execute(
 
216
"""INSERT INTO words (name, symbol, relevance) VALUES ('%s','%s', %d)""" %
 
217
                (name, symbol, relevance))
 
218
    except:
 
219
        try:
 
220
            ret = c.execute(
 
221
    """UPDATE words SET relevance = %d where name = '%s' and symbol = '%s'""" %
 
222
                    (relevance, name, symbol))
 
223
        except:
 
224
            print "Update word (%s, %s, %s) failed command" % (name, symbol, relevance)
 
225
            print "UPDATE words SET relevance = %d where name = '%s' and symbol = '%s'" % (relevance, name, symbol)
 
226
            print sys.exc_type, sys.exc_value
 
227
            return -1
 
228
             
 
229
    return ret
 
230
 
 
231
def updateSymbol(name, module, type, desc):
 
232
    global DB
 
233
 
 
234
    updateWord(name, name, 50)
 
235
    if DB == None:
 
236
        openMySQL()
 
237
    if DB == None:
 
238
        return -1
 
239
    if name == None:
 
240
        return -1
 
241
    if module == None:
 
242
        return -1
 
243
    if type == None:
 
244
        return -1
 
245
 
 
246
    try:
 
247
        desc = string.replace(desc, "'", " ")
 
248
        l = string.split(desc, ".")
 
249
        desc = l[0]
 
250
        desc = desc[0:99]
 
251
    except:
 
252
        desc = ""
 
253
 
 
254
    c = DB.cursor()
 
255
    try:
 
256
        ret = c.execute(
 
257
"""INSERT INTO symbols (name, module, type, descr) VALUES ('%s','%s', '%s', '%s')""" %
 
258
                    (name, module, type, desc))
 
259
    except:
 
260
        try:
 
261
            ret = c.execute(
 
262
"""UPDATE symbols SET module='%s', type='%s', descr='%s' where name='%s'""" %
 
263
                    (module, type, desc, name))
 
264
        except:
 
265
            print "Update symbol (%s, %s, %s) failed command" % (name, module, type)
 
266
            print """UPDATE symbols SET module='%s', type='%s', descr='%s' where name='%s'""" % (module, type, desc, name)
 
267
            print sys.exc_type, sys.exc_value
 
268
            return -1
 
269
             
 
270
    return ret
 
271
        
 
272
def addFunction(name, module, desc = ""):
 
273
    return updateSymbol(name, module, 'function', desc)
 
274
 
 
275
def addMacro(name, module, desc = ""):
 
276
    return updateSymbol(name, module, 'macro', desc)
 
277
 
 
278
def addEnum(name, module, desc = ""):
 
279
    return updateSymbol(name, module, 'enum', desc)
 
280
 
 
281
def addStruct(name, module, desc = ""):
 
282
    return updateSymbol(name, module, 'struct', desc)
 
283
 
 
284
def addConst(name, module, desc = ""):
 
285
    return updateSymbol(name, module, 'const', desc)
 
286
 
 
287
def addType(name, module, desc = ""):
 
288
    return updateSymbol(name, module, 'type', desc)
 
289
 
 
290
def addFunctype(name, module, desc = ""):
 
291
    return updateSymbol(name, module, 'functype', desc)
 
292
 
 
293
def addPage(resource, title):
 
294
    global DB
 
295
 
 
296
    if DB == None:
 
297
        openMySQL()
 
298
    if DB == None:
 
299
        return -1
 
300
    if resource == None:
 
301
        return -1
 
302
 
 
303
    c = DB.cursor()
 
304
    try:
 
305
        ret = c.execute(
 
306
            """INSERT INTO pages (resource, title) VALUES ('%s','%s')""" %
 
307
                    (resource, title))
 
308
    except:
 
309
        try:
 
310
            ret = c.execute(
 
311
                """UPDATE pages SET title='%s' WHERE resource='%s'""" %
 
312
                    (title, resource))
 
313
        except:
 
314
            print "Update symbol (%s, %s, %s) failed command" % (name, module, type)
 
315
            print """UPDATE pages SET title='%s' WHERE resource='%s'""" % (title, resource)
 
316
            print sys.exc_type, sys.exc_value
 
317
            return -1
 
318
             
 
319
    return ret
 
320
 
 
321
def updateWordHTML(name, resource, desc, id, relevance):
 
322
    global DB
 
323
 
 
324
    if DB == None:
 
325
        openMySQL()
 
326
    if DB == None:
 
327
        return -1
 
328
    if name == None:
 
329
        return -1
 
330
    if resource == None:
 
331
        return -1
 
332
    if id == None:
 
333
        id = ""
 
334
    if desc == None:
 
335
        desc = ""
 
336
    else:
 
337
        try:
 
338
            desc = string.replace(desc, "'", " ")
 
339
            desc = desc[0:99]
 
340
        except:
 
341
            desc = ""
 
342
 
 
343
    c = DB.cursor()
 
344
    try:
 
345
        ret = c.execute(
 
346
"""INSERT INTO wordsHTML (name, resource, section, id, relevance) VALUES ('%s','%s', '%s', '%s', '%d')""" %
 
347
                    (name, resource, desc, id, relevance))
 
348
    except:
 
349
        try:
 
350
            ret = c.execute(
 
351
"""UPDATE wordsHTML SET section='%s', id='%s', relevance='%d' where name='%s' and resource='%s'""" %
 
352
                    (desc, id, relevance, name, resource))
 
353
        except:
 
354
            print "Update symbol (%s, %s, %d) failed command" % (name, resource, relevance)
 
355
            print """UPDATE wordsHTML SET section='%s', id='%s', relevance='%d' where name='%s' and resource='%s'""" % (desc, id, relevance, name, resource)
 
356
            print sys.exc_type, sys.exc_value
 
357
            return -1
 
358
             
 
359
    return ret
 
360
 
 
361
def checkXMLMsgArchive(url):
 
362
    global DB
 
363
 
 
364
    if DB == None:
 
365
        openMySQL()
 
366
    if DB == None:
 
367
        return -1
 
368
    if url == None:
 
369
        return -1
 
370
 
 
371
    c = DB.cursor()
 
372
    try:
 
373
        ret = c.execute(
 
374
            """SELECT ID FROM archives WHERE resource='%s'""" % (url))
 
375
        row = c.fetchone()
 
376
        if row == None:
 
377
            return -1
 
378
    except:
 
379
        return -1
 
380
             
 
381
    return row[0]
 
382
    
 
383
def addXMLMsgArchive(url, title):
 
384
    global DB
 
385
 
 
386
    if DB == None:
 
387
        openMySQL()
 
388
    if DB == None:
 
389
        return -1
 
390
    if url == None:
 
391
        return -1
 
392
    if title == None:
 
393
        title = ""
 
394
    else:
 
395
        title = string.replace(title, "'", " ")
 
396
        title = title[0:99]
 
397
 
 
398
    c = DB.cursor()
 
399
    try:
 
400
        cmd = """INSERT INTO archives (resource, title) VALUES ('%s','%s')""" % (url, title)
 
401
        ret = c.execute(cmd)
 
402
        cmd = """SELECT ID FROM archives WHERE resource='%s'""" % (url)
 
403
        ret = c.execute(cmd)
 
404
        row = c.fetchone()
 
405
        if row == None:
 
406
            print "addXMLMsgArchive failed to get the ID: %s" % (url)
 
407
            return -1
 
408
    except:
 
409
        print "addXMLMsgArchive failed command: %s" % (cmd)
 
410
        return -1
 
411
             
 
412
    return((int)(row[0]))
 
413
 
 
414
def updateWordArchive(name, id, relevance):
 
415
    global DB
 
416
 
 
417
    if DB == None:
 
418
        openMySQL()
 
419
    if DB == None:
 
420
        return -1
 
421
    if name == None:
 
422
        return -1
 
423
    if id == None:
 
424
        return -1
 
425
 
 
426
    c = DB.cursor()
 
427
    try:
 
428
        ret = c.execute(
 
429
"""INSERT INTO wordsArchive (name, id, relevance) VALUES ('%s', '%d', '%d')""" %
 
430
                    (name, id, relevance))
 
431
    except:
 
432
        try:
 
433
            ret = c.execute(
 
434
"""UPDATE wordsArchive SET relevance='%d' where name='%s' and ID='%d'""" %
 
435
                    (relevance, name, id))
 
436
        except:
 
437
            print "Update word archive (%s, %d, %d) failed command" % (name, id, relevance)
 
438
            print """UPDATE wordsArchive SET relevance='%d' where name='%s' and ID='%d'""" % (relevance, name, id)
 
439
            print sys.exc_type, sys.exc_value
 
440
            return -1
 
441
             
 
442
    return ret
 
443
 
 
444
#########################################################################
 
445
#                                                                       #
 
446
#                  Word dictionnary and analysis routines               #
 
447
#                                                                       #
 
448
#########################################################################
 
449
 
 
450
#
 
451
# top 100 english word without the one len < 3 + own set
 
452
#
 
453
dropWords = {
 
454
    'the':0, 'this':0, 'can':0, 'man':0, 'had':0, 'him':0, 'only':0,
 
455
    'and':0, 'not':0, 'been':0, 'other':0, 'even':0, 'are':0, 'was':0,
 
456
    'new':0, 'most':0, 'but':0, 'when':0, 'some':0, 'made':0, 'from':0,
 
457
    'who':0, 'could':0, 'after':0, 'that':0, 'will':0, 'time':0, 'also':0,
 
458
    'have':0, 'more':0, 'these':0, 'did':0, 'was':0, 'two':0, 'many':0,
 
459
    'they':0, 'may':0, 'before':0, 'for':0, 'which':0, 'out':0, 'then':0,
 
460
    'must':0, 'one':0, 'through':0, 'with':0, 'you':0, 'said':0,
 
461
    'first':0, 'back':0, 'were':0, 'what':0, 'any':0, 'years':0, 'his':0,
 
462
    'her':0, 'where':0, 'all':0, 'its':0, 'now':0, 'much':0, 'she':0,
 
463
    'about':0, 'such':0, 'your':0, 'there':0, 'into':0, 'like':0, 'may':0,
 
464
    'would':0, 'than':0, 'our':0, 'well':0, 'their':0, 'them':0, 'over':0,
 
465
    'down':0,
 
466
    'net':0, 'www':0, 'bad':0, 'Okay':0, 'bin':0, 'cur':0,
 
467
}
 
468
 
 
469
wordsDict = {}
 
470
wordsDictHTML = {}
 
471
wordsDictArchive = {}
 
472
 
 
473
def cleanupWordsString(str):
 
474
    str = string.replace(str, ".", " ")
 
475
    str = string.replace(str, "!", " ")
 
476
    str = string.replace(str, "?", " ")
 
477
    str = string.replace(str, ",", " ")
 
478
    str = string.replace(str, "'", " ")
 
479
    str = string.replace(str, '"', " ")
 
480
    str = string.replace(str, ";", " ")
 
481
    str = string.replace(str, "(", " ")
 
482
    str = string.replace(str, ")", " ")
 
483
    str = string.replace(str, "{", " ")
 
484
    str = string.replace(str, "}", " ")
 
485
    str = string.replace(str, "<", " ")
 
486
    str = string.replace(str, ">", " ")
 
487
    str = string.replace(str, "=", " ")
 
488
    str = string.replace(str, "/", " ")
 
489
    str = string.replace(str, "*", " ")
 
490
    str = string.replace(str, ":", " ")
 
491
    str = string.replace(str, "#", " ")
 
492
    str = string.replace(str, "\\", " ")
 
493
    str = string.replace(str, "\n", " ")
 
494
    str = string.replace(str, "\r", " ")
 
495
    str = string.replace(str, "\xc2", " ")
 
496
    str = string.replace(str, "\xa0", " ")
 
497
    return str
 
498
    
 
499
def cleanupDescrString(str):
 
500
    str = string.replace(str, "'", " ")
 
501
    str = string.replace(str, "\n", " ")
 
502
    str = string.replace(str, "\r", " ")
 
503
    str = string.replace(str, "\xc2", " ")
 
504
    str = string.replace(str, "\xa0", " ")
 
505
    l = string.split(str)
 
506
    str = string.join(str)
 
507
    return str
 
508
 
 
509
def splitIdentifier(str):
 
510
    ret = []
 
511
    while str != "":
 
512
        cur = string.lower(str[0])
 
513
        str = str[1:]
 
514
        if ((cur < 'a') or (cur > 'z')):
 
515
            continue
 
516
        while (str != "") and (str[0] >= 'A') and (str[0] <= 'Z'):
 
517
            cur = cur + string.lower(str[0])
 
518
            str = str[1:]
 
519
        while (str != "") and (str[0] >= 'a') and (str[0] <= 'z'):
 
520
            cur = cur + str[0]
 
521
            str = str[1:]
 
522
        while (str != "") and (str[0] >= '0') and (str[0] <= '9'):
 
523
            str = str[1:]
 
524
        ret.append(cur)
 
525
    return ret
 
526
 
 
527
def addWord(word, module, symbol, relevance):
 
528
    global wordsDict
 
529
 
 
530
    if word == None or len(word) < 3:
 
531
        return -1
 
532
    if module == None or symbol == None:
 
533
        return -1
 
534
    if dropWords.has_key(word):
 
535
        return 0
 
536
    if ord(word[0]) > 0x80:
 
537
        return 0
 
538
 
 
539
    if wordsDict.has_key(word):
 
540
        d = wordsDict[word]
 
541
        if d == None:
 
542
            return 0
 
543
        if len(d) > 500:
 
544
            wordsDict[word] = None
 
545
            return 0
 
546
        try:
 
547
            relevance = relevance + d[(module, symbol)]
 
548
        except:
 
549
            pass
 
550
    else:
 
551
        wordsDict[word] = {}
 
552
    wordsDict[word][(module, symbol)] = relevance
 
553
    return relevance
 
554
    
 
555
def addString(str, module, symbol, relevance):
 
556
    if str == None or len(str) < 3:
 
557
        return -1
 
558
    ret = 0
 
559
    str = cleanupWordsString(str)
 
560
    l = string.split(str)
 
561
    for word in l:
 
562
        if len(word) > 2:
 
563
            ret = ret + addWord(word, module, symbol, 5)
 
564
 
 
565
    return ret
 
566
 
 
567
def addWordHTML(word, resource, id, section, relevance):
 
568
    global wordsDictHTML
 
569
 
 
570
    if word == None or len(word) < 3:
 
571
        return -1
 
572
    if resource == None or section == None:
 
573
        return -1
 
574
    if dropWords.has_key(word):
 
575
        return 0
 
576
    if ord(word[0]) > 0x80:
 
577
        return 0
 
578
 
 
579
    section = cleanupDescrString(section)
 
580
 
 
581
    if wordsDictHTML.has_key(word):
 
582
        d = wordsDictHTML[word]
 
583
        if d == None:
 
584
            print "skipped %s" % (word)
 
585
            return 0
 
586
        try:
 
587
            (r,i,s) = d[resource]
 
588
            if i != None:
 
589
                id = i
 
590
            if s != None:
 
591
                section = s
 
592
            relevance = relevance + r
 
593
        except:
 
594
            pass
 
595
    else:
 
596
        wordsDictHTML[word] = {}
 
597
    d = wordsDictHTML[word];
 
598
    d[resource] = (relevance, id, section)
 
599
    return relevance
 
600
    
 
601
def addStringHTML(str, resource, id, section, relevance):
 
602
    if str == None or len(str) < 3:
 
603
        return -1
 
604
    ret = 0
 
605
    str = cleanupWordsString(str)
 
606
    l = string.split(str)
 
607
    for word in l:
 
608
        if len(word) > 2:
 
609
            try:
 
610
                r = addWordHTML(word, resource, id, section, relevance)
 
611
                if r < 0:
 
612
                    print "addWordHTML failed: %s %s" % (word, resource)
 
613
                ret = ret + r
 
614
            except:
 
615
                print "addWordHTML failed: %s %s %d" % (word, resource, relevance)
 
616
                print sys.exc_type, sys.exc_value
 
617
 
 
618
    return ret
 
619
 
 
620
def addWordArchive(word, id, relevance):
 
621
    global wordsDictArchive
 
622
 
 
623
    if word == None or len(word) < 3:
 
624
        return -1
 
625
    if id == None or id == -1:
 
626
        return -1
 
627
    if dropWords.has_key(word):
 
628
        return 0
 
629
    if ord(word[0]) > 0x80:
 
630
        return 0
 
631
 
 
632
    if wordsDictArchive.has_key(word):
 
633
        d = wordsDictArchive[word]
 
634
        if d == None:
 
635
            print "skipped %s" % (word)
 
636
            return 0
 
637
        try:
 
638
            r = d[id]
 
639
            relevance = relevance + r
 
640
        except:
 
641
            pass
 
642
    else:
 
643
        wordsDictArchive[word] = {}
 
644
    d = wordsDictArchive[word];
 
645
    d[id] = relevance
 
646
    return relevance
 
647
    
 
648
def addStringArchive(str, id, relevance):
 
649
    if str == None or len(str) < 3:
 
650
        return -1
 
651
    ret = 0
 
652
    str = cleanupWordsString(str)
 
653
    l = string.split(str)
 
654
    for word in l:
 
655
        i = len(word)
 
656
        if i > 2:
 
657
            try:
 
658
                r = addWordArchive(word, id, relevance)
 
659
                if r < 0:
 
660
                    print "addWordArchive failed: %s %s" % (word, id)
 
661
                else:
 
662
                    ret = ret + r
 
663
            except:
 
664
                print "addWordArchive failed: %s %s %d" % (word, id, relevance)
 
665
                print sys.exc_type, sys.exc_value
 
666
    return ret
 
667
 
 
668
#########################################################################
 
669
#                                                                       #
 
670
#                  XML API description analysis                         #
 
671
#                                                                       #
 
672
#########################################################################
 
673
 
 
674
def loadAPI(filename):
 
675
    doc = libxml2.parseFile(filename)
 
676
    print "loaded %s" % (filename)
 
677
    return doc
 
678
 
 
679
def foundExport(file, symbol):
 
680
    if file == None:
 
681
        return 0
 
682
    if symbol == None:
 
683
        return 0
 
684
    addFunction(symbol, file)
 
685
    l = splitIdentifier(symbol)
 
686
    for word in l:
 
687
        addWord(word, file, symbol, 10)
 
688
    return 1
 
689
     
 
690
def analyzeAPIFile(top):
 
691
    count = 0
 
692
    name = top.prop("name")
 
693
    cur = top.children
 
694
    while cur != None:
 
695
        if cur.type == 'text':
 
696
            cur = cur.next
 
697
            continue
 
698
        if cur.name == "exports":
 
699
            count = count + foundExport(name, cur.prop("symbol"))
 
700
        else:
 
701
            print "unexpected element %s in API doc <file name='%s'>" % (name)
 
702
        cur = cur.next
 
703
    return count
 
704
 
 
705
def analyzeAPIFiles(top):
 
706
    count = 0
 
707
    cur = top.children
 
708
        
 
709
    while cur != None:
 
710
        if cur.type == 'text':
 
711
            cur = cur.next
 
712
            continue
 
713
        if cur.name == "file":
 
714
            count = count + analyzeAPIFile(cur)
 
715
        else:
 
716
            print "unexpected element %s in API doc <files>" % (cur.name)
 
717
        cur = cur.next
 
718
    return count
 
719
 
 
720
def analyzeAPIEnum(top):
 
721
    file = top.prop("file")
 
722
    if file == None:
 
723
        return 0
 
724
    symbol = top.prop("name")
 
725
    if symbol == None:
 
726
        return 0
 
727
 
 
728
    addEnum(symbol, file)
 
729
    l = splitIdentifier(symbol)
 
730
    for word in l:
 
731
        addWord(word, file, symbol, 10)
 
732
 
 
733
    return 1
 
734
 
 
735
def analyzeAPIConst(top):
 
736
    file = top.prop("file")
 
737
    if file == None:
 
738
        return 0
 
739
    symbol = top.prop("name")
 
740
    if symbol == None:
 
741
        return 0
 
742
 
 
743
    addConst(symbol, file)
 
744
    l = splitIdentifier(symbol)
 
745
    for word in l:
 
746
        addWord(word, file, symbol, 10)
 
747
 
 
748
    return 1
 
749
 
 
750
def analyzeAPIType(top):
 
751
    file = top.prop("file")
 
752
    if file == None:
 
753
        return 0
 
754
    symbol = top.prop("name")
 
755
    if symbol == None:
 
756
        return 0
 
757
 
 
758
    addType(symbol, file)
 
759
    l = splitIdentifier(symbol)
 
760
    for word in l:
 
761
        addWord(word, file, symbol, 10)
 
762
    return 1
 
763
 
 
764
def analyzeAPIFunctype(top):
 
765
    file = top.prop("file")
 
766
    if file == None:
 
767
        return 0
 
768
    symbol = top.prop("name")
 
769
    if symbol == None:
 
770
        return 0
 
771
 
 
772
    addFunctype(symbol, file)
 
773
    l = splitIdentifier(symbol)
 
774
    for word in l:
 
775
        addWord(word, file, symbol, 10)
 
776
    return 1
 
777
 
 
778
def analyzeAPIStruct(top):
 
779
    file = top.prop("file")
 
780
    if file == None:
 
781
        return 0
 
782
    symbol = top.prop("name")
 
783
    if symbol == None:
 
784
        return 0
 
785
 
 
786
    addStruct(symbol, file)
 
787
    l = splitIdentifier(symbol)
 
788
    for word in l:
 
789
        addWord(word, file, symbol, 10)
 
790
 
 
791
    info = top.prop("info")
 
792
    if info != None:
 
793
        info = string.replace(info, "'", " ")
 
794
        info = string.strip(info)
 
795
        l = string.split(info)
 
796
        for word in l:
 
797
            if len(word) > 2:
 
798
                addWord(word, file, symbol, 5)
 
799
    return 1
 
800
 
 
801
def analyzeAPIMacro(top):
 
802
    file = top.prop("file")
 
803
    if file == None:
 
804
        return 0
 
805
    symbol = top.prop("name")
 
806
    if symbol == None:
 
807
        return 0
 
808
    symbol = string.replace(symbol, "'", " ")
 
809
    symbol = string.strip(symbol)
 
810
 
 
811
    info = None
 
812
    cur = top.children
 
813
    while cur != None:
 
814
        if cur.type == 'text':
 
815
            cur = cur.next
 
816
            continue
 
817
        if cur.name == "info":
 
818
            info = cur.content
 
819
            break
 
820
        cur = cur.next
 
821
 
 
822
    l = splitIdentifier(symbol)
 
823
    for word in l:
 
824
        addWord(word, file, symbol, 10)
 
825
 
 
826
    if info == None:
 
827
        addMacro(symbol, file)
 
828
        print "Macro %s description has no <info>" % (symbol)
 
829
        return 0
 
830
 
 
831
    info = string.replace(info, "'", " ")
 
832
    info = string.strip(info)
 
833
    addMacro(symbol, file, info)
 
834
    l = string.split(info)
 
835
    for word in l:
 
836
        if len(word) > 2:
 
837
            addWord(word, file, symbol, 5)
 
838
    return 1
 
839
 
 
840
def analyzeAPIFunction(top):
 
841
    file = top.prop("file")
 
842
    if file == None:
 
843
        return 0
 
844
    symbol = top.prop("name")
 
845
    if symbol == None:
 
846
        return 0
 
847
 
 
848
    symbol = string.replace(symbol, "'", " ")
 
849
    symbol = string.strip(symbol)
 
850
    info = None
 
851
    cur = top.children
 
852
    while cur != None:
 
853
        if cur.type == 'text':
 
854
            cur = cur.next
 
855
            continue
 
856
        if cur.name == "info":
 
857
            info = cur.content
 
858
        elif cur.name == "return":
 
859
            rinfo = cur.prop("info")
 
860
            if rinfo != None:
 
861
                rinfo = string.replace(rinfo, "'", " ")
 
862
                rinfo = string.strip(rinfo)
 
863
                addString(rinfo, file, symbol, 7)
 
864
        elif cur.name == "arg":
 
865
            ainfo = cur.prop("info")
 
866
            if ainfo != None:
 
867
                ainfo = string.replace(ainfo, "'", " ")
 
868
                ainfo = string.strip(ainfo)
 
869
                addString(ainfo, file, symbol, 5)
 
870
            name = cur.prop("name")
 
871
            if name != None:
 
872
                name = string.replace(name, "'", " ")
 
873
                name = string.strip(name)
 
874
                addWord(name, file, symbol, 7)
 
875
        cur = cur.next
 
876
    if info == None:
 
877
        print "Function %s description has no <info>" % (symbol)
 
878
        addFunction(symbol, file, "")
 
879
    else:
 
880
        info = string.replace(info, "'", " ")
 
881
        info = string.strip(info)
 
882
        addFunction(symbol, file, info)
 
883
        addString(info, file, symbol, 5)
 
884
 
 
885
    l = splitIdentifier(symbol)
 
886
    for word in l:
 
887
        addWord(word, file, symbol, 10)
 
888
 
 
889
    return 1
 
890
 
 
891
def analyzeAPISymbols(top):
 
892
    count = 0
 
893
    cur = top.children
 
894
        
 
895
    while cur != None:
 
896
        if cur.type == 'text':
 
897
            cur = cur.next
 
898
            continue
 
899
        if cur.name == "macro":
 
900
            count = count + analyzeAPIMacro(cur)
 
901
        elif cur.name == "function":
 
902
            count = count + analyzeAPIFunction(cur)
 
903
        elif cur.name == "const":
 
904
            count = count + analyzeAPIConst(cur)
 
905
        elif cur.name == "typedef":
 
906
            count = count + analyzeAPIType(cur)
 
907
        elif cur.name == "struct":
 
908
            count = count + analyzeAPIStruct(cur)
 
909
        elif cur.name == "enum":
 
910
            count = count + analyzeAPIEnum(cur)
 
911
        elif cur.name == "functype":
 
912
            count = count + analyzeAPIFunctype(cur)
 
913
        else:
 
914
            print "unexpected element %s in API doc <files>" % (cur.name)
 
915
        cur = cur.next
 
916
    return count
 
917
 
 
918
def analyzeAPI(doc):
 
919
    count = 0
 
920
    if doc == None:
 
921
        return -1
 
922
    root = doc.getRootElement()
 
923
    if root.name != "api":
 
924
        print "Unexpected root name"
 
925
        return -1
 
926
    cur = root.children
 
927
    while cur != None:
 
928
        if cur.type == 'text':
 
929
            cur = cur.next
 
930
            continue
 
931
        if cur.name == "files":
 
932
            pass
 
933
#           count = count + analyzeAPIFiles(cur)
 
934
        elif cur.name == "symbols":
 
935
            count = count + analyzeAPISymbols(cur)
 
936
        else:
 
937
            print "unexpected element %s in API doc" % (cur.name)
 
938
        cur = cur.next
 
939
    return count
 
940
 
 
941
#########################################################################
 
942
#                                                                       #
 
943
#                  Web pages parsing and analysis                       #
 
944
#                                                                       #
 
945
#########################################################################
 
946
 
 
947
import glob
 
948
 
 
949
def analyzeHTMLText(doc, resource, p, section, id):
 
950
    words = 0
 
951
    try:
 
952
        content = p.content
 
953
        words = words + addStringHTML(content, resource, id, section, 5)
 
954
    except:
 
955
        return -1
 
956
    return words
 
957
 
 
958
def analyzeHTMLPara(doc, resource, p, section, id):
 
959
    words = 0
 
960
    try:
 
961
        content = p.content
 
962
        words = words + addStringHTML(content, resource, id, section, 5)
 
963
    except:
 
964
        return -1
 
965
    return words
 
966
 
 
967
def analyzeHTMLPre(doc, resource, p, section, id):
 
968
    words = 0
 
969
    try:
 
970
        content = p.content
 
971
        words = words + addStringHTML(content, resource, id, section, 5)
 
972
    except:
 
973
        return -1
 
974
    return words
 
975
 
 
976
def analyzeHTML(doc, resource, p, section, id):
 
977
    words = 0
 
978
    try:
 
979
        content = p.content
 
980
        words = words + addStringHTML(content, resource, id, section, 5)
 
981
    except:
 
982
        return -1
 
983
    return words
 
984
 
 
985
def analyzeHTML(doc, resource):
 
986
    para = 0;
 
987
    ctxt = doc.xpathNewContext()
 
988
    try:
 
989
        res = ctxt.xpathEval("//head/title")
 
990
        title = res[0].content
 
991
    except:
 
992
        title = "Page %s" % (resource)
 
993
    addPage(resource, title)
 
994
    try:
 
995
        items = ctxt.xpathEval("//h1 | //h2 | //h3 | //text()")
 
996
        section = title
 
997
        id = ""
 
998
        for item in items:
 
999
            if item.name == 'h1' or item.name == 'h2' or item.name == 'h3':
 
1000
                section = item.content
 
1001
                if item.prop("id"):
 
1002
                    id = item.prop("id")
 
1003
                elif item.prop("name"):
 
1004
                    id = item.prop("name")
 
1005
            elif item.type == 'text':
 
1006
                analyzeHTMLText(doc, resource, item, section, id)
 
1007
                para = para + 1
 
1008
            elif item.name == 'p':
 
1009
                analyzeHTMLPara(doc, resource, item, section, id)
 
1010
                para = para + 1
 
1011
            elif item.name == 'pre':
 
1012
                analyzeHTMLPre(doc, resource, item, section, id)
 
1013
                para = para + 1
 
1014
            else:
 
1015
                print "Page %s, unexpected %s element" % (resource, item.name)
 
1016
    except:
 
1017
        print "Page %s: problem analyzing" % (resource)
 
1018
        print sys.exc_type, sys.exc_value
 
1019
 
 
1020
    return para
 
1021
 
 
1022
def analyzeHTMLPages():
 
1023
    ret = 0
 
1024
    HTMLfiles = glob.glob("*.html") + glob.glob("tutorial/*.html")
 
1025
    for html in HTMLfiles:
 
1026
        if html[0:3] == "API":
 
1027
            continue
 
1028
        if html == "xml.html":
 
1029
            continue
 
1030
        try:
 
1031
            doc = libxml2.parseFile(html)
 
1032
        except:
 
1033
            doc = libxml2.htmlParseFile(html, None)
 
1034
        try:
 
1035
            res = analyzeHTML(doc, html)
 
1036
            print "Parsed %s : %d paragraphs" % (html, res)
 
1037
            ret = ret + 1
 
1038
        except:
 
1039
            print "could not parse %s" % (html)
 
1040
    return ret
 
1041
 
 
1042
#########################################################################
 
1043
#                                                                       #
 
1044
#                  Mail archives parsing and analysis                   #
 
1045
#                                                                       #
 
1046
#########################################################################
 
1047
 
 
1048
import time
 
1049
 
 
1050
def getXMLDateArchive(t = None):
 
1051
    if t == None:
 
1052
        t = time.time()
 
1053
    T = time.gmtime(t)
 
1054
    month = time.strftime("%B", T)
 
1055
    year = T[0]
 
1056
    url = "http://mail.gnome.org/archives/xml/%d-%s/date.html" % (year, month)
 
1057
    return url
 
1058
 
 
1059
def scanXMLMsgArchive(url, title, force = 0):
 
1060
    if url == None or title == None:
 
1061
        return 0
 
1062
 
 
1063
    ID = checkXMLMsgArchive(url)
 
1064
    if force == 0 and ID != -1:
 
1065
        return 0
 
1066
 
 
1067
    if ID == -1:
 
1068
        ID = addXMLMsgArchive(url, title)
 
1069
        if ID == -1:
 
1070
            return 0
 
1071
 
 
1072
    try:
 
1073
        print "Loading %s" % (url)
 
1074
        doc = libxml2.htmlParseFile(url, None);
 
1075
    except:
 
1076
        doc = None
 
1077
    if doc == None:
 
1078
        print "Failed to parse %s" % (url)
 
1079
        return 0
 
1080
 
 
1081
    addStringArchive(title, ID, 20)
 
1082
    ctxt = doc.xpathNewContext()
 
1083
    texts = ctxt.xpathEval("//pre//text()")
 
1084
    for text in texts:
 
1085
        addStringArchive(text.content, ID, 5)
 
1086
 
 
1087
    return 1
 
1088
 
 
1089
def scanXMLDateArchive(t = None, force = 0):
 
1090
    global wordsDictArchive
 
1091
 
 
1092
    wordsDictArchive = {}
 
1093
 
 
1094
    url = getXMLDateArchive(t)
 
1095
    print "loading %s" % (url)
 
1096
    try:
 
1097
        doc = libxml2.htmlParseFile(url, None);
 
1098
    except:
 
1099
        doc = None
 
1100
    if doc == None:
 
1101
        print "Failed to parse %s" % (url)
 
1102
        return -1
 
1103
    ctxt = doc.xpathNewContext()
 
1104
    anchors = ctxt.xpathEval("//a[@href]")
 
1105
    links = 0
 
1106
    newmsg = 0
 
1107
    for anchor in anchors:
 
1108
        href = anchor.prop("href")
 
1109
        if href == None or href[0:3] != "msg":
 
1110
            continue
 
1111
        try:
 
1112
            links = links + 1
 
1113
 
 
1114
            msg = libxml2.buildURI(href, url)
 
1115
            title = anchor.content
 
1116
            if title != None and title[0:4] == 'Re: ':
 
1117
                title = title[4:]
 
1118
            if title != None and title[0:6] == '[xml] ':
 
1119
                title = title[6:]
 
1120
            newmsg = newmsg + scanXMLMsgArchive(msg, title, force)
 
1121
 
 
1122
        except:
 
1123
            pass
 
1124
 
 
1125
    return newmsg
 
1126
    
 
1127
 
 
1128
#########################################################################
 
1129
#                                                                       #
 
1130
#          Main code: open the DB, the API XML and analyze it           #
 
1131
#                                                                       #
 
1132
#########################################################################
 
1133
def analyzeArchives(t = None, force = 0):
 
1134
    global wordsDictArchive
 
1135
 
 
1136
    ret = scanXMLDateArchive(t, force)
 
1137
    print "Indexed %d words in %d archive pages" % (len(wordsDictArchive), ret)
 
1138
 
 
1139
    i = 0
 
1140
    skipped = 0
 
1141
    for word in wordsDictArchive.keys():
 
1142
        refs = wordsDictArchive[word]
 
1143
        if refs  == None:
 
1144
            skipped = skipped + 1
 
1145
            continue;
 
1146
        for id in refs.keys():
 
1147
            relevance = refs[id]
 
1148
            updateWordArchive(word, id, relevance)
 
1149
            i = i + 1
 
1150
 
 
1151
    print "Found %d associations in HTML pages" % (i)
 
1152
 
 
1153
def analyzeHTMLTop():
 
1154
    global wordsDictHTML
 
1155
 
 
1156
    ret = analyzeHTMLPages()
 
1157
    print "Indexed %d words in %d HTML pages" % (len(wordsDictHTML), ret)
 
1158
 
 
1159
    i = 0
 
1160
    skipped = 0
 
1161
    for word in wordsDictHTML.keys():
 
1162
        refs = wordsDictHTML[word]
 
1163
        if refs  == None:
 
1164
            skipped = skipped + 1
 
1165
            continue;
 
1166
        for resource in refs.keys():
 
1167
            (relevance, id, section) = refs[resource]
 
1168
            updateWordHTML(word, resource, section, id, relevance)
 
1169
            i = i + 1
 
1170
 
 
1171
    print "Found %d associations in HTML pages" % (i)
 
1172
 
 
1173
def analyzeAPITop():
 
1174
    global wordsDict
 
1175
    global API
 
1176
 
 
1177
    try:
 
1178
        doc = loadAPI(API)
 
1179
        ret = analyzeAPI(doc)
 
1180
        print "Analyzed %d blocs" % (ret)
 
1181
        doc.freeDoc()
 
1182
    except:
 
1183
        print "Failed to parse and analyze %s" % (API)
 
1184
        print sys.exc_type, sys.exc_value
 
1185
        sys.exit(1)
 
1186
 
 
1187
    print "Indexed %d words" % (len(wordsDict))
 
1188
    i = 0
 
1189
    skipped = 0
 
1190
    for word in wordsDict.keys():
 
1191
        refs = wordsDict[word]
 
1192
        if refs  == None:
 
1193
            skipped = skipped + 1
 
1194
            continue;
 
1195
        for (module, symbol) in refs.keys():
 
1196
            updateWord(word, symbol, refs[(module, symbol)])
 
1197
            i = i + 1
 
1198
 
 
1199
    print "Found %d associations, skipped %d words" % (i, skipped)
 
1200
 
 
1201
def usage():
 
1202
    print "Usage index.py [--force] [--archive]  [--archive-year year] [--archive-month month] [--API] [--docs]"
 
1203
    sys.exit(1)
 
1204
 
 
1205
def main():
 
1206
    try:
 
1207
        openMySQL()
 
1208
    except:
 
1209
        print "Failed to open the database"
 
1210
        print sys.exc_type, sys.exc_value
 
1211
        sys.exit(1)
 
1212
 
 
1213
    args = sys.argv[1:]
 
1214
    force = 0
 
1215
    if args:
 
1216
        i = 0
 
1217
        while i < len(args):
 
1218
            if args[i] == '--force':
 
1219
                force = 1
 
1220
            elif args[i] == '--archive':
 
1221
                analyzeArchives(None, force)
 
1222
            elif args[i] == '--archive-year':
 
1223
                i = i + 1;
 
1224
                year = args[i]
 
1225
                months = ["January" , "February", "March", "April", "May",
 
1226
                          "June", "July", "August", "September", "October",
 
1227
                          "November", "December"];
 
1228
                for month in months:
 
1229
                    try:
 
1230
                        str = "%s-%s" % (year, month)
 
1231
                        T = time.strptime(str, "%Y-%B")
 
1232
                        t = time.mktime(T) + 3600 * 24 * 10;
 
1233
                        analyzeArchives(t, force)
 
1234
                    except:
 
1235
                        print "Failed to index month archive:"
 
1236
                        print sys.exc_type, sys.exc_value
 
1237
            elif args[i] == '--archive-month':
 
1238
                i = i + 1;
 
1239
                month = args[i]
 
1240
                try:
 
1241
                    T = time.strptime(month, "%Y-%B")
 
1242
                    t = time.mktime(T) + 3600 * 24 * 10;
 
1243
                    analyzeArchives(t, force)
 
1244
                except:
 
1245
                    print "Failed to index month archive:"
 
1246
                    print sys.exc_type, sys.exc_value
 
1247
            elif args[i] == '--API':
 
1248
                analyzeAPITop()
 
1249
            elif args[i] == '--docs':
 
1250
                analyzeHTMLTop()
 
1251
            else:
 
1252
                usage()
 
1253
            i = i + 1
 
1254
    else:
 
1255
        usage()
 
1256
 
 
1257
if __name__ == "__main__":
 
1258
    main()