nltk 3.2.1__zip → 3.3__zip

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (404) hide show
  1. {nltk-3.2.1 → nltk-3.3}/LICENSE.txt +1 -1
  2. {nltk-3.2.1/nltk.egg-info → nltk-3.3}/PKG-INFO +13 -5
  3. nltk-3.3/README.md +49 -0
  4. nltk-3.3/nltk/VERSION +1 -0
  5. {nltk-3.2.1 → nltk-3.3}/nltk/__init__.py +3 -3
  6. {nltk-3.2.1 → nltk-3.3}/nltk/app/__init__.py +2 -3
  7. {nltk-3.2.1 → nltk-3.3}/nltk/app/chartparser_app.py +92 -92
  8. {nltk-3.2.1 → nltk-3.3}/nltk/app/chunkparser_app.py +11 -13
  9. {nltk-3.2.1 → nltk-3.3}/nltk/app/collocations_app.py +8 -11
  10. {nltk-3.2.1 → nltk-3.3}/nltk/app/concordance_app.py +9 -11
  11. {nltk-3.2.1 → nltk-3.3}/nltk/app/nemo_app.py +18 -17
  12. {nltk-3.2.1 → nltk-3.3}/nltk/app/rdparser_app.py +10 -12
  13. {nltk-3.2.1 → nltk-3.3}/nltk/app/srparser_app.py +16 -16
  14. {nltk-3.2.1 → nltk-3.3}/nltk/app/wordfreq_app.py +1 -1
  15. {nltk-3.2.1 → nltk-3.3}/nltk/app/wordnet_app.py +11 -11
  16. {nltk-3.2.1 → nltk-3.3}/nltk/book.py +2 -1
  17. {nltk-3.2.1 → nltk-3.3}/nltk/ccg/__init__.py +1 -1
  18. {nltk-3.2.1 → nltk-3.3}/nltk/ccg/api.py +67 -47
  19. {nltk-3.2.1 → nltk-3.3}/nltk/ccg/chart.py +7 -5
  20. {nltk-3.2.1 → nltk-3.3}/nltk/ccg/combinator.py +42 -11
  21. {nltk-3.2.1 → nltk-3.3}/nltk/ccg/lexicon.py +1 -1
  22. {nltk-3.2.1 → nltk-3.3}/nltk/ccg/logic.py +1 -1
  23. {nltk-3.2.1 → nltk-3.3}/nltk/chat/__init__.py +1 -1
  24. {nltk-3.2.1 → nltk-3.3}/nltk/chat/eliza.py +1 -1
  25. {nltk-3.2.1 → nltk-3.3}/nltk/chat/iesha.py +1 -1
  26. {nltk-3.2.1 → nltk-3.3}/nltk/chat/rude.py +1 -1
  27. {nltk-3.2.1 → nltk-3.3}/nltk/chat/suntsu.py +1 -1
  28. {nltk-3.2.1 → nltk-3.3}/nltk/chat/util.py +12 -10
  29. {nltk-3.2.1 → nltk-3.3}/nltk/chat/zen.py +1 -1
  30. {nltk-3.2.1 → nltk-3.3}/nltk/chunk/__init__.py +1 -1
  31. {nltk-3.2.1 → nltk-3.3}/nltk/chunk/api.py +1 -1
  32. {nltk-3.2.1 → nltk-3.3}/nltk/chunk/named_entity.py +13 -13
  33. {nltk-3.2.1 → nltk-3.3}/nltk/chunk/regexp.py +9 -3
  34. {nltk-3.2.1 → nltk-3.3}/nltk/chunk/util.py +12 -12
  35. {nltk-3.2.1 → nltk-3.3}/nltk/classify/__init__.py +1 -1
  36. {nltk-3.2.1 → nltk-3.3}/nltk/classify/api.py +1 -1
  37. {nltk-3.2.1 → nltk-3.3}/nltk/classify/decisiontree.py +18 -18
  38. {nltk-3.2.1 → nltk-3.3}/nltk/classify/maxent.py +26 -8
  39. {nltk-3.2.1 → nltk-3.3}/nltk/classify/megam.py +5 -4
  40. {nltk-3.2.1 → nltk-3.3}/nltk/classify/naivebayes.py +29 -26
  41. {nltk-3.2.1 → nltk-3.3}/nltk/classify/rte_classify.py +58 -89
  42. {nltk-3.2.1 → nltk-3.3}/nltk/classify/scikitlearn.py +4 -2
  43. {nltk-3.2.1 → nltk-3.3}/nltk/classify/senna.py +24 -22
  44. {nltk-3.2.1 → nltk-3.3}/nltk/classify/svm.py +1 -1
  45. {nltk-3.2.1 → nltk-3.3}/nltk/classify/tadm.py +4 -3
  46. {nltk-3.2.1 → nltk-3.3}/nltk/classify/textcat.py +1 -1
  47. {nltk-3.2.1 → nltk-3.3}/nltk/classify/util.py +13 -1
  48. {nltk-3.2.1 → nltk-3.3}/nltk/classify/weka.py +7 -6
  49. {nltk-3.2.1 → nltk-3.3}/nltk/cluster/__init__.py +1 -1
  50. {nltk-3.2.1 → nltk-3.3}/nltk/cluster/api.py +9 -5
  51. {nltk-3.2.1 → nltk-3.3}/nltk/cluster/em.py +1 -1
  52. {nltk-3.2.1 → nltk-3.3}/nltk/cluster/gaac.py +3 -3
  53. {nltk-3.2.1 → nltk-3.3}/nltk/cluster/kmeans.py +1 -1
  54. {nltk-3.2.1 → nltk-3.3}/nltk/cluster/util.py +35 -20
  55. nltk-3.3/nltk/collections.py +640 -0
  56. {nltk-3.2.1 → nltk-3.3}/nltk/collocations.py +2 -2
  57. nltk-3.3/nltk/compat.py +365 -0
  58. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/__init__.py +37 -16
  59. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/europarl_raw.py +1 -1
  60. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/__init__.py +4 -2
  61. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/aligned.py +4 -3
  62. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/api.py +12 -10
  63. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/bnc.py +1 -1
  64. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/bracket_parse.py +1 -1
  65. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/categorized_sents.py +4 -3
  66. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/chasen.py +5 -4
  67. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/childes.py +8 -9
  68. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/chunked.py +4 -4
  69. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/cmudict.py +4 -2
  70. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/comparative_sents.py +4 -2
  71. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/conll.py +19 -12
  72. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/crubadan.py +2 -2
  73. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/dependency.py +1 -1
  74. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/framenet.py +1085 -119
  75. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/ieer.py +4 -3
  76. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/indian.py +4 -5
  77. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/ipipan.py +6 -5
  78. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/knbc.py +2 -2
  79. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/lin.py +1 -1
  80. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/mte.py +5 -4
  81. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/nkjp.py +4 -3
  82. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/nombank.py +8 -8
  83. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/nps_chat.py +1 -1
  84. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/opinion_lexicon.py +3 -3
  85. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/panlex_lite.py +1 -1
  86. nltk-3.3/nltk/corpus/reader/pl196x.py +292 -0
  87. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/plaintext.py +3 -4
  88. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/ppattach.py +4 -3
  89. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/propbank.py +8 -10
  90. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/pros_cons.py +5 -3
  91. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/reviews.py +3 -1
  92. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/rte.py +5 -7
  93. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/semcor.py +1 -1
  94. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/senseval.py +4 -2
  95. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/sentiwordnet.py +3 -3
  96. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/sinica_treebank.py +1 -1
  97. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/string_category.py +4 -3
  98. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/switchboard.py +1 -1
  99. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/tagged.py +4 -3
  100. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/timit.py +10 -8
  101. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/toolbox.py +4 -4
  102. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/twitter.py +4 -6
  103. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/util.py +7 -3
  104. nltk-3.3/nltk/corpus/reader/verbnet.py +595 -0
  105. nltk-3.3/nltk/corpus/reader/wordlist.py +134 -0
  106. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/wordnet.py +357 -285
  107. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/xmldocs.py +10 -5
  108. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/ycoe.py +25 -24
  109. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/util.py +22 -5
  110. {nltk-3.2.1 → nltk-3.3}/nltk/data.py +65 -29
  111. {nltk-3.2.1 → nltk-3.3}/nltk/decorators.py +5 -1
  112. {nltk-3.2.1 → nltk-3.3}/nltk/downloader.py +59 -55
  113. {nltk-3.2.1 → nltk-3.3}/nltk/draw/__init__.py +4 -4
  114. {nltk-3.2.1 → nltk-3.3}/nltk/draw/cfg.py +5 -8
  115. {nltk-3.2.1 → nltk-3.3}/nltk/draw/dispersion.py +1 -1
  116. {nltk-3.2.1 → nltk-3.3}/nltk/draw/table.py +4 -4
  117. {nltk-3.2.1 → nltk-3.3}/nltk/draw/tree.py +2 -5
  118. {nltk-3.2.1 → nltk-3.3}/nltk/draw/util.py +17 -17
  119. {nltk-3.2.1 → nltk-3.3}/nltk/featstruct.py +290 -173
  120. {nltk-3.2.1 → nltk-3.3}/nltk/grammar.py +87 -44
  121. {nltk-3.2.1 → nltk-3.3}/nltk/help.py +1 -1
  122. {nltk-3.2.1 → nltk-3.3}/nltk/inference/__init__.py +1 -1
  123. {nltk-3.2.1 → nltk-3.3}/nltk/inference/api.py +27 -19
  124. {nltk-3.2.1 → nltk-3.3}/nltk/inference/discourse.py +20 -16
  125. {nltk-3.2.1 → nltk-3.3}/nltk/inference/nonmonotonic.py +1 -1
  126. {nltk-3.2.1 → nltk-3.3}/nltk/inference/prover9.py +1 -1
  127. {nltk-3.2.1 → nltk-3.3}/nltk/inference/resolution.py +1 -1
  128. {nltk-3.2.1 → nltk-3.3}/nltk/inference/tableau.py +1 -1
  129. {nltk-3.2.1 → nltk-3.3}/nltk/internals.py +44 -44
  130. {nltk-3.2.1 → nltk-3.3}/nltk/jsontags.py +1 -1
  131. {nltk-3.2.1 → nltk-3.3}/nltk/metrics/__init__.py +2 -1
  132. {nltk-3.2.1 → nltk-3.3}/nltk/metrics/agreement.py +29 -9
  133. nltk-3.3/nltk/metrics/aline.py +607 -0
  134. {nltk-3.2.1 → nltk-3.3}/nltk/metrics/association.py +8 -4
  135. {nltk-3.2.1 → nltk-3.3}/nltk/metrics/confusionmatrix.py +1 -1
  136. {nltk-3.2.1 → nltk-3.3}/nltk/metrics/distance.py +12 -7
  137. {nltk-3.2.1 → nltk-3.3}/nltk/metrics/paice.py +1 -1
  138. {nltk-3.2.1 → nltk-3.3}/nltk/metrics/scores.py +7 -7
  139. {nltk-3.2.1 → nltk-3.3}/nltk/metrics/segmentation.py +4 -5
  140. {nltk-3.2.1 → nltk-3.3}/nltk/metrics/spearman.py +1 -1
  141. {nltk-3.2.1 → nltk-3.3}/nltk/misc/__init__.py +1 -1
  142. {nltk-3.2.1 → nltk-3.3}/nltk/misc/chomsky.py +4 -2
  143. {nltk-3.2.1 → nltk-3.3}/nltk/misc/minimalset.py +1 -1
  144. {nltk-3.2.1 → nltk-3.3}/nltk/misc/sort.py +1 -1
  145. {nltk-3.2.1 → nltk-3.3}/nltk/misc/wordfinder.py +1 -1
  146. {nltk-3.2.1 → nltk-3.3}/nltk/parse/__init__.py +2 -1
  147. {nltk-3.2.1 → nltk-3.3}/nltk/parse/api.py +1 -1
  148. {nltk-3.2.1 → nltk-3.3}/nltk/parse/bllip.py +1 -1
  149. {nltk-3.2.1 → nltk-3.3}/nltk/parse/chart.py +8 -7
  150. nltk-3.3/nltk/parse/corenlp.py +780 -0
  151. {nltk-3.2.1 → nltk-3.3}/nltk/parse/dependencygraph.py +4 -2
  152. {nltk-3.2.1 → nltk-3.3}/nltk/parse/earleychart.py +4 -3
  153. {nltk-3.2.1 → nltk-3.3}/nltk/parse/evaluate.py +1 -1
  154. {nltk-3.2.1 → nltk-3.3}/nltk/parse/featurechart.py +6 -4
  155. {nltk-3.2.1 → nltk-3.3}/nltk/parse/generate.py +15 -4
  156. {nltk-3.2.1 → nltk-3.3}/nltk/parse/malt.py +2 -2
  157. {nltk-3.2.1 → nltk-3.3}/nltk/parse/nonprojectivedependencyparser.py +3 -3
  158. {nltk-3.2.1 → nltk-3.3}/nltk/parse/pchart.py +1 -1
  159. {nltk-3.2.1 → nltk-3.3}/nltk/parse/projectivedependencyparser.py +6 -5
  160. {nltk-3.2.1 → nltk-3.3}/nltk/parse/recursivedescent.py +2 -3
  161. {nltk-3.2.1 → nltk-3.3}/nltk/parse/shiftreduce.py +2 -3
  162. {nltk-3.2.1 → nltk-3.3}/nltk/parse/stanford.py +53 -28
  163. {nltk-3.2.1 → nltk-3.3}/nltk/parse/transitionparser.py +11 -9
  164. {nltk-3.2.1 → nltk-3.3}/nltk/parse/util.py +1 -1
  165. {nltk-3.2.1 → nltk-3.3}/nltk/parse/viterbi.py +1 -1
  166. {nltk-3.2.1 → nltk-3.3}/nltk/probability.py +75 -20
  167. {nltk-3.2.1 → nltk-3.3}/nltk/sem/__init__.py +1 -1
  168. {nltk-3.2.1 → nltk-3.3}/nltk/sem/boxer.py +15 -15
  169. {nltk-3.2.1 → nltk-3.3}/nltk/sem/chat80.py +6 -6
  170. {nltk-3.2.1 → nltk-3.3}/nltk/sem/cooper_storage.py +1 -1
  171. {nltk-3.2.1 → nltk-3.3}/nltk/sem/drt.py +9 -8
  172. {nltk-3.2.1 → nltk-3.3}/nltk/sem/drt_glue_demo.py +5 -9
  173. {nltk-3.2.1 → nltk-3.3}/nltk/sem/evaluate.py +9 -3
  174. {nltk-3.2.1 → nltk-3.3}/nltk/sem/glue.py +8 -6
  175. {nltk-3.2.1 → nltk-3.3}/nltk/sem/hole.py +4 -2
  176. {nltk-3.2.1 → nltk-3.3}/nltk/sem/lfg.py +4 -2
  177. {nltk-3.2.1 → nltk-3.3}/nltk/sem/linearlogic.py +4 -2
  178. {nltk-3.2.1 → nltk-3.3}/nltk/sem/logic.py +14 -14
  179. {nltk-3.2.1 → nltk-3.3}/nltk/sem/relextract.py +11 -18
  180. {nltk-3.2.1 → nltk-3.3}/nltk/sem/skolemize.py +1 -1
  181. {nltk-3.2.1 → nltk-3.3}/nltk/sem/util.py +1 -1
  182. {nltk-3.2.1 → nltk-3.3}/nltk/sentiment/__init__.py +1 -1
  183. {nltk-3.2.1 → nltk-3.3}/nltk/sentiment/sentiment_analyzer.py +1 -1
  184. {nltk-3.2.1 → nltk-3.3}/nltk/sentiment/util.py +14 -4
  185. {nltk-3.2.1 → nltk-3.3}/nltk/sentiment/vader.py +41 -42
  186. {nltk-3.2.1 → nltk-3.3}/nltk/stem/__init__.py +1 -3
  187. {nltk-3.2.1 → nltk-3.3}/nltk/stem/api.py +7 -4
  188. nltk-3.3/nltk/stem/arlstem.py +369 -0
  189. {nltk-3.2.1 → nltk-3.3}/nltk/stem/isri.py +1 -1
  190. {nltk-3.2.1 → nltk-3.3}/nltk/stem/lancaster.py +39 -12
  191. nltk-3.3/nltk/stem/porter.py +710 -0
  192. {nltk-3.2.1 → nltk-3.3}/nltk/stem/regexp.py +2 -2
  193. {nltk-3.2.1 → nltk-3.3}/nltk/stem/rslp.py +1 -1
  194. {nltk-3.2.1 → nltk-3.3}/nltk/stem/snowball.py +537 -13
  195. {nltk-3.2.1 → nltk-3.3}/nltk/stem/util.py +11 -1
  196. {nltk-3.2.1 → nltk-3.3}/nltk/stem/wordnet.py +1 -1
  197. {nltk-3.2.1 → nltk-3.3}/nltk/tag/__init__.py +32 -7
  198. {nltk-3.2.1 → nltk-3.3}/nltk/tag/api.py +13 -8
  199. {nltk-3.2.1 → nltk-3.3}/nltk/tag/brill.py +4 -6
  200. {nltk-3.2.1 → nltk-3.3}/nltk/tag/crf.py +1 -1
  201. {nltk-3.2.1 → nltk-3.3}/nltk/tag/hmm.py +11 -11
  202. {nltk-3.2.1 → nltk-3.3}/nltk/tag/hunpos.py +4 -4
  203. {nltk-3.2.1 → nltk-3.3}/nltk/tag/mapping.py +1 -1
  204. {nltk-3.2.1 → nltk-3.3}/nltk/tag/perceptron.py +25 -10
  205. {nltk-3.2.1 → nltk-3.3}/nltk/tag/senna.py +25 -23
  206. {nltk-3.2.1 → nltk-3.3}/nltk/tag/sequential.py +19 -15
  207. {nltk-3.2.1 → nltk-3.3}/nltk/tag/stanford.py +59 -36
  208. {nltk-3.2.1 → nltk-3.3}/nltk/tag/tnt.py +11 -20
  209. {nltk-3.2.1 → nltk-3.3}/nltk/tag/util.py +1 -1
  210. {nltk-3.2.1 → nltk-3.3}/nltk/tbl/__init__.py +1 -1
  211. {nltk-3.2.1 → nltk-3.3}/nltk/tbl/demo.py +1 -1
  212. {nltk-3.2.1 → nltk-3.3}/nltk/tbl/erroranalysis.py +1 -1
  213. {nltk-3.2.1 → nltk-3.3}/nltk/tbl/feature.py +5 -7
  214. {nltk-3.2.1 → nltk-3.3}/nltk/tbl/rule.py +6 -6
  215. {nltk-3.2.1 → nltk-3.3}/nltk/tbl/template.py +18 -23
  216. {nltk-3.2.1 → nltk-3.3}/nltk/test/__init__.py +1 -1
  217. {nltk-3.2.1 → nltk-3.3}/nltk/test/all.py +7 -6
  218. {nltk-3.2.1 → nltk-3.3}/nltk/test/bnc.doctest +1 -1
  219. {nltk-3.2.1 → nltk-3.3}/nltk/test/ccg.doctest +1 -1
  220. {nltk-3.2.1 → nltk-3.3}/nltk/test/ccg_semantics.doctest +1 -1
  221. {nltk-3.2.1 → nltk-3.3}/nltk/test/chat80.doctest +1 -1
  222. {nltk-3.2.1 → nltk-3.3}/nltk/test/childes_fixt.py +1 -0
  223. {nltk-3.2.1 → nltk-3.3}/nltk/test/chunk.doctest +1 -1
  224. {nltk-3.2.1 → nltk-3.3}/nltk/test/classify.doctest +1 -1
  225. {nltk-3.2.1 → nltk-3.3}/nltk/test/classify_fixt.py +2 -1
  226. nltk-3.3/nltk/test/collections.doctest +20 -0
  227. {nltk-3.2.1 → nltk-3.3}/nltk/test/collocations.doctest +1 -1
  228. {nltk-3.2.1 → nltk-3.3}/nltk/test/compat.doctest +0 -4
  229. {nltk-3.2.1 → nltk-3.3}/nltk/test/compat_fixt.py +1 -0
  230. nltk-3.3/nltk/test/concordance.doctest +55 -0
  231. {nltk-3.2.1 → nltk-3.3}/nltk/test/corpus.doctest +38 -49
  232. {nltk-3.2.1 → nltk-3.3}/nltk/test/crubadan.doctest +1 -1
  233. {nltk-3.2.1 → nltk-3.3}/nltk/test/data.doctest +1 -1
  234. {nltk-3.2.1 → nltk-3.3}/nltk/test/dependency.doctest +1 -1
  235. {nltk-3.2.1 → nltk-3.3}/nltk/test/discourse.doctest +1 -1
  236. {nltk-3.2.1 → nltk-3.3}/nltk/test/discourse_fixt.py +1 -0
  237. {nltk-3.2.1 → nltk-3.3}/nltk/test/doctest_nose_plugin.py +8 -5
  238. {nltk-3.2.1 → nltk-3.3}/nltk/test/drt.doctest +1 -1
  239. {nltk-3.2.1 → nltk-3.3}/nltk/test/featgram.doctest +1 -1
  240. {nltk-3.2.1 → nltk-3.3}/nltk/test/featstruct.doctest +2 -3
  241. {nltk-3.2.1 → nltk-3.3}/nltk/test/framenet.doctest +82 -33
  242. {nltk-3.2.1 → nltk-3.3}/nltk/test/generate.doctest +1 -1
  243. {nltk-3.2.1 → nltk-3.3}/nltk/test/gensim.doctest +6 -7
  244. {nltk-3.2.1 → nltk-3.3}/nltk/test/gensim_fixt.py +1 -0
  245. {nltk-3.2.1 → nltk-3.3}/nltk/test/gluesemantics.doctest +13 -15
  246. {nltk-3.2.1 → nltk-3.3}/nltk/test/gluesemantics_malt.doctest +1 -1
  247. {nltk-3.2.1 → nltk-3.3}/nltk/test/gluesemantics_malt_fixt.py +1 -0
  248. {nltk-3.2.1 → nltk-3.3}/nltk/test/grammar.doctest +1 -1
  249. {nltk-3.2.1 → nltk-3.3}/nltk/test/grammartestsuites.doctest +1 -1
  250. {nltk-3.2.1 → nltk-3.3}/nltk/test/index.doctest +1 -1
  251. {nltk-3.2.1 → nltk-3.3}/nltk/test/inference.doctest +1 -1
  252. {nltk-3.2.1 → nltk-3.3}/nltk/test/inference_fixt.py +1 -0
  253. {nltk-3.2.1 → nltk-3.3}/nltk/test/internals.doctest +1 -1
  254. {nltk-3.2.1 → nltk-3.3}/nltk/test/japanese.doctest +1 -1
  255. {nltk-3.2.1 → nltk-3.3}/nltk/test/logic.doctest +1 -1
  256. {nltk-3.2.1 → nltk-3.3}/nltk/test/metrics.doctest +3 -3
  257. {nltk-3.2.1 → nltk-3.3}/nltk/test/misc.doctest +1 -1
  258. {nltk-3.2.1 → nltk-3.3}/nltk/test/nonmonotonic.doctest +1 -1
  259. {nltk-3.2.1 → nltk-3.3}/nltk/test/nonmonotonic_fixt.py +1 -0
  260. {nltk-3.2.1 → nltk-3.3}/nltk/test/parse.doctest +1 -1
  261. {nltk-3.2.1 → nltk-3.3}/nltk/test/portuguese_en.doctest +1 -1
  262. {nltk-3.2.1 → nltk-3.3}/nltk/test/probability.doctest +1 -1
  263. {nltk-3.2.1 → nltk-3.3}/nltk/test/probability_fixt.py +2 -1
  264. {nltk-3.2.1 → nltk-3.3}/nltk/test/propbank.doctest +1 -1
  265. {nltk-3.2.1 → nltk-3.3}/nltk/test/relextract.doctest +1 -1
  266. {nltk-3.2.1 → nltk-3.3}/nltk/test/resolution.doctest +1 -1
  267. {nltk-3.2.1 → nltk-3.3}/nltk/test/runtests.py +35 -13
  268. {nltk-3.2.1 → nltk-3.3}/nltk/test/semantics.doctest +1 -1
  269. {nltk-3.2.1 → nltk-3.3}/nltk/test/sentiment.doctest +3 -3
  270. {nltk-3.2.1 → nltk-3.3}/nltk/test/sentiwordnet.doctest +1 -1
  271. {nltk-3.2.1 → nltk-3.3}/nltk/test/simple.doctest +1 -1
  272. {nltk-3.2.1 → nltk-3.3}/nltk/test/stem.doctest +2 -2
  273. {nltk-3.2.1 → nltk-3.3}/nltk/test/tag.doctest +1 -1
  274. {nltk-3.2.1 → nltk-3.3}/nltk/test/tokenize.doctest +109 -2
  275. {nltk-3.2.1 → nltk-3.3}/nltk/test/toolbox.doctest +1 -1
  276. {nltk-3.2.1 → nltk-3.3}/nltk/test/translate.doctest +1 -1
  277. {nltk-3.2.1 → nltk-3.3}/nltk/test/tree.doctest +1 -1
  278. {nltk-3.2.1 → nltk-3.3}/nltk/test/treeprettyprinter.doctest +1 -1
  279. {nltk-3.2.1 → nltk-3.3}/nltk/test/treetransforms.doctest +1 -1
  280. nltk-3.3/nltk/test/unit/test_aline.py +52 -0
  281. nltk-3.3/nltk/test/unit/test_chunk.py +56 -0
  282. {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/test_classify.py +20 -18
  283. {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/test_collocations.py +16 -7
  284. nltk-3.3/nltk/test/unit/test_concordance.py +98 -0
  285. nltk-3.3/nltk/test/unit/test_corenlp.py +1000 -0
  286. {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/test_corpora.py +18 -1
  287. {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/test_json2csv_corpus.py +4 -3
  288. nltk-3.3/nltk/test/unit/test_rte_classify.py +86 -0
  289. nltk-3.3/nltk/test/unit/test_senna.py +74 -0
  290. nltk-3.3/nltk/test/unit/test_stem.py +121 -0
  291. {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/test_tgrep.py +4 -2
  292. nltk-3.3/nltk/test/unit/test_tokenize.py +168 -0
  293. nltk-3.3/nltk/test/unit/test_wordnet.py +134 -0
  294. nltk-3.3/nltk/test/unit/translate/test_bleu.py +244 -0
  295. nltk-3.3/nltk/test/unit/translate/test_gdfa.py +57 -0
  296. nltk-3.3/nltk/test/unit/translate/test_nist.py +37 -0
  297. {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/translate/test_stack_decoder.py +1 -1
  298. {nltk-3.2.1 → nltk-3.3}/nltk/test/util.doctest +1 -1
  299. {nltk-3.2.1 → nltk-3.3}/nltk/test/wordnet.doctest +17 -3
  300. {nltk-3.2.1 → nltk-3.3}/nltk/test/wordnet_fixt.py +1 -0
  301. {nltk-3.2.1 → nltk-3.3}/nltk/test/wordnet_lch.doctest +1 -1
  302. {nltk-3.2.1 → nltk-3.3}/nltk/test/wsd.doctest +1 -1
  303. {nltk-3.2.1 → nltk-3.3}/nltk/text.py +92 -39
  304. {nltk-3.2.1 → nltk-3.3}/nltk/tgrep.py +8 -7
  305. {nltk-3.2.1 → nltk-3.3}/nltk/tokenize/__init__.py +37 -15
  306. {nltk-3.2.1 → nltk-3.3}/nltk/tokenize/api.py +3 -4
  307. {nltk-3.2.1 → nltk-3.3}/nltk/tokenize/casual.py +10 -9
  308. {nltk-3.2.1 → nltk-3.3}/nltk/tokenize/mwe.py +2 -2
  309. nltk-3.3/nltk/tokenize/nist.py +173 -0
  310. {nltk-3.2.1 → nltk-3.3}/nltk/tokenize/punkt.py +186 -167
  311. {nltk-3.2.1 → nltk-3.3}/nltk/tokenize/regexp.py +13 -7
  312. nltk-3.3/nltk/tokenize/repp.py +151 -0
  313. {nltk-3.2.1 → nltk-3.3}/nltk/tokenize/sexpr.py +4 -6
  314. {nltk-3.2.1 → nltk-3.3}/nltk/tokenize/simple.py +7 -5
  315. {nltk-3.2.1 → nltk-3.3}/nltk/tokenize/stanford.py +18 -14
  316. nltk-3.3/nltk/tokenize/stanford_segmenter.py +246 -0
  317. {nltk-3.2.1 → nltk-3.3}/nltk/tokenize/texttiling.py +43 -45
  318. nltk-3.3/nltk/tokenize/toktok.py +155 -0
  319. nltk-3.3/nltk/tokenize/treebank.py +363 -0
  320. nltk-3.3/nltk/tokenize/util.py +261 -0
  321. {nltk-3.2.1 → nltk-3.3}/nltk/toolbox.py +4 -2
  322. {nltk-3.2.1 → nltk-3.3}/nltk/translate/__init__.py +1 -1
  323. {nltk-3.2.1 → nltk-3.3}/nltk/translate/api.py +50 -40
  324. {nltk-3.2.1 → nltk-3.3}/nltk/translate/bleu_score.py +221 -156
  325. nltk-3.3/nltk/translate/chrf_score.py +137 -0
  326. {nltk-3.2.1 → nltk-3.3}/nltk/translate/gale_church.py +32 -19
  327. {nltk-3.2.1 → nltk-3.3}/nltk/translate/gdfa.py +14 -10
  328. nltk-3.3/nltk/translate/gleu_score.py +193 -0
  329. {nltk-3.2.1 → nltk-3.3}/nltk/translate/ibm1.py +17 -8
  330. {nltk-3.2.1 → nltk-3.3}/nltk/translate/ibm2.py +4 -4
  331. {nltk-3.2.1 → nltk-3.3}/nltk/translate/ibm4.py +1 -1
  332. {nltk-3.2.1 → nltk-3.3}/nltk/translate/ibm5.py +1 -1
  333. {nltk-3.2.1 → nltk-3.3}/nltk/translate/ibm_model.py +4 -1
  334. {nltk-3.2.1 → nltk-3.3}/nltk/translate/metrics.py +1 -1
  335. nltk-3.3/nltk/translate/nist_score.py +178 -0
  336. {nltk-3.2.1 → nltk-3.3}/nltk/translate/phrase_based.py +1 -1
  337. {nltk-3.2.1 → nltk-3.3}/nltk/translate/ribes_score.py +1 -1
  338. {nltk-3.2.1 → nltk-3.3}/nltk/translate/stack_decoder.py +5 -1
  339. {nltk-3.2.1 → nltk-3.3}/nltk/tree.py +10 -8
  340. {nltk-3.2.1 → nltk-3.3}/nltk/treeprettyprinter.py +6 -6
  341. {nltk-3.2.1 → nltk-3.3}/nltk/twitter/__init__.py +1 -1
  342. {nltk-3.2.1 → nltk-3.3}/nltk/twitter/api.py +8 -3
  343. {nltk-3.2.1 → nltk-3.3}/nltk/twitter/common.py +9 -3
  344. {nltk-3.2.1 → nltk-3.3}/nltk/twitter/twitter_demo.py +1 -1
  345. {nltk-3.2.1 → nltk-3.3}/nltk/twitter/twitterclient.py +1 -1
  346. {nltk-3.2.1 → nltk-3.3}/nltk/twitter/util.py +5 -4
  347. {nltk-3.2.1 → nltk-3.3}/nltk/util.py +41 -654
  348. {nltk-3.2.1 → nltk-3.3}/nltk/wsd.py +2 -2
  349. {nltk-3.2.1 → nltk-3.3/nltk.egg-info}/PKG-INFO +13 -5
  350. {nltk-3.2.1 → nltk-3.3}/nltk.egg-info/SOURCES.txt +23 -1
  351. nltk-3.3/nltk.egg-info/requires.txt +31 -0
  352. {nltk-3.2.1 → nltk-3.3}/setup.cfg +0 -1
  353. {nltk-3.2.1 → nltk-3.3}/setup.py +32 -5
  354. nltk-3.2.1/nltk/VERSION +0 -1
  355. nltk-3.2.1/nltk/compat.py +0 -706
  356. nltk-3.2.1/nltk/corpus/reader/pl196x.py +0 -278
  357. nltk-3.2.1/nltk/corpus/reader/verbnet.py +0 -408
  358. nltk-3.2.1/nltk/corpus/reader/wordlist.py +0 -37
  359. nltk-3.2.1/nltk/six.py +0 -868
  360. nltk-3.2.1/nltk/stem/porter.py +0 -692
  361. nltk-3.2.1/nltk/test/unit/test_stem.py +0 -36
  362. nltk-3.2.1/nltk/test/unit/test_tokenize.py +0 -23
  363. nltk-3.2.1/nltk/test/unit/translate/test_bleu.py +0 -138
  364. nltk-3.2.1/nltk/tokenize/stanford_segmenter.py +0 -157
  365. nltk-3.2.1/nltk/tokenize/treebank.py +0 -124
  366. nltk-3.2.1/nltk/tokenize/util.py +0 -90
  367. {nltk-3.2.1 → nltk-3.3}/INSTALL.txt +0 -0
  368. {nltk-3.2.1 → nltk-3.3}/MANIFEST.in +0 -0
  369. {nltk-3.2.1 → nltk-3.3}/nltk/classify/positivenaivebayes.py +0 -0
  370. {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/udhr.py +0 -0
  371. {nltk-3.2.1 → nltk-3.3}/nltk/inference/mace.py +0 -0
  372. {nltk-3.2.1 → nltk-3.3}/nltk/lazyimport.py +0 -0
  373. {nltk-3.2.1 → nltk-3.3}/nltk/misc/babelfish.py +0 -0
  374. {nltk-3.2.1 → nltk-3.3}/nltk/tag/brill_trainer.py +0 -0
  375. {nltk-3.2.1 → nltk-3.3}/nltk/tbl/api.py +0 -0
  376. {nltk-3.2.1 → nltk-3.3}/nltk/test/bleu.doctest +0 -0
  377. {nltk-3.2.1 → nltk-3.3}/nltk/test/childes.doctest +0 -0
  378. {nltk-3.2.1 → nltk-3.3}/nltk/test/corpus_fixt.py +0 -0
  379. {nltk-3.2.1 → nltk-3.3}/nltk/test/paice.doctest +0 -0
  380. {nltk-3.2.1 → nltk-3.3}/nltk/test/portuguese_en_fixt.py +0 -0
  381. {nltk-3.2.1 → nltk-3.3}/nltk/test/segmentation_fixt.py +0 -0
  382. {nltk-3.2.1 → nltk-3.3}/nltk/test/semantics_fixt.py +0 -0
  383. {nltk-3.2.1 → nltk-3.3}/nltk/test/translate_fixt.py +0 -0
  384. {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/__init__.py +0 -0
  385. {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/test_2x_compat.py +0 -0
  386. {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/test_corpus_views.py +0 -0
  387. {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/test_hmm.py +0 -0
  388. {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/test_naivebayes.py +0 -0
  389. {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/test_seekable_unicode_stream_reader.py +0 -0
  390. {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/test_tag.py +0 -0
  391. {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/test_twitter_auth.py +0 -0
  392. {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/translate/__init__.py +0 -0
  393. {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/translate/test_ibm1.py +0 -0
  394. {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/translate/test_ibm2.py +0 -0
  395. {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/translate/test_ibm3.py +0 -0
  396. {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/translate/test_ibm4.py +0 -0
  397. {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/translate/test_ibm5.py +0 -0
  398. {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/translate/test_ibm_model.py +0 -0
  399. {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/utils.py +0 -0
  400. {nltk-3.2.1 → nltk-3.3}/nltk/translate/ibm3.py +0 -0
  401. {nltk-3.2.1 → nltk-3.3}/nltk/treetransforms.py +0 -0
  402. {nltk-3.2.1 → nltk-3.3}/nltk.egg-info/dependency_links.txt +0 -0
  403. {nltk-3.2.1 → nltk-3.3}/nltk.egg-info/not-zip-safe +0 -0
  404. {nltk-3.2.1 → nltk-3.3}/nltk.egg-info/top_level.txt +0 -0
@@ -1,28 +1,57 @@
1
1
  # Natural Language Toolkit: Framenet Corpus Reader
2
2
  #
3
- # Copyright (C) 2001-2016 NLTK Project
3
+ # Copyright (C) 2001-2018 NLTK Project
4
4
  # Authors: Chuck Wooters <wooters@icsi.berkeley.edu>,
5
- # Nathan Schneider <nschneid@cs.cmu.edu>
5
+ # Nathan Schneider <nathan.schneider@georgetown.edu>
6
6
  # URL: <http://nltk.org/>
7
7
  # For license information, see LICENSE.TXT
8
- from __future__ import print_function, unicode_literals
8
+
9
9
 
10
10
  """
11
- Corpus reader for the Framenet 1.5 Corpus.
11
+ Corpus reader for the FrameNet 1.7 lexicon and corpus.
12
12
  """
13
-
14
- __docformat__ = 'epytext en'
13
+ from __future__ import print_function, unicode_literals
15
14
 
16
15
  import os, sys
17
16
  import re
18
17
  import textwrap
19
- from collections import defaultdict
18
+ import itertools
19
+ import types
20
+
21
+ from six import string_types, text_type
22
+ from six.moves import zip_longest
23
+
24
+ from collections import defaultdict, OrderedDict
25
+ from operator import itemgetter
20
26
  from pprint import pprint, pformat
21
27
  from nltk.internals import ElementWrapper
22
28
  from nltk.corpus.reader import XMLCorpusReader, XMLCorpusView
23
- from nltk.compat import text_type, string_types, python_2_unicode_compatible
24
- from nltk.util import AbstractLazySequence, LazyMap
29
+ from nltk.compat import python_2_unicode_compatible
30
+ from nltk.util import AbstractLazySequence, LazyConcatenation, LazyMap, LazyIteratorList
25
31
 
32
+ __docformat__ = 'epytext en'
33
+
34
+ def mimic_wrap(lines, wrap_at=65, **kwargs):
35
+ """
36
+ Wrap the first of 'lines' with textwrap and the remaining lines at exactly the same
37
+ positions as the first.
38
+ """
39
+ l0 = textwrap.fill(lines[0], wrap_at, drop_whitespace=False).split('\n')
40
+ yield l0
41
+
42
+ def _(line):
43
+ il0 = 0
44
+ while line and il0<len(l0)-1:
45
+ yield line[:len(l0[il0])]
46
+ line = line[len(l0[il0]):]
47
+ il0 += 1
48
+ if line: # Remaining stuff on this line past the end of the mimicked line.
49
+ # So just textwrap this line.
50
+ for ln in textwrap.fill(line, wrap_at, drop_whitespace=False).split('\n'):
51
+ yield ln
52
+
53
+ for l in lines[1:]:
54
+ yield list(_(l))
26
55
 
27
56
  def _pretty_longstring(defstr, prefix='', wrap_at=65):
28
57
 
@@ -163,11 +192,373 @@ def _pretty_lu(lu):
163
192
  if 'semTypes' in lukeys:
164
193
  outstr += "\n[semTypes] {0} semantic types\n".format(len(lu.semTypes))
165
194
  outstr += " "*(len(lu.semTypes)>0) + ", ".join('{0}({1})'.format(x.name, x.ID) for x in lu.semTypes) + '\n'*(len(lu.semTypes)>0)
195
+ if 'URL' in lukeys:
196
+ outstr += "\n[URL] {0}\n".format(lu.URL)
166
197
  if 'subCorpus' in lukeys:
167
198
  subc = [x.name for x in lu.subCorpus]
168
199
  outstr += "\n[subCorpus] {0} subcorpora\n".format(len(lu.subCorpus))
169
200
  for line in textwrap.fill(", ".join(sorted(subc)), 60).split('\n'):
170
201
  outstr += " {0}\n".format(line)
202
+ if 'exemplars' in lukeys:
203
+ outstr += "\n[exemplars] {0} sentences across all subcorpora\n".format(len(lu.exemplars))
204
+
205
+ return outstr
206
+
207
+ def _pretty_exemplars(exemplars, lu):
208
+ """
209
+ Helper function for pretty-printing a list of exemplar sentences for a lexical unit.
210
+
211
+ :param sent: The list of exemplar sentences to be printed.
212
+ :type sent: list(AttrDict)
213
+ :return: An index of the text of the exemplar sentences.
214
+ :rtype: str
215
+ """
216
+
217
+ outstr = ""
218
+ outstr += "exemplar sentences for {0.name} in {0.frame.name}:\n\n".format(lu)
219
+ for i,sent in enumerate(exemplars):
220
+ outstr += "[{0}] {1}\n".format(i, sent.text)
221
+ outstr += "\n"
222
+ return outstr
223
+
224
+ def _pretty_fulltext_sentences(sents):
225
+ """
226
+ Helper function for pretty-printing a list of annotated sentences for a full-text document.
227
+
228
+ :param sent: The list of sentences to be printed.
229
+ :type sent: list(AttrDict)
230
+ :return: An index of the text of the sentences.
231
+ :rtype: str
232
+ """
233
+
234
+ outstr = ""
235
+ outstr += "full-text document ({0.ID}) {0.name}:\n\n".format(sents)
236
+ outstr += "[corpid] {0.corpid}\n[corpname] {0.corpname}\n[description] {0.description}\n[URL] {0.URL}\n\n".format(sents)
237
+ outstr += "[sentence]\n".format(sents)
238
+ for i,sent in enumerate(sents.sentence):
239
+ outstr += "[{0}] {1}\n".format(i, sent.text)
240
+ outstr += "\n"
241
+ return outstr
242
+
243
+ def _pretty_fulltext_sentence(sent):
244
+ """
245
+ Helper function for pretty-printing an annotated sentence from a full-text document.
246
+
247
+ :param sent: The sentence to be printed.
248
+ :type sent: list(AttrDict)
249
+ :return: The text of the sentence with annotation set indices on frame targets.
250
+ :rtype: str
251
+ """
252
+
253
+ outstr = ""
254
+ outstr += "full-text sentence ({0.ID}) in {1}:\n\n".format(sent, sent.doc.get('name',sent.doc.description))
255
+ outstr += "\n[POS] {0} tags\n".format(len(sent.POS))
256
+ outstr += "\n[POS_tagset] {0}\n\n".format(sent.POS_tagset)
257
+ outstr += "[text] + [annotationSet]\n\n"
258
+ outstr += sent._ascii() # -> _annotation_ascii()
259
+ outstr += "\n"
260
+ return outstr
261
+
262
+ def _pretty_pos(aset):
263
+ """
264
+ Helper function for pretty-printing a sentence with its POS tags.
265
+
266
+ :param aset: The POS annotation set of the sentence to be printed.
267
+ :type sent: list(AttrDict)
268
+ :return: The text of the sentence and its POS tags.
269
+ :rtype: str
270
+ """
271
+
272
+ outstr = ""
273
+ outstr += "POS annotation set ({0.ID}) {0.POS_tagset} in sentence {0.sent.ID}:\n\n".format(aset)
274
+
275
+ # list the target spans and their associated aset index
276
+ overt = sorted(aset.POS)
277
+
278
+ sent = aset.sent
279
+ s0 = sent.text
280
+ s1 = ''
281
+ s2 = ''
282
+ i = 0
283
+ adjust = 0
284
+ for j,k,lbl in overt:
285
+ assert j>=i,('Overlapping targets?',(j,k,lbl))
286
+ s1 += ' '*(j-i) + '-'*(k-j)
287
+ if len(lbl)>(k-j):
288
+ # add space in the sentence to make room for the annotation index
289
+ amt = len(lbl)-(k-j)
290
+ s0 = s0[:k+adjust]+ '~'*amt + s0[k+adjust:] # '~' to prevent line wrapping
291
+ s1 = s1[:k+adjust]+ ' '*amt + s1[k+adjust:]
292
+ adjust += amt
293
+ s2 += ' '*(j-i) + lbl.ljust(k-j)
294
+ i = k
295
+
296
+ long_lines = [s0, s1, s2]
297
+
298
+ outstr += '\n\n'.join(map('\n'.join, zip_longest(*mimic_wrap(long_lines), fillvalue=' '))).replace('~',' ')
299
+ outstr += "\n"
300
+ return outstr
301
+
302
+ def _pretty_annotation(sent, aset_level=False):
303
+ """
304
+ Helper function for pretty-printing an exemplar sentence for a lexical unit.
305
+
306
+ :param sent: An annotation set or exemplar sentence to be printed.
307
+ :param aset_level: If True, 'sent' is actually an annotation set within a sentence.
308
+ :type sent: AttrDict
309
+ :return: A nicely formated string representation of the exemplar sentence
310
+ with its target, frame, and FE annotations.
311
+ :rtype: str
312
+ """
313
+
314
+ sentkeys = sent.keys()
315
+ outstr = "annotation set" if aset_level else "exemplar sentence"
316
+ outstr += " ({0.ID}):\n".format(sent)
317
+ if aset_level: # TODO: any UNANN exemplars?
318
+ outstr += "\n[status] {0}\n".format(sent.status)
319
+ for k in ('corpID', 'docID', 'paragNo', 'sentNo', 'aPos'):
320
+ if k in sentkeys:
321
+ outstr += "[{0}] {1}\n".format(k, sent[k])
322
+ outstr += "\n[LU] ({0.ID}) {0.name} in {0.frame.name}\n".format(sent.LU) if sent.LU else '\n[LU] Not found!'
323
+ outstr += "\n[frame] ({0.ID}) {0.name}\n".format(sent.frame) # redundant with above, but .frame is convenient
324
+ if not aset_level:
325
+ outstr += "\n[annotationSet] {0} annotation sets\n".format(len(sent.annotationSet))
326
+ outstr += "\n[POS] {0} tags\n".format(len(sent.POS))
327
+ outstr += "\n[POS_tagset] {0}\n".format(sent.POS_tagset)
328
+ outstr += "\n[GF] {0} relation{1}\n".format(len(sent.GF), "s" if len(sent.GF)!=1 else "")
329
+ outstr += "\n[PT] {0} phrase{1}\n".format(len(sent.PT), "s" if len(sent.PT)!=1 else "")
330
+ """
331
+ Special Layers
332
+ --------------
333
+
334
+ The 'NER' layer contains, for some of the data, named entity labels.
335
+
336
+ The 'WSL' (word status layer) contains, for some of the data,
337
+ spans which should not in principle be considered targets (NT).
338
+
339
+ The 'Other' layer records relative clause constructions (Rel=relativizer, Ant=antecedent),
340
+ pleonastic 'it' (Null), and existential 'there' (Exist).
341
+ On occasion they are duplicated by accident (e.g., annotationSet 1467275 in lu6700.xml).
342
+
343
+ The 'Sent' layer appears to contain labels that the annotator has flagged the
344
+ sentence with for their convenience: values include
345
+ 'sense1', 'sense2', 'sense3', etc.;
346
+ 'Blend', 'Canonical', 'Idiom', 'Metaphor', 'Special-Sent',
347
+ 'keepS', 'deleteS', 'reexamine'
348
+ (sometimes they are duplicated for no apparent reason).
349
+
350
+ The POS-specific layers may contain the following kinds of spans:
351
+ Asp (aspectual particle), Non-Asp (non-aspectual particle),
352
+ Cop (copula), Supp (support), Ctrlr (controller),
353
+ Gov (governor), X. Gov and X always cooccur.
354
+
355
+ >>> from nltk.corpus import framenet as fn
356
+ >>> def f(luRE, lyr, ignore=set()):
357
+ ... for i,ex in enumerate(fn.exemplars(luRE)):
358
+ ... if lyr in ex and ex[lyr] and set(zip(*ex[lyr])[2]) - ignore:
359
+ ... print(i,ex[lyr])
360
+
361
+ - Verb: Asp, Non-Asp
362
+ - Noun: Cop, Supp, Ctrlr, Gov, X
363
+ - Adj: Cop, Supp, Ctrlr, Gov, X
364
+ - Prep: Cop, Supp, Ctrlr
365
+ - Adv: Ctrlr
366
+ - Scon: (none)
367
+ - Art: (none)
368
+ """
369
+ for lyr in ('NER', 'WSL', 'Other', 'Sent'):
370
+ if lyr in sent and sent[lyr]:
371
+ outstr += "\n[{0}] {1} entr{2}\n".format(lyr, len(sent[lyr]), "ies" if len(sent[lyr])!=1 else "y")
372
+ outstr += "\n[text] + [Target] + [FE]"
373
+ # POS-specific layers: syntactically important words that are neither the target
374
+ # nor the FEs. Include these along with the first FE layer but with '^' underlining.
375
+ for lyr in ('Verb', 'Noun', 'Adj', 'Adv', 'Prep', 'Scon', 'Art'):
376
+ if lyr in sent and sent[lyr]:
377
+ outstr += " + [{0}]".format(lyr)
378
+ if 'FE2' in sentkeys:
379
+ outstr += " + [FE2]"
380
+ if 'FE3' in sentkeys:
381
+ outstr += " + [FE3]"
382
+ outstr += "\n\n"
383
+ outstr += sent._ascii() # -> _annotation_ascii()
384
+ outstr += "\n"
385
+
386
+ return outstr
387
+
388
+ def _annotation_ascii(sent):
389
+ '''
390
+ Given a sentence or FE annotation set, construct the width-limited string showing
391
+ an ASCII visualization of the sentence's annotations, calling either
392
+ _annotation_ascii_frames() or _annotation_ascii_FEs() as appropriate.
393
+ This will be attached as a method to appropriate AttrDict instances
394
+ and called in the full pretty-printing of the instance.
395
+ '''
396
+ if sent._type=='fulltext_sentence' or ('annotationSet' in sent and len(sent.annotationSet)>2):
397
+ # a full-text sentence OR sentence with multiple targets.
398
+ # (multiple targets = >2 annotation sets, because the first annotation set is POS.)
399
+ return _annotation_ascii_frames(sent)
400
+ else: # an FE annotation set, or an LU sentence with 1 target
401
+ return _annotation_ascii_FEs(sent)
402
+
403
+ def _annotation_ascii_frames(sent):
404
+ '''
405
+ ASCII string rendering of the sentence along with its targets and frame names.
406
+ Called for all full-text sentences, as well as the few LU sentences with multiple
407
+ targets (e.g., fn.lu(6412).exemplars[82] has two want.v targets).
408
+ Line-wrapped to limit the display width.
409
+ '''
410
+ # list the target spans and their associated aset index
411
+ overt = []
412
+ for a,aset in enumerate(sent.annotationSet[1:]):
413
+ for j,k in aset.Target:
414
+ indexS = "[{0}]".format(a+1)
415
+ if aset.status=='UNANN' or aset.LU.status=='Problem':
416
+ indexS += " "
417
+ if aset.status=='UNANN':
418
+ indexS += "!" # warning indicator that there is a frame annotation but no FE annotation
419
+ if aset.LU.status=='Problem':
420
+ indexS += "?" # warning indicator that there is a missing LU definition (because the LU has Problem status)
421
+ overt.append((j,k,aset.LU.frame.name,indexS))
422
+ overt = sorted(overt)
423
+
424
+ duplicates = set()
425
+ for o,(j,k,fname,asetIndex) in enumerate(overt):
426
+ if o>0 and j<=overt[o-1][1]:
427
+ # multiple annotation sets on the same target
428
+ # (e.g. due to a coordination construction or multiple annotators)
429
+ if overt[o-1][:2]==(j,k) and overt[o-1][2]==fname: # same target, same frame
430
+ # splice indices together
431
+ combinedIndex = overt[o-1][3] + asetIndex # e.g., '[1][2]', '[1]! [2]'
432
+ combinedIndex = combinedIndex.replace(' !', '! ').replace(' ?', '? ')
433
+ overt[o-1] = overt[o-1][:3]+(combinedIndex,)
434
+ duplicates.add(o)
435
+ else: # different frames, same or overlapping targets
436
+ s = sent.text
437
+ for j,k,fname,asetIndex in overt:
438
+ s += '\n' + asetIndex + ' ' + sent.text[j:k] + ' :: ' + fname
439
+ s += '\n(Unable to display sentence with targets marked inline due to overlap)'
440
+ return s
441
+ for o in reversed(sorted(duplicates)):
442
+ del overt[o]
443
+
444
+ s0 = sent.text
445
+ s1 = ''
446
+ s11 = ''
447
+ s2 = ''
448
+ i = 0
449
+ adjust = 0
450
+ fAbbrevs = OrderedDict()
451
+ for j,k,fname,asetIndex in overt:
452
+ if not j>=i:
453
+ assert j>=i,('Overlapping targets?'+(' UNANN' if any(aset.status=='UNANN' for aset in sent.annotationSet[1:]) else ''),(j,k,asetIndex))
454
+ s1 += ' '*(j-i) + '*'*(k-j)
455
+ short = fname[:k-j]
456
+ if (k-j)<len(fname):
457
+ r = 0
458
+ while short in fAbbrevs:
459
+ if fAbbrevs[short]==fname:
460
+ break
461
+ r += 1
462
+ short = fname[:k-j-1] + str(r)
463
+ else: # short not in fAbbrevs
464
+ fAbbrevs[short] = fname
465
+ s11 += ' '*(j-i) + short.ljust(k-j)
466
+ if len(asetIndex)>(k-j):
467
+ # add space in the sentence to make room for the annotation index
468
+ amt = len(asetIndex)-(k-j)
469
+ s0 = s0[:k+adjust]+ '~'*amt + s0[k+adjust:] # '~' to prevent line wrapping
470
+ s1 = s1[:k+adjust]+ ' '*amt + s1[k+adjust:]
471
+ s11 = s11[:k+adjust]+ ' '*amt + s11[k+adjust:]
472
+ adjust += amt
473
+ s2 += ' '*(j-i) + asetIndex.ljust(k-j)
474
+ i = k
475
+
476
+ long_lines = [s0, s1, s11, s2]
477
+
478
+ outstr = '\n\n'.join(map('\n'.join, zip_longest(*mimic_wrap(long_lines), fillvalue=' '))).replace('~',' ')
479
+ outstr += '\n'
480
+ if fAbbrevs:
481
+ outstr += ' ('+', '.join('='.join(pair) for pair in fAbbrevs.items())+')'
482
+ assert len(fAbbrevs)==len(dict(fAbbrevs)),'Abbreviation clash'
483
+
484
+ return outstr
485
+
486
+ def _annotation_ascii_FE_layer(overt, ni, feAbbrevs):
487
+ '''Helper for _annotation_ascii_FEs().'''
488
+ s1 = ''
489
+ s2 = ''
490
+ i = 0
491
+ for j,k,fename in overt:
492
+ s1 += ' '*(j-i) + ('^' if fename.islower() else '-')*(k-j)
493
+ short = fename[:k-j]
494
+ if len(fename)>len(short):
495
+ r = 0
496
+ while short in feAbbrevs:
497
+ if feAbbrevs[short]==fename:
498
+ break
499
+ r += 1
500
+ short = fename[:k-j-1] + str(r)
501
+ else: # short not in feAbbrevs
502
+ feAbbrevs[short] = fename
503
+ s2 += ' '*(j-i) + short.ljust(k-j)
504
+ i = k
505
+
506
+ sNI = ''
507
+ if ni:
508
+ sNI += ' ['+', '.join(':'.join(x) for x in sorted(ni.items()))+']'
509
+ return [s1,s2,sNI]
510
+
511
+ def _annotation_ascii_FEs(sent):
512
+ '''
513
+ ASCII string rendering of the sentence along with a single target and its FEs.
514
+ Secondary and tertiary FE layers are included if present.
515
+ 'sent' can be an FE annotation set or an LU sentence with a single target.
516
+ Line-wrapped to limit the display width.
517
+ '''
518
+ feAbbrevs = OrderedDict()
519
+ posspec = [] # POS-specific layer spans (e.g., Supp[ort], Cop[ula])
520
+ posspec_separate = False
521
+ for lyr in ('Verb', 'Noun', 'Adj', 'Adv', 'Prep', 'Scon', 'Art'):
522
+ if lyr in sent and sent[lyr]:
523
+ for a,b,lbl in sent[lyr]:
524
+ if lbl=='X': # skip this, which covers an entire phrase typically containing the target and all its FEs
525
+ # (but do display the Gov)
526
+ continue
527
+ if any(1 for x,y,felbl in sent.FE[0] if x<=a<y or a<=x<b):
528
+ # overlap between one of the POS-specific layers and first FE layer
529
+ posspec_separate = True # show POS-specific layers on a separate line
530
+ posspec.append((a,b,lbl.lower().replace('-',''))) # lowercase Cop=>cop, Non-Asp=>nonasp, etc. to distinguish from FE names
531
+ if posspec_separate:
532
+ POSSPEC = _annotation_ascii_FE_layer(posspec, {}, feAbbrevs)
533
+ FE1 = _annotation_ascii_FE_layer(sorted(sent.FE[0] + (posspec if not posspec_separate else [])), sent.FE[1], feAbbrevs)
534
+ FE2 = FE3 = None
535
+ if 'FE2' in sent:
536
+ FE2 = _annotation_ascii_FE_layer(sent.FE2[0], sent.FE2[1], feAbbrevs)
537
+ if 'FE3' in sent:
538
+ FE3 = _annotation_ascii_FE_layer(sent.FE3[0], sent.FE3[1], feAbbrevs)
539
+
540
+ for i,j in sent.Target:
541
+ FE1span, FE1name, FE1exp = FE1
542
+ if len(FE1span)<j:
543
+ FE1span += ' '*(j-len(FE1span))
544
+ if len(FE1name)<j:
545
+ FE1name += ' '*(j-len(FE1name))
546
+ FE1[1] = FE1name
547
+ FE1[0] = FE1span[:i] + FE1span[i:j].replace(' ','*').replace('-','=') + FE1span[j:]
548
+ long_lines = [sent.text]
549
+ if posspec_separate:
550
+ long_lines.extend(POSSPEC[:2])
551
+ long_lines.extend([FE1[0], FE1[1]+FE1[2]]) # lines with no length limit
552
+ if FE2:
553
+ long_lines.extend([FE2[0], FE2[1]+FE2[2]])
554
+ if FE3:
555
+ long_lines.extend([FE3[0], FE3[1]+FE3[2]])
556
+ long_lines.append('')
557
+ outstr = '\n'.join(map('\n'.join, zip_longest(*mimic_wrap(long_lines), fillvalue=' ')))
558
+ if feAbbrevs:
559
+ outstr += '('+', '.join('='.join(pair) for pair in feAbbrevs.items())+')'
560
+ assert len(feAbbrevs)==len(dict(feAbbrevs)),'Abbreviation clash'
561
+ outstr += "\n"
171
562
 
172
563
  return outstr
173
564
 
@@ -225,6 +616,7 @@ def _pretty_frame(frame):
225
616
 
226
617
  outstr = ""
227
618
  outstr += "frame ({0.ID}): {0.name}\n\n".format(frame)
619
+ outstr += "[URL] {0}\n\n".format(frame.URL)
228
620
  outstr += "[definition]\n"
229
621
  outstr += _pretty_longstring(frame.definition, ' ') + '\n'
230
622
 
@@ -301,8 +693,11 @@ class AttrDict(dict):
301
693
  return self.__repr__()
302
694
  try:
303
695
  return "<{0} ID={1} name={2}>".format(self['_type'], self['ID'], self['name'])
304
- except KeyError: # no ID--e.g., for _type=lusubcorpus
305
- return "<{0} name={1}>".format(self['_type'], self['name'])
696
+ except KeyError:
697
+ try: # no ID--e.g., for _type=lusubcorpus
698
+ return "<{0} name={1}>".format(self['_type'], self['name'])
699
+ except KeyError: # no name--e.g., for _type=lusentence
700
+ return "<{0} ID={1}>".format(self['_type'], self['ID'])
306
701
  else:
307
702
  return self.__repr__()
308
703
 
@@ -317,6 +712,18 @@ class AttrDict(dict):
317
712
  outstr = _pretty_fe(self)
318
713
  elif self['_type'] == 'lu':
319
714
  outstr = _pretty_lu(self)
715
+ elif self['_type'] == 'luexemplars': # list of ALL exemplars for LU
716
+ outstr = _pretty_exemplars(self, self[0].LU)
717
+ elif self['_type'] == 'fulltext_annotation': # list of all sentences for full-text doc
718
+ outstr = _pretty_fulltext_sentences(self)
719
+ elif self['_type'] == 'lusentence':
720
+ outstr = _pretty_annotation(self)
721
+ elif self['_type'] == 'fulltext_sentence':
722
+ outstr = _pretty_fulltext_sentence(self)
723
+ elif self['_type'] in ('luannotationset', 'fulltext_annotationset'):
724
+ outstr = _pretty_annotation(self, aset_level=True)
725
+ elif self['_type'] == 'posannotationset':
726
+ outstr = _pretty_pos(self)
320
727
  elif self['_type'] == 'semtype':
321
728
  outstr = _pretty_semtype(self)
322
729
  elif self['_type'] == 'framerelationtype':
@@ -340,6 +747,33 @@ class AttrDict(dict):
340
747
  def __repr__(self):
341
748
  return self.__str__()
342
749
 
750
+ @python_2_unicode_compatible
751
+ class SpecialList(list):
752
+ """
753
+ A list subclass which adds a '_type' attribute for special printing
754
+ (similar to an AttrDict, though this is NOT an AttrDict subclass).
755
+ """
756
+ def __init__(self, typ, *args, **kwargs):
757
+ super(SpecialList,self).__init__(*args, **kwargs)
758
+ self._type = typ
759
+
760
+ def _str(self):
761
+ outstr = ""
762
+
763
+ assert self._type
764
+ if len(self)==0:
765
+ outstr = "[]"
766
+ elif self._type == 'luexemplars': # list of ALL exemplars for LU
767
+ outstr = _pretty_exemplars(self, self[0].LU)
768
+ else:
769
+ assert False,self._type
770
+ return outstr
771
+
772
+ def __str__(self):
773
+ return self._str()
774
+ def __repr__(self):
775
+ return self.__str__()
776
+
343
777
  class Future(object):
344
778
  """
345
779
  Wraps and acts as a proxy for a value to be loaded lazily (on demand).
@@ -376,7 +810,6 @@ class Future(object):
376
810
  def __repr__(self):
377
811
  return self._data().__repr__()
378
812
 
379
-
380
813
  @python_2_unicode_compatible
381
814
  class PrettyDict(AttrDict):
382
815
  """
@@ -445,8 +878,60 @@ class PrettyLazyMap(LazyMap):
445
878
  length += len(pieces[-1]) + 2
446
879
  if length > self._MAX_REPR_SIZE and len(pieces) > 2:
447
880
  return "[%s, ...]" % text_type(', ').join(pieces[:-1])
448
- else:
449
- return "[%s]" % text_type(', ').join(pieces)
881
+ return "[%s]" % text_type(', ').join(pieces)
882
+
883
+ @python_2_unicode_compatible
884
+ class PrettyLazyIteratorList(LazyIteratorList):
885
+ """
886
+ Displays an abbreviated repr of only the first several elements, not the whole list.
887
+ """
888
+ # from nltk.util
889
+ _MAX_REPR_SIZE = 60
890
+ def __repr__(self):
891
+ """
892
+ Return a string representation for this corpus view that is
893
+ similar to a list's representation; but if it would be more
894
+ than 60 characters long, it is truncated.
895
+ """
896
+ pieces = []
897
+ length = 5
898
+ for elt in self:
899
+ pieces.append(elt._short_repr()) # key difference from inherited version: call to _short_repr()
900
+ length += len(pieces[-1]) + 2
901
+ if length > self._MAX_REPR_SIZE and len(pieces) > 2:
902
+ return "[%s, ...]" % text_type(', ').join(pieces[:-1])
903
+ return "[%s]" % text_type(', ').join(pieces)
904
+
905
+ @python_2_unicode_compatible
906
+ class PrettyLazyConcatenation(LazyConcatenation):
907
+ """
908
+ Displays an abbreviated repr of only the first several elements, not the whole list.
909
+ """
910
+ # from nltk.util
911
+ _MAX_REPR_SIZE = 60
912
+ def __repr__(self):
913
+ """
914
+ Return a string representation for this corpus view that is
915
+ similar to a list's representation; but if it would be more
916
+ than 60 characters long, it is truncated.
917
+ """
918
+ pieces = []
919
+ length = 5
920
+ for elt in self:
921
+ pieces.append(elt._short_repr()) # key difference from inherited version: call to _short_repr()
922
+ length += len(pieces[-1]) + 2
923
+ if length > self._MAX_REPR_SIZE and len(pieces) > 2:
924
+ return "[%s, ...]" % text_type(', ').join(pieces[:-1])
925
+ return "[%s]" % text_type(', ').join(pieces)
926
+
927
+ def __add__(self, other):
928
+ """Return a list concatenating self with other."""
929
+ return PrettyLazyIteratorList(itertools.chain(self, other))
930
+
931
+ def __radd__(self, other):
932
+ """Return a list concatenating other with self."""
933
+ return PrettyLazyIteratorList(itertools.chain(other, self))
934
+
450
935
 
451
936
  class FramenetCorpusReader(XMLCorpusReader):
452
937
  """A corpus reader for the Framenet Corpus.
@@ -468,6 +953,17 @@ class FramenetCorpusReader(XMLCorpusReader):
468
953
  in the XML index.
469
954
  """
470
955
 
956
+ _warnings = False
957
+
958
+ def warnings(self, v):
959
+ """Enable or disable warnings of data integrity issues as they are encountered.
960
+ If v is truthy, warnings will be enabled.
961
+
962
+ (This is a function rather than just an attribute/property to ensure that if
963
+ enabling warnings is the first action taken, the corpus reader is instantiated first.)
964
+ """
965
+ self._warnings = v
966
+
471
967
  def __init__(self, root, fileids):
472
968
  XMLCorpusReader.__init__(self, root, fileids)
473
969
 
@@ -479,6 +975,9 @@ class FramenetCorpusReader(XMLCorpusReader):
479
975
  # sub dir containing the xml files for fulltext annotation files
480
976
  self._fulltext_dir = "fulltext"
481
977
 
978
+ # location of latest development version of FrameNet
979
+ self._fnweb_url = "https://framenet2.icsi.berkeley.edu/fnReports/data"
980
+
482
981
  # Indexes used for faster look-ups
483
982
  self._frame_idx = None
484
983
  self._cached_frames = {} # name -> ID
@@ -490,6 +989,91 @@ class FramenetCorpusReader(XMLCorpusReader):
490
989
  self._ferel_idx = None # FE-to-FE relation instances
491
990
  self._frel_f_idx = None # frame-to-frame relations associated with each frame
492
991
 
992
+ def help(self, attrname=None):
993
+ """Display help information summarizing the main methods."""
994
+
995
+ if attrname is not None:
996
+ return help(self.__getattribute__(attrname))
997
+
998
+ # No need to mention frame_by_name() or frame_by_id(),
999
+ # as it's easier to just call frame().
1000
+ # Also not mentioning lu_basic().
1001
+
1002
+
1003
+ msg = """
1004
+ Citation: Nathan Schneider and Chuck Wooters (2017),
1005
+ "The NLTK FrameNet API: Designing for Discoverability with a Rich Linguistic Resource".
1006
+ Proceedings of EMNLP: System Demonstrations. https://arxiv.org/abs/1703.07438
1007
+
1008
+ Use the following methods to access data in FrameNet.
1009
+ Provide a method name to `help()` for more information.
1010
+
1011
+ FRAMES
1012
+ ======
1013
+
1014
+ frame() to look up a frame by its exact name or ID
1015
+ frames() to get frames matching a name pattern
1016
+ frames_by_lemma() to get frames containing an LU matching a name pattern
1017
+ frame_ids_and_names() to get a mapping from frame IDs to names
1018
+
1019
+ FRAME ELEMENTS
1020
+ ==============
1021
+
1022
+ fes() to get frame elements (a.k.a. roles) matching a name pattern, optionally constrained
1023
+ by a frame name pattern
1024
+
1025
+ LEXICAL UNITS
1026
+ =============
1027
+
1028
+ lu() to look up an LU by its ID
1029
+ lus() to get lexical units matching a name pattern, optionally constrained by frame
1030
+ lu_ids_and_names() to get a mapping from LU IDs to names
1031
+
1032
+ RELATIONS
1033
+ =========
1034
+
1035
+ frame_relation_types() to get the different kinds of frame-to-frame relations
1036
+ (Inheritance, Subframe, Using, etc.).
1037
+ frame_relations() to get the relation instances, optionally constrained by
1038
+ frame(s) or relation type
1039
+ fe_relations() to get the frame element pairs belonging to a frame-to-frame relation
1040
+
1041
+ SEMANTIC TYPES
1042
+ ==============
1043
+
1044
+ semtypes() to get the different kinds of semantic types that can be applied to
1045
+ FEs, LUs, and entire frames
1046
+ semtype() to look up a particular semtype by name, ID, or abbreviation
1047
+ semtype_inherits() to check whether two semantic types have a subtype-supertype
1048
+ relationship in the semtype hierarchy
1049
+ propagate_semtypes() to apply inference rules that distribute semtypes over relations
1050
+ between FEs
1051
+
1052
+ ANNOTATIONS
1053
+ ===========
1054
+
1055
+ annotations() to get annotation sets, in which a token in a sentence is annotated
1056
+ with a lexical unit in a frame, along with its frame elements and their syntactic properties;
1057
+ can be constrained by LU name pattern and limited to lexicographic exemplars or full-text.
1058
+ Sentences of full-text annotation can have multiple annotation sets.
1059
+ sents() to get annotated sentences illustrating one or more lexical units
1060
+ exemplars() to get sentences of lexicographic annotation, most of which have
1061
+ just 1 annotation set; can be constrained by LU name pattern, frame, and overt FE(s)
1062
+ doc() to look up a document of full-text annotation by its ID
1063
+ docs() to get documents of full-text annotation that match a name pattern
1064
+ docs_metadata() to get metadata about all full-text documents without loading them
1065
+ ft_sents() to iterate over sentences of full-text annotation
1066
+
1067
+ UTILITIES
1068
+ =========
1069
+
1070
+ buildindexes() loads metadata about all frames, LUs, etc. into memory to avoid
1071
+ delay when one is accessed for the first time. It does not load annotations.
1072
+ readme() gives the text of the FrameNet README file
1073
+ warnings(True) to display corpus consistency warnings when loading data
1074
+ """
1075
+ print(msg)
1076
+
493
1077
  def _buildframeindex(self):
494
1078
  # The total number of Frames in Framenet is fairly small (~1200) so
495
1079
  # this index should not be very large
@@ -546,6 +1130,11 @@ class FramenetCorpusReader(XMLCorpusReader):
546
1130
  self._ferel_idx[ferel.ID] = ferel
547
1131
  #print('...done building relation index', file=sys.stderr)
548
1132
 
1133
+ def _warn(self, *message, **kwargs):
1134
+ if self._warnings:
1135
+ kwargs.setdefault('file', sys.stderr)
1136
+ print(*message, **kwargs)
1137
+
549
1138
  def readme(self):
550
1139
  """
551
1140
  Return the contents of the corpus README.txt (or README) file.
@@ -568,7 +1157,7 @@ class FramenetCorpusReader(XMLCorpusReader):
568
1157
  # frame and FE relations
569
1158
  self._buildrelationindex()
570
1159
 
571
- def annotated_document(self, fn_docid):
1160
+ def doc(self, fn_docid):
572
1161
  """
573
1162
  Returns the annotated document whose id number is
574
1163
  ``fn_docid``. This id number can be obtained by calling the
@@ -630,7 +1219,11 @@ class FramenetCorpusReader(XMLCorpusReader):
630
1219
 
631
1220
  # Grab the top-level xml element containing the fulltext annotation
632
1221
  elt = XMLCorpusView(locpath, 'fullTextAnnotation')[0]
633
- return self._handle_fulltextannotation_elt(elt)
1222
+ info = self._handle_fulltextannotation_elt(elt)
1223
+ # add metadata
1224
+ for k,v in self._fulltext_idx[fn_docid].items():
1225
+ info[k] = v
1226
+ return info
634
1227
 
635
1228
  def frame_by_id(self, fn_fid, ignorekeys=[]):
636
1229
  """
@@ -719,11 +1312,13 @@ class FramenetCorpusReader(XMLCorpusReader):
719
1312
  fentry = self._handle_frame_elt(elt, ignorekeys)
720
1313
  assert fentry
721
1314
 
1315
+ fentry.URL = self._fnweb_url + '/' + self._frame_dir + '/' + fn_fname + '.xml'
1316
+
722
1317
  # INFERENCE RULE: propagate lexical semtypes from the frame to all its LUs
723
1318
  for st in fentry.semTypes:
724
1319
  if st.rootType.name=='Lexical_type':
725
1320
  for lu in fentry.lexUnit.values():
726
- if st not in lu.semTypes:
1321
+ if not any(x is st for x in lu.semTypes): # identity containment check
727
1322
  lu.semTypes.append(st)
728
1323
 
729
1324
 
@@ -827,8 +1422,9 @@ class FramenetCorpusReader(XMLCorpusReader):
827
1422
  search through ALL of the frame XML files in the db.
828
1423
 
829
1424
  >>> from nltk.corpus import framenet as fn
830
- >>> fn.frames_by_lemma(r'(?i)a little')
831
- [<frame ID=189 name=Quantity>, <frame ID=2001 name=Degree>]
1425
+ >>> from nltk.corpus.reader.framenet import PrettyList
1426
+ >>> PrettyList(sorted(fn.frames_by_lemma(r'(?i)a little'), key=itemgetter('ID'))) # doctest: +ELLIPSIS
1427
+ [<frame ID=189 name=Quanti...>, <frame ID=2001 name=Degree>]
832
1428
 
833
1429
  :return: A list of frame objects.
834
1430
  :rtype: list(AttrDict)
@@ -842,17 +1438,23 @@ class FramenetCorpusReader(XMLCorpusReader):
842
1438
  ``lu()`` function with "subCorpus" info excluded.
843
1439
 
844
1440
  >>> from nltk.corpus import framenet as fn
845
- >>> PrettyDict(fn.lu_basic(256), breakLines=True)
1441
+ >>> lu = PrettyDict(fn.lu_basic(256), breakLines=True)
1442
+ >>> # ellipses account for differences between FN 1.5 and 1.7
1443
+ >>> lu # doctest: +ELLIPSIS
846
1444
  {'ID': 256,
847
1445
  'POS': 'V',
1446
+ 'URL': u'https://framenet2.icsi.berkeley.edu/fnReports/data/lu/lu256.xml',
848
1447
  '_type': 'lu',
1448
+ 'cBy': ...,
1449
+ 'cDate': '02/08/2001 01:27:50 PST Thu',
849
1450
  'definition': 'COD: be aware of beforehand; predict.',
1451
+ 'definitionMarkup': 'COD: be aware of beforehand; predict.',
850
1452
  'frame': <frame ID=26 name=Expectation>,
851
1453
  'lemmaID': 15082,
852
1454
  'lexemes': [{'POS': 'V', 'breakBefore': 'false', 'headword': 'false', 'name': 'foresee', 'order': 1}],
853
1455
  'name': 'foresee.v',
854
1456
  'semTypes': [],
855
- 'sentenceCount': {'annotated': 44, 'total': 227},
1457
+ 'sentenceCount': {'annotated': ..., 'total': ...},
856
1458
  'status': 'FN1_Sent'}
857
1459
 
858
1460
  :param fn_luid: The id number of the desired LU
@@ -860,15 +1462,15 @@ class FramenetCorpusReader(XMLCorpusReader):
860
1462
  :return: Basic information about the lexical unit
861
1463
  :rtype: dict
862
1464
  """
863
- return self.lu(fn_luid, ignorekeys=['subCorpus'])
1465
+ return self.lu(fn_luid, ignorekeys=['subCorpus', 'exemplars'])
864
1466
 
865
- def lu(self, fn_luid, ignorekeys=[]):
1467
+ def lu(self, fn_luid, ignorekeys=[], luName=None, frameID=None, frameName=None):
866
1468
  """
867
- Get information about a specific Lexical Unit using the id number
868
- ``fn_luid``. This function reads the LU information from the xml
869
- file on disk each time it is called. You may want to cache this
870
- info if you plan to call this function with the same id number
871
- multiple times.
1469
+ Access a lexical unit by its ID. luName, frameID, and frameName are used
1470
+ only in the event that the LU does not have a file in the database
1471
+ (which is the case for LUs with "Problem" status); in this case,
1472
+ a placeholder LU is created which just contains its name, ID, and frame.
1473
+
872
1474
 
873
1475
  Usage examples:
874
1476
 
@@ -882,6 +1484,40 @@ class FramenetCorpusReader(XMLCorpusReader):
882
1484
  >>> pprint(list(map(PrettyDict, fn.lu(256).lexemes)))
883
1485
  [{'POS': 'V', 'breakBefore': 'false', 'headword': 'false', 'name': 'foresee', 'order': 1}]
884
1486
 
1487
+ >>> fn.lu(227).exemplars[23]
1488
+ exemplar sentence (352962):
1489
+ [sentNo] 0
1490
+ [aPos] 59699508
1491
+ <BLANKLINE>
1492
+ [LU] (227) guess.v in Coming_to_believe
1493
+ <BLANKLINE>
1494
+ [frame] (23) Coming_to_believe
1495
+ <BLANKLINE>
1496
+ [annotationSet] 2 annotation sets
1497
+ <BLANKLINE>
1498
+ [POS] 18 tags
1499
+ <BLANKLINE>
1500
+ [POS_tagset] BNC
1501
+ <BLANKLINE>
1502
+ [GF] 3 relations
1503
+ <BLANKLINE>
1504
+ [PT] 3 phrases
1505
+ <BLANKLINE>
1506
+ [Other] 1 entry
1507
+ <BLANKLINE>
1508
+ [text] + [Target] + [FE]
1509
+ <BLANKLINE>
1510
+ When he was inside the house , Culley noticed the characteristic
1511
+ ------------------
1512
+ Content
1513
+ <BLANKLINE>
1514
+ he would n't have guessed at .
1515
+ -- ******* --
1516
+ Co C1 [Evidence:INI]
1517
+ (Co=Cognizer, C1=Content)
1518
+ <BLANKLINE>
1519
+ <BLANKLINE>
1520
+
885
1521
  The dict that is returned from this function will contain most of the
886
1522
  following information about the LU. Note that some LUs do not contain
887
1523
  all of these pieces of information - particularly 'totalAnnotated' and
@@ -959,8 +1595,20 @@ class FramenetCorpusReader(XMLCorpusReader):
959
1595
  # look for this LU in cache
960
1596
  if not self._lu_idx:
961
1597
  self._buildluindex()
962
- luinfo = self._lu_idx[fn_luid]
963
- if '_type' not in luinfo:
1598
+ OOV = object()
1599
+ luinfo = self._lu_idx.get(fn_luid, OOV)
1600
+ if luinfo is OOV:
1601
+ # LU not in the index. We create a placeholder by falling back to
1602
+ # luName, frameID, and frameName. However, this will not be listed
1603
+ # among the LUs for its frame.
1604
+ self._warn('LU ID not found: {0} ({1}) in {2} ({3})'.format(luName, fn_luid, frameName, frameID))
1605
+ luinfo = AttrDict({'_type': 'lu', 'ID': fn_luid, 'name': luName,
1606
+ 'frameID': frameID, 'status': 'Problem'})
1607
+ f = self.frame_by_id(luinfo.frameID)
1608
+ assert f.name==frameName,(f.name,frameName)
1609
+ luinfo['frame'] = f
1610
+ self._lu_idx[fn_luid] = luinfo
1611
+ elif '_type' not in luinfo:
964
1612
  # we only have an index entry for the LU. loading the frame will replace this.
965
1613
  f = self.frame_by_id(luinfo.frameID)
966
1614
  luinfo = self._lu_idx[fn_luid]
@@ -988,9 +1636,18 @@ class FramenetCorpusReader(XMLCorpusReader):
988
1636
  raise FramenetError('Unknown LU id: {0}'.format(fn_luid))
989
1637
 
990
1638
  lu2 = self._handle_lexunit_elt(elt, ignorekeys)
1639
+ lu.URL = self._fnweb_url + '/' + self._lu_dir + '/' + fname
991
1640
  lu.subCorpus = lu2.subCorpus
1641
+ lu.exemplars = SpecialList('luexemplars',
1642
+ [sent for subc in lu.subCorpus for sent in subc.sentence])
1643
+ for sent in lu.exemplars:
1644
+ sent['LU'] = lu
1645
+ sent['frame'] = lu.frame
1646
+ for aset in sent.annotationSet:
1647
+ aset['LU'] = lu
1648
+ aset['frame'] = lu.frame
992
1649
 
993
- return lu.subCorpus
1650
+ return lu
994
1651
 
995
1652
  def _loadsemtypes(self):
996
1653
  """Create the semantic types index."""
@@ -1034,11 +1691,11 @@ class FramenetCorpusReader(XMLCorpusReader):
1034
1691
  to traverse the neighboring relations on demand for each FE semtype.)
1035
1692
 
1036
1693
  >>> from nltk.corpus import framenet as fn
1037
- >>> sum(1 for f in fn.frames() for fe in f.FE.values() if fe.semType)
1038
- 4241
1694
+ >>> x = sum(1 for f in fn.frames() for fe in f.FE.values() if fe.semType)
1039
1695
  >>> fn.propagate_semtypes()
1040
- >>> sum(1 for f in fn.frames() for fe in f.FE.values() if fe.semType)
1041
- 5252
1696
+ >>> y = sum(1 for f in fn.frames() for fe in f.FE.values() if fe.semType)
1697
+ >>> y-x > 1000
1698
+ True
1042
1699
  """
1043
1700
  if not self._semtypes:
1044
1701
  self._loadsemtypes()
@@ -1124,13 +1781,15 @@ class FramenetCorpusReader(XMLCorpusReader):
1124
1781
  Obtain details for a specific frame.
1125
1782
 
1126
1783
  >>> from nltk.corpus import framenet as fn
1127
- >>> len(fn.frames())
1128
- 1019
1129
- >>> PrettyList(fn.frames(r'(?i)medical'), maxReprSize=0, breakLines=True)
1130
- [<frame ID=256 name=Medical_specialties>,
1131
- <frame ID=257 name=Medical_instruments>,
1132
- <frame ID=255 name=Medical_professionals>,
1133
- <frame ID=239 name=Medical_conditions>]
1784
+ >>> len(fn.frames()) in (1019, 1221) # FN 1.5 and 1.7, resp.
1785
+ True
1786
+ >>> x = PrettyList(fn.frames(r'(?i)crim'), maxReprSize=0, breakLines=True)
1787
+ >>> x.sort(key=itemgetter('ID'))
1788
+ >>> x
1789
+ [<frame ID=200 name=Criminal_process>,
1790
+ <frame ID=500 name=Criminal_investigation>,
1791
+ <frame ID=692 name=Crime_scenario>,
1792
+ <frame ID=700 name=Committing_crime>]
1134
1793
 
1135
1794
  A brief intro to Frames (excerpted from "FrameNet II: Extended
1136
1795
  Theory and Practice" by Ruppenhofer et. al., 2010):
@@ -1198,28 +1857,33 @@ class FramenetCorpusReader(XMLCorpusReader):
1198
1857
  self._buildframeindex()
1199
1858
  return dict((fID, finfo.name) for fID,finfo in self._frame_idx.items() if name is None or re.search(name, finfo.name) is not None)
1200
1859
 
1201
- def fes(self, name=None):
1860
+ def fes(self, name=None, frame=None):
1202
1861
  '''
1203
- Lists frame element objects. If 'name' is provided, this is treated as
1204
- a case-insensitive regular expression to filter by frame name.
1205
- (Case-insensitivity is because casing of frame element names is not always
1206
- consistent across frames.)
1207
-
1862
+ Lists frame element objects. If 'name' is provided, this is treated as
1863
+ a case-insensitive regular expression to filter by frame name.
1864
+ (Case-insensitivity is because casing of frame element names is not always
1865
+ consistent across frames.) Specify 'frame' to filter by a frame name pattern,
1866
+ ID, or object.
1867
+
1208
1868
  >>> from nltk.corpus import framenet as fn
1209
1869
  >>> fn.fes('Noise_maker')
1210
1870
  [<fe ID=6043 name=Noise_maker>]
1211
1871
  >>> sorted([(fe.frame.name,fe.name) for fe in fn.fes('sound')])
1212
- [('Cause_to_make_noise', 'Sound_maker'), ('Make_noise', 'Sound'),
1213
- ('Make_noise', 'Sound_source'), ('Sound_movement', 'Location_of_sound_source'),
1214
- ('Sound_movement', 'Sound'), ('Sound_movement', 'Sound_source'),
1215
- ('Sounds', 'Component_sound'), ('Sounds', 'Location_of_sound_source'),
1216
- ('Sounds', 'Sound_source'), ('Vocalizations', 'Location_of_sound_source'),
1872
+ [('Cause_to_make_noise', 'Sound_maker'), ('Make_noise', 'Sound'),
1873
+ ('Make_noise', 'Sound_source'), ('Sound_movement', 'Location_of_sound_source'),
1874
+ ('Sound_movement', 'Sound'), ('Sound_movement', 'Sound_source'),
1875
+ ('Sounds', 'Component_sound'), ('Sounds', 'Location_of_sound_source'),
1876
+ ('Sounds', 'Sound_source'), ('Vocalizations', 'Location_of_sound_source'),
1217
1877
  ('Vocalizations', 'Sound_source')]
1878
+ >>> sorted([(fe.frame.name,fe.name) for fe in fn.fes('sound',r'(?i)make_noise')])
1879
+ [('Cause_to_make_noise', 'Sound_maker'),
1880
+ ('Make_noise', 'Sound'),
1881
+ ('Make_noise', 'Sound_source')]
1218
1882
  >>> sorted(set(fe.name for fe in fn.fes('^sound')))
1219
1883
  ['Sound', 'Sound_maker', 'Sound_source']
1220
1884
  >>> len(fn.fes('^sound$'))
1221
1885
  2
1222
-
1886
+
1223
1887
  :param name: A regular expression pattern used to match against
1224
1888
  frame element names. If 'name' is None, then a list of all
1225
1889
  frame elements will be returned.
@@ -1227,19 +1891,34 @@ class FramenetCorpusReader(XMLCorpusReader):
1227
1891
  :return: A list of matching frame elements
1228
1892
  :rtype: list(AttrDict)
1229
1893
  '''
1230
- return PrettyList(fe for f in self.frames() for fename,fe in f.FE.items() if name is None or re.search(name, fename, re.I))
1894
+ # what frames are we searching in?
1895
+ if frame is not None:
1896
+ if isinstance(frame, int):
1897
+ frames = [self.frame(frame)]
1898
+ elif isinstance(frame, string_types):
1899
+ frames = self.frames(frame)
1900
+ else:
1901
+ frames = [frame]
1902
+ else:
1903
+ frames = self.frames()
1231
1904
 
1232
- def lus(self, name=None):
1905
+ return PrettyList(fe for f in frames for fename,fe in f.FE.items() if name is None or re.search(name, fename, re.I))
1906
+
1907
+ def lus(self, name=None, frame=None):
1233
1908
  """
1234
- Obtain details for a specific lexical unit.
1909
+ Obtain details for lexical units.
1910
+ Optionally restrict by lexical unit name pattern, and/or to a certain frame
1911
+ or frames whose name matches a pattern.
1235
1912
 
1236
1913
  >>> from nltk.corpus import framenet as fn
1237
- >>> len(fn.lus())
1238
- 11829
1239
- >>> PrettyList(fn.lus(r'(?i)a little'), maxReprSize=0, breakLines=True)
1240
- [<lu ID=14744 name=a little bit.adv>,
1241
- <lu ID=14733 name=a little.n>,
1242
- <lu ID=14743 name=a little.adv>]
1914
+ >>> len(fn.lus()) in (11829, 13572) # FN 1.5 and 1.7, resp.
1915
+ True
1916
+ >>> PrettyList(sorted(fn.lus(r'(?i)a little'), key=itemgetter('ID')), maxReprSize=0, breakLines=True)
1917
+ [<lu ID=14733 name=a little.n>,
1918
+ <lu ID=14743 name=a little.adv>,
1919
+ <lu ID=14744 name=a little bit.adv>]
1920
+ >>> PrettyList(sorted(fn.lus(r'interest', r'(?i)stimulus'), key=itemgetter('ID')))
1921
+ [<lu ID=14894 name=interested.a>, <lu ID=14920 name=interesting.a>]
1243
1922
 
1244
1923
  A brief intro to Lexical Units (excerpted from "FrameNet II:
1245
1924
  Extended Theory and Practice" by Ruppenhofer et. al., 2010):
@@ -1324,21 +2003,39 @@ class FramenetCorpusReader(XMLCorpusReader):
1324
2003
  scon - subordinating conjunction
1325
2004
 
1326
2005
  :type name: str
2006
+ :type frame: str or int or frame
1327
2007
  :return: A list of selected (or all) lexical units
1328
2008
  :rtype: list of LU objects (dicts). See the lu() function for info
1329
2009
  about the specifics of LU objects.
1330
2010
 
1331
2011
  """
1332
- try:
1333
- luIDs = list(self._lu_idx.keys())
1334
- except AttributeError:
2012
+ if not self._lu_idx:
1335
2013
  self._buildluindex()
1336
- luIDs = list(self._lu_idx.keys())
1337
2014
 
1338
- if name is not None:
1339
- return PrettyList(self.lu(luID) for luID,luName in self.lu_ids_and_names(name).items())
1340
- else:
1341
- return PrettyLazyMap(self.lu, luIDs)
2015
+
2016
+
2017
+ if name is not None: # match LUs, then restrict by frame
2018
+ result = PrettyList(self.lu(luID) for luID,luName in self.lu_ids_and_names(name).items())
2019
+ if frame is not None:
2020
+ if isinstance(frame, int):
2021
+ frameIDs = {frame}
2022
+ elif isinstance(frame, string_types):
2023
+ frameIDs = {f.ID for f in self.frames(frame)}
2024
+ else:
2025
+ frameIDs = {frame.ID}
2026
+ result = PrettyList(lu for lu in result if lu.frame.ID in frameIDs)
2027
+ elif frame is not None: # all LUs in matching frames
2028
+ if isinstance(frame, int):
2029
+ frames = [self.frame(frame)]
2030
+ elif isinstance(frame, string_types):
2031
+ frames = self.frames(frame)
2032
+ else:
2033
+ frames = [frame]
2034
+ result = PrettyLazyIteratorList(iter(LazyConcatenation(list(f.lexUnit.values()) for f in frames)))
2035
+ else: # all LUs
2036
+ luIDs = [luID for luID,lu in self._lu_idx.items() if lu.status not in self._bad_statuses]
2037
+ result = PrettyLazyMap(self.lu, luIDs)
2038
+ return result
1342
2039
 
1343
2040
  def lu_ids_and_names(self, name=None):
1344
2041
  """
@@ -1347,20 +2044,22 @@ class FramenetCorpusReader(XMLCorpusReader):
1347
2044
  """
1348
2045
  if not self._lu_idx:
1349
2046
  self._buildluindex()
1350
- return dict((luID, luinfo.name) for luID,luinfo in self._lu_idx.items() if name is None or re.search(name, luinfo.name) is not None)
2047
+ return {luID: luinfo.name for luID,luinfo in self._lu_idx.items()
2048
+ if luinfo.status not in self._bad_statuses
2049
+ and (name is None or re.search(name, luinfo.name) is not None)}
1351
2050
 
1352
- def documents(self, name=None):
2051
+ def docs_metadata(self, name=None):
1353
2052
  """
1354
- Return a list of the annotated documents in Framenet.
2053
+ Return an index of the annotated documents in Framenet.
1355
2054
 
1356
2055
  Details for a specific annotated document can be obtained using this
1357
- class's annotated_document() function and pass it the value of the 'ID' field.
2056
+ class's doc() function and pass it the value of the 'ID' field.
1358
2057
 
1359
2058
  >>> from nltk.corpus import framenet as fn
1360
- >>> len(fn.documents())
1361
- 78
1362
- >>> set([x.corpname for x in fn.documents()])==set(['ANC', 'C-4', 'KBEval', \
1363
- 'LUCorpus-v0.3', 'Miscellaneous', 'NTI', 'PropBank', 'QA', 'SemAnno'])
2059
+ >>> len(fn.docs()) in (78, 107) # FN 1.5 and 1.7, resp.
2060
+ True
2061
+ >>> set([x.corpname for x in fn.docs_metadata()])>=set(['ANC', 'KBEval', \
2062
+ 'LUCorpus-v0.3', 'Miscellaneous', 'NTI', 'PropBank'])
1364
2063
  True
1365
2064
 
1366
2065
  :param name: A regular expression pattern used to search the
@@ -1394,16 +2093,162 @@ class FramenetCorpusReader(XMLCorpusReader):
1394
2093
  else:
1395
2094
  return PrettyList(x for x in ftlist if re.search(name, x['filename']) is not None)
1396
2095
 
2096
+ def docs(self, name=None):
2097
+ """
2098
+ Return a list of the annotated full-text documents in FrameNet,
2099
+ optionally filtered by a regex to be matched against the document name.
2100
+ """
2101
+ return PrettyLazyMap((lambda x: self.doc(x.ID)), self.docs_metadata(name))
2102
+
2103
+ def sents(self, exemplars=True, full_text=True):
2104
+ """
2105
+ Annotated sentences matching the specified criteria.
2106
+ """
2107
+ if exemplars:
2108
+ if full_text:
2109
+ return self.exemplars() + self.ft_sents()
2110
+ else:
2111
+ return self.exemplars()
2112
+ elif full_text:
2113
+ return self.ft_sents()
2114
+
2115
+ def annotations(self, luNamePattern=None, exemplars=True, full_text=True):
2116
+ """
2117
+ Frame annotation sets matching the specified criteria.
2118
+ """
2119
+
2120
+ if exemplars:
2121
+ epart = PrettyLazyIteratorList(sent.frameAnnotation for sent in self.exemplars(luNamePattern))
2122
+ else:
2123
+ epart = []
2124
+
2125
+ if full_text:
2126
+ if luNamePattern is not None:
2127
+ matchedLUIDs = set(self.lu_ids_and_names(luNamePattern).keys())
2128
+ ftpart = PrettyLazyIteratorList(aset for sent in self.ft_sents() for aset in sent.annotationSet[1:] if luNamePattern is None or aset.get('luID','CXN_ASET') in matchedLUIDs)
2129
+ else:
2130
+ ftpart = []
2131
+
2132
+ if exemplars:
2133
+ if full_text:
2134
+ return epart + ftpart
2135
+ else:
2136
+ return epart
2137
+ elif full_text:
2138
+ return ftpart
2139
+
2140
+ def exemplars(self, luNamePattern=None, frame=None, fe=None, fe2=None):
2141
+ """
2142
+ Lexicographic exemplar sentences, optionally filtered by LU name and/or 1-2 FEs that
2143
+ are realized overtly. 'frame' may be a name pattern, frame ID, or frame instance.
2144
+ 'fe' may be a name pattern or FE instance; if specified, 'fe2' may also
2145
+ be specified to retrieve sentences with both overt FEs (in either order).
2146
+ """
2147
+ if fe is None and fe2 is not None:
2148
+ raise FramenetError('exemplars(..., fe=None, fe2=<value>) is not allowed')
2149
+ elif fe is not None and fe2 is not None:
2150
+ if not isinstance(fe2, string_types):
2151
+ if isinstance(fe, string_types):
2152
+ # fe2 is specific to a particular frame. swap fe and fe2 so fe is always used to determine the frame.
2153
+ fe, fe2 = fe2, fe
2154
+ elif fe.frame is not fe2.frame: # ensure frames match
2155
+ raise FramenetError('exemplars() call with inconsistent `fe` and `fe2` specification (frames must match)')
2156
+ if frame is None and fe is not None and not isinstance(fe, string_types):
2157
+ frame = fe.frame
2158
+
2159
+ # narrow down to frames matching criteria
2160
+
2161
+ lusByFrame = defaultdict(list) # frame name -> matching LUs, if luNamePattern is specified
2162
+ if frame is not None or luNamePattern is not None:
2163
+ if frame is None or isinstance(frame, string_types):
2164
+ if luNamePattern is not None:
2165
+ frames = set()
2166
+ for lu in self.lus(luNamePattern, frame=frame):
2167
+ frames.add(lu.frame.ID)
2168
+ lusByFrame[lu.frame.name].append(lu)
2169
+ frames = LazyMap(self.frame, list(frames))
2170
+ else:
2171
+ frames = self.frames(frame)
2172
+ else:
2173
+ if isinstance(frame,int):
2174
+ frames = [self.frame(frame)]
2175
+ else: # frame object
2176
+ frames = [frame]
2177
+
2178
+ if luNamePattern is not None:
2179
+ lusByFrame = {frame.name: self.lus(luNamePattern, frame=frame)}
2180
+
2181
+ if fe is not None: # narrow to frames that define this FE
2182
+ if isinstance(fe, string_types):
2183
+ frames = PrettyLazyIteratorList(f for f in frames if fe in f.FE or any(re.search(fe, ffe, re.I) for ffe in f.FE.keys()))
2184
+ else:
2185
+ if fe.frame not in frames:
2186
+ raise FramenetError('exemplars() call with inconsistent `frame` and `fe` specification')
2187
+ frames = [fe.frame]
2188
+
2189
+ if fe2 is not None: # narrow to frames that ALSO define this FE
2190
+ if isinstance(fe2, string_types):
2191
+ frames = PrettyLazyIteratorList(f for f in frames if fe2 in f.FE or any(re.search(fe2, ffe, re.I) for ffe in f.FE.keys()))
2192
+ # else we already narrowed it to a single frame
2193
+ else: # frame, luNamePattern are None. fe, fe2 are None or strings
2194
+ if fe is not None:
2195
+ frames = {ffe.frame.ID for ffe in self.fes(fe)}
2196
+ if fe2 is not None:
2197
+ frames2 = {ffe.frame.ID for ffe in self.fes(fe2)}
2198
+ frames = frames & frames2
2199
+ frames = LazyMap(self.frame, list(frames))
2200
+ else:
2201
+ frames = self.frames()
2202
+
2203
+ # we've narrowed down 'frames'
2204
+ # now get exemplars for relevant LUs in those frames
2205
+
2206
+ def _matching_exs():
2207
+ for f in frames:
2208
+ fes = fes2 = None # FEs of interest
2209
+ if fe is not None:
2210
+ fes = {ffe for ffe in f.FE.keys() if re.search(fe, ffe, re.I)} if isinstance(fe, string_types) else {fe.name}
2211
+ if fe2 is not None:
2212
+ fes2 = {ffe for ffe in f.FE.keys() if re.search(fe2, ffe, re.I)} if isinstance(fe2, string_types) else {fe2.name}
2213
+
2214
+ for lu in lusByFrame[f.name] if luNamePattern is not None else f.lexUnit.values():
2215
+ for ex in lu.exemplars:
2216
+ if (fes is None or self._exemplar_of_fes(ex, fes)) and (fes2 is None or self._exemplar_of_fes(ex, fes2)):
2217
+ yield ex
2218
+
2219
+ return PrettyLazyIteratorList(_matching_exs())
2220
+
2221
+ def _exemplar_of_fes(self, ex, fes=None):
2222
+ """
2223
+ Given an exemplar sentence and a set of FE names, return the subset of FE names
2224
+ that are realized overtly in the sentence on the FE, FE2, or FE3 layer.
2225
+
2226
+ If 'fes' is None, returns all overt FE names.
2227
+ """
2228
+ overtNames = set(list(zip(*ex.FE[0]))[2]) if ex.FE[0] else set()
2229
+ if 'FE2' in ex:
2230
+ overtNames |= set(list(zip(*ex.FE2[0]))[2]) if ex.FE2[0] else set()
2231
+ if 'FE3' in ex:
2232
+ overtNames |= set(list(zip(*ex.FE3[0]))[2]) if ex.FE3[0] else set()
2233
+ return overtNames & fes if fes is not None else overtNames
2234
+
2235
+ def ft_sents(self, docNamePattern=None):
2236
+ """
2237
+ Full-text annotation sentences, optionally filtered by document name.
2238
+ """
2239
+ return PrettyLazyIteratorList(sent for d in self.docs(docNamePattern) for sent in d.sentence)
2240
+
2241
+
1397
2242
  def frame_relation_types(self):
1398
2243
  """
1399
2244
  Obtain a list of frame relation types.
1400
2245
 
1401
2246
  >>> from nltk.corpus import framenet as fn
1402
- >>> frts = list(fn.frame_relation_types())
2247
+ >>> frts = sorted(fn.frame_relation_types(), key=itemgetter('ID'))
1403
2248
  >>> isinstance(frts, list)
1404
2249
  True
1405
- >>> len(frts)
1406
- 9
2250
+ >>> len(frts) in (9, 10) # FN 1.5 and 1.7, resp.
2251
+ True
1407
2252
  >>> PrettyDict(frts[0], breakLines=True)
1408
2253
  {'ID': 1,
1409
2254
  '_type': 'framerelationtype',
@@ -1435,15 +2280,15 @@ class FramenetCorpusReader(XMLCorpusReader):
1435
2280
  >>> frels = fn.frame_relations()
1436
2281
  >>> isinstance(frels, list)
1437
2282
  True
1438
- >>> len(frels)
1439
- 1676
2283
+ >>> len(frels) in (1676, 2070) # FN 1.5 and 1.7, resp.
2284
+ True
1440
2285
  >>> PrettyList(fn.frame_relations('Cooking_creation'), maxReprSize=0, breakLines=True)
1441
2286
  [<Parent=Intentionally_create -- Inheritance -> Child=Cooking_creation>,
1442
2287
  <Parent=Apply_heat -- Using -> Child=Cooking_creation>,
1443
2288
  <MainEntry=Apply_heat -- See_also -> ReferringEntry=Cooking_creation>]
1444
- >>> PrettyList(fn.frame_relations(373), breakLines=True)
1445
- [<Parent=Topic -- Using -> Child=Communication>,
1446
- <Source=Discussion -- ReFraming_Mapping -> Target=Topic>, ...]
2289
+ >>> PrettyList(fn.frame_relations(274), breakLines=True)
2290
+ [<Parent=Avoiding -- Inheritance -> Child=Dodging>,
2291
+ <Parent=Avoiding -- Inheritance -> Child=Evading>, ...]
1447
2292
  >>> PrettyList(fn.frame_relations(fn.frame('Cooking_creation')), breakLines=True)
1448
2293
  [<Parent=Intentionally_create -- Inheritance -> Child=Cooking_creation>,
1449
2294
  <Parent=Apply_heat -- Using -> Child=Cooking_creation>, ...]
@@ -1510,8 +2355,8 @@ class FramenetCorpusReader(XMLCorpusReader):
1510
2355
  >>> ferels = fn.fe_relations()
1511
2356
  >>> isinstance(ferels, list)
1512
2357
  True
1513
- >>> len(ferels)
1514
- 10020
2358
+ >>> len(ferels) in (10020, 12393) # FN 1.5 and 1.7, resp.
2359
+ True
1515
2360
  >>> PrettyDict(ferels[0], breakLines=True)
1516
2361
  {'ID': 14642,
1517
2362
  '_type': 'ferelation',
@@ -1541,10 +2386,10 @@ class FramenetCorpusReader(XMLCorpusReader):
1541
2386
 
1542
2387
  >>> from nltk.corpus import framenet as fn
1543
2388
  >>> stypes = fn.semtypes()
1544
- >>> len(stypes)
1545
- 73
2389
+ >>> len(stypes) in (73, 109) # FN 1.5 and 1.7, resp.
2390
+ True
1546
2391
  >>> sorted(stypes[0].keys())
1547
- ['ID', '_type', 'abbrev', 'definition', 'name', 'rootType', 'subTypes', 'superType']
2392
+ ['ID', '_type', 'abbrev', 'definition', 'definitionMarkup', 'name', 'rootType', 'subTypes', 'superType']
1548
2393
 
1549
2394
  :return: A list of all of the semantic types in framenet
1550
2395
  :rtype: list(dict)
@@ -1577,8 +2422,8 @@ class FramenetCorpusReader(XMLCorpusReader):
1577
2422
  return d
1578
2423
 
1579
2424
  # Ignore these attributes when loading attributes from an xml node
1580
- ignore_attrs = ['cBy', 'cDate', 'mDate', 'xsi',
1581
- 'schemaLocation', 'xmlns', 'bgColor', 'fgColor']
2425
+ ignore_attrs = [ #'cBy', 'cDate', 'mDate', # <-- annotation metadata that could be of interest
2426
+ 'xsi', 'schemaLocation', 'xmlns', 'bgColor', 'fgColor']
1582
2427
 
1583
2428
  for attr in attr_dict:
1584
2429
 
@@ -1602,6 +2447,13 @@ class FramenetCorpusReader(XMLCorpusReader):
1602
2447
  """
1603
2448
 
1604
2449
  try:
2450
+ '''
2451
+ # Look for boundary issues in markup. (Sometimes FEs are pluralized in definitions.)
2452
+ m = re.search(r'\w[<][^/]|[<][/][^>]+[>](s\w|[a-rt-z0-9])', data)
2453
+ if m:
2454
+ print('Markup boundary:', data[max(0,m.start(0)-10):m.end(0)+10].replace('\n',' '), file=sys.stderr)
2455
+ '''
2456
+
1605
2457
  data = data.replace('<t>', '')
1606
2458
  data = data.replace('</t>', '')
1607
2459
  data = re.sub('<fex name="[^"]+">', '', data)
@@ -1657,6 +2509,7 @@ class FramenetCorpusReader(XMLCorpusReader):
1657
2509
  else:
1658
2510
  docname = doc.description
1659
2511
  doc.filename = "{0}__{1}.xml".format(corpname, docname)
2512
+ doc.URL = self._fnweb_url + '/' + self._fulltext_dir + '/' + doc.filename
1660
2513
  doc.corpname = corpname
1661
2514
  doc.corpid = corpid
1662
2515
  retlist.append(doc)
@@ -1664,11 +2517,12 @@ class FramenetCorpusReader(XMLCorpusReader):
1664
2517
  return retlist
1665
2518
 
1666
2519
  def _handle_frame_elt(self, elt, ignorekeys=[]):
1667
- """Load the info for a Frame from an frame xml file"""
2520
+ """Load the info for a Frame from a frame xml file"""
1668
2521
  frinfo = self._load_xml_attributes(AttrDict(), elt)
1669
2522
 
1670
2523
  frinfo['_type'] = 'frame'
1671
2524
  frinfo['definition'] = ""
2525
+ frinfo['definitionMarkup'] = ""
1672
2526
  frinfo['FE'] = PrettyDict()
1673
2527
  frinfo['FEcoreSets'] = []
1674
2528
  frinfo['lexUnit'] = PrettyDict()
@@ -1679,6 +2533,7 @@ class FramenetCorpusReader(XMLCorpusReader):
1679
2533
 
1680
2534
  for sub in elt:
1681
2535
  if sub.tag.endswith('definition') and 'definition' not in ignorekeys:
2536
+ frinfo['definitionMarkup'] = sub.text
1682
2537
  frinfo['definition'] = self._strip_tags(sub.text)
1683
2538
  elif sub.tag.endswith('FE') and 'FE' not in ignorekeys:
1684
2539
  feinfo = self._handle_fe_elt(sub)
@@ -1694,7 +2549,9 @@ class FramenetCorpusReader(XMLCorpusReader):
1694
2549
  # problematic LU entry; ignore it
1695
2550
  continue
1696
2551
  luentry['frame'] = frinfo
1697
- luentry['subCorpus'] = Future((lambda lu: lambda: self._lu_file(lu))(luentry))
2552
+ luentry['URL'] = self._fnweb_url + '/' + self._lu_dir + '/' + "lu{0}.xml".format(luentry['ID'])
2553
+ luentry['subCorpus'] = Future((lambda lu: lambda: self._lu_file(lu).subCorpus)(luentry))
2554
+ luentry['exemplars'] = Future((lambda lu: lambda: self._lu_file(lu).exemplars)(luentry))
1698
2555
  frinfo['lexUnit'][luentry.name] = luentry
1699
2556
  if not self._lu_idx:
1700
2557
  self._buildluindex()
@@ -1765,7 +2622,7 @@ class FramenetCorpusReader(XMLCorpusReader):
1765
2622
  element (which we ignore here) and a bunch of 'sentence'
1766
2623
  elements."""
1767
2624
  info = AttrDict()
1768
- info['_type'] = 'fulltextannotation'
2625
+ info['_type'] = 'fulltext_annotation'
1769
2626
  info['sentence'] = []
1770
2627
 
1771
2628
  for sub in elt:
@@ -1773,40 +2630,59 @@ class FramenetCorpusReader(XMLCorpusReader):
1773
2630
  continue # not used
1774
2631
  elif sub.tag.endswith('sentence'):
1775
2632
  s = self._handle_fulltext_sentence_elt(sub)
2633
+ s.doc = info
1776
2634
  info['sentence'].append(s)
1777
2635
 
1778
2636
  return info
1779
2637
 
1780
2638
  def _handle_fulltext_sentence_elt(self, elt):
1781
2639
  """Load information from the given 'sentence' element. Each
1782
- 'sentence' element contains a "text" and an "annotationSet" sub
1783
- element."""
2640
+ 'sentence' element contains a "text" and "annotationSet" sub
2641
+ elements."""
1784
2642
  info = self._load_xml_attributes(AttrDict(), elt)
1785
- info['_type'] = "sentence"
2643
+ info['_type'] = "fulltext_sentence"
1786
2644
  info['annotationSet'] = []
2645
+ info['targets'] = []
2646
+ target_spans = set()
2647
+ info['_ascii'] = types.MethodType(_annotation_ascii, info) # attach a method for this instance
1787
2648
  info['text'] = ""
1788
2649
 
1789
2650
  for sub in elt:
1790
2651
  if sub.tag.endswith('text'):
1791
2652
  info['text'] = self._strip_tags(sub.text)
1792
2653
  elif sub.tag.endswith('annotationSet'):
1793
- a = self._handle_fulltextannotationset_elt(sub)
2654
+ a = self._handle_fulltextannotationset_elt(sub, is_pos=(len(info['annotationSet'])==0))
2655
+ if 'cxnID' in a: # ignoring construction annotations for now
2656
+ continue
2657
+ a.sent = info
2658
+ a.text = info.text
1794
2659
  info['annotationSet'].append(a)
1795
-
2660
+ if 'Target' in a:
2661
+ for tspan in a.Target:
2662
+ if tspan in target_spans:
2663
+ self._warn('Duplicate target span "{0}"'.format(info.text[slice(*tspan)]),
2664
+ tspan, 'in sentence',info['ID'], info.text)
2665
+ # this can happen in cases like "chemical and biological weapons"
2666
+ # being annotated as "chemical weapons" and "biological weapons"
2667
+ else:
2668
+ target_spans.add(tspan)
2669
+ info['targets'].append((a.Target, a.luName, a.frameName))
2670
+
2671
+ assert info['annotationSet'][0].status=='UNANN'
2672
+ info['POS'] = info['annotationSet'][0].POS
2673
+ info['POS_tagset'] = info['annotationSet'][0].POS_tagset
1796
2674
  return info
1797
2675
 
1798
- def _handle_fulltextannotationset_elt(self, elt):
2676
+ def _handle_fulltextannotationset_elt(self, elt, is_pos=False):
1799
2677
  """Load information from the given 'annotationSet' element. Each
1800
2678
  'annotationSet' contains several "layer" elements."""
1801
- info = self._load_xml_attributes(AttrDict(), elt)
1802
- info['_type'] = "annotationset"
1803
- info['layer'] = []
1804
-
1805
- for sub in elt:
1806
- if sub.tag.endswith('layer'):
1807
- l = self._handle_fulltextlayer_elt(sub)
1808
- info['layer'].append(l)
1809
2679
 
2680
+ info = self._handle_luannotationset_elt(elt, is_pos=is_pos)
2681
+ if not is_pos:
2682
+ info['_type'] = 'fulltext_annotationset'
2683
+ if 'cxnID' not in info: # ignoring construction annotations for now
2684
+ info['LU'] = self.lu(info.luID, luName=info.luName, frameID=info.frameID, frameName=info.frameName)
2685
+ info['frame'] = info.LU.frame
1810
2686
  return info
1811
2687
 
1812
2688
  def _handle_fulltextlayer_elt(self, elt):
@@ -1829,22 +2705,33 @@ class FramenetCorpusReader(XMLCorpusReader):
1829
2705
  luinfo['_type'] = 'lu'
1830
2706
  luinfo = self._load_xml_attributes(luinfo, elt)
1831
2707
  luinfo["definition"] = ""
2708
+ luinfo["definitionMarkup"] = ""
1832
2709
  luinfo["sentenceCount"] = PrettyDict()
1833
2710
  luinfo['lexemes'] = PrettyList() # multiword LUs have multiple lexemes
1834
2711
  luinfo['semTypes'] = PrettyList() # an LU can have multiple semtypes
1835
2712
 
1836
2713
  for sub in elt:
1837
2714
  if sub.tag.endswith('definition'):
2715
+ luinfo['definitionMarkup'] = sub.text
1838
2716
  luinfo['definition'] = self._strip_tags(sub.text)
1839
2717
  elif sub.tag.endswith('sentenceCount'):
1840
2718
  luinfo['sentenceCount'] = self._load_xml_attributes(
1841
2719
  PrettyDict(), sub)
1842
2720
  elif sub.tag.endswith('lexeme'):
1843
- luinfo['lexemes'].append(self._load_xml_attributes(PrettyDict(), sub))
2721
+ lexemeinfo = self._load_xml_attributes(PrettyDict(), sub)
2722
+ if not isinstance(lexemeinfo.name, string_types):
2723
+ # some lexeme names are ints by default: e.g.,
2724
+ # thousand.num has lexeme with name="1000"
2725
+ lexemeinfo.name = str(lexemeinfo.name)
2726
+ luinfo['lexemes'].append(lexemeinfo)
1844
2727
  elif sub.tag.endswith('semType'):
1845
2728
  semtypeinfo = self._load_xml_attributes(PrettyDict(), sub)
1846
2729
  luinfo['semTypes'].append(self.semtype(semtypeinfo.ID))
1847
2730
 
2731
+ # sort lexemes by 'order' attribute
2732
+ # otherwise, e.g., 'write down.v' may have lexemes in wrong order
2733
+ luinfo['lexemes'].sort(key=lambda x: x.order)
2734
+
1848
2735
  return luinfo
1849
2736
 
1850
2737
  def _handle_lexunit_elt(self, elt, ignorekeys):
@@ -1856,6 +2743,7 @@ class FramenetCorpusReader(XMLCorpusReader):
1856
2743
  luinfo = self._load_xml_attributes(AttrDict(), elt)
1857
2744
  luinfo['_type'] = 'lu'
1858
2745
  luinfo['definition'] = ""
2746
+ luinfo['definitionMarkup'] = ""
1859
2747
  luinfo['subCorpus'] = PrettyList()
1860
2748
  luinfo['lexemes'] = PrettyList() # multiword LUs have multiple lexemes
1861
2749
  luinfo['semTypes'] = PrettyList() # an LU can have multiple semtypes
@@ -1869,6 +2757,7 @@ class FramenetCorpusReader(XMLCorpusReader):
1869
2757
  elif sub.tag.endswith('valences'):
1870
2758
  continue # not used
1871
2759
  elif sub.tag.endswith('definition') and 'definition' not in ignorekeys:
2760
+ luinfo['definitionMarkup'] = sub.text
1872
2761
  luinfo['definition'] = self._strip_tags(sub.text)
1873
2762
  elif sub.tag.endswith('subCorpus') and 'subCorpus' not in ignorekeys:
1874
2763
  sc = self._handle_lusubcorpus_elt(sub)
@@ -1886,7 +2775,7 @@ class FramenetCorpusReader(XMLCorpusReader):
1886
2775
  """Load a subcorpus of a lexical unit from the given xml."""
1887
2776
  sc = AttrDict()
1888
2777
  try:
1889
- sc['name'] = str(elt.get('name'))
2778
+ sc['name'] = elt.get('name')
1890
2779
  except AttributeError:
1891
2780
  return None
1892
2781
  sc['_type'] = "lusubcorpus"
@@ -1905,25 +2794,99 @@ class FramenetCorpusReader(XMLCorpusReader):
1905
2794
  info = self._load_xml_attributes(AttrDict(), elt)
1906
2795
  info['_type'] = 'lusentence'
1907
2796
  info['annotationSet'] = []
2797
+ info['_ascii'] = types.MethodType(_annotation_ascii, info) # attach a method for this instance
1908
2798
  for sub in elt:
1909
2799
  if sub.tag.endswith('text'):
1910
2800
  info['text'] = self._strip_tags(sub.text)
1911
2801
  elif sub.tag.endswith('annotationSet'):
1912
- annset = self._handle_luannotationset_elt(sub)
2802
+ annset = self._handle_luannotationset_elt(sub, is_pos=(len(info['annotationSet'])==0))
1913
2803
  if annset is not None:
2804
+ assert annset.status=='UNANN' or 'FE' in annset,annset
2805
+ if annset.status!='UNANN':
2806
+ info['frameAnnotation'] = annset
2807
+ # copy layer info up to current level
2808
+ for k in ('Target', 'FE', 'FE2', 'FE3', 'GF', 'PT', 'POS', 'POS_tagset',
2809
+ 'Other', 'Sent', 'Verb', 'Noun', 'Adj', 'Adv', 'Prep', 'Scon', 'Art'):
2810
+ if k in annset:
2811
+ info[k] = annset[k]
1914
2812
  info['annotationSet'].append(annset)
2813
+ annset['sent'] = info
2814
+ annset['text'] = info.text
1915
2815
  return info
1916
2816
 
1917
- def _handle_luannotationset_elt(self, elt):
2817
+ def _handle_luannotationset_elt(self, elt, is_pos=False):
1918
2818
  """Load an annotation set from a sentence in an subcorpus of an LU"""
1919
2819
  info = self._load_xml_attributes(AttrDict(), elt)
1920
- info['_type'] = 'luannotationset'
2820
+ info['_type'] = 'posannotationset' if is_pos else 'luannotationset'
1921
2821
  info['layer'] = []
2822
+ info['_ascii'] = types.MethodType(_annotation_ascii, info) # attach a method for this instance
2823
+
2824
+ if 'cxnID' in info: # ignoring construction annotations for now.
2825
+ return info
2826
+
1922
2827
  for sub in elt:
1923
2828
  if sub.tag.endswith('layer'):
1924
2829
  l = self._handle_lulayer_elt(sub)
1925
2830
  if l is not None:
2831
+ overt = []
2832
+ ni = {} # null instantiations
2833
+
1926
2834
  info['layer'].append(l)
2835
+ for lbl in l.label:
2836
+ if 'start' in lbl:
2837
+ thespan = (lbl.start,lbl.end+1,lbl.name)
2838
+ if l.name not in ('Sent','Other'): # 'Sent' and 'Other' layers sometimes contain accidental duplicate spans
2839
+ assert thespan not in overt,(info.ID,l.name,thespan)
2840
+ overt.append(thespan)
2841
+ else: # null instantiation
2842
+ if lbl.name in ni:
2843
+ self._warn('FE with multiple NI entries:', lbl.name, ni[lbl.name], lbl.itype)
2844
+ else:
2845
+ ni[lbl.name] = lbl.itype
2846
+ overt = sorted(overt)
2847
+
2848
+ if l.name=='Target':
2849
+ if not overt:
2850
+ self._warn('Skipping empty Target layer in annotation set ID={0}'.format(info.ID))
2851
+ continue
2852
+ assert all(lblname=='Target' for i,j,lblname in overt)
2853
+ if 'Target' in info:
2854
+ self._warn('Annotation set {0} has multiple Target layers'.format(info.ID))
2855
+ else:
2856
+ info['Target'] = [(i,j) for (i,j,_) in overt]
2857
+ elif l.name=='FE':
2858
+ if l.rank==1:
2859
+ assert 'FE' not in info
2860
+ info['FE'] = (overt, ni)
2861
+ #assert False,info
2862
+ else:
2863
+ # sometimes there are 3 FE layers! e.g. Change_position_on_a_scale.fall.v
2864
+ assert 2<=l.rank<=3,l.rank
2865
+ k = 'FE'+str(l.rank)
2866
+ assert k not in info
2867
+ info[k] = (overt, ni)
2868
+ elif l.name in ('GF', 'PT'):
2869
+ assert l.rank==1
2870
+ info[l.name] = overt
2871
+ elif l.name in ('BNC', 'PENN'):
2872
+ assert l.rank==1
2873
+ info['POS'] = overt
2874
+ info['POS_tagset'] = l.name
2875
+ else:
2876
+ if is_pos:
2877
+ if l.name not in ('NER', 'WSL'):
2878
+ self._warn('Unexpected layer in sentence annotationset:', l.name)
2879
+ else:
2880
+ if l.name not in ('Sent', 'Verb', 'Noun', 'Adj', 'Adv', 'Prep', 'Scon', 'Art', 'Other'):
2881
+ self._warn('Unexpected layer in frame annotationset:', l.name)
2882
+ info[l.name] = overt
2883
+ if not is_pos and 'cxnID' not in info:
2884
+ if 'Target' not in info:
2885
+ self._warn('Missing target in annotation set ID={0}'.format(info.ID))
2886
+ assert 'FE' in info
2887
+ if 'FE3' in info:
2888
+ assert 'FE2' in info
2889
+
1927
2890
  return info
1928
2891
 
1929
2892
  def _handle_lulayer_elt(self, elt):
@@ -1943,11 +2906,13 @@ class FramenetCorpusReader(XMLCorpusReader):
1943
2906
  feinfo = self._load_xml_attributes(AttrDict(), elt)
1944
2907
  feinfo['_type'] = 'fe'
1945
2908
  feinfo['definition'] = ""
2909
+ feinfo['definitionMarkup'] = ""
1946
2910
  feinfo['semType'] = None
1947
2911
  feinfo['requiresFE'] = None
1948
2912
  feinfo['excludesFE'] = None
1949
2913
  for sub in elt:
1950
2914
  if sub.tag.endswith('definition'):
2915
+ feinfo['definitionMarkup'] = sub.text
1951
2916
  feinfo['definition'] = self._strip_tags(sub.text)
1952
2917
  elif sub.tag.endswith('semType'):
1953
2918
  stinfo = self._load_xml_attributes(AttrDict(), sub)
@@ -1966,6 +2931,7 @@ class FramenetCorpusReader(XMLCorpusReader):
1966
2931
  semt['subTypes'] = PrettyList()
1967
2932
  for sub in elt:
1968
2933
  if sub.text is not None:
2934
+ semt['definitionMarkup'] = sub.text
1969
2935
  semt['definition'] = self._strip_tags(sub.text)
1970
2936
  else:
1971
2937
  supertypeinfo = self._load_xml_attributes(AttrDict(), sub)
@@ -1994,7 +2960,7 @@ def demo():
1994
2960
  #
1995
2961
  print('Number of Frames:', len(fn.frames()))
1996
2962
  print('Number of Lexical Units:', len(fn.lus()))
1997
- print('Number of annotated documents:', len(fn.documents()))
2963
+ print('Number of annotated documents:', len(fn.docs()))
1998
2964
  print()
1999
2965
 
2000
2966
  #
@@ -2065,14 +3031,14 @@ def demo():
2065
3031
  # Get a list of all of the corpora used for fulltext annotation
2066
3032
  #
2067
3033
  print('\nNames of all of the corpora used for fulltext annotation:')
2068
- allcorpora = set([x.corpname for x in fn.documents()])
3034
+ allcorpora = set([x.corpname for x in fn.docs_metadata()])
2069
3035
  pprint(list(allcorpora))
2070
3036
 
2071
3037
  #
2072
3038
  # Get the names of the annotated documents in the first corpus
2073
3039
  #
2074
3040
  firstcorp = list(allcorpora)[0]
2075
- firstcorp_docs = fn.documents(firstcorp)
3041
+ firstcorp_docs = fn.docs(firstcorp)
2076
3042
  print(
2077
3043
  '\nNames of the annotated documents in the "{0}" corpus:'.format(firstcorp))
2078
3044
  pprint([x.filename for x in firstcorp_docs])