Przeglądaj źródła

Changes to be committed:
modified: .gitmodules
modified: .vimrc
deleted: bundle/ultisnips
new file: bundle/vim-multiple-cursors
deleted: bundle/vim-snippets
deleted: ftplugin/python/pymode.vim
deleted: plugin-info.txt
deleted: pylibs/__init__.py
deleted: pylibs/__init__.pyc
deleted: pylibs/autopep8.py
deleted: pylibs/autopep8.pyc
deleted: pylibs/logilab/__init__.py
deleted: pylibs/logilab/astng/COPYING
deleted: pylibs/logilab/astng/COPYING.LESSER
deleted: pylibs/logilab/astng/README
deleted: pylibs/logilab/astng/README.Python3
deleted: pylibs/logilab/astng/__init__.py
deleted: pylibs/logilab/astng/__pkginfo__.py
deleted: pylibs/logilab/astng/as_string.py
deleted: pylibs/logilab/astng/bases.py
deleted: pylibs/logilab/astng/brain/py2stdlib.py
deleted: pylibs/logilab/astng/builder.py
deleted: pylibs/logilab/astng/exceptions.py
deleted: pylibs/logilab/astng/inference.py
deleted: pylibs/logilab/astng/inspector.py
deleted: pylibs/logilab/astng/manager.py
deleted: pylibs/logilab/astng/mixins.py
deleted: pylibs/logilab/astng/node_classes.py
deleted: pylibs/logilab/astng/nodes.py
deleted: pylibs/logilab/astng/protocols.py
deleted: pylibs/logilab/astng/raw_building.py
deleted: pylibs/logilab/astng/rebuilder.py
deleted: pylibs/logilab/astng/scoped_nodes.py
deleted: pylibs/logilab/astng/utils.py
deleted: pylibs/logilab/common/COPYING
deleted: pylibs/logilab/common/COPYING.LESSER
deleted: pylibs/logilab/common/README
deleted: pylibs/logilab/common/README.Python3
deleted: pylibs/logilab/common/__init__.py
deleted: pylibs/logilab/common/__pkginfo__.py
deleted: pylibs/logilab/common/announce.txt
deleted: pylibs/logilab/common/cache.py
deleted: pylibs/logilab/common/changelog.py
deleted: pylibs/logilab/common/clcommands.py
deleted: pylibs/logilab/common/cli.py
deleted: pylibs/logilab/common/compat.py
deleted: pylibs/logilab/common/configuration.py
deleted: pylibs/logilab/common/contexts.py
deleted: pylibs/logilab/common/corbautils.py
deleted: pylibs/logilab/common/daemon.py
deleted: pylibs/logilab/common/date.py
deleted: pylibs/logilab/common/dbf.py
deleted: pylibs/logilab/common/debugger.py
deleted: pylibs/logilab/common/decorators.py
deleted: pylibs/logilab/common/deprecation.py
deleted: pylibs/logilab/common/fileutils.py
deleted: pylibs/logilab/common/graph.py
deleted: pylibs/logilab/common/hg.py
deleted: pylibs/logilab/common/interface.py
deleted: pylibs/logilab/common/logging_ext.py
deleted: pylibs/logilab/common/modutils.py
deleted: pylibs/logilab/common/optik_ext.py
deleted: pylibs/logilab/common/optparser.py
deleted: pylibs/logilab/common/pdf_ext.py
deleted: pylibs/logilab/common/proc.py
deleted: pylibs/logilab/common/pyro_ext.py
deleted: pylibs/logilab/common/pytest.py
deleted: pylibs/logilab/common/registry.py
deleted: pylibs/logilab/common/shellutils.py
deleted: pylibs/logilab/common/sphinx_ext.py
deleted: pylibs/logilab/common/sphinxutils.py
deleted: pylibs/logilab/common/table.py
deleted: pylibs/logilab/common/tasksqueue.py
deleted: pylibs/logilab/common/testlib.py
deleted: pylibs/logilab/common/textutils.py
deleted: pylibs/logilab/common/tree.py
deleted: pylibs/logilab/common/umessage.py
deleted: pylibs/logilab/common/ureports/__init__.py
deleted: pylibs/logilab/common/ureports/docbook_writer.py
deleted: pylibs/logilab/common/ureports/html_writer.py
deleted: pylibs/logilab/common/ureports/nodes.py
deleted: pylibs/logilab/common/ureports/text_writer.py
deleted: pylibs/logilab/common/urllib2ext.py
deleted: pylibs/logilab/common/vcgutils.py
deleted: pylibs/logilab/common/visitor.py
deleted: pylibs/logilab/common/xmlrpcutils.py
deleted: pylibs/logilab/common/xmlutils.py
deleted: pylibs/mccabe.py
deleted: pylibs/mccabe.pyc
deleted: pylibs/pep8.py
deleted: pylibs/pep8.pyc
deleted: pylibs/pyflakes/__init__.py
deleted: pylibs/pyflakes/__init__.pyc
deleted: pylibs/pyflakes/checker.py
deleted: pylibs/pyflakes/checker.pyc
deleted: pylibs/pyflakes/messages.py
deleted: pylibs/pyflakes/messages.pyc
deleted: pylibs/pylint/README
deleted: pylibs/pylint/README.Python3
deleted: pylibs/pylint/__init__.py
deleted: pylibs/pylint/__pkginfo__.py
deleted: pylibs/pylint/checkers/__init__.py
deleted: pylibs/pylint/checkers/base.py
deleted: pylibs/pylint/checkers/classes.py
deleted: pylibs/pylint/checkers/design_analysis.py
deleted: pylibs/pylint/checkers/exceptions.py
deleted: pylibs/pylint/checkers/format.py
deleted: pylibs/pylint/checkers/imports.py
deleted: pylibs/pylint/checkers/logging.py
deleted: pylibs/pylint/checkers/misc.py
deleted: pylibs/pylint/checkers/newstyle.py
deleted: pylibs/pylint/checkers/raw_metrics.py
deleted: pylibs/pylint/checkers/similar.py
deleted: pylibs/pylint/checkers/string_format.py
deleted: pylibs/pylint/checkers/typecheck.py
deleted: pylibs/pylint/checkers/utils.py
deleted: pylibs/pylint/checkers/variables.py
deleted: pylibs/pylint/config.py
deleted: pylibs/pylint/interfaces.py
deleted: pylibs/pylint/lint.py
deleted: pylibs/pylint/reporters/__init__.py
deleted: pylibs/pylint/reporters/guireporter.py
deleted: pylibs/pylint/reporters/html.py
deleted: pylibs/pylint/reporters/text.py
deleted: pylibs/pylint/utils.py
deleted: pylibs/pymode/__init__.py
deleted: pylibs/pymode/__init__.pyc
deleted: pylibs/pymode/auto.py
deleted: pylibs/pymode/auto.pyc
deleted: pylibs/pymode/interface.py
deleted: pylibs/pymode/interface.pyc
deleted: pylibs/pymode/lint.py
deleted: pylibs/pymode/lint.pyc
deleted: pylibs/pymode/queue.py
deleted: pylibs/pymode/queue.pyc
deleted: pylibs/rope/__init__.py
deleted: pylibs/rope/__init__.pyc
deleted: pylibs/rope/base/__init__.py
deleted: pylibs/rope/base/__init__.pyc
deleted: pylibs/rope/base/arguments.py
deleted: pylibs/rope/base/arguments.pyc
deleted: pylibs/rope/base/ast.py
deleted: pylibs/rope/base/ast.pyc
deleted: pylibs/rope/base/astutils.py
deleted: pylibs/rope/base/astutils.pyc
deleted: pylibs/rope/base/builtins.py
deleted: pylibs/rope/base/builtins.pyc
deleted: pylibs/rope/base/change.py
deleted: pylibs/rope/base/change.pyc
deleted: pylibs/rope/base/codeanalyze.py
deleted: pylibs/rope/base/codeanalyze.pyc
deleted: pylibs/rope/base/default_config.py
deleted: pylibs/rope/base/default_config.pyc
deleted: pylibs/rope/base/evaluate.py
deleted: pylibs/rope/base/evaluate.pyc
deleted: pylibs/rope/base/exceptions.py
deleted: pylibs/rope/base/exceptions.pyc
deleted: pylibs/rope/base/fscommands.py
deleted: pylibs/rope/base/fscommands.pyc
deleted: pylibs/rope/base/history.py
deleted: pylibs/rope/base/history.pyc
deleted: pylibs/rope/base/libutils.py
deleted: pylibs/rope/base/libutils.pyc
deleted: pylibs/rope/base/oi/__init__.py
deleted: pylibs/rope/base/oi/__init__.pyc
deleted: pylibs/rope/base/oi/doa.py
deleted: pylibs/rope/base/oi/doa.pyc
deleted: pylibs/rope/base/oi/memorydb.py
deleted: pylibs/rope/base/oi/memorydb.pyc
deleted: pylibs/rope/base/oi/objectdb.py
deleted: pylibs/rope/base/oi/objectdb.pyc
deleted: pylibs/rope/base/oi/objectinfo.py
deleted: pylibs/rope/base/oi/objectinfo.pyc
deleted: pylibs/rope/base/oi/runmod.py
deleted: pylibs/rope/base/oi/soa.py
deleted: pylibs/rope/base/oi/soa.pyc
deleted: pylibs/rope/base/oi/soi.py
deleted: pylibs/rope/base/oi/soi.pyc
deleted: pylibs/rope/base/oi/transform.py
deleted: pylibs/rope/base/oi/transform.pyc
deleted: pylibs/rope/base/prefs.py
deleted: pylibs/rope/base/prefs.pyc
deleted: pylibs/rope/base/project.py
deleted: pylibs/rope/base/project.pyc
deleted: pylibs/rope/base/pycore.py
deleted: pylibs/rope/base/pycore.pyc
deleted: pylibs/rope/base/pynames.py
deleted: pylibs/rope/base/pynames.pyc
deleted: pylibs/rope/base/pynamesdef.py
deleted: pylibs/rope/base/pynamesdef.pyc
deleted: pylibs/rope/base/pyobjects.py
deleted: pylibs/rope/base/pyobjects.pyc
deleted: pylibs/rope/base/pyobjectsdef.py
deleted: pylibs/rope/base/pyobjectsdef.pyc
deleted: pylibs/rope/base/pyscopes.py
deleted: pylibs/rope/base/pyscopes.pyc
deleted: pylibs/rope/base/resourceobserver.py
deleted: pylibs/rope/base/resourceobserver.pyc
deleted: pylibs/rope/base/resources.py
deleted: pylibs/rope/base/resources.pyc
deleted: pylibs/rope/base/simplify.py
deleted: pylibs/rope/base/simplify.pyc
deleted: pylibs/rope/base/stdmods.py
deleted: pylibs/rope/base/stdmods.pyc
deleted: pylibs/rope/base/taskhandle.py
deleted: pylibs/rope/base/taskhandle.pyc
deleted: pylibs/rope/base/utils.py
deleted: pylibs/rope/base/utils.pyc
deleted: pylibs/rope/base/worder.py
deleted: pylibs/rope/base/worder.pyc
deleted: pylibs/rope/contrib/__init__.py
deleted: pylibs/rope/contrib/__init__.pyc
deleted: pylibs/rope/contrib/autoimport.py
deleted: pylibs/rope/contrib/autoimport.pyc
deleted: pylibs/rope/contrib/changestack.py
deleted: pylibs/rope/contrib/codeassist.py
deleted: pylibs/rope/contrib/codeassist.pyc
deleted: pylibs/rope/contrib/finderrors.py
deleted: pylibs/rope/contrib/findit.py
deleted: pylibs/rope/contrib/findit.pyc
deleted: pylibs/rope/contrib/fixmodnames.py
deleted: pylibs/rope/contrib/fixsyntax.py
deleted: pylibs/rope/contrib/fixsyntax.pyc
deleted: pylibs/rope/contrib/generate.py
deleted: pylibs/rope/contrib/generate.pyc
deleted: pylibs/rope/refactor/__init__.py
deleted: pylibs/rope/refactor/__init__.pyc
deleted: pylibs/rope/refactor/change_signature.py
deleted: pylibs/rope/refactor/change_signature.pyc
deleted: pylibs/rope/refactor/encapsulate_field.py
deleted: pylibs/rope/refactor/extract.py
deleted: pylibs/rope/refactor/extract.pyc
deleted: pylibs/rope/refactor/functionutils.py
deleted: pylibs/rope/refactor/functionutils.pyc
deleted: pylibs/rope/refactor/importutils/__init__.py
deleted: pylibs/rope/refactor/importutils/__init__.pyc
deleted: pylibs/rope/refactor/importutils/actions.py
deleted: pylibs/rope/refactor/importutils/actions.pyc
deleted: pylibs/rope/refactor/importutils/importinfo.py
deleted: pylibs/rope/refactor/importutils/importinfo.pyc
deleted: pylibs/rope/refactor/importutils/module_imports.py
deleted: pylibs/rope/refactor/importutils/module_imports.pyc
deleted: pylibs/rope/refactor/inline.py
deleted: pylibs/rope/refactor/inline.pyc
deleted: pylibs/rope/refactor/introduce_factory.py
deleted: pylibs/rope/refactor/introduce_factory.pyc
deleted: pylibs/rope/refactor/introduce_parameter.py
deleted: pylibs/rope/refactor/localtofield.py
deleted: pylibs/rope/refactor/method_object.py
deleted: pylibs/rope/refactor/method_object.pyc
deleted: pylibs/rope/refactor/move.py
deleted: pylibs/rope/refactor/move.pyc
deleted: pylibs/rope/refactor/multiproject.py
deleted: pylibs/rope/refactor/occurrences.py
deleted: pylibs/rope/refactor/occurrences.pyc
deleted: pylibs/rope/refactor/patchedast.py
deleted: pylibs/rope/refactor/patchedast.pyc
deleted: pylibs/rope/refactor/rename.py
deleted: pylibs/rope/refactor/rename.pyc
deleted: pylibs/rope/refactor/restructure.py
deleted: pylibs/rope/refactor/restructure.pyc
deleted: pylibs/rope/refactor/similarfinder.py
deleted: pylibs/rope/refactor/similarfinder.pyc
deleted: pylibs/rope/refactor/sourceutils.py
deleted: pylibs/rope/refactor/sourceutils.pyc
deleted: pylibs/rope/refactor/suites.py
deleted: pylibs/rope/refactor/suites.pyc
deleted: pylibs/rope/refactor/topackage.py
deleted: pylibs/rope/refactor/topackage.pyc
deleted: pylibs/rope/refactor/usefunction.py
deleted: pylibs/rope/refactor/usefunction.pyc
deleted: pylibs/rope/refactor/wildcards.py
deleted: pylibs/rope/refactor/wildcards.pyc
deleted: pylibs/ropemode/__init__.py
deleted: pylibs/ropemode/__init__.pyc
deleted: pylibs/ropemode/decorators.py
deleted: pylibs/ropemode/decorators.pyc
deleted: pylibs/ropemode/dialog.py
deleted: pylibs/ropemode/dialog.pyc
deleted: pylibs/ropemode/environment.py
deleted: pylibs/ropemode/environment.pyc
deleted: pylibs/ropemode/filter.py
deleted: pylibs/ropemode/filter.pyc
deleted: pylibs/ropemode/interface.py
deleted: pylibs/ropemode/interface.pyc
deleted: pylibs/ropemode/refactor.py
deleted: pylibs/ropemode/refactor.pyc
deleted: pylibs/ropemode/tests/__init__.py
deleted: pylibs/ropemode/tests/decorators_test.py
deleted: pylibs/ropevim.py
deleted: pylibs/ropevim.pyc
deleted: pylint.ini
deleted: syntax/python.vim
modified: tags

wreed4 11 lat temu
rodzic
commit
72c4cb1de8
100 zmienionych plików z 44 dodań i 27704 usunięć
  1. 6 6
      .gitmodules
  2. 37 19
      .vimrc
  3. 0 1
      bundle/ultisnips
  4. 1 0
      bundle/vim-multiple-cursors
  5. 0 1
      bundle/vim-snippets
  6. 0 154
      ftplugin/python/pymode.vim
  7. 0 8
      plugin-info.txt
  8. 0 0
      pylibs/__init__.py
  9. BIN
      pylibs/__init__.pyc
  10. 0 1726
      pylibs/autopep8.py
  11. BIN
      pylibs/autopep8.pyc
  12. 0 0
      pylibs/logilab/__init__.py
  13. 0 339
      pylibs/logilab/astng/COPYING
  14. 0 510
      pylibs/logilab/astng/COPYING.LESSER
  15. 0 54
      pylibs/logilab/astng/README
  16. 0 26
      pylibs/logilab/astng/README.Python3
  17. 0 85
      pylibs/logilab/astng/__init__.py
  18. 0 45
      pylibs/logilab/astng/__pkginfo__.py
  19. 0 427
      pylibs/logilab/astng/as_string.py
  20. 0 629
      pylibs/logilab/astng/bases.py
  21. 0 119
      pylibs/logilab/astng/brain/py2stdlib.py
  22. 0 226
      pylibs/logilab/astng/builder.py
  23. 0 60
      pylibs/logilab/astng/exceptions.py
  24. 0 383
      pylibs/logilab/astng/inference.py
  25. 0 289
      pylibs/logilab/astng/inspector.py
  26. 0 299
      pylibs/logilab/astng/manager.py
  27. 0 136
      pylibs/logilab/astng/mixins.py
  28. 0 903
      pylibs/logilab/astng/node_classes.py
  29. 0 75
      pylibs/logilab/astng/nodes.py
  30. 0 321
      pylibs/logilab/astng/protocols.py
  31. 0 349
      pylibs/logilab/astng/raw_building.py
  32. 0 864
      pylibs/logilab/astng/rebuilder.py
  33. 0 977
      pylibs/logilab/astng/scoped_nodes.py
  34. 0 241
      pylibs/logilab/astng/utils.py
  35. 0 339
      pylibs/logilab/common/COPYING
  36. 0 510
      pylibs/logilab/common/COPYING.LESSER
  37. 0 187
      pylibs/logilab/common/README
  38. 0 29
      pylibs/logilab/common/README.Python3
  39. 0 171
      pylibs/logilab/common/__init__.py
  40. 0 50
      pylibs/logilab/common/__pkginfo__.py
  41. 0 25
      pylibs/logilab/common/announce.txt
  42. 0 114
      pylibs/logilab/common/cache.py
  43. 0 236
      pylibs/logilab/common/changelog.py
  44. 0 332
      pylibs/logilab/common/clcommands.py
  45. 0 208
      pylibs/logilab/common/cli.py
  46. 0 243
      pylibs/logilab/common/compat.py
  47. 0 1069
      pylibs/logilab/common/configuration.py
  48. 0 5
      pylibs/logilab/common/contexts.py
  49. 0 117
      pylibs/logilab/common/corbautils.py
  50. 0 100
      pylibs/logilab/common/daemon.py
  51. 0 327
      pylibs/logilab/common/date.py
  52. 0 229
      pylibs/logilab/common/dbf.py
  53. 0 210
      pylibs/logilab/common/debugger.py
  54. 0 283
      pylibs/logilab/common/decorators.py
  55. 0 130
      pylibs/logilab/common/deprecation.py
  56. 0 402
      pylibs/logilab/common/fileutils.py
  57. 0 273
      pylibs/logilab/common/graph.py
  58. 0 130
      pylibs/logilab/common/hg.py
  59. 0 71
      pylibs/logilab/common/interface.py
  60. 0 178
      pylibs/logilab/common/logging_ext.py
  61. 0 653
      pylibs/logilab/common/modutils.py
  62. 0 397
      pylibs/logilab/common/optik_ext.py
  63. 0 90
      pylibs/logilab/common/optparser.py
  64. 0 111
      pylibs/logilab/common/pdf_ext.py
  65. 0 277
      pylibs/logilab/common/proc.py
  66. 0 180
      pylibs/logilab/common/pyro_ext.py
  67. 0 1177
      pylibs/logilab/common/pytest.py
  68. 0 973
      pylibs/logilab/common/registry.py
  69. 0 456
      pylibs/logilab/common/shellutils.py
  70. 0 87
      pylibs/logilab/common/sphinx_ext.py
  71. 0 122
      pylibs/logilab/common/sphinxutils.py
  72. 0 923
      pylibs/logilab/common/table.py
  73. 0 98
      pylibs/logilab/common/tasksqueue.py
  74. 0 1389
      pylibs/logilab/common/testlib.py
  75. 0 534
      pylibs/logilab/common/textutils.py
  76. 0 369
      pylibs/logilab/common/tree.py
  77. 0 167
      pylibs/logilab/common/umessage.py
  78. 0 174
      pylibs/logilab/common/ureports/__init__.py
  79. 0 139
      pylibs/logilab/common/ureports/docbook_writer.py
  80. 0 131
      pylibs/logilab/common/ureports/html_writer.py
  81. 0 201
      pylibs/logilab/common/ureports/nodes.py
  82. 0 140
      pylibs/logilab/common/ureports/text_writer.py
  83. 0 87
      pylibs/logilab/common/urllib2ext.py
  84. 0 216
      pylibs/logilab/common/vcgutils.py
  85. 0 107
      pylibs/logilab/common/visitor.py
  86. 0 131
      pylibs/logilab/common/xmlrpcutils.py
  87. 0 61
      pylibs/logilab/common/xmlutils.py
  88. 0 293
      pylibs/mccabe.py
  89. BIN
      pylibs/mccabe.pyc
  90. 0 1931
      pylibs/pep8.py
  91. BIN
      pylibs/pep8.pyc
  92. 0 2
      pylibs/pyflakes/__init__.py
  93. BIN
      pylibs/pyflakes/__init__.pyc
  94. 0 635
      pylibs/pyflakes/checker.py
  95. BIN
      pylibs/pyflakes/checker.pyc
  96. 0 106
      pylibs/pyflakes/messages.py
  97. BIN
      pylibs/pyflakes/messages.pyc
  98. 0 70
      pylibs/pylint/README
  99. 0 37
      pylibs/pylint/README.Python3
  100. 0 0
      pylibs/pylint/__init__.py

+ 6 - 6
.gitmodules

@@ -16,9 +16,6 @@
 [submodule "bundle/vim-easymotion"]
 	path = bundle/vim-easymotion
 	url = https://github.com/Lokaltog/vim-easymotion.git
-[submodule "bundle/vim-snippets"]
-	path = bundle/vim-snippets
-	url = https://github.com/honza/vim-snippets.git
 [submodule "bundle/matchit"]
 	path = bundle/matchit
 	url = https://github.com/tmhedberg/matchit.git
@@ -46,9 +43,12 @@
 [submodule "bundle/tabline"]
 	path = bundle/tabline
 	url = https://github.com/mkitt/tabline.vim.git
-[submodule "bundle/ultisnips"]
-	path = bundle/ultisnips
-	url = https://github.com/SirVer/ultisnips.git
 [submodule "bundle/YouCompleteMe"]
 	path = bundle/YouCompleteMe
 	url = https://github.com/Valloric/YouCompleteMe.git
+[submodule "bundle/vim-multiple-cursors"]
+	path = bundle/vim-multiple-cursors
+	url = https://github.com/wreed4/vim-multiple-cursors.git
+[submodule "ultisnips"]
+	path = ultisnips
+	url = https://github.com/wreed4/ultisnips.git

+ 37 - 19
.vimrc

@@ -3,12 +3,12 @@
 
 "{{{ *****  PLUGINS  ***** "
 
-" Pathogen
+" #####Pathogen#####
 call pathogen#infect()
 call pathogen#helptags()
 
-" PyMode options
-let pymode_lint_ignore="E501,E401,E225,W191,W391,W404"
+" #####PyMode##### 
+"let pymode_lint_ignore="E501,E401,E225,W191,W391,W404"
 " use rope code assist instead of a complete function
 " au FileType python inoremap <expr> <S-Space> '<C-r>=RopeCodeAssistInsertMode()<CR><C-r>=pumvisible() ? "\<lt>C-p>\<lt>Down>" : ""<CR>'
 
@@ -16,14 +16,13 @@ let pymode_lint_ignore="E501,E401,E225,W191,W391,W404"
 " Toggle tag list
 " nnoremap <C-T> :TlistToggle<CR>
 
-" Tagbar options
+" #####Tagbar##### 
 let g:tagbar_autofocus = 1
 let g:tagbar_left = 1
 let g:tagbar_zoomwidth = 0
-let g:tagbar_autofocus = 1
 
 " open Tagbar automatically when viewing a supported file/files
-autocmd VimEnter * nested :call tagbar#autoopen(1)
+"autocmd VimEnter * nested :call tagbar#autoopen(1)
 " open Tagbar automatically when entering a buffer of supported file/files
 "autocmd BufEnter * nested :call tagbar#autoopen(0)
 
@@ -31,32 +30,41 @@ autocmd VimEnter * nested :call tagbar#autoopen(1)
 nnoremap <leader>tt :TagbarToggle<CR>
 
 
-" Airline
+" #####Airline#####
 let g:airline#extensions#tabline#enabled = 1
 let g:airline#extensions#tabline#show_tab_nr = 1
 let g:airline#extensions#tabline#tab_nr_type = 1
 
 let g:airline#extensions#tagbar#enabled = 1
 let g:airline#extensions#whitespace#enabled = 0
+"let g:airline#extensions#tmuxline#enabled = 1
 
-"NERDTree
+" #####NERDTree#####
 let g:NERDTreeDirArrows = 0
+let g:NERDTreeWinPos = "right"
 nnoremap <leader>nt :NERDTreeToggle<CR>
 
-" UltiSnips
+" #####NerdCommenter#####
+imap <C-c> <plug>NERDCommenterInsert
+
+" #####UltiSnips#####
 let g:UltiSnipsEditSplit = "vertical"
 let g:UltiSnipsJumpForwardTrigger="<TAB>"
 let g:UltiSnipsJumpBackwardTrigger="<S-TAB>"
 let g:UltiSnipsSnippetsDir="~/.vim/bundle/vim-snippets/UltiSnips"
 
 
-" CCTree
+" #####CCTree#####
 nnoremap <leader>ct :CCTreeWindowToggle<CR>
 
-" ConqueTerm
+" #####ConqueTerm#####
 let g:ConqueTerm_CloseOnEnd = 1
+"Conque spits out an error about CursorHoldI making it run slow.  repress
+"these warnings
+let g:ConqueTerm_StartMessages = 0
+
 
-" Pyclewn
+" #####Pyclewn#####
 " Only map keys if we're in Pyclewn
 if has("netbeans_enabled")
     "nmap <silent> <C-p> :exe ":Cprint " .  expand("<cword>")<CR>
@@ -65,9 +73,11 @@ if has("netbeans_enabled")
     vmap <silent> <C-p> "py :Cprint <C-R>p<CR>
 endif
 
-" YouCompleteMe
+" #####YouCompleteMe#####
+" Open preview window when completing
+let g:ycm_add_preview_to_completeopt = 1
 " Auto Close preview window
-let g:ycm_autoclose_preview_window_after_completion = 0
+let g:ycm_autoclose_preview_window_after_completion = 1
 " Disable Tab for cycling through commands so that UtilSnips will still work
 let g:ycm_key_list_select_completion=['<Down>']
 let g:ycm_key_list_previous_completion=['<Up>']
@@ -114,16 +124,17 @@ set smartindent
 set cindent
 filetype plugin indent on
 
+"set background=light
+"let g:solarized_termcolors=256
+"colorscheme solarized
 "colorscheme carvedwoodcool
 "colorscheme wombat256
 "colorscheme zenburn
-"colorscheme kolor
+colorscheme kolor
 "colorscheme jellybeans
 "colorscheme hybrid
 "colorscheme bubblegum
-colorscheme devbox-dark-256
-"set background=light
-"colorscheme solarized
+"colorscheme devbox-dark-256
 
 syntax on
 
@@ -156,6 +167,10 @@ map <C-l> <C-W>l
 " Open tag in new tab
 nnoremap <M-]> <C-W><C-]><C-W>T
 
+" Toggle TODOs as done or not
+nnoremap <silent> <leader>x :s/\[ \]TODO/[X]TODO/<CR>:nohl<CR>
+nnoremap <silent> <leader><space> :s/\[X\]TODO/[ ]TODO/<CR>:nohl<CR>
+
 " }}}
 
 "{{{ ***** PROJECTS ***** "
@@ -179,8 +194,11 @@ endfunction
 
 "{{{ ***** COMMANDS ***** " 
 " make todo list
-command! -nargs=* -complete=file Todos vimgrep /asdf:/gj *|cw
+command! -nargs=* -complete=file Todos vimgrep /TODO(wreed):/gj *|cw
 
 "Wrapper for make sequence
 command! -nargs=* Make execute '!clear' | make! <args> | cw
+
+" Perforce commands
+command! -nargs=0 PerfEdit execute "!p4 edit %" 
 " }}}

+ 0 - 1
bundle/ultisnips

@@ -1 +0,0 @@
-Subproject commit 4dcfca755b1f6ef20fc5c0b23c9ff60e99ac19a4

+ 1 - 0
bundle/vim-multiple-cursors

@@ -0,0 +1 @@
+Subproject commit 35028be1f71953da9f2c28509bf6c5ebd1d31c28

+ 0 - 1
bundle/vim-snippets

@@ -1 +0,0 @@
-Subproject commit e54c5add591ad547c527894946f3317e1b7e847f

+ 0 - 154
ftplugin/python/pymode.vim

@@ -1,154 +0,0 @@
-if pymode#Default('b:pymode', 1)
-    finish
-endif
-
-
-" Parse pymode modeline
-call pymode#Modeline()
-
-
-" Syntax highlight
-if pymode#Option('syntax')
-    let python_highlight_all=1
-endif
-
-
-" Options {{{
-
-" Python other options
-if pymode#Option('options')
-    setlocal complete+=t
-    setlocal formatoptions-=t
-    if v:version > 702 && !&relativenumber
-        setlocal number
-    endif
-    setlocal nowrap
-    setlocal textwidth=79
-endif
-
-" }}}
-
-
-" Documentation {{{
-
-if pymode#Option('doc')
-
-    " DESC: Set commands
-    command! -buffer -nargs=1 Pydoc call pymode#doc#Show("<args>")
-
-    " DESC: Set keys
-    exe "nnoremap <silent> <buffer> " g:pymode_doc_key ":call pymode#doc#Show(expand('<cword>'))<CR>"
-    exe "vnoremap <silent> <buffer> " g:pymode_doc_key ":<C-U>call pymode#doc#Show(@*)<CR>"
-
-endif
-
-" }}}
-
-
-" Lint {{{
-
-if pymode#Option('lint')
-
-    " DESC: Set commands
-    command! -buffer -nargs=0 PyLintToggle :call pymode#lint#Toggle()
-    command! -buffer -nargs=0 PyLintWindowToggle :call pymode#lint#ToggleWindow()
-    command! -buffer -nargs=0 PyLintCheckerToggle :call pymode#lint#ToggleChecker()
-    command! -buffer -nargs=0 PyLint :call pymode#lint#Check()
-    command! -buffer -nargs=0 PyLintAuto :call pymode#lint#Auto()
-
-    " DESC: Set autocommands
-    if pymode#Option('lint_write')
-        au BufWritePost <buffer> PyLint
-    endif
-
-    if pymode#Option('lint_onfly')
-        au InsertLeave <buffer> PyLint
-    endif
-
-    if pymode#Option('lint_message')
-        au CursorHold <buffer> call pymode#lint#show_errormessage()
-        au CursorMoved <buffer> call pymode#lint#show_errormessage()
-    endif
-
-    " DESC: Run queue
-    let &l:updatetime = g:pymode_updatetime
-    au CursorHold <buffer> call pymode#queue#Poll()
-    au BufLeave <buffer> py queue.stop_queue()
-
-endif
-
-" }}}
-
-
-" Rope {{{
-
-if pymode#Option('rope')
-
-    " DESC: Set keys
-    exe "noremap <silent> <buffer> " . g:pymode_rope_short_prefix . "g :RopeGotoDefinition<CR>"
-    exe "noremap <silent> <buffer> " . g:pymode_rope_short_prefix . "d :RopeShowDoc<CR>"
-    exe "noremap <silent> <buffer> " . g:pymode_rope_short_prefix . "f :RopeFindOccurrences<CR>"
-    exe "noremap <silent> <buffer> " . g:pymode_rope_short_prefix . "m :emenu Rope . <TAB>"
-    inoremap <silent> <buffer> <S-TAB> <C-R>=RopeLuckyAssistInsertMode()<CR>
-
-    if g:pymode_rope_map_space
-        let s:prascm = g:pymode_rope_always_show_complete_menu ? "<C-P>" : ""
-        exe "inoremap <silent> <buffer> <Nul> <C-R>=RopeCodeAssistInsertMode()<CR>" . s:prascm
-        exe "inoremap <silent> <buffer> <c-space> <C-R>=RopeCodeAssistInsertMode()<CR>" . s:prascm
-    endif
-
-endif
-
-" }}}
-
-
-" Execution {{{
-
-if pymode#Option('run')
-
-    " DESC: Set commands
-    command! -buffer -nargs=0 -range=% Pyrun call pymode#run#Run(<f-line1>, <f-line2>)
-
-    " DESC: Set keys
-    exe "nnoremap <silent> <buffer> " g:pymode_run_key ":Pyrun<CR>"
-    exe "vnoremap <silent> <buffer> " g:pymode_run_key ":Pyrun<CR>"
-
-endif
-
-" }}}
-
-
-" Breakpoints {{{
-
-if pymode#Option('breakpoint')
-
-    " DESC: Set keys
-    exe "nnoremap <silent> <buffer> " g:pymode_breakpoint_key ":call pymode#breakpoint#Set(line('.'))<CR>"
-
-endif
-
-" }}}
-
-
-" Utils {{{
-
-if pymode#Option('utils_whitespaces')
-    au BufWritePre <buffer> call pymode#TrimWhiteSpace()
-endif
-
-" }}}
-
-
-" Folding {{{
-
-if pymode#Option('folding')
-
-    setlocal foldmethod=expr
-    setlocal foldexpr=pymode#folding#expr(v:lnum)
-    setlocal foldtext=pymode#folding#text()
-
-endif
-
-" }}}
-
-" vim: fdm=marker:fdl=0

+ 0 - 8
plugin-info.txt

@@ -1,8 +0,0 @@
-{
-  "name" : "snipmate",
-  "version" : "dev",
-  "author" : "Michael Sanders <msanders42@gmail.com>",
-  "repository" : {"type": "git", "url": "git://github.com/msanders/snipmate.vim.git"},
-  "dependencies" : {},
-  "description" : "snipMate.vim aims to be a concise vim script that implements some of TextMate's snippets features in Vim."
-}

+ 0 - 0
pylibs/__init__.py


BIN
pylibs/__init__.pyc


Plik diff jest za duży
+ 0 - 1726
pylibs/autopep8.py


BIN
pylibs/autopep8.pyc


+ 0 - 0
pylibs/logilab/__init__.py


+ 0 - 339
pylibs/logilab/astng/COPYING

@@ -1,339 +0,0 @@
-		    GNU GENERAL PUBLIC LICENSE
-		       Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-			    Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Lesser General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-		    GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-			    NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-		     END OF TERMS AND CONDITIONS
-
-	    How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License along
-    with this program; if not, write to the Free Software Foundation, Inc.,
-    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) year name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  <signature of Ty Coon>, 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Lesser General
-Public License instead of this License.

+ 0 - 510
pylibs/logilab/astng/COPYING.LESSER

@@ -1,510 +0,0 @@
-
-                  GNU LESSER GENERAL PUBLIC LICENSE
-                       Version 2.1, February 1999
-
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
-	51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the Lesser GPL.  It also counts
- as the successor of the GNU Library Public License, version 2, hence
- the version number 2.1.]
-
-                            Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
-  This license, the Lesser General Public License, applies to some
-specially designated software packages--typically libraries--of the
-Free Software Foundation and other authors who decide to use it.  You
-can use it too, but we suggest you first think carefully about whether
-this license or the ordinary General Public License is the better
-strategy to use in any particular case, based on the explanations
-below.
-
-  When we speak of free software, we are referring to freedom of use,
-not price.  Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of
-it in new free programs; and that you are informed that you can do
-these things.
-
-  To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights.  These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
-
-  For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you.  You must make sure that they, too, receive or can get the source
-code.  If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling
-it.  And you must show them these terms so they know their rights.
-
-  We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
-  To protect each distributor, we want to make it very clear that
-there is no warranty for the free library.  Also, if the library is
-modified by someone else and passed on, the recipients should know
-that what they have is not the original version, so that the original
-author's reputation will not be affected by problems that might be
-introduced by others.
-
-  Finally, software patents pose a constant threat to the existence of
-any free program.  We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder.  Therefore, we insist that
-any patent license obtained for a version of the library must be
-consistent with the full freedom of use specified in this license.
-
-  Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License.  This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and
-is quite different from the ordinary General Public License.  We use
-this license for certain libraries in order to permit linking those
-libraries into non-free programs.
-
-  When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library.  The ordinary
-General Public License therefore permits such linking only if the
-entire combination fits its criteria of freedom.  The Lesser General
-Public License permits more lax criteria for linking other code with
-the library.
-
-  We call this license the "Lesser" General Public License because it
-does Less to protect the user's freedom than the ordinary General
-Public License.  It also provides other free software developers Less
-of an advantage over competing non-free programs.  These disadvantages
-are the reason we use the ordinary General Public License for many
-libraries.  However, the Lesser license provides advantages in certain
-special circumstances.
-
-  For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it
-becomes a de-facto standard.  To achieve this, non-free programs must
-be allowed to use the library.  A more frequent case is that a free
-library does the same job as widely used non-free libraries.  In this
-case, there is little to gain by limiting the free library to free
-software only, so we use the Lesser General Public License.
-
-  In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of
-free software.  For example, permission to use the GNU C Library in
-non-free programs enables many more people to use the whole GNU
-operating system, as well as its variant, the GNU/Linux operating
-system.
-
-  Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is
-linked with the Library has the freedom and the wherewithal to run
-that program using a modified version of the Library.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.  Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library".  The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-
-                  GNU LESSER GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License Agreement applies to any software library or other
-program which contains a notice placed by the copyright holder or
-other authorized party saying it may be distributed under the terms of
-this Lesser General Public License (also called "this License").
-Each licensee is addressed as "you".
-
-  A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
-  The "Library", below, refers to any such software library or work
-which has been distributed under these terms.  A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language.  (Hereinafter, translation is
-included without limitation in the term "modification".)
-
-  "Source code" for a work means the preferred form of the work for
-making modifications to it.  For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control
-compilation and installation of the library.
-
-  Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it).  Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-
-  1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
-  You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
-  2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) The modified work must itself be a software library.
-
-    b) You must cause the files modified to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    c) You must cause the whole of the work to be licensed at no
-    charge to all third parties under the terms of this License.
-
-    d) If a facility in the modified Library refers to a function or a
-    table of data to be supplied by an application program that uses
-    the facility, other than as an argument passed when the facility
-    is invoked, then you must make a good faith effort to ensure that,
-    in the event an application does not supply such function or
-    table, the facility still operates, and performs whatever part of
-    its purpose remains meaningful.
-
-    (For example, a function in a library to compute square roots has
-    a purpose that is entirely well-defined independent of the
-    application.  Therefore, Subsection 2d requires that any
-    application-supplied function or table used by this function must
-    be optional: if the application does not supply it, the square
-    root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library.  To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License.  (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.)  Do not make any other change in
-these notices.
-
-  Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
-  This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
-  4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
-  If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library".  Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
-  However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library".  The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
-  When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library.  The
-threshold for this to be true is not precisely defined by law.
-
-  If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work.  (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
-  Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
-  6. As an exception to the Sections above, you may also combine or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
-  You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License.  You must supply a copy of this License.  If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License.  Also, you must do one
-of these things:
-
-    a) Accompany the work with the complete corresponding
-    machine-readable source code for the Library including whatever
-    changes were used in the work (which must be distributed under
-    Sections 1 and 2 above); and, if the work is an executable linked
-    with the Library, with the complete machine-readable "work that
-    uses the Library", as object code and/or source code, so that the
-    user can modify the Library and then relink to produce a modified
-    executable containing the modified Library.  (It is understood
-    that the user who changes the contents of definitions files in the
-    Library will not necessarily be able to recompile the application
-    to use the modified definitions.)
-
-    b) Use a suitable shared library mechanism for linking with the
-    Library.  A suitable mechanism is one that (1) uses at run time a
-    copy of the library already present on the user's computer system,
-    rather than copying library functions into the executable, and (2)
-    will operate properly with a modified version of the library, if
-    the user installs one, as long as the modified version is
-    interface-compatible with the version that the work was made with.
-
-    c) Accompany the work with a written offer, valid for at least
-    three years, to give the same user the materials specified in
-    Subsection 6a, above, for a charge no more than the cost of
-    performing this distribution.
-
-    d) If distribution of the work is made by offering access to copy
-    from a designated place, offer equivalent access to copy the above
-    specified materials from the same place.
-
-    e) Verify that the user has already received a copy of these
-    materials or that you have already sent this user a copy.
-
-  For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it.  However, as a special exception,
-the materials to be distributed need not include anything that is
-normally distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
-  It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system.  Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
-  7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
-    a) Accompany the combined library with a copy of the same work
-    based on the Library, uncombined with any other library
-    facilities.  This must be distributed under the terms of the
-    Sections above.
-
-    b) Give prominent notice with the combined library of the fact
-    that part of it is a work based on the Library, and explaining
-    where to find the accompanying uncombined form of the same work.
-
-  8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License.  Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License.  However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
-  9. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Library or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
-  10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties with
-this License.
-
-  11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply, and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License
-may add an explicit geographical distribution limitation excluding those
-countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  13. The Free Software Foundation may publish revised and/or new
-versions of the Lesser General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation.  If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
-  14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission.  For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this.  Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
-                            NO WARRANTY
-
-  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
-                     END OF TERMS AND CONDITIONS
-
-           How to Apply These Terms to Your New Libraries
-
-  If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change.  You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms
-of the ordinary General Public License).
-
-  To apply these terms, attach the following notices to the library.
-It is safest to attach them to the start of each source file to most
-effectively convey the exclusion of warranty; and each file should
-have at least the "copyright" line and a pointer to where the full
-notice is found.
-
-
-    <one line to give the library's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This library is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Lesser General Public
-    License as published by the Free Software Foundation; either
-    version 2.1 of the License, or (at your option) any later version.
-
-    This library is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-    Lesser General Public License for more details.
-
-    You should have received a copy of the GNU Lesser General Public
-    License along with this library; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or
-your school, if any, to sign a "copyright disclaimer" for the library,
-if necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the
-  library `Frob' (a library for tweaking knobs) written by James
-  Random Hacker.
-
-  <signature of Ty Coon>, 1 April 1990
-  Ty Coon, President of Vice
-
-That's all there is to it!
-
-

+ 0 - 54
pylibs/logilab/astng/README

@@ -1,54 +0,0 @@
-ASTNG
-=====
-
-What's this ?
--------------
-
-The aim of this module is to provide a common base representation of
-python source code for projects such as pychecker, pyreverse,
-pylint... Well, actually the development of this library is essentially
-governed by pylint's needs.
-
-It provides a compatible representation which comes from the `_ast` module.
-It rebuilds the tree generated by the builtin _ast module by recursively
-walking down the AST and building an extended ast (let's call it astng ;). The
-new node classes have additional methods and attributes for different usages.
-They include some support for static inference and local name scopes.
-Furthermore, astng builds partial trees by inspecting living objects.
-
-Main modules are:
-
-* `bases`, `node_classses` and `scoped_nodes` contain the classes for the
-  different type of nodes of the tree.
-
-* the `manager` contains a high level object to get astng trees from
-  source files and living objects. It maintains a cache of previously
-  constructed tree for quick access
-
-
-Installation
-------------
-
-Extract the tarball, jump into the created directory and run ::
-
-	python setup.py install
-
-For installation options, see ::
-
-	python setup.py install --help
-
-
-If you have any questions, please mail the
-python-project@lists.logilab.org mailing list for support. See
-http://lists.logilab.org/mailman/listinfo/python-projects for
-subscription information and archives.
-
-Test
-----
-
-Tests are in the 'test' subdirectory. To launch the whole tests suite
-at once, you may use the 'pytest' utility from logilab-common (simply
-type 'pytest' from within this directory) or if you're running python
->= 2.7, using discover, for instance::
-
-  python -m unittest discover -p "unittest*.py"

+ 0 - 26
pylibs/logilab/astng/README.Python3

@@ -1,26 +0,0 @@
-Python3
-=======
-
-Approach
---------
-
-We maintain a Python 2 base and use 2to3 to generate Python 3 code.
-
-2to3 is integrated into the distutils installation process and will be run as a
-build step when invoked by the python3 interpreter::
-
-  python3 setup.py install --no-compile
-
-
-Debian
-------
-
-For the Debian packaging, you can use the debian.py3k/ content against
-the debian/ folder::
-
-  cp debian.py3k/* debian/
-
-
-Resources
----------
-http://wiki.python.org/moin/PortingPythonToPy3k

+ 0 - 85
pylibs/logilab/astng/__init__.py

@@ -1,85 +0,0 @@
-# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-# copyright 2003-2010 Sylvain Thenault, all rights reserved.
-# contact mailto:thenault@gmail.com
-#
-# This file is part of logilab-astng.
-#
-# logilab-astng is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# logilab-astng is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-astng. If not, see <http://www.gnu.org/licenses/>.
-"""Python Abstract Syntax Tree New Generation
-
-The aim of this module is to provide a common base representation of
-python source code for projects such as pychecker, pyreverse,
-pylint... Well, actually the development of this library is essentially
-governed by pylint's needs.
-
-It extends class defined in the python's _ast module with some
-additional methods and attributes. Instance attributes are added by a
-builder object, which can either generate extended ast (let's call
-them astng ;) by visiting an existent ast tree or by inspecting living
-object. Methods are added by monkey patching ast classes.
-
-Main modules are:
-
-* nodes and scoped_nodes for more information about methods and
-  attributes added to different node classes
-
-* the manager contains a high level object to get astng trees from
-  source files and living objects. It maintains a cache of previously
-  constructed tree for quick access
-
-* builder contains the class responsible to build astng trees
-"""
-__doctype__ = "restructuredtext en"
-
-import sys
-if sys.version_info >= (3, 0):
-    BUILTINS_MODULE = 'builtins'
-else:
-    BUILTINS_MODULE = '__builtin__'
-
-# WARNING: internal imports order matters !
-
-# make all exception classes accessible from astng package
-from logilab.astng.exceptions import *
-
-# make all node classes accessible from astng package
-from logilab.astng.nodes import *
-
-# trigger extra monkey-patching
-from logilab.astng import inference
-
-# more stuff available
-from logilab.astng import raw_building
-from logilab.astng.bases import YES, Instance, BoundMethod, UnboundMethod
-from logilab.astng.node_classes import are_exclusive, unpack_infer
-from logilab.astng.scoped_nodes import builtin_lookup
-
-# make a manager instance (borg) as well as Project and Package classes
-# accessible from astng package
-from logilab.astng.manager import ASTNGManager, Project
-MANAGER = ASTNGManager()
-del ASTNGManager
-
-# load brain plugins
-from os import listdir
-from os.path import join, dirname
-BRAIN_MODULES_DIR = join(dirname(__file__), 'brain')
-if BRAIN_MODULES_DIR not in sys.path:
-    # add it to the end of the list so user path take precedence
-    sys.path.append(BRAIN_MODULES_DIR)
-# load modules in this directory
-for module in listdir(BRAIN_MODULES_DIR):
-    if module.endswith('.py'):
-        __import__(module[:-3])

+ 0 - 45
pylibs/logilab/astng/__pkginfo__.py

@@ -1,45 +0,0 @@
-# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-# copyright 2003-2010 Sylvain Thenault, all rights reserved.
-# contact mailto:thenault@gmail.com
-#
-# This file is part of logilab-astng.
-#
-# logilab-astng is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# logilab-astng is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-astng. If not, see <http://www.gnu.org/licenses/>.
-"""logilab.astng packaging information"""
-
-distname = 'logilab-astng'
-
-modname = 'astng'
-subpackage_of = 'logilab'
-
-numversion = (0, 24, 0)
-version = '.'.join([str(num) for num in numversion])
-
-install_requires = ['logilab-common >= 0.53.0']
-
-license = 'LGPL'
-
-author = 'Logilab'
-author_email = 'python-projects@lists.logilab.org'
-mailinglist = "mailto://%s" % author_email
-web = "http://www.logilab.org/project/%s" % distname
-ftp = "ftp://ftp.logilab.org/pub/%s" % modname
-
-description = "rebuild a new abstract syntax tree from Python's ast"
-
-from os.path import join
-include_dirs = ['brain',
-                join('test', 'regrtest_data'),
-                join('test', 'data'), join('test', 'data2')]

+ 0 - 427
pylibs/logilab/astng/as_string.py

@@ -1,427 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-# copyright 2003-2010 Sylvain Thenault, all rights reserved.
-# contact mailto:thenault@gmail.com
-#
-# This file is part of logilab-astng.
-#
-# logilab-astng is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# logilab-astng is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-astng. If not, see <http://www.gnu.org/licenses/>.
-"""This module renders ASTNG nodes to string representation.
-
-It will probably not work on bare _ast trees.
-"""
-import sys
-
-
-INDENT = '    ' # 4 spaces ; keep indentation variable
-
-
-def _import_string(names):
-    """return a list of (name, asname) formatted as a string"""
-    _names = []
-    for name, asname in names:
-        if asname is not None:
-            _names.append('%s as %s' % (name, asname))
-        else:
-            _names.append(name)
-    return  ', '.join(_names)
-
-
-class AsStringVisitor(object):
-    """Visitor to render an ASTNG node as string """
-
-    def __call__(self, node):
-        """Makes this visitor behave as a simple function"""
-        return node.accept(self)
-
-    def _stmt_list(self, stmts):
-        """return a list of nodes to string"""
-        stmts = '\n'.join([nstr for nstr in [n.accept(self) for n in stmts] if nstr])
-        return INDENT + stmts.replace('\n', '\n'+INDENT)
-
-
-    ## visit_<node> methods ###########################################
-
-    def visit_arguments(self, node):
-        """return an astng.Function node as string"""
-        return node.format_args()
-
-    def visit_assattr(self, node):
-        """return an astng.AssAttr node as string"""
-        return self.visit_getattr(node)
-
-    def visit_assert(self, node):
-        """return an astng.Assert node as string"""
-        if node.fail:
-            return 'assert %s, %s' % (node.test.accept(self),
-                                        node.fail.accept(self))
-        return 'assert %s' % node.test.accept(self)
-
-    def visit_assname(self, node):
-        """return an astng.AssName node as string"""
-        return node.name
-
-    def visit_assign(self, node):
-        """return an astng.Assign node as string"""
-        lhs = ' = '.join([n.accept(self) for n in node.targets])
-        return '%s = %s' % (lhs, node.value.accept(self))
-
-    def visit_augassign(self, node):
-        """return an astng.AugAssign node as string"""
-        return '%s %s %s' % (node.target.accept(self), node.op, node.value.accept(self))
-
-    def visit_backquote(self, node):
-        """return an astng.Backquote node as string"""
-        return '`%s`' % node.value.accept(self)
-
-    def visit_binop(self, node):
-        """return an astng.BinOp node as string"""
-        return '(%s) %s (%s)' % (node.left.accept(self), node.op, node.right.accept(self))
-
-    def visit_boolop(self, node):
-        """return an astng.BoolOp node as string"""
-        return (' %s ' % node.op).join(['(%s)' % n.accept(self)
-                                            for n in node.values])
-
-    def visit_break(self, node):
-        """return an astng.Break node as string"""
-        return 'break'
-
-    def visit_callfunc(self, node):
-        """return an astng.CallFunc node as string"""
-        expr_str = node.func.accept(self)
-        args = [arg.accept(self) for arg in node.args]
-        if node.starargs:
-            args.append( '*' + node.starargs.accept(self))
-        if node.kwargs:
-            args.append( '**' + node.kwargs.accept(self))
-        return '%s(%s)' % (expr_str, ', '.join(args))
-
-    def visit_class(self, node):
-        """return an astng.Class node as string"""
-        decorate = node.decorators and node.decorators.accept(self)  or ''
-        bases =  ', '.join([n.accept(self) for n in node.bases])
-        bases = bases and '(%s)' % bases or ''
-        docs = node.doc and '\n%s"""%s"""' % (INDENT, node.doc) or ''
-        return '\n\n%sclass %s%s:%s\n%s\n' % (decorate, node.name, bases, docs,
-                                            self._stmt_list( node.body))
-
-    def visit_compare(self, node):
-        """return an astng.Compare node as string"""
-        rhs_str = ' '.join(['%s %s' % (op, expr.accept(self))
-                            for op, expr in node.ops])
-        return '%s %s' % (node.left.accept(self), rhs_str)
-
-    def visit_comprehension(self, node):
-        """return an astng.Comprehension node as string"""
-        ifs = ''.join([ ' if %s' % n.accept(self) for n in node.ifs])
-        return 'for %s in %s%s' % (node.target.accept(self),
-                                    node.iter.accept(self), ifs )
-
-    def visit_const(self, node):
-        """return an astng.Const node as string"""
-        return repr(node.value)
-
-    def visit_continue(self, node):
-        """return an astng.Continue node as string"""
-        return 'continue'
-
-    def visit_delete(self, node): # XXX check if correct
-        """return an astng.Delete node as string"""
-        return 'del %s' % ', '.join([child.accept(self)
-                                for child in node.targets])
-
-    def visit_delattr(self, node):
-        """return an astng.DelAttr node as string"""
-        return self.visit_getattr(node)
-
-    def visit_delname(self, node):
-        """return an astng.DelName node as string"""
-        return node.name
-
-    def visit_decorators(self, node):
-        """return an astng.Decorators node as string"""
-        return '@%s\n' % '\n@'.join([item.accept(self) for item in node.nodes])
-
-    def visit_dict(self, node):
-        """return an astng.Dict node as string"""
-        return '{%s}' % ', '.join(['%s: %s' % (key.accept(self),
-                            value.accept(self)) for key, value in node.items])
-
-    def visit_dictcomp(self, node):
-        """return an astng.DictComp node as string"""
-        return '{%s: %s %s}' % (node.key.accept(self), node.value.accept(self),
-                ' '.join([n.accept(self) for n in node.generators]))
-
-    def visit_discard(self, node):
-        """return an astng.Discard node as string"""
-        return node.value.accept(self)
-
-    def visit_emptynode(self, node):
-        """dummy method for visiting an Empty node"""
-        return ''
-
-    def visit_excepthandler(self, node):
-        if node.type:
-            if node.name:
-                excs = 'except %s, %s' % (node.type.accept(self),
-                                        node.name.accept(self))
-            else:
-                excs = 'except %s' % node.type.accept(self)
-        else:
-            excs = 'except'
-        return '%s:\n%s' % (excs, self._stmt_list(node.body))
-
-    def visit_ellipsis(self, node):
-        """return an astng.Ellipsis node as string"""
-        return '...'
-
-    def visit_empty(self, node):
-        """return an Empty node as string"""
-        return ''
-
-    def visit_exec(self, node):
-        """return an astng.Exec node as string"""
-        if node.locals:
-            return 'exec %s in %s, %s' % (node.expr.accept(self),
-                                          node.locals.accept(self),
-                                          node.globals.accept(self))
-        if node.globals:
-            return 'exec %s in %s' % (node.expr.accept(self),
-                                      node.globals.accept(self))
-        return 'exec %s' % node.expr.accept(self)
-
-    def visit_extslice(self, node):
-        """return an astng.ExtSlice node as string"""
-        return ','.join( [dim.accept(self) for dim in node.dims] )
-
-    def visit_for(self, node):
-        """return an astng.For node as string"""
-        fors = 'for %s in %s:\n%s' % (node.target.accept(self),
-                                    node.iter.accept(self),
-                                    self._stmt_list( node.body))
-        if node.orelse:
-            fors = '%s\nelse:\n%s' % (fors, self._stmt_list(node.orelse))
-        return fors
-
-    def visit_from(self, node):
-        """return an astng.From node as string"""
-        return 'from %s import %s' % ('.' * (node.level or 0) + node.modname,
-                                      _import_string(node.names))
-
-    def visit_function(self, node):
-        """return an astng.Function node as string"""
-        decorate = node.decorators and node.decorators.accept(self)  or ''
-        docs = node.doc and '\n%s"""%s"""' % (INDENT, node.doc) or ''
-        return '\n%sdef %s(%s):%s\n%s' % (decorate, node.name, node.args.accept(self),
-                                        docs, self._stmt_list(node.body))
-
-    def visit_genexpr(self, node):
-        """return an astng.GenExpr node as string"""
-        return '(%s %s)' % (node.elt.accept(self), ' '.join([n.accept(self)
-                                                    for n in node.generators]))
-
-    def visit_getattr(self, node):
-        """return an astng.Getattr node as string"""
-        return '%s.%s' % (node.expr.accept(self), node.attrname)
-
-    def visit_global(self, node):
-        """return an astng.Global node as string"""
-        return 'global %s' % ', '.join(node.names)
-
-    def visit_if(self, node):
-        """return an astng.If node as string"""
-        ifs = ['if %s:\n%s' % (node.test.accept(self), self._stmt_list(node.body))]
-        if node.orelse:# XXX use elif ???
-            ifs.append('else:\n%s' % self._stmt_list(node.orelse))
-        return '\n'.join(ifs)
-
-    def visit_ifexp(self, node):
-        """return an astng.IfExp node as string"""
-        return '%s if %s else %s' % (node.body.accept(self),
-                node.test.accept(self), node.orelse.accept(self))
-
-    def visit_import(self, node):
-        """return an astng.Import node as string"""
-        return 'import %s' % _import_string(node.names)
-
-    def visit_keyword(self, node):
-        """return an astng.Keyword node as string"""
-        return '%s=%s' % (node.arg, node.value.accept(self))
-
-    def visit_lambda(self, node):
-        """return an astng.Lambda node as string"""
-        return 'lambda %s: %s' % (node.args.accept(self), node.body.accept(self))
-
-    def visit_list(self, node):
-        """return an astng.List node as string"""
-        return '[%s]' % ', '.join([child.accept(self) for child in node.elts])
-
-    def visit_listcomp(self, node):
-        """return an astng.ListComp node as string"""
-        return '[%s %s]' % (node.elt.accept(self), ' '.join([n.accept(self)
-                                                for n in node.generators]))
-
-    def visit_module(self, node):
-        """return an astng.Module node as string"""
-        docs = node.doc and '"""%s"""\n\n' % node.doc or ''
-        return docs + '\n'.join([n.accept(self) for n in node.body]) + '\n\n'
-
-    def visit_name(self, node):
-        """return an astng.Name node as string"""
-        return node.name
-
-    def visit_pass(self, node):
-        """return an astng.Pass node as string"""
-        return 'pass'
-
-    def visit_print(self, node):
-        """return an astng.Print node as string"""
-        nodes = ', '.join([n.accept(self) for n in node.values])
-        if not node.nl:
-            nodes = '%s,' % nodes
-        if node.dest:
-            return 'print >> %s, %s' % (node.dest.accept(self), nodes)
-        return 'print %s' % nodes
-
-    def visit_raise(self, node):
-        """return an astng.Raise node as string"""
-        if node.exc:
-            if node.inst:
-                if node.tback:
-                    return 'raise %s, %s, %s' % (node.exc.accept(self),
-                                                node.inst.accept(self),
-                                                node.tback.accept(self))
-                return 'raise %s, %s' % (node.exc.accept(self),
-                                        node.inst.accept(self))
-            return 'raise %s' % node.exc.accept(self)
-        return 'raise'
-
-    def visit_return(self, node):
-        """return an astng.Return node as string"""
-        if node.value:
-            return 'return %s' % node.value.accept(self)
-        else:
-            return 'return'
-
-    def visit_index(self, node):
-        """return a astng.Index node as string"""
-        return node.value.accept(self)
-
-    def visit_set(self, node):
-        """return an astng.Set node as string"""
-        return '{%s}' % ', '.join([child.accept(self) for child in node.elts])
-
-    def visit_setcomp(self, node):
-        """return an astng.SetComp node as string"""
-        return '{%s %s}' % (node.elt.accept(self), ' '.join([n.accept(self)
-                                                for n in node.generators]))
-
-    def visit_slice(self, node):
-        """return a astng.Slice node as string"""
-        lower = node.lower and node.lower.accept(self) or ''
-        upper = node.upper and node.upper.accept(self) or ''
-        step = node.step and node.step.accept(self) or ''
-        if step:
-            return '%s:%s:%s' % (lower, upper, step)
-        return  '%s:%s' % (lower, upper)
-
-    def visit_subscript(self, node):
-        """return an astng.Subscript node as string"""
-        return '%s[%s]' % (node.value.accept(self), node.slice.accept(self))
-
-    def visit_tryexcept(self, node):
-        """return an astng.TryExcept node as string"""
-        trys = ['try:\n%s' % self._stmt_list( node.body)]
-        for handler in node.handlers:
-            trys.append(handler.accept(self))
-        if node.orelse:
-            trys.append('else:\n%s' % self._stmt_list(node.orelse))
-        return '\n'.join(trys)
-
-    def visit_tryfinally(self, node):
-        """return an astng.TryFinally node as string"""
-        return 'try:\n%s\nfinally:\n%s' % (self._stmt_list( node.body),
-                                        self._stmt_list(node.finalbody))
-
-    def visit_tuple(self, node):
-        """return an astng.Tuple node as string"""
-        return '(%s)' % ', '.join([child.accept(self) for child in node.elts])
-
-    def visit_unaryop(self, node):
-        """return an astng.UnaryOp node as string"""
-        if node.op == 'not':
-            operator = 'not '
-        else:
-            operator = node.op
-        return '%s%s' % (operator, node.operand.accept(self))
-
-    def visit_while(self, node):
-        """return an astng.While node as string"""
-        whiles = 'while %s:\n%s' % (node.test.accept(self),
-                                    self._stmt_list(node.body))
-        if node.orelse:
-            whiles = '%s\nelse:\n%s' % (whiles, self._stmt_list(node.orelse))
-        return whiles
-
-    def visit_with(self, node): # 'with' without 'as' is possible
-        """return an astng.With node as string"""
-        as_var = node.vars and " as (%s)" % (node.vars.accept(self)) or ""
-        withs = 'with (%s)%s:\n%s' % (node.expr.accept(self), as_var,
-                                        self._stmt_list( node.body))
-        return withs
-
-    def visit_yield(self, node):
-        """yield an ast.Yield node as string"""
-        yi_val = node.value and (" " + node.value.accept(self)) or ""
-        return 'yield' + yi_val
-
-
-class AsStringVisitor3k(AsStringVisitor):
-    """AsStringVisitor3k overwrites some AsStringVisitor methods"""
-
-    def visit_excepthandler(self, node):
-        if node.type:
-            if node.name:
-                excs = 'except %s as %s' % (node.type.accept(self),
-                                        node.name.accept(self))
-            else:
-                excs = 'except %s' % node.type.accept(self)
-        else:
-            excs = 'except'
-        return '%s:\n%s' % (excs, self._stmt_list(node.body))
-
-    def visit_nonlocal(self, node):
-        """return an astng.Nonlocal node as string"""
-        return 'nonlocal %s' % ', '.join(node.names)
-
-    def visit_raise(self, node):
-        """return an astng.Raise node as string"""
-        if node.exc:
-            if node.cause:
-                return 'raise %s from %s' % (node.exc.accept(self),
-                                             node.cause.accept(self))
-            return 'raise %s' % node.exc.accept(self)
-        return 'raise'
-
-    def visit_starred(self, node):
-        """return Starred node as string"""
-        return "*" + node.value.accept(self)
-
-if sys.version_info >= (3, 0):
-    AsStringVisitor = AsStringVisitor3k
-
-# this visitor is stateless, thus it can be reused
-as_string = AsStringVisitor()
-

+ 0 - 629
pylibs/logilab/astng/bases.py

@@ -1,629 +0,0 @@
-# -*- coding: utf-8 -*-
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-# copyright 2003-2010 Sylvain Thenault, all rights reserved.
-# contact mailto:thenault@gmail.com
-#
-# This file is part of logilab-astng.
-#
-# logilab-astng is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# logilab-astng is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-astng. If not, see <http://www.gnu.org/licenses/>.
-"""This module contains base classes and functions for the nodes and some
-inference utils.
-"""
-
-__docformat__ = "restructuredtext en"
-
-from contextlib import contextmanager
-
-from logilab.common.compat import builtins
-
-from logilab.astng import BUILTINS_MODULE
-from logilab.astng.exceptions import InferenceError, ASTNGError, \
-                                       NotFoundError, UnresolvableName
-from logilab.astng.as_string import as_string
-
-BUILTINS_NAME = builtins.__name__
-
-class Proxy(object):
-    """a simple proxy object"""
-    _proxied = None
-
-    def __init__(self, proxied=None):
-        if proxied is not None:
-            self._proxied = proxied
-
-    def __getattr__(self, name):
-        if name == '_proxied':
-            return getattr(self.__class__, '_proxied')
-        if name in self.__dict__:
-            return self.__dict__[name]
-        return getattr(self._proxied, name)
-
-    def infer(self, context=None):
-        yield self
-
-
-# Inference ##################################################################
-
-class InferenceContext(object):
-    __slots__ = ('path', 'lookupname', 'callcontext', 'boundnode')
-
-    def __init__(self, path=None):
-        if path is None:
-            self.path = set()
-        else:
-            self.path = path
-        self.lookupname = None
-        self.callcontext = None
-        self.boundnode = None
-
-    def push(self, node):
-        name = self.lookupname
-        if (node, name) in self.path:
-            raise StopIteration()
-        self.path.add( (node, name) )
-
-    def clone(self):
-        # XXX copy lookupname/callcontext ?
-        clone = InferenceContext(self.path)
-        clone.callcontext = self.callcontext
-        clone.boundnode = self.boundnode
-        return clone
-
-    @contextmanager
-    def restore_path(self):
-        path = set(self.path)
-        yield
-        self.path = path
-
-def copy_context(context):
-    if context is not None:
-        return context.clone()
-    else:
-        return InferenceContext()
-
-
-def _infer_stmts(stmts, context, frame=None):
-    """return an iterator on statements inferred by each statement in <stmts>
-    """
-    stmt = None
-    infered = False
-    if context is not None:
-        name = context.lookupname
-        context = context.clone()
-    else:
-        name = None
-        context = InferenceContext()
-    for stmt in stmts:
-        if stmt is YES:
-            yield stmt
-            infered = True
-            continue
-        context.lookupname = stmt._infer_name(frame, name)
-        try:
-            for infered in stmt.infer(context):
-                yield infered
-                infered = True
-        except UnresolvableName:
-            continue
-        except InferenceError:
-            yield YES
-            infered = True
-    if not infered:
-        raise InferenceError(str(stmt))
-
-
-# special inference objects (e.g. may be returned as nodes by .infer()) #######
-
-class _Yes(object):
-    """a yes object"""
-    def __repr__(self):
-        return 'YES'
-    def __getattribute__(self, name):
-        if name.startswith('__') and name.endswith('__'):
-            # to avoid inspection pb
-            return super(_Yes, self).__getattribute__(name)
-        return self
-    def __call__(self, *args, **kwargs):
-        return self
-
-
-YES = _Yes()
-
-
-class Instance(Proxy):
-    """a special node representing a class instance"""
-    def getattr(self, name, context=None, lookupclass=True):
-        try:
-            values = self._proxied.instance_attr(name, context)
-        except NotFoundError:
-            if name == '__class__':
-                return [self._proxied]
-            if lookupclass:
-                # class attributes not available through the instance
-                # unless they are explicitly defined
-                if name in ('__name__', '__bases__', '__mro__', '__subclasses__'):
-                    return self._proxied.local_attr(name)
-                return self._proxied.getattr(name, context)
-            raise NotFoundError(name)
-        # since we've no context information, return matching class members as
-        # well
-        if lookupclass:
-            try:
-                return values + self._proxied.getattr(name, context)
-            except NotFoundError:
-                pass
-        return values
-
-    def igetattr(self, name, context=None):
-        """inferred getattr"""
-        try:
-            # XXX frame should be self._proxied, or not ?
-            get_attr = self.getattr(name, context, lookupclass=False)
-            return _infer_stmts(self._wrap_attr(get_attr, context), context,
-                                frame=self)
-        except NotFoundError:
-            try:
-                # fallback to class'igetattr since it has some logic to handle
-                # descriptors
-                return self._wrap_attr(self._proxied.igetattr(name, context),
-                                       context)
-            except NotFoundError:
-                raise InferenceError(name)
-
-    def _wrap_attr(self, attrs, context=None):
-        """wrap bound methods of attrs in a InstanceMethod proxies"""
-        for attr in attrs:
-            if isinstance(attr, UnboundMethod):
-                if BUILTINS_NAME + '.property' in attr.decoratornames():
-                    for infered in attr.infer_call_result(self, context):
-                        yield infered
-                else:
-                    yield BoundMethod(attr, self)
-            else:
-                yield attr
-
-    def infer_call_result(self, caller, context=None):
-        """infer what a class instance is returning when called"""
-        infered = False
-        for node in self._proxied.igetattr('__call__', context):
-            for res in node.infer_call_result(caller, context):
-                infered = True
-                yield res
-        if not infered:
-            raise InferenceError()
-
-    def __repr__(self):
-        return '<Instance of %s.%s at 0x%s>' % (self._proxied.root().name,
-                                                self._proxied.name,
-                                                id(self))
-    def __str__(self):
-        return 'Instance of %s.%s' % (self._proxied.root().name,
-                                      self._proxied.name)
-
-    def callable(self):
-        try:
-            self._proxied.getattr('__call__')
-            return True
-        except NotFoundError:
-            return False
-
-    def pytype(self):
-        return self._proxied.qname()
-
-    def display_type(self):
-        return 'Instance of'
-
-
-class UnboundMethod(Proxy):
-    """a special node representing a method not bound to an instance"""
-    def __repr__(self):
-        frame = self._proxied.parent.frame()
-        return '<%s %s of %s at 0x%s' % (self.__class__.__name__,
-                                         self._proxied.name,
-                                         frame.qname(), id(self))
-
-    def is_bound(self):
-        return False
-
-    def getattr(self, name, context=None):
-        if name == 'im_func':
-            return [self._proxied]
-        return super(UnboundMethod, self).getattr(name, context)
-
-    def igetattr(self, name, context=None):
-        if name == 'im_func':
-            return iter((self._proxied,))
-        return super(UnboundMethod, self).igetattr(name, context)
-
-    def infer_call_result(self, caller, context):
-        # If we're unbound method __new__ of builtin object, the result is an
-        # instance of the class given as first argument.
-        if (self._proxied.name == '__new__' and
-                self._proxied.parent.frame().qname() == '%s.object' % BUILTINS_MODULE):
-            return (x is YES and x or Instance(x) for x in caller.args[0].infer())
-        return self._proxied.infer_call_result(caller, context)
-
-
-class BoundMethod(UnboundMethod):
-    """a special node representing a method bound to an instance"""
-    def __init__(self,  proxy, bound):
-        UnboundMethod.__init__(self, proxy)
-        self.bound = bound
-
-    def is_bound(self):
-        return True
-
-    def infer_call_result(self, caller, context):
-        context = context.clone()
-        context.boundnode = self.bound
-        return self._proxied.infer_call_result(caller, context)
-
-
-class Generator(Instance):
-    """a special node representing a generator"""
-    def callable(self):
-        return True
-
-    def pytype(self):
-        return '%s.generator' % BUILTINS_MODULE
-
-    def display_type(self):
-        return 'Generator'
-
-    def __repr__(self):
-        return '<Generator(%s) l.%s at 0x%s>' % (self._proxied.name, self.lineno, id(self))
-
-    def __str__(self):
-        return 'Generator(%s)' % (self._proxied.name)
-
-
-# decorators ##################################################################
-
-def path_wrapper(func):
-    """return the given infer function wrapped to handle the path"""
-    def wrapped(node, context=None, _func=func, **kwargs):
-        """wrapper function handling context"""
-        if context is None:
-            context = InferenceContext()
-        context.push(node)
-        yielded = set()
-        for res in _func(node, context, **kwargs):
-            # unproxy only true instance, not const, tuple, dict...
-            if res.__class__ is Instance:
-                ares = res._proxied
-            else:
-                ares = res
-            if not ares in yielded:
-                yield res
-                yielded.add(ares)
-    return wrapped
-
-def yes_if_nothing_infered(func):
-    def wrapper(*args, **kwargs):
-        infered = False
-        for node in func(*args, **kwargs):
-            infered = True
-            yield node
-        if not infered:
-            yield YES
-    return wrapper
-
-def raise_if_nothing_infered(func):
-    def wrapper(*args, **kwargs):
-        infered = False
-        for node in func(*args, **kwargs):
-            infered = True
-            yield node
-        if not infered:
-            raise InferenceError()
-    return wrapper
-
-
-# Node  ######################################################################
-
-class NodeNG(object):
-    """Base Class for all ASTNG node classes.
-
-    It represents a node of the new abstract syntax tree.
-    """
-    is_statement = False
-    optional_assign = False # True  for For (and for Comprehension if py <3.0)
-    is_function = False # True for Function nodes
-    # attributes below are set by the builder module or by raw factories
-    lineno = None
-    fromlineno = None
-    tolineno = None
-    col_offset = None
-    # parent node in the tree
-    parent = None
-    # attributes containing child node(s) redefined in most concrete classes:
-    _astng_fields = ()
-
-    def _repr_name(self):
-        """return self.name or self.attrname or '' for nice representation"""
-        return getattr(self, 'name', getattr(self, 'attrname', ''))
-
-    def __str__(self):
-        return '%s(%s)' % (self.__class__.__name__, self._repr_name())
-
-    def __repr__(self):
-        return '<%s(%s) l.%s [%s] at Ox%x>' % (self.__class__.__name__,
-                                           self._repr_name(),
-                                           self.fromlineno,
-                                           self.root().name,
-                                           id(self))
-
-
-    def accept(self, visitor):
-        klass = self.__class__.__name__
-        func = getattr(visitor, "visit_" + self.__class__.__name__.lower())
-        return func(self)
-
-    def get_children(self):
-        for field in self._astng_fields:
-            attr = getattr(self, field)
-            if attr is None:
-                continue
-            if isinstance(attr, (list, tuple)):
-                for elt in attr:
-                    yield elt
-            else:
-                yield attr
-
-    def last_child(self):
-        """an optimized version of list(get_children())[-1]"""
-        for field in self._astng_fields[::-1]:
-            attr = getattr(self, field)
-            if not attr: # None or empty listy / tuple
-                continue
-            if isinstance(attr, (list, tuple)):
-                return attr[-1]
-            else:
-                return attr
-        return None
-
-    def parent_of(self, node):
-        """return true if i'm a parent of the given node"""
-        parent = node.parent
-        while parent is not None:
-            if self is parent:
-                return True
-            parent = parent.parent
-        return False
-
-    def statement(self):
-        """return the first parent node marked as statement node"""
-        if self.is_statement:
-            return self
-        return self.parent.statement()
-
-    def frame(self):
-        """return the first parent frame node (i.e. Module, Function or Class)
-        """
-        return self.parent.frame()
-
-    def scope(self):
-        """return the first node defining a new scope (i.e. Module, Function,
-        Class, Lambda but also GenExpr)
-        """
-        return self.parent.scope()
-
-    def root(self):
-        """return the root node of the tree, (i.e. a Module)"""
-        if self.parent:
-            return self.parent.root()
-        return self
-
-    def child_sequence(self, child):
-        """search for the right sequence where the child lies in"""
-        for field in self._astng_fields:
-            node_or_sequence = getattr(self, field)
-            if node_or_sequence is child:
-                return [node_or_sequence]
-            # /!\ compiler.ast Nodes have an __iter__ walking over child nodes
-            if isinstance(node_or_sequence, (tuple, list)) and child in node_or_sequence:
-                return node_or_sequence
-        else:
-            msg = 'Could not found %s in %s\'s children'
-            raise ASTNGError(msg % (repr(child), repr(self)))
-
-    def locate_child(self, child):
-        """return a 2-uple (child attribute name, sequence or node)"""
-        for field in self._astng_fields:
-            node_or_sequence = getattr(self, field)
-            # /!\ compiler.ast Nodes have an __iter__ walking over child nodes
-            if child is node_or_sequence:
-                return field, child
-            if isinstance(node_or_sequence, (tuple, list)) and child in node_or_sequence:
-                return field, node_or_sequence
-        msg = 'Could not found %s in %s\'s children'
-        raise ASTNGError(msg % (repr(child), repr(self)))
-    # FIXME : should we merge child_sequence and locate_child ? locate_child
-    # is only used in are_exclusive, child_sequence one time in pylint.
-
-    def next_sibling(self):
-        """return the next sibling statement"""
-        return self.parent.next_sibling()
-
-    def previous_sibling(self):
-        """return the previous sibling statement"""
-        return self.parent.previous_sibling()
-
-    def nearest(self, nodes):
-        """return the node which is the nearest before this one in the
-        given list of nodes
-        """
-        myroot = self.root()
-        mylineno = self.fromlineno
-        nearest = None, 0
-        for node in nodes:
-            assert node.root() is myroot, \
-                   'nodes %s and %s are not from the same module' % (self, node)
-            lineno = node.fromlineno
-            if node.fromlineno > mylineno:
-                break
-            if lineno > nearest[1]:
-                nearest = node, lineno
-        # FIXME: raise an exception if nearest is None ?
-        return nearest[0]
-
-    def set_line_info(self, lastchild):
-        if self.lineno is None:
-            self.fromlineno = self._fixed_source_line()
-        else:
-            self.fromlineno = self.lineno
-        if lastchild is None:
-            self.tolineno = self.fromlineno
-        else:
-            self.tolineno = lastchild.tolineno
-        return
-        # TODO / FIXME:
-        assert self.fromlineno is not None, self
-        assert self.tolineno is not None, self
-
-    def _fixed_source_line(self):
-        """return the line number where the given node appears
-
-        we need this method since not all nodes have the lineno attribute
-        correctly set...
-        """
-        line = self.lineno
-        _node = self
-        try:
-            while line is None:
-                _node = _node.get_children().next()
-                line = _node.lineno
-        except StopIteration:
-            _node = self.parent
-            while _node and line is None:
-                line = _node.lineno
-                _node = _node.parent
-        return line
-
-    def block_range(self, lineno):
-        """handle block line numbers range for non block opening statements
-        """
-        return lineno, self.tolineno
-
-    def set_local(self, name, stmt):
-        """delegate to a scoped parent handling a locals dictionary"""
-        self.parent.set_local(name, stmt)
-
-    def nodes_of_class(self, klass, skip_klass=None):
-        """return an iterator on nodes which are instance of the given class(es)
-
-        klass may be a class object or a tuple of class objects
-        """
-        if isinstance(self, klass):
-            yield self
-        for child_node in self.get_children():
-            if skip_klass is not None and isinstance(child_node, skip_klass):
-                continue
-            for matching in child_node.nodes_of_class(klass, skip_klass):
-                yield matching
-
-    def _infer_name(self, frame, name):
-        # overridden for From, Import, Global, TryExcept and Arguments
-        return None
-
-    def infer(self, context=None):
-        """we don't know how to resolve a statement by default"""
-        # this method is overridden by most concrete classes
-        raise InferenceError(self.__class__.__name__)
-
-    def infered(self):
-        '''return list of infered values for a more simple inference usage'''
-        return list(self.infer())
-
-    def instanciate_class(self):
-        """instanciate a node if it is a Class node, else return self"""
-        return self
-
-    def has_base(self, node):
-        return False
-
-    def callable(self):
-        return False
-
-    def eq(self, value):
-        return False
-
-    def as_string(self):
-        return as_string(self)
-
-    def repr_tree(self, ids=False):
-        """print a nice astng tree representation.
-
-        :param ids: if true, we also print the ids (usefull for debugging)"""
-        result = []
-        _repr_tree(self, result, ids=ids)
-        return "\n".join(result)
-
-
-class Statement(NodeNG):
-    """Statement node adding a few attributes"""
-    is_statement = True
-
-    def next_sibling(self):
-        """return the next sibling statement"""
-        stmts = self.parent.child_sequence(self)
-        index = stmts.index(self)
-        try:
-            return stmts[index +1]
-        except IndexError:
-            pass
-
-    def previous_sibling(self):
-        """return the previous sibling statement"""
-        stmts = self.parent.child_sequence(self)
-        index = stmts.index(self)
-        if index >= 1:
-            return stmts[index -1]
-
-INDENT = "    "
-
-def _repr_tree(node, result, indent='', _done=None, ids=False):
-    """built a tree representation of a node as a list of lines"""
-    if _done is None:
-        _done = set()
-    if not hasattr(node, '_astng_fields'): # not a astng node
-        return
-    if node in _done:
-        result.append( indent + 'loop in tree: %s' % node )
-        return
-    _done.add(node)
-    node_str = str(node)
-    if ids:
-        node_str += '  . \t%x' % id(node)
-    result.append( indent + node_str )
-    indent += INDENT
-    for field in node._astng_fields:
-        value = getattr(node, field)
-        if isinstance(value, (list, tuple) ):
-            result.append(  indent + field + " = [" )
-            for child in value:
-                if isinstance(child, (list, tuple) ):
-                    # special case for Dict # FIXME
-                    _repr_tree(child[0], result, indent, _done, ids)
-                    _repr_tree(child[1], result, indent, _done, ids)
-                    result.append(indent + ',')
-                else:
-                    _repr_tree(child, result, indent, _done, ids)
-            result.append(  indent + "]" )
-        else:
-            result.append(  indent + field + " = " )
-            _repr_tree(value, result, indent, _done, ids)
-
-

+ 0 - 119
pylibs/logilab/astng/brain/py2stdlib.py

@@ -1,119 +0,0 @@
-"""ASTNG hooks for the Python 2 standard library.
-
-Currently help understanding of :
-
-* hashlib.md5 and hashlib.sha1
-"""
-
-from logilab.astng import MANAGER
-from logilab.astng.builder import ASTNGBuilder
-
-MODULE_TRANSFORMS = {}
-
-def hashlib_transform(module):
-    fake = ASTNGBuilder(MANAGER).string_build('''
-
-class md5(object):
-  def __init__(self, value): pass
-  def hexdigest(self):
-    return u''
-
-class sha1(object):
-  def __init__(self, value): pass
-  def hexdigest(self):
-    return u''
-
-''')
-    for hashfunc in ('sha1', 'md5'):
-        module.locals[hashfunc] = fake.locals[hashfunc]
-
-def collections_transform(module):
-    fake = ASTNGBuilder(MANAGER).string_build('''
-
-class defaultdict(dict):
-    default_factory = None
-    def __missing__(self, key): pass
-
-class deque(object):
-    maxlen = 0
-    def __init__(iterable=None, maxlen=None): pass
-    def append(self, x): pass
-    def appendleft(self, x): pass
-    def clear(self): pass
-    def count(self, x): return 0
-    def extend(self, iterable): pass
-    def extendleft(self, iterable): pass
-    def pop(self): pass
-    def popleft(self): pass
-    def remove(self, value): pass
-    def reverse(self): pass
-    def rotate(self, n): pass
-
-''')
-
-    for klass in ('deque', 'defaultdict'):
-        module.locals[klass] = fake.locals[klass]
-
-def pkg_resources_transform(module):
-    fake = ASTNGBuilder(MANAGER).string_build('''
-
-def resource_exists(package_or_requirement, resource_name):
-    pass
-
-def resource_isdir(package_or_requirement, resource_name):
-    pass
-
-def resource_filename(package_or_requirement, resource_name):
-    pass
-
-def resource_stream(package_or_requirement, resource_name):
-    pass
-
-def resource_string(package_or_requirement, resource_name):
-    pass
-
-def resource_listdir(package_or_requirement, resource_name):
-    pass
-
-def extraction_error():
-    pass
-
-def get_cache_path(archive_name, names=()):
-    pass
-
-def postprocess(tempname, filename):
-    pass
-
-def set_extraction_path(path):
-    pass
-
-def cleanup_resources(force=False):
-    pass
-
-''')
-
-    for func_name, func in fake.locals.items():
-        module.locals[func_name] = func
-
-    # for func in ('resource_exists', 'resource_isdir', 'resource_filename',
-    #     'resource_stream', 'resource_string', 'resource_listdir',
-    #     'extraction_error', 'get_cache_path', 'postprocess',
-    #     'set_extraction_path', 'cleanup_resources'):
-
-    #     module.locals[func] = fake.locals[func]
-
-MODULE_TRANSFORMS['hashlib'] = hashlib_transform
-MODULE_TRANSFORMS['collections'] = collections_transform
-MODULE_TRANSFORMS['pkg_resources'] = pkg_resources_transform
-
-
-def transform(module):
-    try:
-        tr = MODULE_TRANSFORMS[module.name]
-    except KeyError:
-        pass
-    else:
-        tr(module)
-
-from logilab.astng import MANAGER
-MANAGER.register_transformer(transform)

+ 0 - 226
pylibs/logilab/astng/builder.py

@@ -1,226 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-# copyright 2003-2010 Sylvain Thenault, all rights reserved.
-# contact mailto:thenault@gmail.com
-#
-# This file is part of logilab-astng.
-#
-# logilab-astng is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# logilab-astng is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-astng. If not, see <http://www.gnu.org/licenses/>.
-"""The ASTNGBuilder makes astng from living object and / or from _ast
-
-The builder is not thread safe and can't be used to parse different sources
-at the same time.
-"""
-
-__docformat__ = "restructuredtext en"
-
-import sys, re
-from os.path import splitext, basename, dirname, exists, abspath
-
-from logilab.common.modutils import modpath_from_file
-
-from logilab.astng.exceptions import ASTNGBuildingException, InferenceError
-from logilab.astng.raw_building import InspectBuilder
-from logilab.astng.rebuilder import TreeRebuilder
-from logilab.astng.manager import ASTNGManager
-from logilab.astng.bases import YES, Instance
-
-from _ast import PyCF_ONLY_AST
-def parse(string):
-    return compile(string, "<string>", 'exec', PyCF_ONLY_AST)
-
-if sys.version_info >= (3, 0):
-    from tokenize import detect_encoding
-
-    def open_source_file(filename):
-        byte_stream = open(filename, 'bU')
-        encoding = detect_encoding(byte_stream.readline)[0]
-        stream = open(filename, 'U', encoding=encoding)
-        try:
-            data = stream.read()
-        except UnicodeError, uex: # wrong encodingg
-            # detect_encoding returns utf-8 if no encoding specified
-            msg = 'Wrong (%s) or no encoding specified' % encoding
-            raise ASTNGBuildingException(msg)
-        return stream, encoding, data
-
-else:
-    import re
-
-    _ENCODING_RGX = re.compile("\s*#+.*coding[:=]\s*([-\w.]+)")
-
-    def _guess_encoding(string):
-        """get encoding from a python file as string or return None if not found
-        """
-        # check for UTF-8 byte-order mark
-        if string.startswith('\xef\xbb\xbf'):
-            return 'UTF-8'
-        for line in string.split('\n', 2)[:2]:
-            # check for encoding declaration
-            match = _ENCODING_RGX.match(line)
-            if match is not None:
-                return match.group(1)
-
-    def open_source_file(filename):
-        """get data for parsing a file"""
-        stream = open(filename, 'U')
-        data = stream.read()
-        encoding = _guess_encoding(data)
-        return stream, encoding, data
-
-# ast NG builder ##############################################################
-
-MANAGER = ASTNGManager()
-
-class ASTNGBuilder(InspectBuilder):
-    """provide astng building methods"""
-    rebuilder = TreeRebuilder()
-
-    def __init__(self, manager=None):
-        self._manager = manager or MANAGER
-
-    def module_build(self, module, modname=None):
-        """build an astng from a living module instance
-        """
-        node = None
-        path = getattr(module, '__file__', None)
-        if path is not None:
-            path_, ext = splitext(module.__file__)
-            if ext in ('.py', '.pyc', '.pyo') and exists(path_ + '.py'):
-                node = self.file_build(path_ + '.py', modname)
-        if node is None:
-            # this is a built-in module
-            # get a partial representation by introspection
-            node = self.inspect_build(module, modname=modname, path=path)
-        return node
-
-    def file_build(self, path, modname=None):
-        """build astng from a source code file (i.e. from an ast)
-
-        path is expected to be a python source file
-        """
-        try:
-            stream, encoding, data = open_source_file(path)
-        except IOError, exc:
-            msg = 'Unable to load file %r (%s)' % (path, exc)
-            raise ASTNGBuildingException(msg)
-        except SyntaxError, exc: # py3k encoding specification error
-            raise ASTNGBuildingException(exc)
-        except LookupError, exc: # unknown encoding
-            raise ASTNGBuildingException(exc)
-        # get module name if necessary
-        if modname is None:
-            try:
-                modname = '.'.join(modpath_from_file(path))
-            except ImportError:
-                modname = splitext(basename(path))[0]
-        # build astng representation
-        node = self.string_build(data, modname, path)
-        node.file_encoding = encoding
-        return node
-
-    def string_build(self, data, modname='', path=None):
-        """build astng from source code string and return rebuilded astng"""
-        module = self._data_build(data, modname, path)
-        self._manager.astng_cache[module.name] = module
-        # post tree building steps after we stored the module in the cache:
-        for from_node in module._from_nodes:
-            self.add_from_names_to_locals(from_node)
-        # handle delayed assattr nodes
-        for delayed in module._delayed_assattr:
-            self.delayed_assattr(delayed)
-        if modname:
-            for transformer in self._manager.transformers:
-                transformer(module)
-        return module
-
-    def _data_build(self, data, modname, path):
-        """build tree node from data and add some informations"""
-        # this method could be wrapped with a pickle/cache function
-        node = parse(data + '\n')
-        if path is not None:
-            node_file = abspath(path)
-        else:
-            node_file = '<?>'
-        if modname.endswith('.__init__'):
-            modname = modname[:-9]
-            package = True
-        else:
-            package = path and path.find('__init__.py') > -1 or False
-        self.rebuilder.init()
-        module = self.rebuilder.visit_module(node, modname, package)
-        module.file = module.path = node_file
-        module._from_nodes = self.rebuilder._from_nodes
-        module._delayed_assattr = self.rebuilder._delayed_assattr
-        return module
-
-    def add_from_names_to_locals(self, node):
-        """store imported names to the locals;
-        resort the locals if coming from a delayed node
-        """
-
-        _key_func = lambda node: node.fromlineno
-        def sort_locals(my_list):
-            my_list.sort(key=_key_func)
-        for (name, asname) in node.names:
-            if name == '*':
-                try:
-                    imported = node.root().import_module(node.modname)
-                except ASTNGBuildingException:
-                    continue
-                for name in imported.wildcard_import_names():
-                    node.parent.set_local(name, node)
-                    sort_locals(node.parent.scope().locals[name])
-            else:
-                node.parent.set_local(asname or name, node)
-                sort_locals(node.parent.scope().locals[asname or name])
-
-    def delayed_assattr(self, node):
-        """visit a AssAttr node -> add name to locals, handle members
-        definition
-        """
-        try:
-            frame = node.frame()
-            for infered in node.expr.infer():
-                if infered is YES:
-                    continue
-                try:
-                    if infered.__class__ is Instance:
-                        infered = infered._proxied
-                        iattrs = infered.instance_attrs
-                    elif isinstance(infered, Instance):
-                        # Const, Tuple, ... we may be wrong, may be not, but
-                        # anyway we don't want to pollute builtin's namespace
-                        continue
-                    elif infered.is_function:
-                        iattrs = infered.instance_attrs
-                    else:
-                        iattrs = infered.locals
-                except AttributeError:
-                    # XXX log error
-                    #import traceback
-                    #traceback.print_exc()
-                    continue
-                values = iattrs.setdefault(node.attrname, [])
-                if node in values:
-                    continue
-                # get assign in __init__ first XXX useful ?
-                if frame.name == '__init__' and values and not \
-                       values[0].frame().name == '__init__':
-                    values.insert(0, node)
-                else:
-                    values.append(node)
-        except InferenceError:
-            pass
-

+ 0 - 60
pylibs/logilab/astng/exceptions.py

@@ -1,60 +0,0 @@
-# This program is free software; you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free Software
-# Foundation; either version 2 of the License, or (at your option) any later
-# version.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-# copyright 2003-2010 Sylvain Thenault, all rights reserved.
-# contact mailto:thenault@gmail.com
-#
-# This file is part of logilab-astng.
-#
-# logilab-astng is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# logilab-astng is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-astng. If not, see <http://www.gnu.org/licenses/>.
-"""this module contains exceptions used in the astng library
-
-"""
-
-__doctype__ = "restructuredtext en"
-
-class ASTNGError(Exception):
-    """base exception class for all astng related exceptions"""
-
-class ASTNGBuildingException(ASTNGError):
-    """exception class when we are unable to build an astng representation"""
-
-class ResolveError(ASTNGError):
-    """base class of astng resolution/inference error"""
-
-class NotFoundError(ResolveError):
-    """raised when we are unable to resolve a name"""
-
-class InferenceError(ResolveError):
-    """raised when we are unable to infer a node"""
-
-class UnresolvableName(InferenceError):
-    """raised when we are unable to resolve a name"""
-
-class NoDefault(ASTNGError):
-    """raised by function's `default_value` method when an argument has
-    no default value
-    """
-

+ 0 - 383
pylibs/logilab/astng/inference.py

@@ -1,383 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-# copyright 2003-2010 Sylvain Thenault, all rights reserved.
-# contact mailto:thenault@gmail.com
-#
-# This file is part of logilab-astng.
-#
-# logilab-astng is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# logilab-astng is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-astng. If not, see <http://www.gnu.org/licenses/>.
-"""this module contains a set of functions to handle inference on astng trees
-"""
-
-__doctype__ = "restructuredtext en"
-
-from itertools import chain
-import sys
-
-from logilab.astng import nodes
-
-from logilab.astng.manager import ASTNGManager
-from logilab.astng.exceptions import (ASTNGBuildingException, ASTNGError,
-    InferenceError, NoDefault, NotFoundError, UnresolvableName)
-from logilab.astng.bases import YES, Instance, InferenceContext, Generator, \
-     _infer_stmts, copy_context, path_wrapper, raise_if_nothing_infered
-from logilab.astng.protocols import _arguments_infer_argname
-
-MANAGER = ASTNGManager()
-
-
-class CallContext:
-    """when inferring a function call, this class is used to remember values
-    given as argument
-    """
-    def __init__(self, args, starargs, dstarargs):
-        self.args = []
-        self.nargs = {}
-        for arg in args:
-            if isinstance(arg, nodes.Keyword):
-                self.nargs[arg.arg] = arg.value
-            else:
-                self.args.append(arg)
-        self.starargs = starargs
-        self.dstarargs = dstarargs
-
-    def infer_argument(self, funcnode, name, context):
-        """infer a function argument value according to the call context"""
-        # 1. search in named keywords
-        try:
-            return self.nargs[name].infer(context)
-        except KeyError:
-            # Function.args.args can be None in astng (means that we don't have
-            # information on argnames)
-            argindex = funcnode.args.find_argname(name)[0]
-            if argindex is not None:
-                # 2. first argument of instance/class method
-                if argindex == 0 and funcnode.type in ('method', 'classmethod'):
-                    if context.boundnode is not None:
-                        boundnode = context.boundnode
-                    else:
-                        # XXX can do better ?
-                        boundnode = funcnode.parent.frame()
-                    if funcnode.type == 'method':
-                        if not isinstance(boundnode, Instance):
-                            boundnode = Instance(boundnode)
-                        return iter((boundnode,))
-                    if funcnode.type == 'classmethod':
-                        return iter((boundnode,))
-                # 2. search arg index
-                try:
-                    return self.args[argindex].infer(context)
-                except IndexError:
-                    pass
-                # 3. search in *args (.starargs)
-                if self.starargs is not None:
-                    its = []
-                    for infered in self.starargs.infer(context):
-                        if infered is YES:
-                            its.append((YES,))
-                            continue
-                        try:
-                            its.append(infered.getitem(argindex, context).infer(context))
-                        except (InferenceError, AttributeError):
-                            its.append((YES,))
-                        except (IndexError, TypeError):
-                            continue
-                    if its:
-                        return chain(*its)
-        # 4. XXX search in **kwargs (.dstarargs)
-        if self.dstarargs is not None:
-            its = []
-            for infered in self.dstarargs.infer(context):
-                if infered is YES:
-                    its.append((YES,))
-                    continue
-                try:
-                    its.append(infered.getitem(name, context).infer(context))
-                except (InferenceError, AttributeError):
-                    its.append((YES,))
-                except (IndexError, TypeError):
-                    continue
-            if its:
-                return chain(*its)
-        # 5. */** argument, (Tuple or Dict)
-        if name == funcnode.args.vararg:
-            return iter((nodes.const_factory(())))
-        if name == funcnode.args.kwarg:
-            return iter((nodes.const_factory({})))
-        # 6. return default value if any
-        try:
-            return funcnode.args.default_value(name).infer(context)
-        except NoDefault:
-            raise InferenceError(name)
-
-
-# .infer method ###############################################################
-
-
-def infer_end(self, context=None):
-    """inference's end for node such as Module, Class, Function, Const...
-    """
-    yield self
-nodes.Module.infer = infer_end
-nodes.Class.infer = infer_end
-nodes.Function.infer = infer_end
-nodes.Lambda.infer = infer_end
-nodes.Const.infer = infer_end
-nodes.List.infer = infer_end
-nodes.Tuple.infer = infer_end
-nodes.Dict.infer = infer_end
-
-
-def infer_name(self, context=None):
-    """infer a Name: use name lookup rules"""
-    frame, stmts = self.lookup(self.name)
-    if not stmts:
-        raise UnresolvableName(self.name)
-    context = context.clone()
-    context.lookupname = self.name
-    return _infer_stmts(stmts, context, frame)
-nodes.Name.infer = path_wrapper(infer_name)
-nodes.AssName.infer_lhs = infer_name # won't work with a path wrapper
-
-
-def infer_callfunc(self, context=None):
-    """infer a CallFunc node by trying to guess what the function returns"""
-    callcontext = context.clone()
-    callcontext.callcontext = CallContext(self.args, self.starargs, self.kwargs)
-    callcontext.boundnode = None
-    for callee in self.func.infer(context):
-        if callee is YES:
-            yield callee
-            continue
-        try:
-            if hasattr(callee, 'infer_call_result'):
-                for infered in callee.infer_call_result(self, callcontext):
-                    yield infered
-        except InferenceError:
-            ## XXX log error ?
-            continue
-nodes.CallFunc.infer = path_wrapper(raise_if_nothing_infered(infer_callfunc))
-
-
-def infer_import(self, context=None, asname=True):
-    """infer an Import node: return the imported module/object"""
-    name = context.lookupname
-    if name is None:
-        raise InferenceError()
-    if asname:
-        yield self.do_import_module(self.real_name(name))
-    else:
-        yield self.do_import_module(name)
-nodes.Import.infer = path_wrapper(infer_import)
-
-def infer_name_module(self, name):
-    context = InferenceContext()
-    context.lookupname = name
-    return self.infer(context, asname=False)
-nodes.Import.infer_name_module = infer_name_module
-
-
-def infer_from(self, context=None, asname=True):
-    """infer a From nodes: return the imported module/object"""
-    name = context.lookupname
-    if name is None:
-        raise InferenceError()
-    if asname:
-        name = self.real_name(name)
-    module = self.do_import_module(self.modname)
-    try:
-        context = copy_context(context)
-        context.lookupname = name
-        return _infer_stmts(module.getattr(name, ignore_locals=module is self.root()), context)
-    except NotFoundError:
-        raise InferenceError(name)
-nodes.From.infer = path_wrapper(infer_from)
-
-
-def infer_getattr(self, context=None):
-    """infer a Getattr node by using getattr on the associated object"""
-    #context = context.clone()
-    for owner in self.expr.infer(context):
-        if owner is YES:
-            yield owner
-            continue
-        try:
-            context.boundnode = owner
-            for obj in owner.igetattr(self.attrname, context):
-                yield obj
-            context.boundnode = None
-        except (NotFoundError, InferenceError):
-            context.boundnode = None
-        except AttributeError:
-            # XXX method / function
-            context.boundnode = None
-nodes.Getattr.infer = path_wrapper(raise_if_nothing_infered(infer_getattr))
-nodes.AssAttr.infer_lhs = raise_if_nothing_infered(infer_getattr) # # won't work with a path wrapper
-
-
-def infer_global(self, context=None):
-    if context.lookupname is None:
-        raise InferenceError()
-    try:
-        return _infer_stmts(self.root().getattr(context.lookupname), context)
-    except NotFoundError:
-        raise InferenceError()
-nodes.Global.infer = path_wrapper(infer_global)
-
-
-def infer_subscript(self, context=None):
-    """infer simple subscription such as [1,2,3][0] or (1,2,3)[-1]"""
-    if isinstance(self.slice, nodes.Index):
-        index = self.slice.value.infer(context).next()
-        if index is YES:
-            yield YES
-            return
-        try:
-            # suppose it's a Tuple/List node (attribute error else)
-            # XXX infer self.value?
-            assigned = self.value.getitem(index.value, context)
-        except AttributeError:
-            raise InferenceError()
-        except (IndexError, TypeError):
-            yield YES
-            return
-        for infered in assigned.infer(context):
-            yield infered
-    else:
-        raise InferenceError()
-nodes.Subscript.infer = path_wrapper(infer_subscript)
-nodes.Subscript.infer_lhs = raise_if_nothing_infered(infer_subscript)
-
-
-UNARY_OP_METHOD = {'+': '__pos__',
-                   '-': '__neg__',
-                   '~': '__invert__',
-                   'not': None, # XXX not '__nonzero__'
-                  }
-
-def infer_unaryop(self, context=None):
-    for operand in self.operand.infer(context):
-        try:
-            yield operand.infer_unary_op(self.op)
-        except TypeError:
-            continue
-        except AttributeError:
-            meth = UNARY_OP_METHOD[self.op]
-            if meth is None:
-                yield YES
-            else:
-                try:
-                    # XXX just suppose if the type implement meth, returned type
-                    # will be the same
-                    operand.getattr(meth)
-                    yield operand
-                except GeneratorExit:
-                    raise
-                except:
-                    yield YES
-nodes.UnaryOp.infer = path_wrapper(infer_unaryop)
-
-
-BIN_OP_METHOD = {'+':  '__add__',
-                 '-':  '__sub__',
-                 '/':  '__div__',
-                 '//': '__floordiv__',
-                 '*':  '__mul__',
-                 '**': '__power__',
-                 '%':  '__mod__',
-                 '&':  '__and__',
-                 '|':  '__or__',
-                 '^':  '__xor__',
-                 '<<': '__lshift__',
-                 '>>': '__rshift__',
-                 }
-
-def _infer_binop(operator, operand1, operand2, context, failures=None):
-    if operand1 is YES:
-        yield operand1
-        return
-    try:
-        for valnode in operand1.infer_binary_op(operator, operand2, context):
-            yield valnode
-    except AttributeError:
-        try:
-            # XXX just suppose if the type implement meth, returned type
-            # will be the same
-            operand1.getattr(BIN_OP_METHOD[operator])
-            yield operand1
-        except:
-            if failures is None:
-                yield YES
-            else:
-                failures.append(operand1)
-
-def infer_binop(self, context=None):
-    failures = []
-    for lhs in self.left.infer(context):
-        for val in _infer_binop(self.op, lhs, self.right, context, failures):
-            yield val
-    for lhs in failures:
-        for rhs in self.right.infer(context):
-            for val in _infer_binop(self.op, rhs, lhs, context):
-                yield val
-nodes.BinOp.infer = path_wrapper(infer_binop)
-
-
-def infer_arguments(self, context=None):
-    name = context.lookupname
-    if name is None:
-        raise InferenceError()
-    return _arguments_infer_argname(self, name, context)
-nodes.Arguments.infer = infer_arguments
-
-
-def infer_ass(self, context=None):
-    """infer a AssName/AssAttr: need to inspect the RHS part of the
-    assign node
-    """
-    stmt = self.statement()
-    if isinstance(stmt, nodes.AugAssign):
-        return stmt.infer(context)
-    stmts = list(self.assigned_stmts(context=context))
-    return _infer_stmts(stmts, context)
-nodes.AssName.infer = path_wrapper(infer_ass)
-nodes.AssAttr.infer = path_wrapper(infer_ass)
-
-def infer_augassign(self, context=None):
-    failures = []
-    for lhs in self.target.infer_lhs(context):
-        for val in _infer_binop(self.op, lhs, self.value, context, failures):
-            yield val
-    for lhs in failures:
-        for rhs in self.value.infer(context):
-            for val in _infer_binop(self.op, rhs, lhs, context):
-                yield val
-nodes.AugAssign.infer = path_wrapper(infer_augassign)
-
-
-# no infer method on DelName and DelAttr (expected InferenceError)
-
-
-def infer_empty_node(self, context=None):
-    if not self.has_underlying_object():
-        yield YES
-    else:
-        try:
-            for infered in MANAGER.infer_astng_from_something(self.object,
-                                                              context=context):
-                yield infered
-        except ASTNGError:
-            yield YES
-nodes.EmptyNode.infer = path_wrapper(infer_empty_node)
-

+ 0 - 289
pylibs/logilab/astng/inspector.py

@@ -1,289 +0,0 @@
-# This program is free software; you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free Software
-# Foundation; either version 2 of the License, or (at your option) any later
-# version.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-# copyright 2003-2010 Sylvain Thenault, all rights reserved.
-# contact mailto:thenault@gmail.com
-#
-# This file is part of logilab-astng.
-#
-# logilab-astng is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# logilab-astng is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-astng. If not, see <http://www.gnu.org/licenses/>.
-"""visitor doing some postprocessing on the astng tree.
-Try to resolve definitions (namespace) dictionary, relationship...
-
-This module has been imported from pyreverse
-"""
-
-__docformat__ = "restructuredtext en"
-
-from os.path import dirname
-
-from logilab.common.modutils import get_module_part, is_relative, \
-     is_standard_module
-
-from logilab import astng
-from logilab.astng.exceptions import InferenceError
-from logilab.astng.utils import LocalsVisitor
-
-class IdGeneratorMixIn:
-    """
-    Mixin adding the ability to generate integer uid
-    """
-    def __init__(self, start_value=0):
-        self.id_count = start_value
-    
-    def init_counter(self, start_value=0):
-        """init the id counter
-        """
-        self.id_count = start_value
-        
-    def generate_id(self):
-        """generate a new identifier
-        """
-        self.id_count += 1
-        return self.id_count
-
-
-class Linker(IdGeneratorMixIn, LocalsVisitor):
-    """
-    walk on the project tree and resolve relationships.
-    
-    According to options the following attributes may be added to visited nodes:
-    
-    * uid,
-      a unique identifier for the node (on astng.Project, astng.Module,
-      astng.Class and astng.locals_type). Only if the linker has been instantiated
-      with tag=True parameter (False by default).
-            
-    * Function
-      a mapping from locals names to their bounded value, which may be a
-      constant like a string or an integer, or an astng node (on astng.Module,
-      astng.Class and astng.Function).
-
-    * instance_attrs_type
-      as locals_type but for klass member attributes (only on astng.Class)
-      
-    * implements,
-      list of implemented interface _objects_ (only on astng.Class nodes)
-    """
-    
-    def __init__(self, project, inherited_interfaces=0, tag=False):
-        IdGeneratorMixIn.__init__(self)
-        LocalsVisitor.__init__(self)
-        # take inherited interface in consideration or not
-        self.inherited_interfaces = inherited_interfaces
-        # tag nodes or not
-        self.tag = tag
-        # visited project
-        self.project = project
-
-        
-    def visit_project(self, node):
-        """visit an astng.Project node
-        
-         * optionally tag the node with a unique id
-        """
-        if self.tag:
-            node.uid = self.generate_id()
-        for module in node.modules:
-            self.visit(module)
-            
-    def visit_package(self, node):
-        """visit an astng.Package node
-        
-         * optionally tag the node with a unique id
-        """
-        if self.tag:
-            node.uid = self.generate_id()
-        for subelmt in node.values():
-            self.visit(subelmt)
-            
-    def visit_module(self, node):
-        """visit an astng.Module node
-        
-         * set the locals_type mapping
-         * set the depends mapping
-         * optionally tag the node with a unique id
-        """
-        if hasattr(node, 'locals_type'):
-            return
-        node.locals_type = {}
-        node.depends = []
-        if self.tag:
-            node.uid = self.generate_id()
-    
-    def visit_class(self, node):
-        """visit an astng.Class node
-        
-         * set the locals_type and instance_attrs_type mappings
-         * set the implements list and build it
-         * optionally tag the node with a unique id
-        """
-        if hasattr(node, 'locals_type'):
-            return
-        node.locals_type = {}
-        if self.tag:
-            node.uid = self.generate_id()
-        # resolve ancestors
-        for baseobj in node.ancestors(recurs=False):
-            specializations = getattr(baseobj, 'specializations', [])
-            specializations.append(node)
-            baseobj.specializations = specializations
-        # resolve instance attributes
-        node.instance_attrs_type = {}
-        for assattrs in node.instance_attrs.values():
-            for assattr in assattrs:
-                self.handle_assattr_type(assattr, node)
-        # resolve implemented interface
-        try:
-            node.implements = list(node.interfaces(self.inherited_interfaces))
-        except InferenceError:
-            node.implements = ()
-
-    def visit_function(self, node):
-        """visit an astng.Function node
-        
-         * set the locals_type mapping
-         * optionally tag the node with a unique id
-        """
-        if hasattr(node, 'locals_type'):
-            return
-        node.locals_type = {}
-        if self.tag:
-            node.uid = self.generate_id()
-            
-    link_project = visit_project
-    link_module = visit_module
-    link_class = visit_class
-    link_function = visit_function
-        
-    def visit_assname(self, node):
-        """visit an astng.AssName node
-
-        handle locals_type
-        """
-        # avoid double parsing done by different Linkers.visit
-        # running over the same project:
-        if hasattr(node, '_handled'):
-            return
-        node._handled = True
-        if node.name in node.frame():
-            frame = node.frame()
-        else:
-            # the name has been defined as 'global' in the frame and belongs
-            # there. Btw the frame is not yet visited as the name is in the 
-            # root locals; the frame hence has no locals_type attribute
-            frame = node.root()
-        try:
-            values = node.infered()
-            try:
-                already_infered = frame.locals_type[node.name]
-                for valnode in values:
-                    if not valnode in already_infered:
-                        already_infered.append(valnode)
-            except KeyError:
-                frame.locals_type[node.name] = values
-        except astng.InferenceError:
-            pass
-
-    def handle_assattr_type(self, node, parent):
-        """handle an astng.AssAttr node
-
-        handle instance_attrs_type
-        """
-        try:
-            values = list(node.infer())
-            try:
-                already_infered = parent.instance_attrs_type[node.attrname]
-                for valnode in values:
-                    if not valnode in already_infered:
-                        already_infered.append(valnode)
-            except KeyError:
-                parent.instance_attrs_type[node.attrname] = values
-        except astng.InferenceError:
-            pass
-            
-    def visit_import(self, node):
-        """visit an astng.Import node
-        
-        resolve module dependencies
-        """
-        context_file = node.root().file
-        for name in node.names:
-            relative = is_relative(name[0], context_file)
-            self._imported_module(node, name[0], relative)
-        
-
-    def visit_from(self, node):
-        """visit an astng.From node
-        
-        resolve module dependencies
-        """
-        basename = node.modname
-        context_file = node.root().file
-        if context_file is not None:
-            relative = is_relative(basename, context_file)
-        else:
-            relative = False
-        for name in node.names:
-            if name[0] == '*':
-                continue
-            # analyze dependencies
-            fullname = '%s.%s' % (basename, name[0])
-            if fullname.find('.') > -1:
-                try:
-                    # XXX: don't use get_module_part, missing package precedence
-                    fullname = get_module_part(fullname)
-                except ImportError:
-                    continue
-            if fullname != basename:
-                self._imported_module(node, fullname, relative)
-
-        
-    def compute_module(self, context_name, mod_path):
-        """return true if the module should be added to dependencies"""
-        package_dir = dirname(self.project.path)
-        if context_name == mod_path:
-            return 0
-        elif is_standard_module(mod_path, (package_dir,)):
-            return 1
-        return 0
-    
-    # protected methods ########################################################
-
-    def _imported_module(self, node, mod_path, relative):
-        """notify an imported module, used to analyze dependencies
-        """
-        module = node.root()
-        context_name = module.name
-        if relative:
-            mod_path = '%s.%s' % ('.'.join(context_name.split('.')[:-1]),
-                                  mod_path)
-        if self.compute_module(context_name, mod_path):
-            # handle dependencies
-            if not hasattr(module, 'depends'):
-                module.depends = []
-            mod_paths = module.depends
-            if not mod_path in mod_paths:
-                mod_paths.append(mod_path)

+ 0 - 299
pylibs/logilab/astng/manager.py

@@ -1,299 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-# copyright 2003-2010 Sylvain Thenault, all rights reserved.
-# contact mailto:thenault@gmail.com
-#
-# This file is part of logilab-astng.
-#
-# logilab-astng is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# logilab-astng is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-astng. If not, see <http://www.gnu.org/licenses/>.
-"""astng manager: avoid multiple astng build of a same module when
-possible by providing a class responsible to get astng representation
-from various source and using a cache of built modules)
-"""
-
-__docformat__ = "restructuredtext en"
-
-import sys
-import os
-from os.path import dirname, basename, abspath, join, isdir, exists
-
-from logilab.common.modutils import NoSourceFile, is_python_source, \
-     file_from_modpath, load_module_from_name, modpath_from_file, \
-     get_module_files, get_source_file, zipimport
-from logilab.common.configuration import OptionsProviderMixIn
-
-from logilab.astng.exceptions import ASTNGBuildingException
-
-def astng_wrapper(func, modname):
-    """wrapper to give to ASTNGManager.project_from_files"""
-    print 'parsing %s...' % modname
-    try:
-        return func(modname)
-    except ASTNGBuildingException, exc:
-        print exc
-    except Exception, exc:
-        import traceback
-        traceback.print_exc()
-
-def _silent_no_wrap(func, modname):
-    """silent wrapper that doesn't do anything; can be used for tests"""
-    return func(modname)
-
-def safe_repr(obj):
-    try:
-        return repr(obj)
-    except:
-        return '???'
-
-
-
-class ASTNGManager(OptionsProviderMixIn):
-    """the astng manager, responsible to build astng from files
-     or modules.
-
-    Use the Borg pattern.
-    """
-
-    name = 'astng loader'
-    options = (("ignore",
-                {'type' : "csv", 'metavar' : "<file>",
-                 'dest' : "black_list", "default" : ('CVS',),
-                 'help' : "add <file> (may be a directory) to the black list\
-. It should be a base name, not a path. You may set this option multiple times\
-."}),
-               ("project",
-                {'default': "No Name", 'type' : 'string', 'short': 'p',
-                 'metavar' : '<project name>',
-                 'help' : 'set the project name.'}),
-               )
-    brain = {}
-    def __init__(self):
-        self.__dict__ = ASTNGManager.brain
-        if not self.__dict__:
-            OptionsProviderMixIn.__init__(self)
-            self.load_defaults()
-            # NOTE: cache entries are added by the [re]builder
-            self.astng_cache = {}
-            self._mod_file_cache = {}
-            self.transformers = []
-
-    def astng_from_file(self, filepath, modname=None, fallback=True, source=False):
-        """given a module name, return the astng object"""
-        try:
-            filepath = get_source_file(filepath, include_no_ext=True)
-            source = True
-        except NoSourceFile:
-            pass
-        if modname is None:
-            try:
-                modname = '.'.join(modpath_from_file(filepath))
-            except ImportError:
-                modname = filepath
-        if modname in self.astng_cache:
-            return self.astng_cache[modname]
-        if source:
-            from logilab.astng.builder import ASTNGBuilder
-            return ASTNGBuilder(self).file_build(filepath, modname)
-        elif fallback and modname:
-            return self.astng_from_module_name(modname)
-        raise ASTNGBuildingException('unable to get astng for file %s' %
-                                     filepath)
-
-    def astng_from_module_name(self, modname, context_file=None):
-        """given a module name, return the astng object"""
-        if modname in self.astng_cache:
-            return self.astng_cache[modname]
-        if modname == '__main__':
-            from logilab.astng.builder import ASTNGBuilder
-            return ASTNGBuilder(self).string_build('', modname)
-        old_cwd = os.getcwd()
-        if context_file:
-            os.chdir(dirname(context_file))
-        try:
-            filepath = self.file_from_module_name(modname, context_file)
-            if filepath is not None and not is_python_source(filepath):
-                module = self.zip_import_data(filepath)
-                if module is not None:
-                    return module
-            if filepath is None or not is_python_source(filepath):
-                try:
-                    module = load_module_from_name(modname)
-                except Exception, ex:
-                    msg = 'Unable to load module %s (%s)' % (modname, ex)
-                    raise ASTNGBuildingException(msg)
-                return self.astng_from_module(module, modname)
-            return self.astng_from_file(filepath, modname, fallback=False)
-        finally:
-            os.chdir(old_cwd)
-
-    def zip_import_data(self, filepath):
-        if zipimport is None:
-            return None
-        from logilab.astng.builder import ASTNGBuilder
-        builder = ASTNGBuilder(self)
-        for ext in ('.zip', '.egg'):
-            try:
-                eggpath, resource = filepath.rsplit(ext + '/', 1)
-            except ValueError:
-                continue
-            try:
-                importer = zipimport.zipimporter(eggpath + ext)
-                zmodname = resource.replace('/', '.')
-                if importer.is_package(resource):
-                    zmodname =  zmodname + '.__init__'
-                module = builder.string_build(importer.get_source(resource),
-                                              zmodname, filepath)
-                return module
-            except:
-                continue
-        return None
-
-    def file_from_module_name(self, modname, contextfile):
-        try:
-            value = self._mod_file_cache[(modname, contextfile)]
-        except KeyError:
-            try:
-                value = file_from_modpath(modname.split('.'),
-                                          context_file=contextfile)
-            except ImportError, ex:
-                msg = 'Unable to load module %s (%s)' % (modname, ex)
-                value = ASTNGBuildingException(msg)
-            self._mod_file_cache[(modname, contextfile)] = value
-        if isinstance(value, ASTNGBuildingException):
-            raise value
-        return value
-
-    def astng_from_module(self, module, modname=None):
-        """given an imported module, return the astng object"""
-        modname = modname or module.__name__
-        if modname in self.astng_cache:
-            return self.astng_cache[modname]
-        try:
-            # some builtin modules don't have __file__ attribute
-            filepath = module.__file__
-            if is_python_source(filepath):
-                return self.astng_from_file(filepath, modname)
-        except AttributeError:
-            pass
-        from logilab.astng.builder import ASTNGBuilder
-        return ASTNGBuilder(self).module_build(module, modname)
-
-    def astng_from_class(self, klass, modname=None):
-        """get astng for the given class"""
-        if modname is None:
-            try:
-                modname = klass.__module__
-            except AttributeError:
-                raise ASTNGBuildingException(
-                    'Unable to get module for class %s' % safe_repr(klass))
-        modastng = self.astng_from_module_name(modname)
-        return modastng.getattr(klass.__name__)[0] # XXX
-
-
-    def infer_astng_from_something(self, obj, context=None):
-        """infer astng for the given class"""
-        if hasattr(obj, '__class__') and not isinstance(obj, type):
-            klass = obj.__class__
-        else:
-            klass = obj
-        try:
-            modname = klass.__module__
-        except AttributeError:
-            raise ASTNGBuildingException(
-                'Unable to get module for %s' % safe_repr(klass))
-        except Exception, ex:
-            raise ASTNGBuildingException(
-                'Unexpected error while retrieving module for %s: %s'
-                % (safe_repr(klass), ex))
-        try:
-            name = klass.__name__
-        except AttributeError:
-            raise ASTNGBuildingException(
-                'Unable to get name for %s' % safe_repr(klass))
-        except Exception, ex:
-            raise ASTNGBuildingException(
-                'Unexpected error while retrieving name for %s: %s'
-                % (safe_repr(klass), ex))
-        # take care, on living object __module__ is regularly wrong :(
-        modastng = self.astng_from_module_name(modname)
-        if klass is obj:
-            for  infered in modastng.igetattr(name, context):
-                yield infered
-        else:
-            for infered in modastng.igetattr(name, context):
-                yield infered.instanciate_class()
-
-    def project_from_files(self, files, func_wrapper=astng_wrapper,
-                           project_name=None, black_list=None):
-        """return a Project from a list of files or modules"""
-        # build the project representation
-        project_name = project_name or self.config.project
-        black_list = black_list or self.config.black_list
-        project = Project(project_name)
-        for something in files:
-            if not exists(something):
-                fpath = file_from_modpath(something.split('.'))
-            elif isdir(something):
-                fpath = join(something, '__init__.py')
-            else:
-                fpath = something
-            astng = func_wrapper(self.astng_from_file, fpath)
-            if astng is None:
-                continue
-            # XXX why is first file defining the project.path ?
-            project.path = project.path or astng.file
-            project.add_module(astng)
-            base_name = astng.name
-            # recurse in package except if __init__ was explicitly given
-            if astng.package and something.find('__init__') == -1:
-                # recurse on others packages / modules if this is a package
-                for fpath in get_module_files(dirname(astng.file),
-                                              black_list):
-                    astng = func_wrapper(self.astng_from_file, fpath)
-                    if astng is None or astng.name == base_name:
-                        continue
-                    project.add_module(astng)
-        return project
-
-    def register_transformer(self, transformer):
-        self.transformers.append(transformer)
-
-class Project:
-    """a project handle a set of modules / packages"""
-    def __init__(self, name=''):
-        self.name = name
-        self.path = None
-        self.modules = []
-        self.locals = {}
-        self.__getitem__ = self.locals.__getitem__
-        self.__iter__ = self.locals.__iter__
-        self.values = self.locals.values
-        self.keys = self.locals.keys
-        self.items = self.locals.items
-
-    def add_module(self, node):
-        self.locals[node.name] = node
-        self.modules.append(node)
-
-    def get_module(self, name):
-        return self.locals[name]
-
-    def get_children(self):
-        return self.modules
-
-    def __repr__(self):
-        return '<Project %r at %s (%s modules)>' % (self.name, id(self),
-                                                    len(self.modules))
-
-

+ 0 - 136
pylibs/logilab/astng/mixins.py

@@ -1,136 +0,0 @@
-# This program is free software; you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free Software
-# Foundation; either version 2 of the License, or (at your option) any later
-# version.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc.,
-# 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-# copyright 2003-2010 Sylvain Thenault, all rights reserved.
-# contact mailto:thenault@gmail.com
-#
-# This file is part of logilab-astng.
-#
-# logilab-astng is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# logilab-astng is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-astng. If not, see <http://www.gnu.org/licenses/>.
-"""This module contains some mixins for the different nodes.
-"""
-
-from logilab.astng.exceptions import (ASTNGBuildingException, InferenceError,
-                                      NotFoundError)
-
-
-class BlockRangeMixIn(object):
-    """override block range """
-    def set_line_info(self, lastchild):
-        self.fromlineno = self.lineno
-        self.tolineno = lastchild.tolineno
-        self.blockstart_tolineno = self._blockstart_toline()
-
-    def _elsed_block_range(self, lineno, orelse, last=None):
-        """handle block line numbers range for try/finally, for, if and while
-        statements
-        """
-        if lineno == self.fromlineno:
-            return lineno, lineno
-        if orelse:
-            if lineno >= orelse[0].fromlineno:
-                return lineno, orelse[-1].tolineno
-            return lineno, orelse[0].fromlineno - 1
-        return lineno, last or self.tolineno
-
-class FilterStmtsMixin(object):
-    """Mixin for statement filtering and assignment type"""
-
-    def _get_filtered_stmts(self, _, node, _stmts, mystmt):
-        """method used in _filter_stmts to get statemtents and trigger break"""
-        if self.statement() is mystmt:
-            # original node's statement is the assignment, only keep
-            # current node (gen exp, list comp)
-            return [node], True
-        return _stmts, False
-
-    def ass_type(self):
-        return self
-
-
-class AssignTypeMixin(object):
-
-    def ass_type(self):
-        return self
-
-    def _get_filtered_stmts(self, lookup_node, node, _stmts, mystmt):
-        """method used in filter_stmts"""
-        if self is mystmt:
-            return _stmts, True
-        if self.statement() is mystmt:
-            # original node's statement is the assignment, only keep
-            # current node (gen exp, list comp)
-            return [node], True
-        return _stmts, False
-
-
-class ParentAssignTypeMixin(AssignTypeMixin):
-
-    def ass_type(self):
-        return self.parent.ass_type()
-
-
-
-class FromImportMixIn(FilterStmtsMixin):
-    """MixIn for From and Import Nodes"""
-
-    def _infer_name(self, frame, name):
-        return name
-
-    def do_import_module(self, modname):
-        """return the ast for a module whose name is <modname> imported by <self>
-        """
-        # handle special case where we are on a package node importing a module
-        # using the same name as the package, which may end in an infinite loop
-        # on relative imports
-        # XXX: no more needed ?
-        mymodule = self.root()
-        level = getattr(self, 'level', None) # Import as no level
-        # XXX we should investigate deeper if we really want to check
-        # importing itself: modname and mymodule.name be relative or absolute
-        if mymodule.relative_to_absolute_name(modname, level) == mymodule.name:
-            # FIXME: we used to raise InferenceError here, but why ?
-            return mymodule
-        try:
-            return mymodule.import_module(modname, level=level)
-        except ASTNGBuildingException:
-            raise InferenceError(modname)
-        except SyntaxError, ex:
-            raise InferenceError(str(ex))
-
-    def real_name(self, asname):
-        """get name from 'as' name"""
-        for name, _asname in self.names:
-            if name == '*':
-                return asname
-            if not _asname:
-                name = name.split('.', 1)[0]
-                _asname = name
-            if asname == _asname:
-                return name
-        raise NotFoundError(asname)
-
-
-

+ 0 - 903
pylibs/logilab/astng/node_classes.py

@@ -1,903 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-# copyright 2003-2010 Sylvain Thenault, all rights reserved.
-# contact mailto:thenault@gmail.com
-#
-# This file is part of logilab-astng.
-#
-# logilab-astng is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# logilab-astng is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-astng. If not, see <http://www.gnu.org/licenses/>.
-"""Module for some node classes. More nodes in scoped_nodes.py
-"""
-
-import sys
-
-from logilab.astng import BUILTINS_MODULE
-from logilab.astng.exceptions import NoDefault
-from logilab.astng.bases import (NodeNG, Statement, Instance, InferenceContext,
-                                 _infer_stmts, YES)
-from logilab.astng.mixins import BlockRangeMixIn, AssignTypeMixin, \
-                                 ParentAssignTypeMixin, FromImportMixIn
-
-
-def unpack_infer(stmt, context=None):
-    """recursively generate nodes inferred by the given statement.
-    If the inferred value is a list or a tuple, recurse on the elements
-    """
-    if isinstance(stmt, (List, Tuple)):
-        for elt in stmt.elts:
-            for infered_elt in unpack_infer(elt, context):
-                yield infered_elt
-        return
-    infered = stmt.infer(context).next()
-    if infered is stmt or infered is YES:
-        yield infered
-        return
-    for infered in stmt.infer(context):
-        for inf_inf in unpack_infer(infered, context):
-            yield inf_inf
-
-
-def are_exclusive(stmt1, stmt2, exceptions=None):
-    """return true if the two given statements are mutually exclusive
-
-    `exceptions` may be a list of exception names. If specified, discard If
-    branches and check one of the statement is in an exception handler catching
-    one of the given exceptions.
-
-    algorithm :
-     1) index stmt1's parents
-     2) climb among stmt2's parents until we find a common parent
-     3) if the common parent is a If or TryExcept statement, look if nodes are
-        in exclusive branches
-    """
-    # index stmt1's parents
-    stmt1_parents = {}
-    children = {}
-    node = stmt1.parent
-    previous = stmt1
-    while node:
-        stmt1_parents[node] = 1
-        children[node] = previous
-        previous = node
-        node = node.parent
-    # climb among stmt2's parents until we find a common parent
-    node = stmt2.parent
-    previous = stmt2
-    while node:
-        if node in stmt1_parents:
-            # if the common parent is a If or TryExcept statement, look if
-            # nodes are in exclusive branches
-            if isinstance(node, If) and exceptions is None:
-                if (node.locate_child(previous)[1]
-                    is not node.locate_child(children[node])[1]):
-                    return True
-            elif isinstance(node, TryExcept):
-                c2attr, c2node = node.locate_child(previous)
-                c1attr, c1node = node.locate_child(children[node])
-                if c1node is not c2node:
-                    if ((c2attr == 'body' and c1attr == 'handlers' and children[node].catch(exceptions)) or
-                        (c2attr == 'handlers' and c1attr == 'body' and previous.catch(exceptions)) or
-                        (c2attr == 'handlers' and c1attr == 'orelse') or
-                        (c2attr == 'orelse' and c1attr == 'handlers')):
-                        return True
-                elif c2attr == 'handlers' and c1attr == 'handlers':
-                    return previous is not children[node]
-            return False
-        previous = node
-        node = node.parent
-    return False
-
-
-class LookupMixIn(object):
-    """Mixin looking up a name in the right scope
-    """
-
-    def lookup(self, name):
-        """lookup a variable name
-
-        return the scope node and the list of assignments associated to the given
-        name according to the scope where it has been found (locals, globals or
-        builtin)
-
-        The lookup is starting from self's scope. If self is not a frame itself and
-        the name is found in the inner frame locals, statements will be filtered
-        to remove ignorable statements according to self's location
-        """
-        return self.scope().scope_lookup(self, name)
-
-    def ilookup(self, name):
-        """infered lookup
-
-        return an iterator on infered values of the statements returned by
-        the lookup method
-        """
-        frame, stmts = self.lookup(name)
-        context = InferenceContext()
-        return _infer_stmts(stmts, context, frame)
-
-    def _filter_stmts(self, stmts, frame, offset):
-        """filter statements to remove ignorable statements.
-
-        If self is not a frame itself and the name is found in the inner
-        frame locals, statements will be filtered to remove ignorable
-        statements according to self's location
-        """
-        # if offset == -1, my actual frame is not the inner frame but its parent
-        #
-        # class A(B): pass
-        #
-        # we need this to resolve B correctly
-        if offset == -1:
-            myframe = self.frame().parent.frame()
-        else:
-            myframe = self.frame()
-        if not myframe is frame or self is frame:
-            return stmts
-        mystmt = self.statement()
-        # line filtering if we are in the same frame
-        #
-        # take care node may be missing lineno information (this is the case for
-        # nodes inserted for living objects)
-        if myframe is frame and mystmt.fromlineno is not None:
-            assert mystmt.fromlineno is not None, mystmt
-            mylineno = mystmt.fromlineno + offset
-        else:
-            # disabling lineno filtering
-            mylineno = 0
-        _stmts = []
-        _stmt_parents = []
-        for node in stmts:
-            stmt = node.statement()
-            # line filtering is on and we have reached our location, break
-            if mylineno > 0 and stmt.fromlineno > mylineno:
-                break
-            assert hasattr(node, 'ass_type'), (node, node.scope(),
-                                               node.scope().locals)
-            ass_type = node.ass_type()
-
-            if node.has_base(self):
-                break
-
-            _stmts, done = ass_type._get_filtered_stmts(self, node, _stmts, mystmt)
-            if done:
-                break
-
-            optional_assign = ass_type.optional_assign
-            if optional_assign and ass_type.parent_of(self):
-                # we are inside a loop, loop var assigment is hidding previous
-                # assigment
-                _stmts = [node]
-                _stmt_parents = [stmt.parent]
-                continue
-
-            # XXX comment various branches below!!!
-            try:
-                pindex = _stmt_parents.index(stmt.parent)
-            except ValueError:
-                pass
-            else:
-                # we got a parent index, this means the currently visited node
-                # is at the same block level as a previously visited node
-                if _stmts[pindex].ass_type().parent_of(ass_type):
-                    # both statements are not at the same block level
-                    continue
-                # if currently visited node is following previously considered
-                # assignement and both are not exclusive, we can drop the
-                # previous one. For instance in the following code ::
-                #
-                #   if a:
-                #     x = 1
-                #   else:
-                #     x = 2
-                #   print x
-                #
-                # we can't remove neither x = 1 nor x = 2 when looking for 'x'
-                # of 'print x'; while in the following ::
-                #
-                #   x = 1
-                #   x = 2
-                #   print x
-                #
-                # we can remove x = 1 when we see x = 2
-                #
-                # moreover, on loop assignment types, assignment won't
-                # necessarily be done if the loop has no iteration, so we don't
-                # want to clear previous assigments if any (hence the test on
-                # optional_assign)
-                if not (optional_assign or are_exclusive(_stmts[pindex], node)):
-                    del _stmt_parents[pindex]
-                    del _stmts[pindex]
-            if isinstance(node, AssName):
-                if not optional_assign and stmt.parent is mystmt.parent:
-                    _stmts = []
-                    _stmt_parents = []
-            elif isinstance(node, DelName):
-                _stmts = []
-                _stmt_parents = []
-                continue
-            if not are_exclusive(self, node):
-                _stmts.append(node)
-                _stmt_parents.append(stmt.parent)
-        return _stmts
-
-# Name classes
-
-class AssName(LookupMixIn, ParentAssignTypeMixin, NodeNG):
-    """class representing an AssName node"""
-
-
-class DelName(LookupMixIn, ParentAssignTypeMixin, NodeNG):
-    """class representing a DelName node"""
-
-
-class Name(LookupMixIn, NodeNG):
-    """class representing a Name node"""
-
-
-
-
-#####################   node classes   ########################################
-
-class Arguments(NodeNG, AssignTypeMixin):
-    """class representing an Arguments node"""
-    _astng_fields = ('args', 'defaults')
-    args = None
-    defaults = None
-
-    def __init__(self, vararg=None, kwarg=None):
-        self.vararg = vararg
-        self.kwarg = kwarg
-
-    def _infer_name(self, frame, name):
-        if self.parent is frame:
-            return name
-        return None
-
-    def format_args(self):
-        """return arguments formatted as string"""
-        result = [_format_args(self.args, self.defaults)]
-        if self.vararg:
-            result.append('*%s' % self.vararg)
-        if self.kwarg:
-            result.append('**%s' % self.kwarg)
-        return ', '.join(result)
-
-    def default_value(self, argname):
-        """return the default value for an argument
-
-        :raise `NoDefault`: if there is no default value defined
-        """
-        i = _find_arg(argname, self.args)[0]
-        if i is not None:
-            idx = i - (len(self.args) - len(self.defaults))
-            if idx >= 0:
-                return self.defaults[idx]
-        raise NoDefault()
-
-    def is_argument(self, name):
-        """return True if the name is defined in arguments"""
-        if name == self.vararg:
-            return True
-        if name == self.kwarg:
-            return True
-        return self.find_argname(name, True)[1] is not None
-
-    def find_argname(self, argname, rec=False):
-        """return index and Name node with given name"""
-        if self.args: # self.args may be None in some cases (builtin function)
-            return _find_arg(argname, self.args, rec)
-        return None, None
-
-
-def _find_arg(argname, args, rec=False):
-    for i, arg in enumerate(args):
-        if isinstance(arg, Tuple):
-            if rec:
-                found = _find_arg(argname, arg.elts)
-                if found[0] is not None:
-                    return found
-        elif arg.name == argname:
-            return i, arg
-    return None, None
-
-
-def _format_args(args, defaults=None):
-    values = []
-    if args is None:
-        return ''
-    if defaults is not None:
-        default_offset = len(args) - len(defaults)
-    for i, arg in enumerate(args):
-        if isinstance(arg, Tuple):
-            values.append('(%s)' % _format_args(arg.elts))
-        else:
-            values.append(arg.name)
-            if defaults is not None and i >= default_offset:
-                values[-1] += '=' + defaults[i-default_offset].as_string()
-    return ', '.join(values)
-
-
-class AssAttr(NodeNG, ParentAssignTypeMixin):
-    """class representing an AssAttr node"""
-    _astng_fields = ('expr',)
-    expr = None
-
-class Assert(Statement):
-    """class representing an Assert node"""
-    _astng_fields = ('test', 'fail',)
-    test = None
-    fail = None
-
-class Assign(Statement, AssignTypeMixin):
-    """class representing an Assign node"""
-    _astng_fields = ('targets', 'value',)
-    targets = None
-    value = None
-
-class AugAssign(Statement, AssignTypeMixin):
-    """class representing an AugAssign node"""
-    _astng_fields = ('target', 'value',)
-    target = None
-    value = None
-
-class Backquote(NodeNG):
-    """class representing a Backquote node"""
-    _astng_fields = ('value',)
-    value = None
-
-class BinOp(NodeNG):
-    """class representing a BinOp node"""
-    _astng_fields = ('left', 'right',)
-    left = None
-    right = None
-
-class BoolOp(NodeNG):
-    """class representing a BoolOp node"""
-    _astng_fields = ('values',)
-    values = None
-
-class Break(Statement):
-    """class representing a Break node"""
-
-
-class CallFunc(NodeNG):
-    """class representing a CallFunc node"""
-    _astng_fields = ('func', 'args', 'starargs', 'kwargs')
-    func = None
-    args = None
-    starargs = None
-    kwargs = None
-
-    def __init__(self):
-        self.starargs = None
-        self.kwargs = None
-
-class Compare(NodeNG):
-    """class representing a Compare node"""
-    _astng_fields = ('left', 'ops',)
-    left = None
-    ops = None
-
-    def get_children(self):
-        """override get_children for tuple fields"""
-        yield self.left
-        for _, comparator in self.ops:
-            yield comparator # we don't want the 'op'
-
-    def last_child(self):
-        """override last_child"""
-        # XXX maybe if self.ops:
-        return self.ops[-1][1]
-        #return self.left
-
-class Comprehension(NodeNG):
-    """class representing a Comprehension node"""
-    _astng_fields = ('target', 'iter' ,'ifs')
-    target = None
-    iter = None
-    ifs = None
-
-    optional_assign = True
-    def ass_type(self):
-        return self
-
-    def _get_filtered_stmts(self, lookup_node, node, stmts, mystmt):
-        """method used in filter_stmts"""
-        if self is mystmt:
-            if isinstance(lookup_node, (Const, Name)):
-                return [lookup_node], True
-
-        elif self.statement() is mystmt:
-            # original node's statement is the assignment, only keeps
-            # current node (gen exp, list comp)
-
-            return [node], True
-
-        return stmts, False
-
-
-class Const(NodeNG, Instance):
-    """represent a constant node like num, str, bool, None, bytes"""
-
-    def __init__(self, value=None):
-        self.value = value
-
-    def getitem(self, index, context=None):
-        if isinstance(self.value, basestring):
-            return Const(self.value[index])
-        raise TypeError('%r (value=%s)' % (self, self.value))
-
-    def has_dynamic_getattr(self):
-        return False
-
-    def itered(self):
-        if isinstance(self.value, basestring):
-            return self.value
-        raise TypeError()
-
-    def pytype(self):
-        return self._proxied.qname()
-
-
-class Continue(Statement):
-    """class representing a Continue node"""
-
-
-class Decorators(NodeNG):
-    """class representing a Decorators node"""
-    _astng_fields = ('nodes',)
-    nodes = None
-
-    def __init__(self, nodes=None):
-        self.nodes = nodes
-
-    def scope(self):
-        # skip the function node to go directly to the upper level scope
-        return self.parent.parent.scope()
-
-class DelAttr(NodeNG, ParentAssignTypeMixin):
-    """class representing a DelAttr node"""
-    _astng_fields = ('expr',)
-    expr = None
-
-
-class Delete(Statement, AssignTypeMixin):
-    """class representing a Delete node"""
-    _astng_fields = ('targets',)
-    targets = None
-
-
-class Dict(NodeNG, Instance):
-    """class representing a Dict node"""
-    _astng_fields = ('items',)
-
-    def __init__(self, items=None):
-        if items is None:
-            self.items = []
-        else:
-            self.items = [(const_factory(k), const_factory(v))
-                          for k,v in items.iteritems()]
-
-    def pytype(self):
-        return '%s.dict' % BUILTINS_MODULE
-
-    def get_children(self):
-        """get children of a Dict node"""
-        # overrides get_children
-        for key, value in self.items:
-            yield key
-            yield value
-
-    def last_child(self):
-        """override last_child"""
-        if self.items:
-            return self.items[-1][1]
-        return None
-
-    def itered(self):
-        return self.items[::2]
-
-    def getitem(self, key, context=None):
-        for i in xrange(0, len(self.items), 2):
-            for inferedkey in self.items[i].infer(context):
-                if inferedkey is YES:
-                    continue
-                if isinstance(inferedkey, Const) and inferedkey.value == key:
-                    return self.items[i+1]
-        raise IndexError(key)
-
-
-class Discard(Statement):
-    """class representing a Discard node"""
-    _astng_fields = ('value',)
-    value = None
-
-
-class Ellipsis(NodeNG):
-    """class representing an Ellipsis node"""
-
-
-class EmptyNode(NodeNG):
-    """class representing an EmptyNode node"""
-
-
-class ExceptHandler(Statement, AssignTypeMixin):
-    """class representing an ExceptHandler node"""
-    _astng_fields = ('type', 'name', 'body',)
-    type = None
-    name = None
-    body = None
-
-    def _blockstart_toline(self):
-        if self.name:
-            return self.name.tolineno
-        elif self.type:
-            return self.type.tolineno
-        else:
-            return self.lineno
-
-    def set_line_info(self, lastchild):
-        self.fromlineno = self.lineno
-        self.tolineno = lastchild.tolineno
-        self.blockstart_tolineno = self._blockstart_toline()
-
-    def catch(self, exceptions):
-        if self.type is None or exceptions is None:
-            return True
-        for node in self.type.nodes_of_class(Name):
-            if node.name in exceptions:
-                return True
-
-
-class Exec(Statement):
-    """class representing an Exec node"""
-    _astng_fields = ('expr', 'globals', 'locals',)
-    expr = None
-    globals = None
-    locals = None
-
-
-class ExtSlice(NodeNG):
-    """class representing an ExtSlice node"""
-    _astng_fields = ('dims',)
-    dims = None
-
-class For(BlockRangeMixIn, AssignTypeMixin, Statement):
-    """class representing a For node"""
-    _astng_fields = ('target', 'iter', 'body', 'orelse',)
-    target = None
-    iter = None
-    body = None
-    orelse = None
-
-    optional_assign = True
-    def _blockstart_toline(self):
-        return self.iter.tolineno
-
-
-class From(FromImportMixIn, Statement):
-    """class representing a From node"""
-
-    def __init__(self,  fromname, names, level=0):
-        self.modname = fromname
-        self.names = names
-        self.level = level
-
-class Getattr(NodeNG):
-    """class representing a Getattr node"""
-    _astng_fields = ('expr',)
-    expr = None
-
-
-class Global(Statement):
-    """class representing a Global node"""
-
-    def __init__(self, names):
-        self.names = names
-
-    def _infer_name(self, frame, name):
-        return name
-
-
-class If(BlockRangeMixIn, Statement):
-    """class representing an If node"""
-    _astng_fields = ('test', 'body', 'orelse')
-    test = None
-    body = None
-    orelse = None
-
-    def _blockstart_toline(self):
-        return self.test.tolineno
-
-    def block_range(self, lineno):
-        """handle block line numbers range for if statements"""
-        if lineno == self.body[0].fromlineno:
-            return lineno, lineno
-        if lineno <= self.body[-1].tolineno:
-            return lineno, self.body[-1].tolineno
-        return self._elsed_block_range(lineno, self.orelse,
-                                       self.body[0].fromlineno - 1)
-
-
-class IfExp(NodeNG):
-    """class representing an IfExp node"""
-    _astng_fields = ('test', 'body', 'orelse')
-    test = None
-    body = None
-    orelse = None
-
-
-class Import(FromImportMixIn, Statement):
-    """class representing an Import node"""
-
-
-class Index(NodeNG):
-    """class representing an Index node"""
-    _astng_fields = ('value',)
-    value = None
-
-
-class Keyword(NodeNG):
-    """class representing a Keyword node"""
-    _astng_fields = ('value',)
-    value = None
-
-
-class List(NodeNG, Instance, ParentAssignTypeMixin):
-    """class representing a List node"""
-    _astng_fields = ('elts',)
-
-    def __init__(self, elts=None):
-        if elts is None:
-            self.elts = []
-        else:
-            self.elts = [const_factory(e) for e in elts]
-
-    def pytype(self):
-        return '%s.list' % BUILTINS_MODULE
-
-    def getitem(self, index, context=None):
-        return self.elts[index]
-
-    def itered(self):
-        return self.elts
-
-
-class Nonlocal(Statement):
-    """class representing a Nonlocal node"""
-
-    def __init__(self, names):
-        self.names = names
-
-    def _infer_name(self, frame, name):
-        return name
-
-
-class Pass(Statement):
-    """class representing a Pass node"""
-
-
-class Print(Statement):
-    """class representing a Print node"""
-    _astng_fields = ('dest', 'values',)
-    dest = None
-    values = None
-
-
-class Raise(Statement):
-    """class representing a Raise node"""
-    exc = None
-    if sys.version_info < (3, 0):
-        _astng_fields = ('exc', 'inst', 'tback')
-        inst = None
-        tback = None
-    else:
-        _astng_fields = ('exc', 'cause')
-        exc = None
-        cause = None
-
-    def raises_not_implemented(self):
-        if not self.exc:
-            return
-        for name in self.exc.nodes_of_class(Name):
-            if name.name == 'NotImplementedError':
-                return True
-
-
-class Return(Statement):
-    """class representing a Return node"""
-    _astng_fields = ('value',)
-    value = None
-
-
-class Set(NodeNG, Instance, ParentAssignTypeMixin):
-    """class representing a Set node"""
-    _astng_fields = ('elts',)
-
-    def __init__(self, elts=None):
-        if elts is None:
-            self.elts = []
-        else:
-            self.elts = [const_factory(e) for e in elts]
-
-    def pytype(self):
-        return '%s.set' % BUILTINS_MODULE
-
-    def itered(self):
-        return self.elts
-
-
-class Slice(NodeNG):
-    """class representing a Slice node"""
-    _astng_fields = ('lower', 'upper', 'step')
-    lower = None
-    upper = None
-    step = None
-
-class Starred(NodeNG):
-    """class representing a Starred node"""
-    _astng_fields = ('value',)
-    value = None
-
-
-class Subscript(NodeNG):
-    """class representing a Subscript node"""
-    _astng_fields = ('value', 'slice')
-    value = None
-    slice = None
-
-
-class TryExcept(BlockRangeMixIn, Statement):
-    """class representing a TryExcept node"""
-    _astng_fields = ('body', 'handlers', 'orelse',)
-    body = None
-    handlers = None
-    orelse = None
-
-    def _infer_name(self, frame, name):
-        return name
-
-    def _blockstart_toline(self):
-        return self.lineno
-
-    def block_range(self, lineno):
-        """handle block line numbers range for try/except statements"""
-        last = None
-        for exhandler in self.handlers:
-            if exhandler.type and lineno == exhandler.type.fromlineno:
-                return lineno, lineno
-            if exhandler.body[0].fromlineno <= lineno <= exhandler.body[-1].tolineno:
-                return lineno, exhandler.body[-1].tolineno
-            if last is None:
-                last = exhandler.body[0].fromlineno - 1
-        return self._elsed_block_range(lineno, self.orelse, last)
-
-
-class TryFinally(BlockRangeMixIn, Statement):
-    """class representing a TryFinally node"""
-    _astng_fields = ('body', 'finalbody',)
-    body = None
-    finalbody = None
-
-    def _blockstart_toline(self):
-        return self.lineno
-
-    def block_range(self, lineno):
-        """handle block line numbers range for try/finally statements"""
-        child = self.body[0]
-        # py2.5 try: except: finally:
-        if (isinstance(child, TryExcept) and child.fromlineno == self.fromlineno
-            and lineno > self.fromlineno and lineno <= child.tolineno):
-            return child.block_range(lineno)
-        return self._elsed_block_range(lineno, self.finalbody)
-
-
-class Tuple(NodeNG, Instance, ParentAssignTypeMixin):
-    """class representing a Tuple node"""
-    _astng_fields = ('elts',)
-
-    def __init__(self, elts=None):
-        if elts is None:
-            self.elts = []
-        else:
-            self.elts = [const_factory(e) for e in elts]
-
-    def pytype(self):
-        return '%s.tuple' % BUILTINS_MODULE
-
-    def getitem(self, index, context=None):
-        return self.elts[index]
-
-    def itered(self):
-        return self.elts
-
-
-class UnaryOp(NodeNG):
-    """class representing an UnaryOp node"""
-    _astng_fields = ('operand',)
-    operand = None
-
-
-class While(BlockRangeMixIn, Statement):
-    """class representing a While node"""
-    _astng_fields = ('test', 'body', 'orelse',)
-    test = None
-    body = None
-    orelse = None
-
-    def _blockstart_toline(self):
-        return self.test.tolineno
-
-    def block_range(self, lineno):
-        """handle block line numbers range for for and while statements"""
-        return self. _elsed_block_range(lineno, self.orelse)
-
-
-class With(BlockRangeMixIn, AssignTypeMixin, Statement):
-    """class representing a With node"""
-    _astng_fields = ('expr', 'vars', 'body')
-    expr = None
-    vars = None
-    body = None
-
-    def _blockstart_toline(self):
-        if self.vars:
-            return self.vars.tolineno
-        else:
-            return self.expr.tolineno
-
-
-class Yield(NodeNG):
-    """class representing a Yield node"""
-    _astng_fields = ('value',)
-    value = None
-
-# constants ##############################################################
-
-CONST_CLS = {
-    list: List,
-    tuple: Tuple,
-    dict: Dict,
-    set: Set,
-    type(None): Const,
-    }
-
-def _update_const_classes():
-    """update constant classes, so the keys of CONST_CLS can be reused"""
-    klasses = (bool, int, float, complex, str)
-    if sys.version_info < (3, 0):
-        klasses += (unicode, long)
-    if sys.version_info >= (2, 6):
-        klasses += (bytes,)
-    for kls in klasses:
-        CONST_CLS[kls] = Const
-_update_const_classes()
-
-def const_factory(value):
-    """return an astng node for a python value"""
-    # since const_factory is called to evaluate content of container (eg list,
-    # tuple), it may be called with some node as argument that should be left
-    # untouched
-    if isinstance(value, NodeNG):
-        return value
-    try:
-        return CONST_CLS[value.__class__](value)
-    except (KeyError, AttributeError):
-        # some constants (like from gtk._gtk) don't have their class in
-        # CONST_CLS, though we can "assert isinstance(value, tuple(CONST_CLS))"
-        if isinstance(value, tuple(CONST_CLS)):
-            return Const(value)
-        node = EmptyNode()
-        node.object = value
-        return node

+ 0 - 75
pylibs/logilab/astng/nodes.py

@@ -1,75 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-# copyright 2003-2010 Sylvain Thenault, all rights reserved.
-# contact mailto:thenault@gmail.com
-#
-# This file is part of logilab-astng.
-#
-# logilab-astng is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# logilab-astng is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-astng. If not, see <http://www.gnu.org/licenses/>.
-"""
-on all nodes :
- .is_statement, returning true if the node should be considered as a
-  statement node
- .root(), returning the root node of the tree (i.e. a Module)
- .previous_sibling(), returning previous sibling statement node
- .next_sibling(), returning next sibling statement node
- .statement(), returning the first parent node marked as statement node
- .frame(), returning the first node defining a new local scope (i.e.
-  Module, Function or Class)
- .set_local(name, node), define an identifier <name> on the first parent frame,
-  with the node defining it. This is used by the astng builder and should not
-  be used from out there.
-
-on From and Import :
- .real_name(name),
-
-
-"""
-
-__docformat__ = "restructuredtext en"
-
-from logilab.astng.node_classes import Arguments, AssAttr, Assert, Assign, \
-    AssName, AugAssign, Backquote, BinOp, BoolOp, Break, CallFunc, Compare, \
-    Comprehension, Const, Continue, Decorators, DelAttr, DelName, Delete, \
-    Dict, Discard, Ellipsis, EmptyNode, ExceptHandler, Exec, ExtSlice, For, \
-    From, Getattr, Global, If, IfExp, Import, Index, Keyword, \
-    List, Name, Nonlocal, Pass, Print, Raise, Return, Set, Slice, Starred, Subscript, \
-    TryExcept, TryFinally, Tuple, UnaryOp, While, With, Yield, \
-    const_factory
-from logilab.astng.scoped_nodes import Module, GenExpr, Lambda, DictComp, \
-    ListComp, SetComp, Function, Class
-
-ALL_NODE_CLASSES = (
-    Arguments, AssAttr, Assert, Assign, AssName, AugAssign,
-    Backquote, BinOp, BoolOp, Break,
-    CallFunc, Class, Compare, Comprehension, Const, Continue,
-    Decorators, DelAttr, DelName, Delete,
-    Dict, DictComp, Discard,
-    Ellipsis, EmptyNode, ExceptHandler, Exec, ExtSlice,
-    For, From, Function,
-    Getattr, GenExpr, Global,
-    If, IfExp, Import, Index,
-    Keyword,
-    Lambda, List, ListComp,
-    Name, Nonlocal,
-    Module,
-    Pass, Print,
-    Raise, Return,
-    Set, SetComp, Slice, Starred, Subscript,
-    TryExcept, TryFinally, Tuple,
-    UnaryOp,
-    While, With,
-    Yield,
-    )
-

+ 0 - 321
pylibs/logilab/astng/protocols.py

@@ -1,321 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-# copyright 2003-2010 Sylvain Thenault, all rights reserved.
-# contact mailto:thenault@gmail.com
-#
-# This file is part of logilab-astng.
-#
-# logilab-astng is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# logilab-astng is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-astng. If not, see <http://www.gnu.org/licenses/>.
-"""this module contains a set of functions to handle python protocols for nodes
-where it makes sense.
-"""
-
-__doctype__ = "restructuredtext en"
-
-from logilab.astng.exceptions import InferenceError, NoDefault
-from logilab.astng.node_classes import unpack_infer
-from logilab.astng.bases import copy_context, \
-     raise_if_nothing_infered, yes_if_nothing_infered, Instance, Generator, YES
-from logilab.astng.nodes import const_factory
-from logilab.astng import nodes
-
-# unary operations ############################################################
-
-def tl_infer_unary_op(self, operator):
-    if operator == 'not':
-        return const_factory(not bool(self.elts))
-    raise TypeError() # XXX log unsupported operation
-nodes.Tuple.infer_unary_op = tl_infer_unary_op
-nodes.List.infer_unary_op = tl_infer_unary_op
-
-
-def dict_infer_unary_op(self, operator):
-    if operator == 'not':
-        return const_factory(not bool(self.items))
-    raise TypeError() # XXX log unsupported operation
-nodes.Dict.infer_unary_op = dict_infer_unary_op
-
-
-def const_infer_unary_op(self, operator):
-    if operator == 'not':
-        return const_factory(not self.value)
-    # XXX log potentially raised TypeError
-    elif operator == '+':
-        return const_factory(+self.value)
-    else: # operator == '-':
-        return const_factory(-self.value)
-nodes.Const.infer_unary_op = const_infer_unary_op
-
-
-# binary operations ###########################################################
-
-BIN_OP_IMPL = {'+':  lambda a, b: a + b,
-               '-':  lambda a, b: a - b,
-               '/':  lambda a, b: a / b,
-               '//': lambda a, b: a // b,
-               '*':  lambda a, b: a * b,
-               '**': lambda a, b: a ** b,
-               '%':  lambda a, b: a % b,
-               '&':  lambda a, b: a & b,
-               '|':  lambda a, b: a | b,
-               '^':  lambda a, b: a ^ b,
-               '<<': lambda a, b: a << b,
-               '>>': lambda a, b: a >> b,
-               }
-for key, impl in BIN_OP_IMPL.items():
-    BIN_OP_IMPL[key+'='] = impl
-
-def const_infer_binary_op(self, operator, other, context):
-    for other in other.infer(context):
-        if isinstance(other, nodes.Const):
-            try:
-                impl = BIN_OP_IMPL[operator]
-
-                try:
-                    yield const_factory(impl(self.value, other.value))
-                except Exception:
-                    # ArithmeticError is not enough: float >> float is a TypeError
-                    # TODO : let pylint know about the problem
-                    pass
-            except TypeError:
-                # XXX log TypeError
-                continue
-        elif other is YES:
-            yield other
-        else:
-            try:
-                for val in other.infer_binary_op(operator, self, context):
-                    yield val
-            except AttributeError:
-                yield YES
-nodes.Const.infer_binary_op = yes_if_nothing_infered(const_infer_binary_op)
-
-
-def tl_infer_binary_op(self, operator, other, context):
-    for other in other.infer(context):
-        if isinstance(other, self.__class__) and operator == '+':
-            node = self.__class__()
-            elts = [n for elt in self.elts for n in elt.infer(context)
-                    if not n is YES]
-            elts += [n for elt in other.elts for n in elt.infer(context)
-                     if not n is YES]
-            node.elts = elts
-            yield node
-        elif isinstance(other, nodes.Const) and operator == '*':
-            if not isinstance(other.value, int):
-                yield YES
-                continue
-            node = self.__class__()
-            elts = [n for elt in self.elts for n in elt.infer(context)
-                    if not n is YES] * other.value
-            node.elts = elts
-            yield node
-        elif isinstance(other, Instance) and not isinstance(other, nodes.Const):
-            yield YES
-    # XXX else log TypeError
-nodes.Tuple.infer_binary_op = yes_if_nothing_infered(tl_infer_binary_op)
-nodes.List.infer_binary_op = yes_if_nothing_infered(tl_infer_binary_op)
-
-
-def dict_infer_binary_op(self, operator, other, context):
-    for other in other.infer(context):
-        if isinstance(other, Instance) and isinstance(other._proxied, nodes.Class):
-            yield YES
-        # XXX else log TypeError
-nodes.Dict.infer_binary_op = yes_if_nothing_infered(dict_infer_binary_op)
-
-
-# assignment ##################################################################
-
-"""the assigned_stmts method is responsible to return the assigned statement
-(e.g. not inferred) according to the assignment type.
-
-The `asspath` argument is used to record the lhs path of the original node.
-For instance if we want assigned statements for 'c' in 'a, (b,c)', asspath
-will be [1, 1] once arrived to the Assign node.
-
-The `context` argument is the current inference context which should be given
-to any intermediary inference necessary.
-"""
-
-def _resolve_looppart(parts, asspath, context):
-    """recursive function to resolve multiple assignments on loops"""
-    asspath = asspath[:]
-    index = asspath.pop(0)
-    for part in parts:
-        if part is YES:
-            continue
-        # XXX handle __iter__ and log potentially detected errors
-        if not hasattr(part, 'itered'):
-            continue
-        try:
-            itered = part.itered()
-        except TypeError:
-            continue # XXX log error
-        for stmt in itered:
-            try:
-                assigned = stmt.getitem(index, context)
-            except (AttributeError, IndexError):
-                continue
-            except TypeError, exc: # stmt is unsubscriptable Const
-                continue
-            if not asspath:
-                # we achieved to resolved the assignment path,
-                # don't infer the last part
-                yield assigned
-            elif assigned is YES:
-                break
-            else:
-                # we are not yet on the last part of the path
-                # search on each possibly inferred value
-                try:
-                    for infered in _resolve_looppart(assigned.infer(context),
-                                                     asspath, context):
-                        yield infered
-                except InferenceError:
-                    break
-
-
-def for_assigned_stmts(self, node, context=None, asspath=None):
-    if asspath is None:
-        for lst in self.iter.infer(context):
-            if isinstance(lst, (nodes.Tuple, nodes.List)):
-                for item in lst.elts:
-                    yield item
-    else:
-        for infered in _resolve_looppart(self.iter.infer(context),
-                                         asspath, context):
-            yield infered
-
-nodes.For.assigned_stmts = raise_if_nothing_infered(for_assigned_stmts)
-nodes.Comprehension.assigned_stmts = raise_if_nothing_infered(for_assigned_stmts)
-
-
-def mulass_assigned_stmts(self, node, context=None, asspath=None):
-    if asspath is None:
-        asspath = []
-    asspath.insert(0, self.elts.index(node))
-    return self.parent.assigned_stmts(self, context, asspath)
-nodes.Tuple.assigned_stmts = mulass_assigned_stmts
-nodes.List.assigned_stmts = mulass_assigned_stmts
-
-
-def assend_assigned_stmts(self, context=None):
-    return self.parent.assigned_stmts(self, context=context)
-nodes.AssName.assigned_stmts = assend_assigned_stmts
-nodes.AssAttr.assigned_stmts = assend_assigned_stmts
-
-
-def _arguments_infer_argname(self, name, context):
-    # arguments information may be missing, in which case we can't do anything
-    # more
-    if not (self.args or self.vararg or self.kwarg):
-        yield YES
-        return
-    # first argument of instance/class method
-    if self.args and getattr(self.args[0], 'name', None) == name:
-        functype = self.parent.type
-        if functype == 'method':
-            yield Instance(self.parent.parent.frame())
-            return
-        if functype == 'classmethod':
-            yield self.parent.parent.frame()
-            return
-    if name == self.vararg:
-        yield const_factory(())
-        return
-    if name == self.kwarg:
-        yield const_factory({})
-        return
-    # if there is a default value, yield it. And then yield YES to reflect
-    # we can't guess given argument value
-    try:
-        context = copy_context(context)
-        for infered in self.default_value(name).infer(context):
-            yield infered
-        yield YES
-    except NoDefault:
-        yield YES
-
-
-def arguments_assigned_stmts(self, node, context, asspath=None):
-    if context.callcontext:
-        # reset call context/name
-        callcontext = context.callcontext
-        context = copy_context(context)
-        context.callcontext = None
-        for infered in callcontext.infer_argument(self.parent, node.name, context):
-            yield infered
-        return
-    for infered in _arguments_infer_argname(self, node.name, context):
-        yield infered
-nodes.Arguments.assigned_stmts = arguments_assigned_stmts
-
-
-def assign_assigned_stmts(self, node, context=None, asspath=None):
-    if not asspath:
-        yield self.value
-        return
-    for infered in _resolve_asspart(self.value.infer(context), asspath, context):
-        yield infered
-nodes.Assign.assigned_stmts = raise_if_nothing_infered(assign_assigned_stmts)
-nodes.AugAssign.assigned_stmts = raise_if_nothing_infered(assign_assigned_stmts)
-
-
-def _resolve_asspart(parts, asspath, context):
-    """recursive function to resolve multiple assignments"""
-    asspath = asspath[:]
-    index = asspath.pop(0)
-    for part in parts:
-        if hasattr(part, 'getitem'):
-            try:
-                assigned = part.getitem(index, context)
-            # XXX raise a specific exception to avoid potential hiding of
-            # unexpected exception ?
-            except (TypeError, IndexError):
-                return
-            if not asspath:
-                # we achieved to resolved the assignment path, don't infer the
-                # last part
-                yield assigned
-            elif assigned is YES:
-                return
-            else:
-                # we are not yet on the last part of the path search on each
-                # possibly inferred value
-                try:
-                    for infered in _resolve_asspart(assigned.infer(context),
-                                                    asspath, context):
-                        yield infered
-                except InferenceError:
-                    return
-
-
-def excepthandler_assigned_stmts(self, node, context=None, asspath=None):
-    for assigned in unpack_infer(self.type):
-        if isinstance(assigned, nodes.Class):
-            assigned = Instance(assigned)
-        yield assigned
-nodes.ExceptHandler.assigned_stmts = raise_if_nothing_infered(excepthandler_assigned_stmts)
-
-
-def with_assigned_stmts(self, node, context=None, asspath=None):
-    if asspath is None:
-        for lst in self.vars.infer(context):
-            if isinstance(lst, (nodes.Tuple, nodes.List)):
-                for item in lst.nodes:
-                    yield item
-nodes.With.assigned_stmts = raise_if_nothing_infered(with_assigned_stmts)
-
-

+ 0 - 349
pylibs/logilab/astng/raw_building.py

@@ -1,349 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-# copyright 2003-2010 Sylvain Thenault, all rights reserved.
-# contact mailto:thenault@gmail.com
-#
-# This file is part of logilab-astng.
-#
-# logilab-astng is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# logilab-astng is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-astng. If not, see <http://www.gnu.org/licenses/>.
-"""this module contains a set of functions to create astng trees from scratch
-(build_* functions) or from living object (object_build_* functions)
-"""
-
-__docformat__ = "restructuredtext en"
-
-import sys
-from os.path import abspath
-from inspect import (getargspec, isdatadescriptor, isfunction, ismethod,
-                     ismethoddescriptor, isclass, isbuiltin)
-
-from logilab.astng import BUILTINS_MODULE
-from logilab.astng.node_classes import CONST_CLS
-from logilab.astng.nodes import (Module, Class, Const, const_factory, From,
-    Function, EmptyNode, Name, Arguments, Dict, List, Set, Tuple)
-from logilab.astng.bases import Generator
-from logilab.astng.manager import ASTNGManager
-MANAGER = ASTNGManager()
-
-_CONSTANTS = tuple(CONST_CLS) # the keys of CONST_CLS eg python builtin types
-
-def _attach_local_node(parent, node, name):
-    node.name = name # needed by add_local_node
-    parent.add_local_node(node)
-
-_marker = object()
-
-def attach_dummy_node(node, name, object=_marker):
-    """create a dummy node and register it in the locals of the given
-    node with the specified name
-    """
-    enode = EmptyNode()
-    enode.object = object
-    _attach_local_node(node, enode, name)
-
-EmptyNode.has_underlying_object = lambda self: self.object is not _marker
-
-def attach_const_node(node, name, value):
-    """create a Const node and register it in the locals of the given
-    node with the specified name
-    """
-    if not name in node.special_attributes:
-        _attach_local_node(node, const_factory(value), name)
-
-def attach_import_node(node, modname, membername):
-    """create a From node and register it in the locals of the given
-    node with the specified name
-    """
-    from_node = From(modname, [(membername, None)])
-    _attach_local_node(node, from_node, membername)
-
-
-def build_module(name, doc=None):
-    """create and initialize a astng Module node"""
-    node = Module(name, doc, pure_python=False)
-    node.package = False
-    node.parent = None
-    return node
-
-def build_class(name, basenames=(), doc=None):
-    """create and initialize a astng Class node"""
-    node = Class(name, doc)
-    for base in basenames:
-        basenode = Name()
-        basenode.name = base
-        node.bases.append(basenode)
-        basenode.parent = node
-    return node
-
-def build_function(name, args=None, defaults=None, flag=0, doc=None):
-    """create and initialize a astng Function node"""
-    args, defaults = args or [], defaults or []
-    # first argument is now a list of decorators
-    func = Function(name, doc)
-    func.args = argsnode = Arguments()
-    argsnode.args = []
-    for arg in args:
-        argsnode.args.append(Name())
-        argsnode.args[-1].name = arg
-        argsnode.args[-1].parent = argsnode
-    argsnode.defaults = []
-    for default in defaults:
-        argsnode.defaults.append(const_factory(default))
-        argsnode.defaults[-1].parent = argsnode
-    argsnode.kwarg = None
-    argsnode.vararg = None
-    argsnode.parent = func
-    if args:
-        register_arguments(func)
-    return func
-
-
-def build_from_import(fromname, names):
-    """create and initialize an astng From import statement"""
-    return From(fromname, [(name, None) for name in names])
-
-def register_arguments(func, args=None):
-    """add given arguments to local
-
-    args is a list that may contains nested lists
-    (i.e. def func(a, (b, c, d)): ...)
-    """
-    if args is None:
-        args = func.args.args
-        if func.args.vararg:
-            func.set_local(func.args.vararg, func.args)
-        if func.args.kwarg:
-            func.set_local(func.args.kwarg, func.args)
-    for arg in args:
-        if isinstance(arg, Name):
-            func.set_local(arg.name, arg)
-        else:
-            register_arguments(func, arg.elts)
-
-def object_build_class(node, member, localname):
-    """create astng for a living class object"""
-    basenames = [base.__name__ for base in member.__bases__]
-    return _base_class_object_build(node, member, basenames,
-                                    localname=localname)
-
-def object_build_function(node, member, localname):
-    """create astng for a living function object"""
-    args, varargs, varkw, defaults = getargspec(member)
-    if varargs is not None:
-        args.append(varargs)
-    if varkw is not None:
-        args.append(varkw)
-    func = build_function(getattr(member, '__name__', None) or localname, args,
-                          defaults, member.func_code.co_flags, member.__doc__)
-    node.add_local_node(func, localname)
-
-def object_build_datadescriptor(node, member, name):
-    """create astng for a living data descriptor object"""
-    return _base_class_object_build(node, member, [], name)
-
-def object_build_methoddescriptor(node, member, localname):
-    """create astng for a living method descriptor object"""
-    # FIXME get arguments ?
-    func = build_function(getattr(member, '__name__', None) or localname,
-                          doc=member.__doc__)
-    # set node's arguments to None to notice that we have no information, not
-    # and empty argument list
-    func.args.args = None
-    node.add_local_node(func, localname)
-
-def _base_class_object_build(node, member, basenames, name=None, localname=None):
-    """create astng for a living class object, with a given set of base names
-    (e.g. ancestors)
-    """
-    klass = build_class(name or getattr(member, '__name__', None) or localname,
-                        basenames, member.__doc__)
-    klass._newstyle = isinstance(member, type)
-    node.add_local_node(klass, localname)
-    try:
-        # limit the instantiation trick since it's too dangerous
-        # (such as infinite test execution...)
-        # this at least resolves common case such as Exception.args,
-        # OSError.errno
-        if issubclass(member, Exception):
-            instdict = member().__dict__
-        else:
-            raise TypeError
-    except:
-        pass
-    else:
-        for name, obj in instdict.items():
-            valnode = EmptyNode()
-            valnode.object = obj
-            valnode.parent = klass
-            valnode.lineno = 1
-            klass.instance_attrs[name] = [valnode]
-    return klass
-
-
-
-
-class InspectBuilder(object):
-    """class for building nodes from living object
-
-    this is actually a really minimal representation, including only Module,
-    Function and Class nodes and some others as guessed.
-    """
-
-    # astng from living objects ###############################################
-
-    def __init__(self):
-        self._done = {}
-        self._module = None
-
-    def inspect_build(self, module, modname=None, path=None):
-        """build astng from a living module (i.e. using inspect)
-        this is used when there is no python source code available (either
-        because it's a built-in module or because the .py is not available)
-        """
-        self._module = module
-        if modname is None:
-            modname = module.__name__
-        node = build_module(modname, module.__doc__)
-        node.file = node.path = path and abspath(path) or path
-        MANAGER.astng_cache[modname] = node
-        node.package = hasattr(module, '__path__')
-        self._done = {}
-        self.object_build(node, module)
-        return node
-
-    def object_build(self, node, obj):
-        """recursive method which create a partial ast from real objects
-         (only function, class, and method are handled)
-        """
-        if obj in self._done:
-            return self._done[obj]
-        self._done[obj] = node
-        for name in dir(obj):
-            try:
-                member = getattr(obj, name)
-            except AttributeError:
-                # damned ExtensionClass.Base, I know you're there !
-                attach_dummy_node(node, name)
-                continue
-            if ismethod(member):
-                member = member.im_func
-            if isfunction(member):
-                # verify this is not an imported function
-                filename = getattr(member.func_code, 'co_filename', None)
-                if filename is None:
-                    assert isinstance(member, object)
-                    object_build_methoddescriptor(node, member, name)
-                elif filename != getattr(self._module, '__file__', None):
-                    attach_dummy_node(node, name, member)
-                else:
-                    object_build_function(node, member, name)
-            elif isbuiltin(member):
-                if self.imported_member(node, member, name):
-                    #if obj is object:
-                    #    print 'skippp', obj, name, member
-                    continue
-                object_build_methoddescriptor(node, member, name)
-            elif isclass(member):
-                if self.imported_member(node, member, name):
-                    continue
-                if member in self._done:
-                    class_node = self._done[member]
-                    if not class_node in node.locals.get(name, ()):
-                        node.add_local_node(class_node, name)
-                else:
-                    class_node = object_build_class(node, member, name)
-                    # recursion
-                    self.object_build(class_node, member)
-                if name == '__class__' and class_node.parent is None:
-                    class_node.parent = self._done[self._module]
-            elif ismethoddescriptor(member):
-                assert isinstance(member, object)
-                object_build_methoddescriptor(node, member, name)
-            elif isdatadescriptor(member):
-                assert isinstance(member, object)
-                object_build_datadescriptor(node, member, name)
-            elif isinstance(member, _CONSTANTS):
-                attach_const_node(node, name, member)
-            else:
-                # create an empty node so that the name is actually defined
-                attach_dummy_node(node, name, member)
-
-    def imported_member(self, node, member, name):
-        """verify this is not an imported class or handle it"""
-        # /!\ some classes like ExtensionClass doesn't have a __module__
-        # attribute ! Also, this may trigger an exception on badly built module
-        # (see http://www.logilab.org/ticket/57299 for instance)
-        try:
-            modname = getattr(member, '__module__', None)
-        except:
-            # XXX use logging
-            print 'unexpected error while building astng from living object'
-            import traceback
-            traceback.print_exc()
-            modname = None
-        if modname is None:
-            if name in ('__new__', '__subclasshook__'):
-                # Python 2.5.1 (r251:54863, Sep  1 2010, 22:03:14)
-                # >>> print object.__new__.__module__
-                # None
-                modname = BUILTINS_MODULE
-            else:
-                attach_dummy_node(node, name, member)
-                return True
-        if {'gtk': 'gtk._gtk'}.get(modname, modname) != self._module.__name__:
-            # check if it sounds valid and then add an import node, else use a
-            # dummy node
-            try:
-                getattr(sys.modules[modname], name)
-            except (KeyError, AttributeError):
-                attach_dummy_node(node, name, member)
-            else:
-                attach_import_node(node, modname, name)
-            return True
-        return False
-
-
-### astng boot strapping ################################################### ###
-
-_CONST_PROXY = {}
-def astng_boot_strapping():
-    """astng boot strapping the builtins module"""
-    # this boot strapping is necessary since we need the Const nodes to
-    # inspect_build builtins, and then we can proxy Const
-    builder = InspectBuilder()
-    from logilab.common.compat import builtins
-    astng_builtin = builder.inspect_build(builtins)
-    for cls, node_cls in CONST_CLS.items():
-        if cls is type(None):
-            proxy = build_class('NoneType')
-            proxy.parent = astng_builtin
-        else:
-            proxy = astng_builtin.getattr(cls.__name__)[0] # XXX
-        if cls in (dict, list, set, tuple):
-            node_cls._proxied = proxy
-        else:
-            _CONST_PROXY[cls] = proxy
-
-astng_boot_strapping()
-
-# TODO : find a nicer way to handle this situation;
-# However __proxied introduced an
-# infinite recursion (see https://bugs.launchpad.net/pylint/+bug/456870)
-def _set_proxied(const):
-    return _CONST_PROXY[const.value.__class__]
-Const._proxied = property(_set_proxied)
-
-# FIXME : is it alright that Generator._proxied is not a astng node?
-Generator._proxied = MANAGER.infer_astng_from_something(type(a for a in ()))
-

+ 0 - 864
pylibs/logilab/astng/rebuilder.py

@@ -1,864 +0,0 @@
-# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-# copyright 2003-2010 Sylvain Thenault, all rights reserved.
-# contact mailto:thenault@gmail.com
-#
-# This file is part of logilab-astng.
-#
-# logilab-astng is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# logilab-astng is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-astng. If not, see <http://www.gnu.org/licenses/>.
-"""this module contains utilities for rebuilding a _ast tree in
-order to get a single ASTNG representation
-"""
-
-import sys
-from _ast import (Expr as Discard, Str,
-    # binary operators
-    Add, Div, FloorDiv,  Mod, Mult, Pow, Sub, BitAnd, BitOr, BitXor,
-    LShift, RShift,
-    # logical operators
-    And, Or,
-    # unary operators
-    UAdd, USub, Not, Invert,
-    # comparison operators
-    Eq, Gt, GtE, In, Is, IsNot, Lt, LtE, NotEq, NotIn,
-    )
-
-from logilab.astng.exceptions import ASTNGBuildingException
-from logilab.astng import nodes as new
-
-
-_BIN_OP_CLASSES = {Add: '+',
-                   BitAnd: '&',
-                   BitOr: '|',
-                   BitXor: '^',
-                   Div: '/',
-                   FloorDiv: '//',
-                   Mod: '%',
-                   Mult: '*',
-                   Pow: '**',
-                   Sub: '-',
-                   LShift: '<<',
-                   RShift: '>>'}
-
-_BOOL_OP_CLASSES = {And: 'and',
-                    Or: 'or'}
-
-_UNARY_OP_CLASSES = {UAdd: '+',
-                     USub: '-',
-                     Not: 'not',
-                     Invert: '~'}
-
-_CMP_OP_CLASSES = {Eq: '==',
-                   Gt: '>',
-                   GtE: '>=',
-                   In: 'in',
-                   Is: 'is',
-                   IsNot: 'is not',
-                   Lt: '<',
-                   LtE: '<=',
-                   NotEq: '!=',
-                   NotIn: 'not in'}
-
-CONST_NAME_TRANSFORMS = {'None':  None,
-                         'True':  True,
-                         'False': False}
-
-REDIRECT = {'arguments': 'Arguments',
-            'Attribute': 'Getattr',
-            'comprehension': 'Comprehension',
-            'Call': 'CallFunc',
-            'ClassDef': 'Class',
-            "ListCompFor": 'Comprehension',
-            "GenExprFor": 'Comprehension',
-            'excepthandler': 'ExceptHandler',
-            'Expr': 'Discard',
-            'FunctionDef': 'Function',
-            'GeneratorExp': 'GenExpr',
-            'ImportFrom': 'From',
-            'keyword': 'Keyword',
-            'Repr': 'Backquote',
-            }
-
-def _init_set_doc(node, newnode):
-    newnode.doc = None
-    try:
-        if isinstance(node.body[0], Discard) and isinstance(node.body[0].value, Str):
-            newnode.tolineno = node.body[0].lineno
-            newnode.doc = node.body[0].value.s
-            node.body = node.body[1:]
-
-    except IndexError:
-        pass # ast built from scratch
-
-def _lineno_parent(oldnode, newnode, parent):
-    newnode.parent = parent
-    if hasattr(oldnode, 'lineno'):
-        newnode.lineno = oldnode.lineno
-    if hasattr(oldnode, 'col_offset'):
-        newnode.col_offset = oldnode.col_offset
-
-def _set_infos(oldnode, newnode, parent):
-    newnode.parent = parent
-    if hasattr(oldnode, 'lineno'):
-        newnode.lineno = oldnode.lineno
-    if hasattr(oldnode, 'col_offset'):
-        newnode.col_offset = oldnode.col_offset
-    newnode.set_line_info(newnode.last_child()) # set_line_info accepts None
-
-
-
-
-class TreeRebuilder(object):
-    """Rebuilds the _ast tree to become an ASTNG tree"""
-
-    _visit_meths = {}
-    def __init__(self):
-        self.init()
-
-    def init(self):
-        self.asscontext = None
-        self._metaclass = ['']
-        self._global_names = []
-        self._from_nodes = []
-        self._delayed_assattr = []
-
-    def visit(self, node, parent):
-        cls = node.__class__
-        if cls in self._visit_meths:
-            return self._visit_meths[cls](node, parent)
-        else:
-            cls_name = cls.__name__
-            visit_name = 'visit_' + REDIRECT.get(cls_name, cls_name).lower()
-            visit_method = getattr(self, visit_name)
-            self._visit_meths[cls] = visit_method
-            return visit_method(node, parent)
-
-    def _save_assignment(self, node, name=None):
-        """save assignement situation since node.parent is not available yet"""
-        if self._global_names and node.name in self._global_names[-1]:
-            node.root().set_local(node.name, node)
-        else:
-            node.parent.set_local(node.name, node)
-
-
-    def visit_arguments(self, node, parent):
-        """visit a Arguments node by returning a fresh instance of it"""
-        newnode = new.Arguments()
-        _lineno_parent(node, newnode, parent)
-        self.asscontext = "Ass"
-        newnode.args = [self.visit(child, newnode) for child in node.args]
-        self.asscontext = None
-        newnode.defaults = [self.visit(child, newnode) for child in node.defaults]
-        newnode.vararg = node.vararg
-        newnode.kwarg = node.kwarg
-        # save argument names in locals:
-        if node.vararg:
-            newnode.parent.set_local(newnode.vararg, newnode)
-        if node.kwarg:
-            newnode.parent.set_local(newnode.kwarg, newnode)
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_assattr(self, node, parent):
-        """visit a AssAttr node by returning a fresh instance of it"""
-        assc, self.asscontext = self.asscontext, None
-        newnode = new.AssAttr()
-        _lineno_parent(node, newnode, parent)
-        newnode.expr = self.visit(node.expr, newnode)
-        self.asscontext = assc
-        self._delayed_assattr.append(newnode)
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_assert(self, node, parent):
-        """visit a Assert node by returning a fresh instance of it"""
-        newnode = new.Assert()
-        _lineno_parent(node, newnode, parent)
-        newnode.test = self.visit(node.test, newnode)
-        if node.msg is not None:
-            newnode.fail = self.visit(node.msg, newnode)
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_assign(self, node, parent):
-        """visit a Assign node by returning a fresh instance of it"""
-        newnode = new.Assign()
-        _lineno_parent(node, newnode, parent)
-        self.asscontext = "Ass"
-        newnode.targets = [self.visit(child, newnode) for child in node.targets]
-        self.asscontext = None
-        newnode.value = self.visit(node.value, newnode)
-        # set some function or metaclass infos  XXX explain ?
-        klass = newnode.parent.frame()
-        if (isinstance(klass, new.Class)
-            and isinstance(newnode.value, new.CallFunc)
-            and isinstance(newnode.value.func, new.Name)):
-            func_name = newnode.value.func.name
-            for ass_node in newnode.targets:
-                try:
-                    meth = klass[ass_node.name]
-                    if isinstance(meth, new.Function):
-                        if func_name in ('classmethod', 'staticmethod'):
-                            meth.type = func_name
-                        elif func_name == 'classproperty': # see lgc.decorators
-                            meth.type = 'classmethod'
-                        meth.extra_decorators.append(newnode.value)
-                except (AttributeError, KeyError):
-                    continue
-        elif getattr(newnode.targets[0], 'name', None) == '__metaclass__':
-            # XXX check more...
-            self._metaclass[-1] = 'type' # XXX get the actual metaclass
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_assname(self, node, parent, node_name=None):
-        '''visit a node and return a AssName node'''
-        newnode = new.AssName()
-        _set_infos(node, newnode, parent)
-        newnode.name = node_name
-        self._save_assignment(newnode)
-        return newnode
-
-    def visit_augassign(self, node, parent):
-        """visit a AugAssign node by returning a fresh instance of it"""
-        newnode = new.AugAssign()
-        _lineno_parent(node, newnode, parent)
-        newnode.op = _BIN_OP_CLASSES[node.op.__class__] + "="
-        self.asscontext = "Ass"
-        newnode.target = self.visit(node.target, newnode)
-        self.asscontext = None
-        newnode.value = self.visit(node.value, newnode)
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_backquote(self, node, parent):
-        """visit a Backquote node by returning a fresh instance of it"""
-        newnode = new.Backquote()
-        _lineno_parent(node, newnode, parent)
-        newnode.value = self.visit(node.value, newnode)
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_binop(self, node, parent):
-        """visit a BinOp node by returning a fresh instance of it"""
-        newnode = new.BinOp()
-        _lineno_parent(node, newnode, parent)
-        newnode.left = self.visit(node.left, newnode)
-        newnode.right = self.visit(node.right, newnode)
-        newnode.op = _BIN_OP_CLASSES[node.op.__class__]
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_boolop(self, node, parent):
-        """visit a BoolOp node by returning a fresh instance of it"""
-        newnode = new.BoolOp()
-        _lineno_parent(node, newnode, parent)
-        newnode.values = [self.visit(child, newnode) for child in node.values]
-        newnode.op = _BOOL_OP_CLASSES[node.op.__class__]
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_break(self, node, parent):
-        """visit a Break node by returning a fresh instance of it"""
-        newnode = new.Break()
-        _set_infos(node, newnode, parent)
-        return newnode
-
-    def visit_callfunc(self, node, parent):
-        """visit a CallFunc node by returning a fresh instance of it"""
-        newnode = new.CallFunc()
-        _lineno_parent(node, newnode, parent)
-        newnode.func = self.visit(node.func, newnode)
-        newnode.args = [self.visit(child, newnode) for child in node.args]
-        if node.starargs is not None:
-            newnode.starargs = self.visit(node.starargs, newnode)
-        if node.kwargs is not None:
-            newnode.kwargs = self.visit(node.kwargs, newnode)
-        newnode.args.extend(self.visit(child, newnode) for child in node.keywords)
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_class(self, node, parent):
-        """visit a Class node to become astng"""
-        self._metaclass.append(self._metaclass[-1])
-        newnode = new.Class(node.name, None)
-        _lineno_parent(node, newnode, parent)
-        _init_set_doc(node, newnode)
-        newnode.bases = [self.visit(child, newnode) for child in node.bases]
-        newnode.body = [self.visit(child, newnode) for child in node.body]
-        if 'decorator_list' in node._fields and node.decorator_list:# py >= 2.6
-            newnode.decorators = self.visit_decorators(node, newnode)
-        newnode.set_line_info(newnode.last_child())
-        metaclass = self._metaclass.pop()
-        if not newnode.bases:
-            # no base classes, detect new / style old style according to
-            # current scope
-            newnode._newstyle = metaclass == 'type'
-        newnode.parent.frame().set_local(newnode.name, newnode)
-        return newnode
-
-    def visit_const(self, node, parent):
-        """visit a Const node by returning a fresh instance of it"""
-        newnode = new.Const(node.value)
-        _set_infos(node, newnode, parent)
-        return newnode
-
-    def visit_continue(self, node, parent):
-        """visit a Continue node by returning a fresh instance of it"""
-        newnode = new.Continue()
-        _set_infos(node, newnode, parent)
-        return newnode
-
-    def visit_compare(self, node, parent):
-        """visit a Compare node by returning a fresh instance of it"""
-        newnode = new.Compare()
-        _lineno_parent(node, newnode, parent)
-        newnode.left = self.visit(node.left, newnode)
-        newnode.ops = [(_CMP_OP_CLASSES[op.__class__], self.visit(expr, newnode))
-                    for (op, expr) in zip(node.ops, node.comparators)]
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_comprehension(self, node, parent):
-        """visit a Comprehension node by returning a fresh instance of it"""
-        newnode = new.Comprehension()
-        _lineno_parent(node, newnode, parent)
-        self.asscontext = "Ass"
-        newnode.target = self.visit(node.target, newnode)
-        self.asscontext = None
-        newnode.iter = self.visit(node.iter, newnode)
-        newnode.ifs = [self.visit(child, newnode) for child in node.ifs]
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_decorators(self, node, parent):
-        """visit a Decorators node by returning a fresh instance of it"""
-        # /!\ node is actually a _ast.Function node while
-        # parent is a astng.nodes.Function node
-        newnode = new.Decorators()
-        _lineno_parent(node, newnode, parent)
-        if 'decorators' in node._fields: # py < 2.6, i.e. 2.5
-            decorators = node.decorators
-        else:
-            decorators= node.decorator_list
-        newnode.nodes = [self.visit(child, newnode) for child in decorators]
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_delete(self, node, parent):
-        """visit a Delete node by returning a fresh instance of it"""
-        newnode = new.Delete()
-        _lineno_parent(node, newnode, parent)
-        self.asscontext = "Del"
-        newnode.targets = [self.visit(child, newnode) for child in node.targets]
-        self.asscontext = None
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_dict(self, node, parent):
-        """visit a Dict node by returning a fresh instance of it"""
-        newnode = new.Dict()
-        _lineno_parent(node, newnode, parent)
-        newnode.items = [(self.visit(key, newnode), self.visit(value, newnode))
-                          for key, value in zip(node.keys, node.values)]
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_dictcomp(self, node, parent):
-        """visit a DictComp node by returning a fresh instance of it"""
-        newnode = new.DictComp()
-        _lineno_parent(node, newnode, parent)
-        newnode.key = self.visit(node.key, newnode)
-        newnode.value = self.visit(node.value, newnode)
-        newnode.generators = [self.visit(child, newnode)
-                              for child in node.generators]
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_discard(self, node, parent):
-        """visit a Discard node by returning a fresh instance of it"""
-        newnode = new.Discard()
-        _lineno_parent(node, newnode, parent)
-        newnode.value = self.visit(node.value, newnode)
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_ellipsis(self, node, parent):
-        """visit an Ellipsis node by returning a fresh instance of it"""
-        newnode = new.Ellipsis()
-        _set_infos(node, newnode, parent)
-        return newnode
-
-    def visit_emptynode(self, node, parent):
-        """visit an EmptyNode node by returning a fresh instance of it"""
-        newnode = new.EmptyNode()
-        _set_infos(node, newnode, parent)
-        return newnode
-
-    def visit_excepthandler(self, node, parent):
-        """visit an ExceptHandler node by returning a fresh instance of it"""
-        newnode = new.ExceptHandler()
-        _lineno_parent(node, newnode, parent)
-        if node.type is not None:
-            newnode.type = self.visit(node.type, newnode)
-        if node.name is not None:
-            # /!\ node.name can be a tuple
-            self.asscontext = "Ass"
-            newnode.name = self.visit(node.name, newnode)
-            self.asscontext = None
-        newnode.body = [self.visit(child, newnode) for child in node.body]
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_exec(self, node, parent):
-        """visit an Exec node by returning a fresh instance of it"""
-        newnode = new.Exec()
-        _lineno_parent(node, newnode, parent)
-        newnode.expr = self.visit(node.body, newnode)
-        if node.globals is not None:
-            newnode.globals = self.visit(node.globals, newnode)
-        if node.locals is not None:
-            newnode.locals = self.visit(node.locals, newnode)
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_extslice(self, node, parent):
-        """visit an ExtSlice node by returning a fresh instance of it"""
-        newnode = new.ExtSlice()
-        _lineno_parent(node, newnode, parent)
-        newnode.dims = [self.visit(dim, newnode) for dim in node.dims]
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_for(self, node, parent):
-        """visit a For node by returning a fresh instance of it"""
-        newnode = new.For()
-        _lineno_parent(node, newnode, parent)
-        self.asscontext = "Ass"
-        newnode.target = self.visit(node.target, newnode)
-        self.asscontext = None
-        newnode.iter = self.visit(node.iter, newnode)
-        newnode.body = [self.visit(child, newnode) for child in node.body]
-        newnode.orelse = [self.visit(child, newnode) for child in node.orelse]
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_from(self, node, parent):
-        """visit a From node by returning a fresh instance of it"""
-        names = [(alias.name, alias.asname) for alias in node.names]
-        newnode = new.From(node.module or '', names, node.level)
-        _set_infos(node, newnode, parent)
-        # store From names to add them to locals after building
-        self._from_nodes.append(newnode)
-        return newnode
-
-    def visit_function(self, node, parent):
-        """visit an Function node to become astng"""
-        self._global_names.append({})
-        newnode = new.Function(node.name, None)
-        _lineno_parent(node, newnode, parent)
-        _init_set_doc(node, newnode)
-        newnode.args = self.visit(node.args, newnode)
-        newnode.body = [self.visit(child, newnode) for child in node.body]
-        if 'decorators' in node._fields: # py < 2.6
-            attr = 'decorators'
-        else:
-            attr = 'decorator_list'
-        decorators = getattr(node, attr)
-        if decorators:
-            newnode.decorators = self.visit_decorators(node, newnode)
-        newnode.set_line_info(newnode.last_child())
-        self._global_names.pop()
-        frame = newnode.parent.frame()
-        if isinstance(frame, new.Class):
-            if newnode.name == '__new__':
-                newnode.type = 'classmethod'
-            else:
-                newnode.type = 'method'
-        if newnode.decorators is not None:
-            for decorator_expr in newnode.decorators.nodes:
-                if isinstance(decorator_expr, new.Name):
-                    if decorator_expr.name in ('classmethod', 'staticmethod'):
-                        newnode.type = decorator_expr.name
-                    elif decorator_expr.name == 'classproperty':
-                        newnode.type = 'classmethod'
-        frame.set_local(newnode.name, newnode)
-        return newnode
-
-    def visit_genexpr(self, node, parent):
-        """visit a GenExpr node by returning a fresh instance of it"""
-        newnode = new.GenExpr()
-        _lineno_parent(node, newnode, parent)
-        newnode.elt = self.visit(node.elt, newnode)
-        newnode.generators = [self.visit(child, newnode) for child in node.generators]
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_getattr(self, node, parent):
-        """visit a Getattr node by returning a fresh instance of it"""
-        if self.asscontext == "Del":
-            # FIXME : maybe we should reintroduce and visit_delattr ?
-            # for instance, deactivating asscontext
-            newnode = new.DelAttr()
-        elif self.asscontext == "Ass":
-            # FIXME : maybe we should call visit_assattr ?
-            newnode = new.AssAttr()
-            self._delayed_assattr.append(newnode)
-        else:
-            newnode = new.Getattr()
-        _lineno_parent(node, newnode, parent)
-        asscontext, self.asscontext = self.asscontext, None
-        newnode.expr = self.visit(node.value, newnode)
-        self.asscontext = asscontext
-        newnode.attrname = node.attr
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_global(self, node, parent):
-        """visit an Global node to become astng"""
-        newnode = new.Global(node.names)
-        _set_infos(node, newnode, parent)
-        if self._global_names: # global at the module level, no effect
-            for name in node.names:
-                self._global_names[-1].setdefault(name, []).append(newnode)
-        return newnode
-
-    def visit_if(self, node, parent):
-        """visit a If node by returning a fresh instance of it"""
-        newnode = new.If()
-        _lineno_parent(node, newnode, parent)
-        newnode.test = self.visit(node.test, newnode)
-        newnode.body = [self.visit(child, newnode) for child in node.body]
-        newnode.orelse = [self.visit(child, newnode) for child in node.orelse]
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_ifexp(self, node, parent):
-        """visit a IfExp node by returning a fresh instance of it"""
-        newnode = new.IfExp()
-        _lineno_parent(node, newnode, parent)
-        newnode.test = self.visit(node.test, newnode)
-        newnode.body = self.visit(node.body, newnode)
-        newnode.orelse = self.visit(node.orelse, newnode)
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_import(self, node, parent):
-        """visit a Import node by returning a fresh instance of it"""
-        newnode = new.Import()
-        _set_infos(node, newnode, parent)
-        newnode.names = [(alias.name, alias.asname) for alias in node.names]
-        # save import names in parent's locals:
-        for (name, asname) in newnode.names:
-            name = asname or name
-            newnode.parent.set_local(name.split('.')[0], newnode)
-        return newnode
-
-    def visit_index(self, node, parent):
-        """visit a Index node by returning a fresh instance of it"""
-        newnode = new.Index()
-        _lineno_parent(node, newnode, parent)
-        newnode.value = self.visit(node.value, newnode)
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_keyword(self, node, parent):
-        """visit a Keyword node by returning a fresh instance of it"""
-        newnode = new.Keyword()
-        _lineno_parent(node, newnode, parent)
-        newnode.arg = node.arg
-        newnode.value = self.visit(node.value, newnode)
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_lambda(self, node, parent):
-        """visit a Lambda node by returning a fresh instance of it"""
-        newnode = new.Lambda()
-        _lineno_parent(node, newnode, parent)
-        newnode.args = self.visit(node.args, newnode)
-        newnode.body = self.visit(node.body, newnode)
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_list(self, node, parent):
-        """visit a List node by returning a fresh instance of it"""
-        newnode = new.List()
-        _lineno_parent(node, newnode, parent)
-        newnode.elts = [self.visit(child, newnode) for child in node.elts]
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_listcomp(self, node, parent):
-        """visit a ListComp node by returning a fresh instance of it"""
-        newnode = new.ListComp()
-        _lineno_parent(node, newnode, parent)
-        newnode.elt = self.visit(node.elt, newnode)
-        newnode.generators = [self.visit(child, newnode)
-                              for child in node.generators]
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_module(self, node, modname, package):
-        """visit a Module node by returning a fresh instance of it"""
-        newnode = new.Module(modname, None)
-        newnode.package = package
-        _lineno_parent(node, newnode, parent=None)
-        _init_set_doc(node, newnode)
-        newnode.body = [self.visit(child, newnode) for child in node.body]
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_name(self, node, parent):
-        """visit a Name node by returning a fresh instance of it"""
-        # True and False can be assigned to something in py2x, so we have to
-        # check first the asscontext
-        if self.asscontext == "Del":
-            newnode = new.DelName()
-        elif self.asscontext is not None: # Ass
-            assert self.asscontext == "Ass"
-            newnode = new.AssName()
-        elif node.id in CONST_NAME_TRANSFORMS:
-            newnode = new.Const(CONST_NAME_TRANSFORMS[node.id])
-            _set_infos(node, newnode, parent)
-            return newnode
-        else:
-            newnode = new.Name()
-        _lineno_parent(node, newnode, parent)
-        newnode.name = node.id
-        # XXX REMOVE me :
-        if self.asscontext in ('Del', 'Ass'): # 'Aug' ??
-            self._save_assignment(newnode)
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_bytes(self, node, parent):
-        """visit a Bytes node by returning a fresh instance of Const"""
-        newnode = new.Const(node.s)
-        _set_infos(node, newnode, parent)
-        return newnode
-
-    def visit_num(self, node, parent):
-        """visit a Num node by returning a fresh instance of Const"""
-        newnode = new.Const(node.n)
-        _set_infos(node, newnode, parent)
-        return newnode
-
-    def visit_pass(self, node, parent):
-        """visit a Pass node by returning a fresh instance of it"""
-        newnode = new.Pass()
-        _set_infos(node, newnode, parent)
-        return newnode
-
-    def visit_str(self, node, parent):
-        """visit a Str node by returning a fresh instance of Const"""
-        newnode = new.Const(node.s)
-        _set_infos(node, newnode, parent)
-        return newnode
-
-    def visit_print(self, node, parent):
-        """visit a Print node by returning a fresh instance of it"""
-        newnode = new.Print()
-        _lineno_parent(node, newnode, parent)
-        newnode.nl = node.nl
-        if node.dest is not None:
-            newnode.dest = self.visit(node.dest, newnode)
-        newnode.values = [self.visit(child, newnode) for child in node.values]
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_raise(self, node, parent):
-        """visit a Raise node by returning a fresh instance of it"""
-        newnode = new.Raise()
-        _lineno_parent(node, newnode, parent)
-        if node.type is not None:
-            newnode.exc = self.visit(node.type, newnode)
-        if node.inst is not None:
-            newnode.inst = self.visit(node.inst, newnode)
-        if node.tback is not None:
-            newnode.tback = self.visit(node.tback, newnode)
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_return(self, node, parent):
-        """visit a Return node by returning a fresh instance of it"""
-        newnode = new.Return()
-        _lineno_parent(node, newnode, parent)
-        if node.value is not None:
-            newnode.value = self.visit(node.value, newnode)
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_set(self, node, parent):
-        """visit a Tuple node by returning a fresh instance of it"""
-        newnode = new.Set()
-        _lineno_parent(node, newnode, parent)
-        newnode.elts = [self.visit(child, newnode) for child in node.elts]
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_setcomp(self, node, parent):
-        """visit a SetComp node by returning a fresh instance of it"""
-        newnode = new.SetComp()
-        _lineno_parent(node, newnode, parent)
-        newnode.elt = self.visit(node.elt, newnode)
-        newnode.generators = [self.visit(child, newnode)
-                              for child in node.generators]
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_slice(self, node, parent):
-        """visit a Slice node by returning a fresh instance of it"""
-        newnode = new.Slice()
-        _lineno_parent(node, newnode, parent)
-        if node.lower is not None:
-            newnode.lower = self.visit(node.lower, newnode)
-        if node.upper is not None:
-            newnode.upper = self.visit(node.upper, newnode)
-        if node.step is not None:
-            newnode.step = self.visit(node.step, newnode)
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_subscript(self, node, parent):
-        """visit a Subscript node by returning a fresh instance of it"""
-        newnode = new.Subscript()
-        _lineno_parent(node, newnode, parent)
-        subcontext, self.asscontext = self.asscontext, None
-        newnode.value = self.visit(node.value, newnode)
-        newnode.slice = self.visit(node.slice, newnode)
-        self.asscontext = subcontext
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_tryexcept(self, node, parent):
-        """visit a TryExcept node by returning a fresh instance of it"""
-        newnode = new.TryExcept()
-        _lineno_parent(node, newnode, parent)
-        newnode.body = [self.visit(child, newnode) for child in node.body]
-        newnode.handlers = [self.visit(child, newnode) for child in node.handlers]
-        newnode.orelse = [self.visit(child, newnode) for child in node.orelse]
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_tryfinally(self, node, parent):
-        """visit a TryFinally node by returning a fresh instance of it"""
-        newnode = new.TryFinally()
-        _lineno_parent(node, newnode, parent)
-        newnode.body = [self.visit(child, newnode) for child in node.body]
-        newnode.finalbody = [self.visit(n, newnode) for n in node.finalbody]
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_tuple(self, node, parent):
-        """visit a Tuple node by returning a fresh instance of it"""
-        newnode = new.Tuple()
-        _lineno_parent(node, newnode, parent)
-        newnode.elts = [self.visit(child, newnode) for child in node.elts]
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_unaryop(self, node, parent):
-        """visit a UnaryOp node by returning a fresh instance of it"""
-        newnode = new.UnaryOp()
-        _lineno_parent(node, newnode, parent)
-        newnode.operand = self.visit(node.operand, newnode)
-        newnode.op = _UNARY_OP_CLASSES[node.op.__class__]
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_while(self, node, parent):
-        """visit a While node by returning a fresh instance of it"""
-        newnode = new.While()
-        _lineno_parent(node, newnode, parent)
-        newnode.test = self.visit(node.test, newnode)
-        newnode.body = [self.visit(child, newnode) for child in node.body]
-        newnode.orelse = [self.visit(child, newnode) for child in node.orelse]
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_with(self, node, parent):
-        """visit a With node by returning a fresh instance of it"""
-        newnode = new.With()
-        _lineno_parent(node, newnode, parent)
-        newnode.expr = self.visit(node.context_expr, newnode)
-        self.asscontext = "Ass"
-        if node.optional_vars is not None:
-            newnode.vars = self.visit(node.optional_vars, newnode)
-        self.asscontext = None
-        newnode.body = [self.visit(child, newnode) for child in node.body]
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_yield(self, node, parent):
-        """visit a Yield node by returning a fresh instance of it"""
-        newnode = new.Yield()
-        _lineno_parent(node, newnode, parent)
-        if node.value is not None:
-            newnode.value = self.visit(node.value, newnode)
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-
-class TreeRebuilder3k(TreeRebuilder):
-    """extend and overwrite TreeRebuilder for python3k"""
-
-    def visit_arg(self, node, parent):
-        """visit a arg node by returning a fresh AssName instance"""
-        # the <arg> node is coming from py>=3.0, but we use AssName in py2.x
-        # XXX or we should instead introduce a Arg node in astng ?
-        return self.visit_assname(node, parent, node.arg)
-
-    def visit_excepthandler(self, node, parent):
-        """visit an ExceptHandler node by returning a fresh instance of it"""
-        newnode = new.ExceptHandler()
-        _lineno_parent(node, newnode, parent)
-        if node.type is not None:
-            newnode.type = self.visit(node.type, newnode)
-        if node.name is not None:
-            newnode.name = self.visit_assname(node, newnode, node.name)
-        newnode.body = [self.visit(child, newnode) for child in node.body]
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_nonlocal(self, node, parent):
-        """visit a Nonlocal node and return a new instance of it"""
-        newnode = new.Nonlocal(node.names)
-        _set_infos(node, newnode, parent)
-        return newnode
-
-    def visit_raise(self, node, parent):
-        """visit a Raise node by returning a fresh instance of it"""
-        newnode = new.Raise()
-        _lineno_parent(node, newnode, parent)
-        # no traceback; anyway it is not used in Pylint
-        if node.exc is not None:
-            newnode.exc = self.visit(node.exc, newnode)
-        if node.cause is not None:
-            newnode.cause = self.visit(node.cause, newnode)
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-    def visit_starred(self, node, parent):
-        """visit a Starred node and return a new instance of it"""
-        newnode = new.Starred()
-        _lineno_parent(node, newnode, parent)
-        newnode.value = self.visit(node.value, newnode)
-        newnode.set_line_info(newnode.last_child())
-        return newnode
-
-
-if sys.version_info >= (3, 0):
-    TreeRebuilder = TreeRebuilder3k
-
-

+ 0 - 977
pylibs/logilab/astng/scoped_nodes.py

@@ -1,977 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-# copyright 2003-2010 Sylvain Thenault, all rights reserved.
-# contact mailto:thenault@gmail.com
-#
-# This file is part of logilab-astng.
-#
-# logilab-astng is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# logilab-astng is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-astng. If not, see <http://www.gnu.org/licenses/>.
-"""This module contains the classes for "scoped" node, i.e. which are opening a
-new local scope in the language definition : Module, Class, Function (and
-Lambda, GenExpr, DictComp and SetComp to some extent).
-"""
-from __future__ import with_statement
-
-__doctype__ = "restructuredtext en"
-
-import sys
-from itertools import chain
-
-from logilab.common.compat import builtins
-from logilab.common.decorators import cached
-
-from logilab.astng import BUILTINS_MODULE
-from logilab.astng.exceptions import NotFoundError, NoDefault, \
-     ASTNGBuildingException, InferenceError
-from logilab.astng.node_classes import Const, DelName, DelAttr, \
-     Dict, From, List, Name, Pass, Raise, Return, Tuple, Yield, \
-     are_exclusive, LookupMixIn, const_factory as cf, unpack_infer
-from logilab.astng.bases import NodeNG, InferenceContext, Instance,\
-     YES, Generator, UnboundMethod, BoundMethod, _infer_stmts, copy_context, \
-     BUILTINS_NAME
-from logilab.astng.mixins import FilterStmtsMixin
-from logilab.astng.bases import Statement
-from logilab.astng.manager import ASTNGManager
-
-
-def remove_nodes(func, cls):
-    def wrapper(*args, **kwargs):
-        nodes = [n for n in func(*args, **kwargs) if not isinstance(n, cls)]
-        if not nodes:
-            raise NotFoundError()
-        return nodes
-    return wrapper
-
-
-def function_to_method(n, klass):
-    if isinstance(n, Function):
-        if n.type == 'classmethod':
-            return BoundMethod(n, klass)
-        if n.type != 'staticmethod':
-            return UnboundMethod(n)
-    return n
-
-def std_special_attributes(self, name, add_locals=True):
-    if add_locals:
-        locals = self.locals
-    else:
-        locals = {}
-    if name == '__name__':
-        return [cf(self.name)] + locals.get(name, [])
-    if name == '__doc__':
-        return [cf(self.doc)] + locals.get(name, [])
-    if name == '__dict__':
-        return [Dict()] + locals.get(name, [])
-    raise NotFoundError(name)
-
-MANAGER = ASTNGManager()
-def builtin_lookup(name):
-    """lookup a name into the builtin module
-    return the list of matching statements and the astng for the builtin
-    module
-    """
-    builtin_astng = MANAGER.astng_from_module(builtins)
-    if name == '__dict__':
-        return builtin_astng, ()
-    try:
-        stmts = builtin_astng.locals[name]
-    except KeyError:
-        stmts = ()
-    return builtin_astng, stmts
-
-
-# TODO move this Mixin to mixins.py; problem: 'Function' in _scope_lookup
-class LocalsDictNodeNG(LookupMixIn, NodeNG):
-    """ this class provides locals handling common to Module, Function
-    and Class nodes, including a dict like interface for direct access
-    to locals information
-    """
-
-    # attributes below are set by the builder module or by raw factories
-
-    # dictionary of locals with name as key and node defining the local as
-    # value
-
-    def qname(self):
-        """return the 'qualified' name of the node, eg module.name,
-        module.class.name ...
-        """
-        if self.parent is None:
-            return self.name
-        return '%s.%s' % (self.parent.frame().qname(), self.name)
-
-    def frame(self):
-        """return the first parent frame node (i.e. Module, Function or Class)
-        """
-        return self
-
-    def scope(self):
-        """return the first node defining a new scope (i.e. Module,
-        Function, Class, Lambda but also GenExpr, DictComp and SetComp)
-        """
-        return self
-
-
-    def _scope_lookup(self, node, name, offset=0):
-        """XXX method for interfacing the scope lookup"""
-        try:
-            stmts = node._filter_stmts(self.locals[name], self, offset)
-        except KeyError:
-            stmts = ()
-        if stmts:
-            return self, stmts
-        if self.parent: # i.e. not Module
-            # nested scope: if parent scope is a function, that's fine
-            # else jump to the module
-            pscope = self.parent.scope()
-            if not pscope.is_function:
-                pscope = pscope.root()
-            return pscope.scope_lookup(node, name)
-        return builtin_lookup(name) # Module
-
-
-
-    def set_local(self, name, stmt):
-        """define <name> in locals (<stmt> is the node defining the name)
-        if the node is a Module node (i.e. has globals), add the name to
-        globals
-
-        if the name is already defined, ignore it
-        """
-        #assert not stmt in self.locals.get(name, ()), (self, stmt)
-        self.locals.setdefault(name, []).append(stmt)
-
-    __setitem__ = set_local
-
-    def _append_node(self, child):
-        """append a child, linking it in the tree"""
-        self.body.append(child)
-        child.parent = self
-
-    def add_local_node(self, child_node, name=None):
-        """append a child which should alter locals to the given node"""
-        if name != '__class__':
-            # add __class__ node as a child will cause infinite recursion later!
-            self._append_node(child_node)
-        self.set_local(name or child_node.name, child_node)
-
-
-    def __getitem__(self, item):
-        """method from the `dict` interface returning the first node
-        associated with the given name in the locals dictionary
-
-        :type item: str
-        :param item: the name of the locally defined object
-        :raises KeyError: if the name is not defined
-        """
-        return self.locals[item][0]
-
-    def __iter__(self):
-        """method from the `dict` interface returning an iterator on
-        `self.keys()`
-        """
-        return iter(self.keys())
-
-    def keys(self):
-        """method from the `dict` interface returning a tuple containing
-        locally defined names
-        """
-        return self.locals.keys()
-
-    def values(self):
-        """method from the `dict` interface returning a tuple containing
-        locally defined nodes which are instance of `Function` or `Class`
-        """
-        return [self[key] for key in self.keys()]
-
-    def items(self):
-        """method from the `dict` interface returning a list of tuple
-        containing each locally defined name with its associated node,
-        which is an instance of `Function` or `Class`
-        """
-        return zip(self.keys(), self.values())
-
-
-    def __contains__(self, name):
-        return name in self.locals
-    has_key = __contains__
-
-# Module  #####################################################################
-
-class Module(LocalsDictNodeNG):
-    _astng_fields = ('body',)
-
-    fromlineno = 0
-    lineno = 0
-
-    # attributes below are set by the builder module or by raw factories
-
-    # the file from which as been extracted the astng representation. It may
-    # be None if the representation has been built from a built-in module
-    file = None
-    # the module name
-    name = None
-    # boolean for astng built from source (i.e. ast)
-    pure_python = None
-    # boolean for package module
-    package = None
-    # dictionary of globals with name as key and node defining the global
-    # as value
-    globals = None
-
-    # names of python special attributes (handled by getattr impl.)
-    special_attributes = set(('__name__', '__doc__', '__file__', '__path__',
-                              '__dict__'))
-    # names of module attributes available through the global scope
-    scope_attrs = set(('__name__', '__doc__', '__file__', '__path__'))
-
-    def __init__(self, name, doc, pure_python=True):
-        self.name = name
-        self.doc = doc
-        self.pure_python = pure_python
-        self.locals = self.globals = {}
-        self.body = []
-
-    @property
-    def file_stream(self):
-        if self.file is not None:
-            return open(self.file)
-        return None
-
-    def block_range(self, lineno):
-        """return block line numbers.
-
-        start from the beginning whatever the given lineno
-        """
-        return self.fromlineno, self.tolineno
-
-    def scope_lookup(self, node, name, offset=0):
-        if name in self.scope_attrs and not name in self.locals:
-            try:
-                return self, self.getattr(name)
-            except NotFoundError:
-                return self, ()
-        return self._scope_lookup(node, name, offset)
-
-    def pytype(self):
-        return '%s.module' % BUILTINS_MODULE
-
-    def display_type(self):
-        return 'Module'
-
-    def getattr(self, name, context=None, ignore_locals=False):
-        if name in self.special_attributes:
-            if name == '__file__':
-                return [cf(self.file)] + self.locals.get(name, [])
-            if name == '__path__' and self.package:
-                return [List()] + self.locals.get(name, [])
-            return std_special_attributes(self, name)
-        if not ignore_locals and name in self.locals:
-            return self.locals[name]
-        if self.package:
-            try:
-                return [self.import_module(name, relative_only=True)]
-            except ASTNGBuildingException:
-                raise NotFoundError(name)
-            except Exception:# XXX pylint tests never pass here; do we need it?
-                import traceback
-                traceback.print_exc()
-        raise NotFoundError(name)
-    getattr = remove_nodes(getattr, DelName)
-
-    def igetattr(self, name, context=None):
-        """inferred getattr"""
-        # set lookup name since this is necessary to infer on import nodes for
-        # instance
-        context = copy_context(context)
-        context.lookupname = name
-        try:
-            return _infer_stmts(self.getattr(name, context), context, frame=self)
-        except NotFoundError:
-            raise InferenceError(name)
-
-    def fully_defined(self):
-        """return True if this module has been built from a .py file
-        and so contains a complete representation including the code
-        """
-        return self.file is not None and self.file.endswith('.py')
-
-    def statement(self):
-        """return the first parent node marked as statement node
-        consider a module as a statement...
-        """
-        return self
-
-    def previous_sibling(self):
-        """module has no sibling"""
-        return
-
-    def next_sibling(self):
-        """module has no sibling"""
-        return
-
-    if sys.version_info < (2, 8):
-        def absolute_import_activated(self):
-            for stmt in self.locals.get('absolute_import', ()):
-                if isinstance(stmt, From) and stmt.modname == '__future__':
-                    return True
-            return False
-    else:
-        absolute_import_activated = lambda self: True
-
-    def import_module(self, modname, relative_only=False, level=None):
-        """import the given module considering self as context"""
-        if relative_only and level is None:
-            level = 0
-        absmodname = self.relative_to_absolute_name(modname, level)
-        try:
-            return MANAGER.astng_from_module_name(absmodname)
-        except ASTNGBuildingException:
-            # we only want to import a sub module or package of this module,
-            # skip here
-            if relative_only:
-                raise
-        return MANAGER.astng_from_module_name(modname)
-
-    def relative_to_absolute_name(self, modname, level):
-        """return the absolute module name for a relative import.
-
-        The relative import can be implicit or explicit.
-        """
-        # XXX this returns non sens when called on an absolute import
-        # like 'pylint.checkers.logilab.astng.utils'
-        # XXX doesn't return absolute name if self.name isn't absolute name
-        if self.absolute_import_activated() and level is None:
-            return modname
-        if level:
-            if self.package:
-                level = level - 1
-            package_name = self.name.rsplit('.', level)[0]
-        elif self.package:
-            package_name = self.name
-        else:
-            package_name = self.name.rsplit('.', 1)[0]
-        if package_name:
-            if not modname:
-                return package_name
-            return '%s.%s' % (package_name, modname)
-        return modname
-
-
-    def wildcard_import_names(self):
-        """return the list of imported names when this module is 'wildcard
-        imported'
-
-        It doesn't include the '__builtins__' name which is added by the
-        current CPython implementation of wildcard imports.
-        """
-        # take advantage of a living module if it exists
-        try:
-            living = sys.modules[self.name]
-        except KeyError:
-            pass
-        else:
-            try:
-                return living.__all__
-            except AttributeError:
-                return [name for name in living.__dict__.keys()
-                        if not name.startswith('_')]
-        # else lookup the astng
-        #
-        # We separate the different steps of lookup in try/excepts
-        # to avoid catching too many Exceptions
-        # However, we can not analyse dynamically constructed __all__
-        try:
-            all = self['__all__']
-        except KeyError:
-            return [name for name in self.keys() if not name.startswith('_')]
-        try:
-            explicit = all.assigned_stmts().next()
-        except InferenceError:
-            return [name for name in self.keys() if not name.startswith('_')]
-        except AttributeError:
-            # not an assignment node
-            # XXX infer?
-            return [name for name in self.keys() if not name.startswith('_')]
-        try:
-            # should be a Tuple/List of constant string / 1 string not allowed
-            return [const.value for const in explicit.elts]
-        except AttributeError:
-            return [name for name in self.keys() if not name.startswith('_')]
-
-
-class ComprehensionScope(LocalsDictNodeNG):
-    def frame(self):
-        return self.parent.frame()
-
-    scope_lookup = LocalsDictNodeNG._scope_lookup
-
-
-class GenExpr(ComprehensionScope):
-    _astng_fields = ('elt', 'generators')
-
-    def __init__(self):
-        self.locals = {}
-        self.elt = None
-        self.generators = []
-
-
-class DictComp(ComprehensionScope):
-    _astng_fields = ('key', 'value', 'generators')
-
-    def __init__(self):
-        self.locals = {}
-        self.key = None
-        self.value = None
-        self.generators = []
-
-
-class SetComp(ComprehensionScope):
-    _astng_fields = ('elt', 'generators')
-
-    def __init__(self):
-        self.locals = {}
-        self.elt = None
-        self.generators = []
-
-
-class _ListComp(NodeNG):
-    """class representing a ListComp node"""
-    _astng_fields = ('elt', 'generators')
-    elt = None
-    generators = None
-
-if sys.version_info >= (3, 0):
-    class ListComp(_ListComp, ComprehensionScope):
-        """class representing a ListComp node"""
-        def __init__(self):
-            self.locals = {}
-else:
-    class ListComp(_ListComp):
-        """class representing a ListComp node"""
-
-# Function  ###################################################################
-
-
-class Lambda(LocalsDictNodeNG, FilterStmtsMixin):
-    _astng_fields = ('args', 'body',)
-    name = '<lambda>'
-
-    # function's type, 'function' | 'method' | 'staticmethod' | 'classmethod'
-    type = 'function'
-
-    def __init__(self):
-        self.locals = {}
-        self.args = []
-        self.body = []
-
-    def pytype(self):
-        if 'method' in self.type:
-            return '%s.instancemethod' % BUILTINS_MODULE
-        return '%s.function' % BUILTINS_MODULE
-
-    def display_type(self):
-        if 'method' in self.type:
-            return 'Method'
-        return 'Function'
-
-    def callable(self):
-        return True
-
-    def argnames(self):
-        """return a list of argument names"""
-        if self.args.args: # maybe None with builtin functions
-            names = _rec_get_names(self.args.args)
-        else:
-            names = []
-        if self.args.vararg:
-            names.append(self.args.vararg)
-        if self.args.kwarg:
-            names.append(self.args.kwarg)
-        return names
-
-    def infer_call_result(self, caller, context=None):
-        """infer what a function is returning when called"""
-        return self.body.infer(context)
-
-    def scope_lookup(self, node, name, offset=0):
-        if node in self.args.defaults:
-            frame = self.parent.frame()
-            # line offset to avoid that def func(f=func) resolve the default
-            # value to the defined function
-            offset = -1
-        else:
-            # check this is not used in function decorators
-            frame = self
-        return frame._scope_lookup(node, name, offset)
-
-
-class Function(Statement, Lambda):
-    _astng_fields = ('decorators', 'args', 'body')
-
-    special_attributes = set(('__name__', '__doc__', '__dict__'))
-    is_function = True
-    # attributes below are set by the builder module or by raw factories
-    blockstart_tolineno = None
-    decorators = None
-
-    def __init__(self, name, doc):
-        self.locals = {}
-        self.args = []
-        self.body = []
-        self.decorators = None
-        self.name = name
-        self.doc = doc
-        self.extra_decorators = []
-        self.instance_attrs = {}
-
-    def set_line_info(self, lastchild):
-        self.fromlineno = self.lineno
-        # lineno is the line number of the first decorator, we want the def statement lineno
-        if self.decorators is not None:
-            self.fromlineno += len(self.decorators.nodes)
-        self.tolineno = lastchild.tolineno
-        self.blockstart_tolineno = self.args.tolineno
-
-    def block_range(self, lineno):
-        """return block line numbers.
-
-        start from the "def" position whatever the given lineno
-        """
-        return self.fromlineno, self.tolineno
-
-    def getattr(self, name, context=None):
-        """this method doesn't look in the instance_attrs dictionary since it's
-        done by an Instance proxy at inference time.
-        """
-        if name == '__module__':
-            return [cf(self.root().qname())]
-        if name in self.instance_attrs:
-            return self.instance_attrs[name]
-        return std_special_attributes(self, name, False)
-
-    def is_method(self):
-        """return true if the function node should be considered as a method"""
-        # check we are defined in a Class, because this is usually expected
-        # (e.g. pylint...) when is_method() return True
-        return self.type != 'function' and isinstance(self.parent.frame(), Class)
-
-    def decoratornames(self):
-        """return a list of decorator qualified names"""
-        result = set()
-        decoratornodes = []
-        if self.decorators is not None:
-            decoratornodes += self.decorators.nodes
-        decoratornodes += self.extra_decorators
-        for decnode in decoratornodes:
-            for infnode in decnode.infer():
-                result.add(infnode.qname())
-        return result
-    decoratornames = cached(decoratornames)
-
-    def is_bound(self):
-        """return true if the function is bound to an Instance or a class"""
-        return self.type == 'classmethod'
-
-    def is_abstract(self, pass_is_abstract=True):
-        """return true if the method is abstract
-        It's considered as abstract if the only statement is a raise of
-        NotImplementError, or, if pass_is_abstract, a pass statement
-        """
-        for child_node in self.body:
-            if isinstance(child_node, Raise):
-                if child_node.raises_not_implemented():
-                    return True
-            if pass_is_abstract and isinstance(child_node, Pass):
-                return True
-            return False
-        # empty function is the same as function with a single "pass" statement
-        if pass_is_abstract:
-            return True
-
-    def is_generator(self):
-        """return true if this is a generator function"""
-        # XXX should be flagged, not computed
-        try:
-            return self.nodes_of_class(Yield, skip_klass=Function).next()
-        except StopIteration:
-            return False
-
-    def infer_call_result(self, caller, context=None):
-        """infer what a function is returning when called"""
-        if self.is_generator():
-            yield Generator(self)
-            return
-        returns = self.nodes_of_class(Return, skip_klass=Function)
-        for returnnode in returns:
-            if returnnode.value is None:
-                yield Const(None)
-            else:
-                try:
-                    for infered in returnnode.value.infer(context):
-                        yield infered
-                except InferenceError:
-                    yield YES
-
-
-def _rec_get_names(args, names=None):
-    """return a list of all argument names"""
-    if names is None:
-        names = []
-    for arg in args:
-        if isinstance(arg, Tuple):
-            _rec_get_names(arg.elts, names)
-        else:
-            names.append(arg.name)
-    return names
-
-
-# Class ######################################################################
-
-def _class_type(klass, ancestors=None):
-    """return a Class node type to differ metaclass, interface and exception
-    from 'regular' classes
-    """
-    # XXX we have to store ancestors in case we have a ancestor loop
-    if klass._type is not None:
-        return klass._type
-    if klass.name == 'type':
-        klass._type = 'metaclass'
-    elif klass.name.endswith('Interface'):
-        klass._type = 'interface'
-    elif klass.name.endswith('Exception'):
-        klass._type = 'exception'
-    else:
-        if ancestors is None:
-            ancestors = set()
-        if klass in ancestors:
-            # XXX we are in loop ancestors, and have found no type
-            klass._type = 'class'
-            return 'class'
-        ancestors.add(klass)
-        # print >> sys.stderr, '_class_type', repr(klass)
-        for base in klass.ancestors(recurs=False):
-            if _class_type(base, ancestors) != 'class':
-                klass._type = base.type
-                break
-    if klass._type is None:
-        klass._type = 'class'
-    return klass._type
-
-def _iface_hdlr(iface_node):
-    """a handler function used by interfaces to handle suspicious
-    interface nodes
-    """
-    return True
-
-
-class Class(Statement, LocalsDictNodeNG, FilterStmtsMixin):
-
-    # some of the attributes below are set by the builder module or
-    # by a raw factories
-
-    # a dictionary of class instances attributes
-    _astng_fields = ('decorators', 'bases', 'body') # name
-
-    decorators = None
-    special_attributes = set(('__name__', '__doc__', '__dict__', '__module__',
-                              '__bases__', '__mro__', '__subclasses__'))
-    blockstart_tolineno = None
-
-    _type = None
-    type = property(_class_type,
-                    doc="class'type, possible values are 'class' | "
-                    "'metaclass' | 'interface' | 'exception'")
-
-    def __init__(self, name, doc):
-        self.instance_attrs = {}
-        self.locals = {}
-        self.bases = []
-        self.body = []
-        self.name = name
-        self.doc = doc
-
-    def _newstyle_impl(self, context=None):
-        if context is None:
-            context = InferenceContext()
-        if self._newstyle is not None:
-            return self._newstyle
-        for base in self.ancestors(recurs=False, context=context):
-            if base._newstyle_impl(context):
-                self._newstyle = True
-                break
-        if self._newstyle is None:
-            self._newstyle = False
-        return self._newstyle
-
-    _newstyle = None
-    newstyle = property(_newstyle_impl,
-                        doc="boolean indicating if it's a new style class"
-                        "or not")
-
-    def set_line_info(self, lastchild):
-        self.fromlineno = self.lineno
-        self.blockstart_tolineno = self.bases and self.bases[-1].tolineno or self.fromlineno
-        if lastchild is not None:
-            self.tolineno = lastchild.tolineno
-        # else this is a class with only a docstring, then tolineno is (should be) already ok
-
-    def block_range(self, lineno):
-        """return block line numbers.
-
-        start from the "class" position whatever the given lineno
-        """
-        return self.fromlineno, self.tolineno
-
-    def pytype(self):
-        if self.newstyle:
-            return '%s.type' % BUILTINS_MODULE
-        return '%s.classobj' % BUILTINS_MODULE
-
-    def display_type(self):
-        return 'Class'
-
-    def callable(self):
-        return True
-
-    def infer_call_result(self, caller, context=None):
-        """infer what a class is returning when called"""
-        yield Instance(self)
-
-    def scope_lookup(self, node, name, offset=0):
-        if node in self.bases:
-            frame = self.parent.frame()
-            # line offset to avoid that class A(A) resolve the ancestor to
-            # the defined class
-            offset = -1
-        else:
-            frame = self
-        return frame._scope_lookup(node, name, offset)
-
-    # list of parent class as a list of string (i.e. names as they appear
-    # in the class definition) XXX bw compat
-    def basenames(self):
-        return [bnode.as_string() for bnode in self.bases]
-    basenames = property(basenames)
-
-    def ancestors(self, recurs=True, context=None):
-        """return an iterator on the node base classes in a prefixed
-        depth first order
-
-        :param recurs:
-          boolean indicating if it should recurse or return direct
-          ancestors only
-        """
-        # FIXME: should be possible to choose the resolution order
-        # XXX inference make infinite loops possible here (see BaseTransformer
-        # manipulation in the builder module for instance)
-        yielded = set([self])
-        if context is None:
-            context = InferenceContext()
-        for stmt in self.bases:
-            with context.restore_path():
-                try:
-                    for baseobj in stmt.infer(context):
-                        if not isinstance(baseobj, Class):
-                            # duh ?
-                            continue
-                        if baseobj in yielded:
-                            continue # cf xxx above
-                        yielded.add(baseobj)
-                        yield baseobj
-                        if recurs:
-                            for grandpa in baseobj.ancestors(True, context):
-                                if grandpa in yielded:
-                                    continue # cf xxx above
-                                yielded.add(grandpa)
-                                yield grandpa
-                except InferenceError:
-                    # XXX log error ?
-                    continue
-
-    def local_attr_ancestors(self, name, context=None):
-        """return an iterator on astng representation of parent classes
-        which have <name> defined in their locals
-        """
-        for astng in self.ancestors(context=context):
-            if name in astng:
-                yield astng
-
-    def instance_attr_ancestors(self, name, context=None):
-        """return an iterator on astng representation of parent classes
-        which have <name> defined in their instance attribute dictionary
-        """
-        for astng in self.ancestors(context=context):
-            if name in astng.instance_attrs:
-                yield astng
-
-    def has_base(self, node):
-        return node in self.bases
-
-    def local_attr(self, name, context=None):
-        """return the list of assign node associated to name in this class
-        locals or in its parents
-
-        :raises `NotFoundError`:
-          if no attribute with this name has been find in this class or
-          its parent classes
-        """
-        try:
-            return self.locals[name]
-        except KeyError:
-            # get if from the first parent implementing it if any
-            for class_node in self.local_attr_ancestors(name, context):
-                return class_node.locals[name]
-        raise NotFoundError(name)
-    local_attr = remove_nodes(local_attr, DelAttr)
-
-    def instance_attr(self, name, context=None):
-        """return the astng nodes associated to name in this class instance
-        attributes dictionary and in its parents
-
-        :raises `NotFoundError`:
-          if no attribute with this name has been find in this class or
-          its parent classes
-        """
-        values = self.instance_attrs.get(name, [])
-        # get all values from parents
-        for class_node in self.instance_attr_ancestors(name, context):
-            values += class_node.instance_attrs[name]
-        if not values:
-            raise NotFoundError(name)
-        return values
-    instance_attr = remove_nodes(instance_attr, DelAttr)
-
-    def instanciate_class(self):
-        """return Instance of Class node, else return self"""
-        return Instance(self)
-
-    def getattr(self, name, context=None):
-        """this method doesn't look in the instance_attrs dictionary since it's
-        done by an Instance proxy at inference time.
-
-        It may return a YES object if the attribute has not been actually
-        found but a __getattr__ or __getattribute__ method is defined
-        """
-        values = self.locals.get(name, [])
-        if name in self.special_attributes:
-            if name == '__module__':
-                return [cf(self.root().qname())] + values
-            # FIXME : what is expected by passing the list of ancestors to cf:
-            # you can just do [cf(tuple())] + values without breaking any test
-            # this is ticket http://www.logilab.org/ticket/52785
-            if name == '__bases__':
-                return [cf(tuple(self.ancestors(recurs=False, context=context)))] + values
-            # XXX need proper meta class handling + MRO implementation
-            if name == '__mro__' and self.newstyle:
-                # XXX mro is read-only but that's not our job to detect that
-                return [cf(tuple(self.ancestors(recurs=True, context=context)))] + values
-            return std_special_attributes(self, name)
-        # don't modify the list in self.locals!
-        values = list(values)
-        for classnode in self.ancestors(recurs=True, context=context):
-            values += classnode.locals.get(name, [])
-        if not values:
-            raise NotFoundError(name)
-        return values
-
-    def igetattr(self, name, context=None):
-        """inferred getattr, need special treatment in class to handle
-        descriptors
-        """
-        # set lookup name since this is necessary to infer on import nodes for
-        # instance
-        context = copy_context(context)
-        context.lookupname = name
-        try:
-            for infered in _infer_stmts(self.getattr(name, context), context,
-                                        frame=self):
-                # yield YES object instead of descriptors when necessary
-                if not isinstance(infered, Const) and isinstance(infered, Instance):
-                    try:
-                        infered._proxied.getattr('__get__', context)
-                    except NotFoundError:
-                        yield infered
-                    else:
-                        yield YES
-                else:
-                    yield function_to_method(infered, self)
-        except NotFoundError:
-            if not name.startswith('__') and self.has_dynamic_getattr(context):
-                # class handle some dynamic attributes, return a YES object
-                yield YES
-            else:
-                raise InferenceError(name)
-
-    def has_dynamic_getattr(self, context=None):
-        """return True if the class has a custom __getattr__ or
-        __getattribute__ method
-        """
-        # need to explicitly handle optparse.Values (setattr is not detected)
-        if self.name == 'Values' and self.root().name == 'optparse':
-            return True
-        try:
-            self.getattr('__getattr__', context)
-            return True
-        except NotFoundError:
-            #if self.newstyle: XXX cause an infinite recursion error
-            try:
-                getattribute = self.getattr('__getattribute__', context)[0]
-                if getattribute.root().name != BUILTINS_NAME:
-                    # class has a custom __getattribute__ defined
-                    return True
-            except NotFoundError:
-                pass
-        return False
-
-    def methods(self):
-        """return an iterator on all methods defined in the class and
-        its ancestors
-        """
-        done = {}
-        for astng in chain(iter((self,)), self.ancestors()):
-            for meth in astng.mymethods():
-                if meth.name in done:
-                    continue
-                done[meth.name] = None
-                yield meth
-
-    def mymethods(self):
-        """return an iterator on all methods defined in the class"""
-        for member in self.values():
-            if isinstance(member, Function):
-                yield member
-
-    def interfaces(self, herited=True, handler_func=_iface_hdlr):
-        """return an iterator on interfaces implemented by the given
-        class node
-        """
-        # FIXME: what if __implements__ = (MyIFace, MyParent.__implements__)...
-        try:
-            implements = Instance(self).getattr('__implements__')[0]
-        except NotFoundError:
-            return
-        if not herited and not implements.frame() is self:
-            return
-        found = set()
-        missing = False
-        for iface in unpack_infer(implements):
-            if iface is YES:
-                missing = True
-                continue
-            if not iface in found and handler_func(iface):
-                found.add(iface)
-                yield iface
-        if missing:
-            raise InferenceError()

+ 0 - 241
pylibs/logilab/astng/utils.py

@@ -1,241 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-# copyright 2003-2010 Sylvain Thenault, all rights reserved.
-# contact mailto:thenault@gmail.com
-#
-# This file is part of logilab-astng.
-#
-# logilab-astng is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# logilab-astng is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
-# for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-astng. If not, see <http://www.gnu.org/licenses/>.
-"""this module contains some utilities to navigate in the tree or to
-extract information from it
-"""
-
-__docformat__ = "restructuredtext en"
-
-from logilab.astng.exceptions import ASTNGBuildingException
-
-
-class ASTWalker:
-    """a walker visiting a tree in preorder, calling on the handler:
-
-    * visit_<class name> on entering a node, where class name is the class of
-    the node in lower case
-
-    * leave_<class name> on leaving a node, where class name is the class of
-    the node in lower case
-    """
-
-    def __init__(self, handler):
-        self.handler = handler
-        self._cache = {}
-
-    def walk(self, node, _done=None):
-        """walk on the tree from <node>, getting callbacks from handler"""
-        if _done is None:
-            _done = set()
-        if node in _done:
-            raise AssertionError((id(node), node, node.parent))
-        _done.add(node)
-        self.visit(node)
-        for child_node in node.get_children():
-            self.handler.set_context(node, child_node)
-            assert child_node is not node
-            self.walk(child_node, _done)
-        self.leave(node)
-        assert node.parent is not node
-
-    def get_callbacks(self, node):
-        """get callbacks from handler for the visited node"""
-        klass = node.__class__
-        methods = self._cache.get(klass)
-        if methods is None:
-            handler = self.handler
-            kid = klass.__name__.lower()
-            e_method = getattr(handler, 'visit_%s' % kid,
-                               getattr(handler, 'visit_default', None))
-            l_method = getattr(handler, 'leave_%s' % kid,
-                               getattr(handler, 'leave_default', None))
-            self._cache[klass] = (e_method, l_method)
-        else:
-            e_method, l_method = methods
-        return e_method, l_method
-
-    def visit(self, node):
-        """walk on the tree from <node>, getting callbacks from handler"""
-        method = self.get_callbacks(node)[0]
-        if method is not None:
-            method(node)
-
-    def leave(self, node):
-        """walk on the tree from <node>, getting callbacks from handler"""
-        method = self.get_callbacks(node)[1]
-        if method is not None:
-            method(node)
-
-
-class LocalsVisitor(ASTWalker):
-    """visit a project by traversing the locals dictionary"""
-    def __init__(self):
-        ASTWalker.__init__(self, self)
-        self._visited = {}
-
-    def visit(self, node):
-        """launch the visit starting from the given node"""
-        if node in self._visited:
-            return
-        self._visited[node] = 1 # FIXME: use set ?
-        methods = self.get_callbacks(node)
-        if methods[0] is not None:
-            methods[0](node)
-        if 'locals' in node.__dict__: # skip Instance and other proxy
-            for name, local_node in node.items():
-                self.visit(local_node)
-        if methods[1] is not None:
-            return methods[1](node)
-
-
-def _check_children(node):
-    """a helper function to check children - parent relations"""
-    for child in node.get_children():
-        ok = False
-        if child is None:
-            print "Hm, child of %s is None" % node
-            continue
-        if not hasattr(child, 'parent'):
-            print " ERROR: %s has child %s %x with no parent" % (node, child, id(child))
-        elif not child.parent:
-            print " ERROR: %s has child %s %x with parent %r" % (node, child, id(child), child.parent)
-        elif child.parent is not node:
-            print " ERROR: %s %x has child %s %x with wrong parent %s" % (node,
-                                      id(node), child, id(child), child.parent)
-        else:
-            ok = True
-        if not ok:
-            print "lines;", node.lineno, child.lineno
-            print "of module", node.root(), node.root().name
-            raise ASTNGBuildingException
-        _check_children(child)
-
-
-from _ast import PyCF_ONLY_AST
-def parse(string):
-    return compile(string, "<string>", 'exec', PyCF_ONLY_AST)
-
-class TreeTester(object):
-    '''A helper class to see _ast tree and compare with astng tree
-
-    indent: string for tree indent representation
-    lineno: bool to tell if we should print the line numbers
-
-    >>> tester = TreeTester('print')
-    >>> print tester.native_tree_repr()
-
-    <Module>
-    .   body = [
-    .   <Print>
-    .   .   nl = True
-    .   ]
-    >>> print tester.astng_tree_repr()
-    Module()
-        body = [
-        Print()
-            dest = 
-            values = [
-            ]
-        ]
-    '''
-
-    indent = '.   '
-    lineno = False
-
-    def __init__(self, sourcecode):
-        self._string = ''
-        self.sourcecode = sourcecode
-        self._ast_node = None
-        self.build_ast()
-
-    def build_ast(self):
-        """build the _ast tree from the source code"""
-        self._ast_node = parse(self.sourcecode)
-
-    def native_tree_repr(self, node=None, indent=''):
-        """get a nice representation of the _ast tree"""
-        self._string = ''
-        if node is None:
-            node = self._ast_node
-        self._native_repr_tree(node, indent)
-        return self._string
-
-
-    def _native_repr_tree(self, node, indent, _done=None):
-        """recursive method for the native tree representation"""
-        from _ast import Load as _Load, Store as _Store, Del as _Del
-        from _ast import AST as Node
-        if _done is None:
-            _done = set()
-        if node in _done:
-            self._string += '\nloop in tree: %r (%s)' % (node,
-                                            getattr(node, 'lineno', None))
-            return
-        _done.add(node)
-        self._string += '\n' + indent +  '<%s>' % node.__class__.__name__
-        indent += self.indent
-        if not hasattr(node, '__dict__'):
-            self._string += '\n' + self.indent + " ** node has no __dict__ " + str(node)
-            return
-        node_dict = node.__dict__
-        if hasattr(node, '_attributes'):
-            for a in node._attributes:
-                attr = node_dict[a]
-                if attr is None:
-                    continue
-                if a in ("lineno", "col_offset") and not self.lineno:
-                    continue
-                self._string +='\n' +  indent + a + " = " + repr(attr)
-        for field in node._fields or ():
-            attr = node_dict[field]
-            if attr is None:
-                continue
-            if isinstance(attr, list):
-                if not attr:
-                    continue
-                self._string += '\n' + indent + field + ' = ['
-                for elt in attr:
-                    self._native_repr_tree(elt, indent, _done)
-                self._string += '\n' + indent + ']'
-                continue
-            if isinstance(attr, (_Load, _Store, _Del)):
-                continue
-            if isinstance(attr, Node):
-                self._string += '\n' + indent + field + " = "
-                self._native_repr_tree(attr, indent, _done)
-            else:
-                self._string += '\n' + indent + field + " = " + repr(attr)
-
-
-    def build_astng_tree(self):
-        """build astng tree from the _ast tree
-        """
-        from logilab.astng.builder import ASTNGBuilder
-        tree = ASTNGBuilder().string_build(self.sourcecode)
-        return tree
-
-    def astng_tree_repr(self, ids=False):
-        """build the astng tree and return a nice tree representation"""
-        mod = self.build_astng_tree()
-        return mod.repr_tree(ids)
-
-
-__all__ = ('LocalsVisitor', 'ASTWalker',)
-

+ 0 - 339
pylibs/logilab/common/COPYING

@@ -1,339 +0,0 @@
-		    GNU GENERAL PUBLIC LICENSE
-		       Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-			    Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Lesser General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-		    GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-			    NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-		     END OF TERMS AND CONDITIONS
-
-	    How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License along
-    with this program; if not, write to the Free Software Foundation, Inc.,
-    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) year name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  <signature of Ty Coon>, 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Lesser General
-Public License instead of this License.

+ 0 - 510
pylibs/logilab/common/COPYING.LESSER

@@ -1,510 +0,0 @@
-
-                  GNU LESSER GENERAL PUBLIC LICENSE
-                       Version 2.1, February 1999
-
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
-	51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the Lesser GPL.  It also counts
- as the successor of the GNU Library Public License, version 2, hence
- the version number 2.1.]
-
-                            Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
-  This license, the Lesser General Public License, applies to some
-specially designated software packages--typically libraries--of the
-Free Software Foundation and other authors who decide to use it.  You
-can use it too, but we suggest you first think carefully about whether
-this license or the ordinary General Public License is the better
-strategy to use in any particular case, based on the explanations
-below.
-
-  When we speak of free software, we are referring to freedom of use,
-not price.  Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of
-it in new free programs; and that you are informed that you can do
-these things.
-
-  To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights.  These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
-
-  For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you.  You must make sure that they, too, receive or can get the source
-code.  If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling
-it.  And you must show them these terms so they know their rights.
-
-  We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
-  To protect each distributor, we want to make it very clear that
-there is no warranty for the free library.  Also, if the library is
-modified by someone else and passed on, the recipients should know
-that what they have is not the original version, so that the original
-author's reputation will not be affected by problems that might be
-introduced by others.
-
-  Finally, software patents pose a constant threat to the existence of
-any free program.  We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder.  Therefore, we insist that
-any patent license obtained for a version of the library must be
-consistent with the full freedom of use specified in this license.
-
-  Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License.  This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and
-is quite different from the ordinary General Public License.  We use
-this license for certain libraries in order to permit linking those
-libraries into non-free programs.
-
-  When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library.  The ordinary
-General Public License therefore permits such linking only if the
-entire combination fits its criteria of freedom.  The Lesser General
-Public License permits more lax criteria for linking other code with
-the library.
-
-  We call this license the "Lesser" General Public License because it
-does Less to protect the user's freedom than the ordinary General
-Public License.  It also provides other free software developers Less
-of an advantage over competing non-free programs.  These disadvantages
-are the reason we use the ordinary General Public License for many
-libraries.  However, the Lesser license provides advantages in certain
-special circumstances.
-
-  For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it
-becomes a de-facto standard.  To achieve this, non-free programs must
-be allowed to use the library.  A more frequent case is that a free
-library does the same job as widely used non-free libraries.  In this
-case, there is little to gain by limiting the free library to free
-software only, so we use the Lesser General Public License.
-
-  In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of
-free software.  For example, permission to use the GNU C Library in
-non-free programs enables many more people to use the whole GNU
-operating system, as well as its variant, the GNU/Linux operating
-system.
-
-  Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is
-linked with the Library has the freedom and the wherewithal to run
-that program using a modified version of the Library.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.  Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library".  The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-
-                  GNU LESSER GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License Agreement applies to any software library or other
-program which contains a notice placed by the copyright holder or
-other authorized party saying it may be distributed under the terms of
-this Lesser General Public License (also called "this License").
-Each licensee is addressed as "you".
-
-  A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
-  The "Library", below, refers to any such software library or work
-which has been distributed under these terms.  A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language.  (Hereinafter, translation is
-included without limitation in the term "modification".)
-
-  "Source code" for a work means the preferred form of the work for
-making modifications to it.  For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control
-compilation and installation of the library.
-
-  Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it).  Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-
-  1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
-  You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
-  2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) The modified work must itself be a software library.
-
-    b) You must cause the files modified to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    c) You must cause the whole of the work to be licensed at no
-    charge to all third parties under the terms of this License.
-
-    d) If a facility in the modified Library refers to a function or a
-    table of data to be supplied by an application program that uses
-    the facility, other than as an argument passed when the facility
-    is invoked, then you must make a good faith effort to ensure that,
-    in the event an application does not supply such function or
-    table, the facility still operates, and performs whatever part of
-    its purpose remains meaningful.
-
-    (For example, a function in a library to compute square roots has
-    a purpose that is entirely well-defined independent of the
-    application.  Therefore, Subsection 2d requires that any
-    application-supplied function or table used by this function must
-    be optional: if the application does not supply it, the square
-    root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library.  To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License.  (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.)  Do not make any other change in
-these notices.
-
-  Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
-  This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
-  4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
-  If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library".  Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
-  However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library".  The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
-  When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library.  The
-threshold for this to be true is not precisely defined by law.
-
-  If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work.  (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
-  Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
-  6. As an exception to the Sections above, you may also combine or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
-  You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License.  You must supply a copy of this License.  If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License.  Also, you must do one
-of these things:
-
-    a) Accompany the work with the complete corresponding
-    machine-readable source code for the Library including whatever
-    changes were used in the work (which must be distributed under
-    Sections 1 and 2 above); and, if the work is an executable linked
-    with the Library, with the complete machine-readable "work that
-    uses the Library", as object code and/or source code, so that the
-    user can modify the Library and then relink to produce a modified
-    executable containing the modified Library.  (It is understood
-    that the user who changes the contents of definitions files in the
-    Library will not necessarily be able to recompile the application
-    to use the modified definitions.)
-
-    b) Use a suitable shared library mechanism for linking with the
-    Library.  A suitable mechanism is one that (1) uses at run time a
-    copy of the library already present on the user's computer system,
-    rather than copying library functions into the executable, and (2)
-    will operate properly with a modified version of the library, if
-    the user installs one, as long as the modified version is
-    interface-compatible with the version that the work was made with.
-
-    c) Accompany the work with a written offer, valid for at least
-    three years, to give the same user the materials specified in
-    Subsection 6a, above, for a charge no more than the cost of
-    performing this distribution.
-
-    d) If distribution of the work is made by offering access to copy
-    from a designated place, offer equivalent access to copy the above
-    specified materials from the same place.
-
-    e) Verify that the user has already received a copy of these
-    materials or that you have already sent this user a copy.
-
-  For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it.  However, as a special exception,
-the materials to be distributed need not include anything that is
-normally distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
-  It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system.  Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
-  7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
-    a) Accompany the combined library with a copy of the same work
-    based on the Library, uncombined with any other library
-    facilities.  This must be distributed under the terms of the
-    Sections above.
-
-    b) Give prominent notice with the combined library of the fact
-    that part of it is a work based on the Library, and explaining
-    where to find the accompanying uncombined form of the same work.
-
-  8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License.  Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License.  However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
-  9. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Library or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
-  10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties with
-this License.
-
-  11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply, and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License
-may add an explicit geographical distribution limitation excluding those
-countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  13. The Free Software Foundation may publish revised and/or new
-versions of the Lesser General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation.  If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
-  14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission.  For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this.  Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
-                            NO WARRANTY
-
-  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
-                     END OF TERMS AND CONDITIONS
-
-           How to Apply These Terms to Your New Libraries
-
-  If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change.  You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms
-of the ordinary General Public License).
-
-  To apply these terms, attach the following notices to the library.
-It is safest to attach them to the start of each source file to most
-effectively convey the exclusion of warranty; and each file should
-have at least the "copyright" line and a pointer to where the full
-notice is found.
-
-
-    <one line to give the library's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This library is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Lesser General Public
-    License as published by the Free Software Foundation; either
-    version 2.1 of the License, or (at your option) any later version.
-
-    This library is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-    Lesser General Public License for more details.
-
-    You should have received a copy of the GNU Lesser General Public
-    License along with this library; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or
-your school, if any, to sign a "copyright disclaimer" for the library,
-if necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the
-  library `Frob' (a library for tweaking knobs) written by James
-  Random Hacker.
-
-  <signature of Ty Coon>, 1 April 1990
-  Ty Coon, President of Vice
-
-That's all there is to it!
-
-

+ 0 - 187
pylibs/logilab/common/README

@@ -1,187 +0,0 @@
-Logilab's common library
-========================
-
-What's this ?
--------------
-
-This package contains some modules used by differents Logilab's projects.
-
-It is released under the GNU Lesser General Public License.
-
-There is no documentation available yet but the source code should be clean and
-well documented.
-
-Designed to ease:
-
-* handling command line options and configuration files
-* writing interactive command line tools
-* manipulation of files and character strings
-* manipulation of common structures such as graph, tree, and pattern such as visitor
-* generating text and HTML reports
-* accessing some external libraries such as OmniORB_, Pyro_...
-* more...
-
-
-Installation
-------------
-
-Extract the tarball, jump into the created directory and run ::
-
-	python setup.py install
-
-For installation options, see ::
-
-	python setup.py install --help
-
-
-Provided modules
-----------------
-
-Here is a brief description of the available modules.
-
-Modules providing high-level features
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-* `cache`, a cache implementation with a least recently used algorithm.
-
-* `changelog`, a tiny library to manipulate our simplified ChangeLog file format.
-
-* `clcommands`, high-level classes to define command line programs handling
-  different subcommands. It is based on `configuration` to get easy command line
-  / configuration file handling.
-
-* `cli`, a base class for interactive programs using the command line.
-
-* `configuration`, some classes to handle unified configuration from both
-  command line (using optparse) and configuration file (using ConfigParser).
-
-* `dbf`, read Visual Fox Pro DBF files.
-
-* `proc`, interface to Linux /proc.
-
-* `umessage`, unicode email support.
-
-* `ureports`, micro-reports, a way to create simple reports using python objects
-  without care of the final formatting. ReST and html formatters are provided.
-
-
-Modules providing low-level functions and structures
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-* `compat`, provides a transparent compatibility layer between different python
-  versions.
-
-* `date`, a set of date manipulation functions.
-
-* `daemon`, a daemon function and mix-in class to properly start an Unix daemon
-  process.
-
-* `decorators`, function decorators such as cached, timed...
-
-* `deprecation`, decorator, metaclass & all to mark functions / classes as
-  deprecated or moved
-
-* `fileutils`, some file / file path manipulation utilities.
-
-* `graph`, graph manipulations functions such as cycle detection, bases for dot
-  file generation.
-
-* `modutils`, python module manipulation functions.
-
-* `shellutils`, some powerful shell like functions to replace shell scripts with
-  python scripts.
-
-* `tasksqueue`, a prioritized tasks queue implementation.
-
-* `textutils`, some text manipulation functions (ansi colorization, line wrapping,
-  rest support...).
-
-* `tree`, base class to represent tree structure, and some others to make it
-  works with the visitor implementation (see below).
-
-* `visitor`, a generic visitor pattern implementation.
-
-
-Modules extending some standard modules
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-* `debugger`,  `pdb` customization.
-
-* `logging_ext`, extensions to `logging` module such as a colorized formatter
-  and an easier initialization function.
-
-* `optik_ext`, defines some new option types (regexp, csv, color, date, etc.)
-  for `optik` / `optparse`
-
-* `xmlrpcutils`, auth support for XML-RPC
-
-
-Modules extending some external modules
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-* `corbautils`, useful functions for use with the OmniORB_ CORBA library.
-
-* `hg`, some Mercurial_ utility functions.
-
-* `pdf_ext`, pdf and fdf file manipulations, with pdftk.
-
-* `pyro_ext`, some Pyro_ utility functions.
-
-* `sphinx_ext`, Sphinx_ plugin defining a `autodocstring` directive.
-
-* `vcgutils` , utilities functions to generate file readable with Georg Sander's
-  vcg tool (Visualization of Compiler Graphs).
-
-
-To be deprecated modules
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-Those `logilab.common` modules will much probably be deprecated in future
-versions:
-
-* `testlib`: use `unittest2`_ instead
-* `pytest`: use `discover`_ instead
-* `interface`: use `zope.interface`_ if you really want this
-* `table`, `xmlutils`: is that used?
-* `sphinxutils`: we won't go that way imo (i == syt)
-
-
-Deprecated modules
-~~~~~~~~~~~~~~~~~~
-
-Those `logilab.common` modules are only there for backward compatibility. They
-can go away at anytime.
-
-* `optparser`: use `clcommands` instead
-
-* `adbh`, `db`, `sqlgen`: see `logilab.database`_ instead
-
-* `contexts`: content move to `shellutils`
-
-* `html`: deprecated without replacement
-
-
-Comments, support, bug reports
-------------------------------
-
-Project page http://www.logilab.org/project/logilab-common
-
-Use the python-projects@lists.logilab.org mailing list. Since we do not have
-publicly available bug tracker yet, bug reports should be emailed
-there too.
-
-You can subscribe to this mailing list at
-http://lists.logilab.org/mailman/listinfo/python-projects
-
-Archives are available at
-http://lists.logilab.org/pipermail/python-projects/
-
-
-.. _Pyro: http://pyro.sourceforge.net/
-.. _OmniORB: http://omniorb.sourceforge.net/
-.. _Mercurial: http://mercurial.selenic.com
-.. _Sphinx: http://sphinx.pocoo.org/
-.. _`logilab.database`: http://www.logilab.org/project/logilab-database/
-.. _`unittest2`: http://pypi.python.org/pypi/unittest2
-.. _`discover`: http://pypi.python.org/pypi/discover
-.. _`zope.interface`: http://pypi.python.org/pypi/zope.interface

+ 0 - 29
pylibs/logilab/common/README.Python3

@@ -1,29 +0,0 @@
-Python3
-=======
-
-Approach
---------
-
-We maintain a Python 2 base and use 2to3 to generate Python 3 code.
-
-2to3 is integrated into the distutils installation process and will be run as a
-build step when invoked by the python3 interpreter::
-
-  python3 setup.py install
-
-Tests
------
-
-Set your PYTHONPATH and run pytest3 against the test directory.
-
-Debian
-------
-
-For the Debian packaging of python3-logilab-common, you can use the debian.sid/
-content against the debian/ folder::
-
-  cp debian.sid/* debian/
-
-Resources
----------
-http://wiki.python.org/moin/PortingPythonToPy3k

+ 0 - 171
pylibs/logilab/common/__init__.py

@@ -1,171 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""Logilab common library (aka Logilab's extension to the standard library).
-
-:type STD_BLACKLIST: tuple
-:var STD_BLACKLIST: directories ignored by default by the functions in
-  this package which have to recurse into directories
-
-:type IGNORED_EXTENSIONS: tuple
-:var IGNORED_EXTENSIONS: file extensions that may usually be ignored
-"""
-__docformat__ = "restructuredtext en"
-from logilab.common.__pkginfo__ import version as __version__
-
-STD_BLACKLIST = ('CVS', '.svn', '.hg', 'debian', 'dist', 'build')
-
-IGNORED_EXTENSIONS = ('.pyc', '.pyo', '.elc', '~', '.swp', '.orig')
-
-# set this to False if you've mx DateTime installed but you don't want your db
-# adapter to use it (should be set before you got a connection)
-USE_MX_DATETIME = True
-
-
-class attrdict(dict):
-    """A dictionary for which keys are also accessible as attributes."""
-    def __getattr__(self, attr):
-        try:
-            return self[attr]
-        except KeyError:
-            raise AttributeError(attr)
-
-class dictattr(dict):
-    def __init__(self, proxy):
-        self.__proxy = proxy
-
-    def __getitem__(self, attr):
-        try:
-            return getattr(self.__proxy, attr)
-        except AttributeError:
-            raise KeyError(attr)
-
-class nullobject(object):
-    def __repr__(self):
-        return '<nullobject>'
-    def __nonzero__(self):
-        return False
-
-class tempattr(object):
-    def __init__(self, obj, attr, value):
-        self.obj = obj
-        self.attr = attr
-        self.value = value
-
-    def __enter__(self):
-        self.oldvalue = getattr(self.obj, self.attr)
-        setattr(self.obj, self.attr, self.value)
-        return self.obj
-
-    def __exit__(self, exctype, value, traceback):
-        setattr(self.obj, self.attr, self.oldvalue)
-
-
-
-# flatten -----
-# XXX move in a specific module and use yield instead
-# do not mix flatten and translate
-#
-# def iterable(obj):
-#    try: iter(obj)
-#    except: return False
-#    return True
-#
-# def is_string_like(obj):
-#    try: obj +''
-#    except (TypeError, ValueError): return False
-#    return True
-#
-#def is_scalar(obj):
-#    return is_string_like(obj) or not iterable(obj)
-#
-#def flatten(seq):
-#    for item in seq:
-#        if is_scalar(item):
-#            yield item
-#        else:
-#            for subitem in flatten(item):
-#               yield subitem
-
-def flatten(iterable, tr_func=None, results=None):
-    """Flatten a list of list with any level.
-
-    If tr_func is not None, it should be a one argument function that'll be called
-    on each final element.
-
-    :rtype: list
-
-    >>> flatten([1, [2, 3]])
-    [1, 2, 3]
-    """
-    if results is None:
-        results = []
-    for val in iterable:
-        if isinstance(val, (list, tuple)):
-            flatten(val, tr_func, results)
-        elif tr_func is None:
-            results.append(val)
-        else:
-            results.append(tr_func(val))
-    return results
-
-
-# XXX is function below still used ?
-
-def make_domains(lists):
-    """
-    Given a list of lists, return a list of domain for each list to produce all
-    combinations of possibles values.
-
-    :rtype: list
-
-    Example:
-
-    >>> make_domains(['a', 'b'], ['c','d', 'e'])
-    [['a', 'b', 'a', 'b', 'a', 'b'], ['c', 'c', 'd', 'd', 'e', 'e']]
-    """
-    domains = []
-    for iterable in lists:
-        new_domain = iterable[:]
-        for i in range(len(domains)):
-            domains[i] = domains[i]*len(iterable)
-        if domains:
-            missing = (len(domains[0]) - len(iterable)) / len(iterable)
-            i = 0
-            for j in range(len(iterable)):
-                value = iterable[j]
-                for dummy in range(missing):
-                    new_domain.insert(i, value)
-                    i += 1
-                i += 1
-        domains.append(new_domain)
-    return domains
-
-
-# private stuff ################################################################
-
-def _handle_blacklist(blacklist, dirnames, filenames):
-    """remove files/directories in the black list
-
-    dirnames/filenames are usually from os.walk
-    """
-    for norecurs in blacklist:
-        if norecurs in dirnames:
-            dirnames.remove(norecurs)
-        elif norecurs in filenames:
-            filenames.remove(norecurs)
-

+ 0 - 50
pylibs/logilab/common/__pkginfo__.py

@@ -1,50 +0,0 @@
-# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""logilab.common packaging information"""
-__docformat__ = "restructuredtext en"
-import sys
-
-distname = 'logilab-common'
-modname = 'common'
-subpackage_of = 'logilab'
-subpackage_master = True
-
-numversion = (0, 58, 0)
-version = '.'.join([str(num) for num in numversion])
-
-license = 'LGPL' # 2.1 or later
-description = "collection of low-level Python packages and modules used by Logilab projects"
-web = "http://www.logilab.org/project/%s" % distname
-ftp = "ftp://ftp.logilab.org/pub/%s" % modname
-mailinglist = "mailto://python-projects@lists.logilab.org"
-author = "Logilab"
-author_email = "contact@logilab.fr"
-
-
-from os.path import join
-scripts = [join('bin', 'pytest')]
-include_dirs = [join('test', 'data')]
-
-if sys.version_info < (2, 7):
-    install_requires = ['unittest2 >= 0.5.1']
-
-classifiers = ["Topic :: Utilities",
-               "Programming Language :: Python",
-               "Programming Language :: Python :: 2",
-               "Programming Language :: Python :: 3",
-               ]

+ 0 - 25
pylibs/logilab/common/announce.txt

@@ -1,25 +0,0 @@
-I'm pleased to announce the %(VERSION)s release of %(DISTNAME)s.
-
-What's new ?
-------------
-%(CHANGELOG)s
-
-
-What is %(DISTNAME)s ?
-------------------------
-%(LONG_DESC)s
-
-
-Home page
----------
-%(WEB)s
-
-Download
---------
-%(FTP)s
-
-Mailing list
-------------
-%(MAILINGLIST)s
-
-%(ADDITIONAL_DESCR)s

+ 0 - 114
pylibs/logilab/common/cache.py

@@ -1,114 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""Cache module, with a least recently used algorithm for the management of the
-deletion of entries.
-
-
-
-
-"""
-__docformat__ = "restructuredtext en"
-
-from threading import Lock
-
-from logilab.common.decorators import locked
-
-_marker = object()
-
-class Cache(dict):
-    """A dictionary like cache.
-
-    inv:
-        len(self._usage) <= self.size
-        len(self.data) <= self.size
-    """
-
-    def __init__(self, size=100):
-        """ Warning : Cache.__init__() != dict.__init__().
-        Constructor does not take any arguments beside size.
-        """
-        assert size >= 0, 'cache size must be >= 0 (0 meaning no caching)'
-        self.size = size
-        self._usage = []
-        self._lock = Lock()
-        super(Cache, self).__init__()
-
-    def _acquire(self):
-        self._lock.acquire()
-
-    def _release(self):
-        self._lock.release()
-
-    def _update_usage(self, key):
-        if not self._usage:
-            self._usage.append(key)
-        elif self._usage[-1] != key:
-            try:
-                self._usage.remove(key)
-            except ValueError:
-                # we are inserting a new key
-                # check the size of the dictionary
-                # and remove the oldest item in the cache
-                if self.size and len(self._usage) >= self.size:
-                    super(Cache, self).__delitem__(self._usage[0])
-                    del self._usage[0]
-            self._usage.append(key)
-        else:
-            pass # key is already the most recently used key
-
-    def __getitem__(self, key):
-        value = super(Cache, self).__getitem__(key)
-        self._update_usage(key)
-        return value
-    __getitem__ = locked(_acquire, _release)(__getitem__)
-
-    def __setitem__(self, key, item):
-        # Just make sure that size > 0 before inserting a new item in the cache
-        if self.size > 0:
-            super(Cache, self).__setitem__(key, item)
-            self._update_usage(key)
-    __setitem__ = locked(_acquire, _release)(__setitem__)
-
-    def __delitem__(self, key):
-        super(Cache, self).__delitem__(key)
-        self._usage.remove(key)
-    __delitem__ = locked(_acquire, _release)(__delitem__)
-
-    def clear(self):
-        super(Cache, self).clear()
-        self._usage = []
-    clear = locked(_acquire, _release)(clear)
-
-    def pop(self, key, default=_marker):
-        if key in self:
-            self._usage.remove(key)
-        #if default is _marker:
-        #    return super(Cache, self).pop(key)
-        return super(Cache, self).pop(key, default)
-    pop = locked(_acquire, _release)(pop)
-
-    def popitem(self):
-        raise NotImplementedError()
-
-    def setdefault(self, key, default=None):
-        raise NotImplementedError()
-
-    def update(self, other):
-        raise NotImplementedError()
-
-

+ 0 - 236
pylibs/logilab/common/changelog.py

@@ -1,236 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""Manipulation of upstream change log files.
-
-The upstream change log files format handled is simpler than the one
-often used such as those generated by the default Emacs changelog mode.
-
-Sample ChangeLog format::
-
-  Change log for project Yoo
-  ==========================
-
-   --
-      * add a new functionality
-
-  2002-02-01 -- 0.1.1
-      * fix bug #435454
-      * fix bug #434356
-
-  2002-01-01 -- 0.1
-      * initial release
-
-
-There is 3 entries in this change log, one for each released version and one
-for the next version (i.e. the current entry).
-Each entry contains a set of messages corresponding to changes done in this
-release.
-All the non empty lines before the first entry are considered as the change
-log title.
-"""
-
-__docformat__ = "restructuredtext en"
-
-import sys
-from stat import S_IWRITE
-
-BULLET = '*'
-SUBBULLET = '-'
-INDENT = ' ' * 4
-
-class NoEntry(Exception):
-    """raised when we are unable to find an entry"""
-
-class EntryNotFound(Exception):
-    """raised when we are unable to find a given entry"""
-
-class Version(tuple):
-    """simple class to handle soft version number has a tuple while
-    correctly printing it as X.Y.Z
-    """
-    def __new__(cls, versionstr):
-        if isinstance(versionstr, basestring):
-            versionstr = versionstr.strip(' :') # XXX (syt) duh?
-            parsed = cls.parse(versionstr)
-        else:
-            parsed = versionstr
-        return tuple.__new__(cls, parsed)
-
-    @classmethod
-    def parse(cls, versionstr):
-        versionstr = versionstr.strip(' :')
-        try:
-            return [int(i) for i in versionstr.split('.')]
-        except ValueError, ex:
-            raise ValueError("invalid literal for version '%s' (%s)"%(versionstr, ex))
-
-    def __str__(self):
-        return '.'.join([str(i) for i in self])
-
-# upstream change log #########################################################
-
-class ChangeLogEntry(object):
-    """a change log entry, i.e. a set of messages associated to a version and
-    its release date
-    """
-    version_class = Version
-
-    def __init__(self, date=None, version=None, **kwargs):
-        self.__dict__.update(kwargs)
-        if version:
-            self.version = self.version_class(version)
-        else:
-            self.version = None
-        self.date = date
-        self.messages = []
-
-    def add_message(self, msg):
-        """add a new message"""
-        self.messages.append(([msg], []))
-
-    def complete_latest_message(self, msg_suite):
-        """complete the latest added message
-        """
-        if not self.messages:
-            raise ValueError('unable to complete last message as there is no previous message)')
-        if self.messages[-1][1]: # sub messages
-            self.messages[-1][1][-1].append(msg_suite)
-        else: # message
-            self.messages[-1][0].append(msg_suite)
-
-    def add_sub_message(self, sub_msg, key=None):
-        if not self.messages:
-            raise ValueError('unable to complete last message as there is no previous message)')
-        if key is None:
-            self.messages[-1][1].append([sub_msg])
-        else:
-            raise NotImplementedError("sub message to specific key are not implemented yet")
-
-    def write(self, stream=sys.stdout):
-        """write the entry to file """
-        stream.write('%s  --  %s\n' % (self.date or '', self.version or ''))
-        for msg, sub_msgs in self.messages:
-            stream.write('%s%s %s\n' % (INDENT, BULLET, msg[0]))
-            stream.write(''.join(msg[1:]))
-            if sub_msgs:
-                stream.write('\n')
-            for sub_msg in sub_msgs:
-                stream.write('%s%s %s\n' % (INDENT * 2, SUBBULLET, sub_msg[0]))
-                stream.write(''.join(sub_msg[1:]))
-            stream.write('\n')
-
-        stream.write('\n\n')
-
-class ChangeLog(object):
-    """object representation of a whole ChangeLog file"""
-
-    entry_class = ChangeLogEntry
-
-    def __init__(self, changelog_file, title=''):
-        self.file = changelog_file
-        self.title = title
-        self.additional_content = ''
-        self.entries = []
-        self.load()
-
-    def __repr__(self):
-        return '<ChangeLog %s at %s (%s entries)>' % (self.file, id(self),
-                                                      len(self.entries))
-
-    def add_entry(self, entry):
-        """add a new entry to the change log"""
-        self.entries.append(entry)
-
-    def get_entry(self, version='', create=None):
-        """ return a given changelog entry
-        if version is omitted, return the current entry
-        """
-        if not self.entries:
-            if version or not create:
-                raise NoEntry()
-            self.entries.append(self.entry_class())
-        if not version:
-            if self.entries[0].version and create is not None:
-                self.entries.insert(0, self.entry_class())
-            return self.entries[0]
-        version = self.version_class(version)
-        for entry in self.entries:
-            if entry.version == version:
-                return entry
-        raise EntryNotFound()
-
-    def add(self, msg, create=None):
-        """add a new message to the latest opened entry"""
-        entry = self.get_entry(create=create)
-        entry.add_message(msg)
-
-    def load(self):
-        """ read a logilab's ChangeLog from file """
-        try:
-            stream = open(self.file)
-        except IOError:
-            return
-        last = None
-        expect_sub = False
-        for line in stream.readlines():
-            sline = line.strip()
-            words = sline.split()
-            # if new entry
-            if len(words) == 1 and words[0] == '--':
-                expect_sub = False
-                last = self.entry_class()
-                self.add_entry(last)
-            # if old entry
-            elif len(words) == 3 and words[1] == '--':
-                expect_sub = False
-                last = self.entry_class(words[0], words[2])
-                self.add_entry(last)
-            # if title
-            elif sline and last is None:
-                self.title = '%s%s' % (self.title, line)
-            # if new entry
-            elif sline and sline[0] == BULLET:
-                expect_sub = False
-                last.add_message(sline[1:].strip())
-            # if new sub_entry
-            elif expect_sub and sline and sline[0] == SUBBULLET:
-                last.add_sub_message(sline[1:].strip())
-            # if new line for current entry
-            elif sline and last.messages:
-                last.complete_latest_message(line)
-            else:
-                expect_sub = True
-                self.additional_content += line
-        stream.close()
-
-    def format_title(self):
-        return '%s\n\n' % self.title.strip()
-
-    def save(self):
-        """write back change log"""
-        # filetutils isn't importable in appengine, so import locally
-        from logilab.common.fileutils import ensure_fs_mode
-        ensure_fs_mode(self.file, S_IWRITE)
-        self.write(open(self.file, 'w'))
-
-    def write(self, stream=sys.stdout):
-        """write changelog to stream"""
-        stream.write(self.format_title())
-        for entry in self.entries:
-            entry.write(stream)
-

+ 0 - 332
pylibs/logilab/common/clcommands.py

@@ -1,332 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""Helper functions to support command line tools providing more than
-one command.
-
-e.g called as "tool command [options] args..." where <options> and <args> are
-command'specific
-"""
-
-__docformat__ = "restructuredtext en"
-
-import sys
-import logging
-from os.path import basename
-
-from logilab.common.configuration import Configuration
-from logilab.common.logging_ext import init_log, get_threshold
-from logilab.common.deprecation import deprecated
-
-
-class BadCommandUsage(Exception):
-    """Raised when an unknown command is used or when a command is not
-    correctly used (bad options, too much / missing arguments...).
-
-    Trigger display of command usage.
-    """
-
-class CommandError(Exception):
-    """Raised when a command can't be processed and we want to display it and
-    exit, without traceback nor usage displayed.
-    """
-
-
-# command line access point ####################################################
-
-class CommandLine(dict):
-    """Usage:
-
-    >>> LDI = cli.CommandLine('ldi', doc='Logilab debian installer',
-                              version=version, rcfile=RCFILE)
-    >>> LDI.register(MyCommandClass)
-    >>> LDI.register(MyOtherCommandClass)
-    >>> LDI.run(sys.argv[1:])
-
-    Arguments:
-
-    * `pgm`, the program name, default to `basename(sys.argv[0])`
-
-    * `doc`, a short description of the command line tool
-
-    * `copyright`, additional doc string that will be appended to the generated
-      doc
-
-    * `version`, version number of string of the tool. If specified, global
-      --version option will be available.
-
-    * `rcfile`, path to a configuration file. If specified, global --C/--rc-file
-      option will be available?  self.rcfile = rcfile
-
-    * `logger`, logger to propagate to commands, default to
-      `logging.getLogger(self.pgm))`
-    """
-    def __init__(self, pgm=None, doc=None, copyright=None, version=None,
-                 rcfile=None, logthreshold=logging.ERROR,
-                 check_duplicated_command=True):
-        if pgm is None:
-            pgm = basename(sys.argv[0])
-        self.pgm = pgm
-        self.doc = doc
-        self.copyright = copyright
-        self.version = version
-        self.rcfile = rcfile
-        self.logger = None
-        self.logthreshold = logthreshold
-        self.check_duplicated_command = check_duplicated_command
-
-    def register(self, cls, force=False):
-        """register the given :class:`Command` subclass"""
-        assert not self.check_duplicated_command or force or not cls.name in self, \
-               'a command %s is already defined' % cls.name
-        self[cls.name] = cls
-        return cls
-
-    def run(self, args):
-        """main command line access point:
-        * init logging
-        * handle global options (-h/--help, --version, -C/--rc-file)
-        * check command
-        * run command
-
-        Terminate by :exc:`SystemExit`
-        """
-        init_log(debug=True, # so that we use StreamHandler
-                 logthreshold=self.logthreshold,
-                 logformat='%(levelname)s: %(message)s')
-        try:
-            arg = args.pop(0)
-        except IndexError:
-            self.usage_and_exit(1)
-        if arg in ('-h', '--help'):
-            self.usage_and_exit(0)
-        if self.version is not None and arg in ('--version'):
-            print self.version
-            sys.exit(0)
-        rcfile = self.rcfile
-        if rcfile is not None and arg in ('-C', '--rc-file'):
-            try:
-                rcfile = args.pop(0)
-                arg = args.pop(0)
-            except IndexError:
-                self.usage_and_exit(1)
-        try:
-            command = self.get_command(arg)
-        except KeyError:
-            print 'ERROR: no %s command' % arg
-            print
-            self.usage_and_exit(1)
-        try:
-            sys.exit(command.main_run(args, rcfile))
-        except KeyboardInterrupt, exc:
-            print 'Interrupted',
-            if str(exc):
-                print ': %s' % exc,
-            print
-            sys.exit(4)
-        except BadCommandUsage, err:
-            print 'ERROR:', err
-            print
-            print command.help()
-            sys.exit(1)
-
-    def create_logger(self, handler, logthreshold=None):
-        logger = logging.Logger(self.pgm)
-        logger.handlers = [handler]
-        if logthreshold is None:
-            logthreshold = get_threshold(self.logthreshold)
-        logger.setLevel(logthreshold)
-        return logger
-
-    def get_command(self, cmd, logger=None):
-        if logger is None:
-            logger = self.logger
-        if logger is None:
-            logger = self.logger = logging.getLogger(self.pgm)
-            logger.setLevel(get_threshold(self.logthreshold))
-        return self[cmd](logger)
-
-    def usage(self):
-        """display usage for the main program (i.e. when no command supplied)
-        and exit
-        """
-        print 'usage:', self.pgm,
-        if self.rcfile:
-            print '[--rc-file=<configuration file>]',
-        print '<command> [options] <command argument>...'
-        if self.doc:
-            print '\n%s' % self.doc
-        print  '''
-Type "%(pgm)s <command> --help" for more information about a specific
-command. Available commands are :\n''' % self.__dict__
-        max_len = max([len(cmd) for cmd in self])
-        padding = ' ' * max_len
-        for cmdname, cmd in sorted(self.items()):
-            if not cmd.hidden:
-                print ' ', (cmdname + padding)[:max_len], cmd.short_description()
-        if self.rcfile:
-            print '''
-Use --rc-file=<configuration file> / -C <configuration file> before the command
-to specify a configuration file. Default to %s.
-''' % self.rcfile
-        print  '''%(pgm)s -h/--help
-      display this usage information and exit''' % self.__dict__
-        if self.version:
-            print  '''%(pgm)s -v/--version
-      display version configuration and exit''' % self.__dict__
-        if self.copyright:
-            print '\n', self.copyright
-
-    def usage_and_exit(self, status):
-        self.usage()
-        sys.exit(status)
-
-
-# base command classes #########################################################
-
-class Command(Configuration):
-    """Base class for command line commands.
-
-    Class attributes:
-
-    * `name`, the name of the command
-
-    * `min_args`, minimum number of arguments, None if unspecified
-
-    * `max_args`, maximum number of arguments, None if unspecified
-
-    * `arguments`, string describing arguments, used in command usage
-
-    * `hidden`, boolean flag telling if the command should be hidden, e.g. does
-      not appear in help's commands list
-
-    * `options`, options list, as allowed by :mod:configuration
-    """
-
-    arguments = ''
-    name = ''
-    # hidden from help ?
-    hidden = False
-    # max/min args, None meaning unspecified
-    min_args = None
-    max_args = None
-
-    @classmethod
-    def description(cls):
-        return cls.__doc__.replace('    ', '')
-
-    @classmethod
-    def short_description(cls):
-        return cls.description().split('.')[0]
-
-    def __init__(self, logger):
-        usage = '%%prog %s %s\n\n%s' % (self.name, self.arguments,
-                                        self.description())
-        Configuration.__init__(self, usage=usage)
-        self.logger = logger
-
-    def check_args(self, args):
-        """check command's arguments are provided"""
-        if self.min_args is not None and len(args) < self.min_args:
-            raise BadCommandUsage('missing argument')
-        if self.max_args is not None and len(args) > self.max_args:
-            raise BadCommandUsage('too many arguments')
-
-    def main_run(self, args, rcfile=None):
-        """Run the command and return status 0 if everything went fine.
-
-        If :exc:`CommandError` is raised by the underlying command, simply log
-        the error and return status 2.
-
-        Any other exceptions, including :exc:`BadCommandUsage` will be
-        propagated.
-        """
-        if rcfile:
-            self.load_file_configuration(rcfile)
-        args = self.load_command_line_configuration(args)
-        try:
-            self.check_args(args)
-            self.run(args)
-        except CommandError, err:
-            self.logger.error(err)
-            return 2
-        return 0
-
-    def run(self, args):
-        """run the command with its specific arguments"""
-        raise NotImplementedError()
-
-
-class ListCommandsCommand(Command):
-    """list available commands, useful for bash completion."""
-    name = 'listcommands'
-    arguments = '[command]'
-    hidden = True
-
-    def run(self, args):
-        """run the command with its specific arguments"""
-        if args:
-            command = args.pop()
-            cmd = _COMMANDS[command]
-            for optname, optdict in cmd.options:
-                print '--help'
-                print '--' + optname
-        else:
-            commands = sorted(_COMMANDS.keys())
-            for command in commands:
-                cmd = _COMMANDS[command]
-                if not cmd.hidden:
-                    print command
-
-
-# deprecated stuff #############################################################
-
-_COMMANDS = CommandLine()
-
-DEFAULT_COPYRIGHT = '''\
-Copyright (c) 2004-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-http://www.logilab.fr/ -- mailto:contact@logilab.fr'''
-
-@deprecated('use cls.register(cli)')
-def register_commands(commands):
-    """register existing commands"""
-    for command_klass in commands:
-        _COMMANDS.register(command_klass)
-
-@deprecated('use args.pop(0)')
-def main_run(args, doc=None, copyright=None, version=None):
-    """command line tool: run command specified by argument list (without the
-    program name). Raise SystemExit with status 0 if everything went fine.
-
-    >>> main_run(sys.argv[1:])
-    """
-    _COMMANDS.doc = doc
-    _COMMANDS.copyright = copyright
-    _COMMANDS.version = version
-    _COMMANDS.run(args)
-
-@deprecated('use args.pop(0)')
-def pop_arg(args_list, expected_size_after=None, msg="Missing argument"):
-    """helper function to get and check command line arguments"""
-    try:
-        value = args_list.pop(0)
-    except IndexError:
-        raise BadCommandUsage(msg)
-    if expected_size_after is not None and len(args_list) > expected_size_after:
-        raise BadCommandUsage('too many arguments')
-    return value
-

+ 0 - 208
pylibs/logilab/common/cli.py

@@ -1,208 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""Command line interface helper classes.
-
-It provides some default commands, a help system, a default readline
-configuration with completion and persistent history.
-
-Example::
-
-    class BookShell(CLIHelper):
-
-        def __init__(self):
-            # quit and help are builtins
-            # CMD_MAP keys are commands, values are topics
-            self.CMD_MAP['pionce'] = _("Sommeil")
-            self.CMD_MAP['ronfle'] = _("Sommeil")
-            CLIHelper.__init__(self)
-
-        help_do_pionce = ("pionce", "pionce duree", _("met ton corps en veille"))
-        def do_pionce(self):
-            print 'nap is good'
-
-        help_do_ronfle = ("ronfle", "ronfle volume", _("met les autres en veille"))
-        def do_ronfle(self):
-            print 'fuuuuuuuuuuuu rhhhhhrhrhrrh'
-
-    cl = BookShell()
-"""
-
-__docformat__ = "restructuredtext en"
-
-from logilab.common.compat import raw_input, builtins
-if not hasattr(builtins, '_'):
-    builtins._ = str
-
-
-def init_readline(complete_method, histfile=None):
-    """Init the readline library if available."""
-    try:
-        import readline
-        readline.parse_and_bind("tab: complete")
-        readline.set_completer(complete_method)
-        string = readline.get_completer_delims().replace(':', '')
-        readline.set_completer_delims(string)
-        if histfile is not None:
-            try:
-                readline.read_history_file(histfile)
-            except IOError:
-                pass
-            import atexit
-            atexit.register(readline.write_history_file, histfile)
-    except:
-        print 'readline is not available :-('
-
-
-class Completer :
-    """Readline completer."""
-
-    def __init__(self, commands):
-        self.list = commands
-
-    def complete(self, text, state):
-        """Hook called by readline when <tab> is pressed."""
-        n = len(text)
-        matches = []
-        for cmd in self.list :
-            if cmd[:n] == text :
-                matches.append(cmd)
-        try:
-            return matches[state]
-        except IndexError:
-            return None
-
-
-class CLIHelper:
-    """An abstract command line interface client which recognize commands
-    and provide an help system.
-    """
-
-    CMD_MAP = {'help': _("Others"),
-               'quit': _("Others"),
-               }
-    CMD_PREFIX = ''
-
-    def __init__(self, histfile=None) :
-        self._topics = {}
-        self.commands = None
-        self._completer = Completer(self._register_commands())
-        init_readline(self._completer.complete, histfile)
-
-    def run(self):
-        """loop on user input, exit on EOF"""
-        while True:
-            try:
-                line = raw_input('>>> ')
-            except EOFError:
-                print
-                break
-            s_line = line.strip()
-            if not s_line:
-                continue
-            args = s_line.split()
-            if args[0] in self.commands:
-                try:
-                    cmd = 'do_%s' % self.commands[args[0]]
-                    getattr(self, cmd)(*args[1:])
-                except EOFError:
-                    break
-                except:
-                    import traceback
-                    traceback.print_exc()
-            else:
-                try:
-                    self.handle_line(s_line)
-                except:
-                    import traceback
-                    traceback.print_exc()
-
-    def handle_line(self, stripped_line):
-        """Method to overload in the concrete class (should handle
-        lines which are not commands).
-        """
-        raise NotImplementedError()
-
-
-    # private methods #########################################################
-
-    def _register_commands(self):
-        """ register available commands method and return the list of
-        commands name
-        """
-        self.commands = {}
-        self._command_help = {}
-        commands = [attr[3:] for attr in dir(self) if attr[:3] == 'do_']
-        for command in commands:
-            topic = self.CMD_MAP[command]
-            help_method = getattr(self, 'help_do_%s' % command)
-            self._topics.setdefault(topic, []).append(help_method)
-            self.commands[self.CMD_PREFIX + command] = command
-            self._command_help[command] = help_method
-        return self.commands.keys()
-
-    def _print_help(self, cmd, syntax, explanation):
-        print _('Command %s') % cmd
-        print _('Syntax: %s') % syntax
-        print '\t', explanation
-        print
-
-
-    # predefined commands #####################################################
-
-    def do_help(self, command=None) :
-        """base input of the help system"""
-        if command in self._command_help:
-            self._print_help(*self._command_help[command])
-        elif command is None or command not in self._topics:
-            print _("Use help <topic> or help <command>.")
-            print _("Available topics are:")
-            topics = sorted(self._topics.keys())
-            for topic in topics:
-                print '\t', topic
-            print
-            print _("Available commands are:")
-            commands = self.commands.keys()
-            commands.sort()
-            for command in commands:
-                print '\t', command[len(self.CMD_PREFIX):]
-
-        else:
-            print _('Available commands about %s:') % command
-            print
-            for command_help_method in self._topics[command]:
-                try:
-                    if callable(command_help_method):
-                        self._print_help(*command_help_method())
-                    else:
-                        self._print_help(*command_help_method)
-                except:
-                    import traceback
-                    traceback.print_exc()
-                    print 'ERROR in help method %s'% (
-                        command_help_method.func_name)
-
-    help_do_help = ("help", "help [topic|command]",
-                    _("print help message for the given topic/command or \
-available topics when no argument"))
-
-    def do_quit(self):
-        """quit the CLI"""
-        raise EOFError()
-
-    def help_do_quit(self):
-        return ("quit", "quit", _("quit the application"))

+ 0 - 243
pylibs/logilab/common/compat.py

@@ -1,243 +0,0 @@
-# pylint: disable=E0601,W0622,W0611
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""Wrappers around some builtins introduced in python 2.3, 2.4 and
-2.5, making them available in for earlier versions of python.
-
-See another compatibility snippets from other projects:
-
-    :mod:`lib2to3.fixes`
-    :mod:`coverage.backward`
-    :mod:`unittest2.compatibility`
-"""
-
-from __future__ import generators
-
-__docformat__ = "restructuredtext en"
-
-import os
-import sys
-import types
-from warnings import warn
-
-import __builtin__ as builtins # 2to3 will tranform '__builtin__' to 'builtins'
-
-if sys.version_info < (3, 0):
-    str_to_bytes = str
-    def str_encode(string, encoding):
-        if isinstance(string, unicode):
-            return string.encode(encoding)
-        return str(string)
-else:
-    def str_to_bytes(string):
-        return str.encode(string)
-    # we have to ignore the encoding in py3k to be able to write a string into a
-    # TextIOWrapper or like object (which expect an unicode string)
-    def str_encode(string, encoding):
-        return str(string)
-
-# XXX callable built-in seems back in all python versions
-try:
-    callable = builtins.callable
-except AttributeError:
-    from collections import Callable
-    def callable(something):
-        return isinstance(something, Callable)
-    del Callable
-
-# See also http://bugs.python.org/issue11776
-if sys.version_info[0] == 3:
-    def method_type(callable, instance, klass):
-        # api change. klass is no more considered
-        return types.MethodType(callable, instance)
-else:
-    # alias types otherwise
-    method_type = types.MethodType
-
-if sys.version_info < (3, 0):
-    raw_input = raw_input
-else:
-    raw_input = input
-
-# Pythons 2 and 3 differ on where to get StringIO
-if sys.version_info < (3, 0):
-    from cStringIO import StringIO
-    FileIO = file
-    BytesIO = StringIO
-    reload = reload
-else:
-    from io import FileIO, BytesIO, StringIO
-    from imp import reload
-
-# Where do pickles come from?
-try:
-    import cPickle as pickle
-except ImportError:
-    import pickle
-
-from logilab.common.deprecation import deprecated
-
-from itertools import izip, chain, imap
-if sys.version_info < (3, 0):# 2to3 will remove the imports
-    izip = deprecated('izip exists in itertools since py2.3')(izip)
-    imap = deprecated('imap exists in itertools since py2.3')(imap)
-chain = deprecated('chain exists in itertools since py2.3')(chain)
-
-sum = deprecated('sum exists in builtins since py2.3')(sum)
-enumerate = deprecated('enumerate exists in builtins since py2.3')(enumerate)
-frozenset = deprecated('frozenset exists in builtins since py2.4')(frozenset)
-reversed = deprecated('reversed exists in builtins since py2.4')(reversed)
-sorted = deprecated('sorted exists in builtins since py2.4')(sorted)
-max = deprecated('max exists in builtins since py2.4')(max)
-
-
-# Python2.5 builtins
-try:
-    any = any
-    all = all
-except NameError:
-    def any(iterable):
-        """any(iterable) -> bool
-
-        Return True if bool(x) is True for any x in the iterable.
-        """
-        for elt in iterable:
-            if elt:
-                return True
-        return False
-
-    def all(iterable):
-        """all(iterable) -> bool
-
-        Return True if bool(x) is True for all values x in the iterable.
-        """
-        for elt in iterable:
-            if not elt:
-                return False
-        return True
-
-
-# Python2.5 subprocess added functions and exceptions
-try:
-    from subprocess import Popen
-except ImportError:
-    # gae or python < 2.3
-
-    class CalledProcessError(Exception):
-        """This exception is raised when a process run by check_call() returns
-        a non-zero exit status.  The exit status will be stored in the
-        returncode attribute."""
-        def __init__(self, returncode, cmd):
-            self.returncode = returncode
-            self.cmd = cmd
-        def __str__(self):
-            return "Command '%s' returned non-zero exit status %d" % (self.cmd,
-    self.returncode)
-
-    def call(*popenargs, **kwargs):
-        """Run command with arguments.  Wait for command to complete, then
-        return the returncode attribute.
-
-        The arguments are the same as for the Popen constructor.  Example:
-
-        retcode = call(["ls", "-l"])
-        """
-        # workaround: subprocess.Popen(cmd, stdout=sys.stdout) fails
-        # see http://bugs.python.org/issue1531862
-        if "stdout" in kwargs:
-            fileno = kwargs.get("stdout").fileno()
-            del kwargs['stdout']
-            return Popen(stdout=os.dup(fileno), *popenargs, **kwargs).wait()
-        return Popen(*popenargs, **kwargs).wait()
-
-    def check_call(*popenargs, **kwargs):
-        """Run command with arguments.  Wait for command to complete.  If
-        the exit code was zero then return, otherwise raise
-        CalledProcessError.  The CalledProcessError object will have the
-        return code in the returncode attribute.
-
-        The arguments are the same as for the Popen constructor.  Example:
-
-        check_call(["ls", "-l"])
-        """
-        retcode = call(*popenargs, **kwargs)
-        cmd = kwargs.get("args")
-        if cmd is None:
-            cmd = popenargs[0]
-        if retcode:
-            raise CalledProcessError(retcode, cmd)
-        return retcode
-
-try:
-    from os.path import relpath
-except ImportError: # python < 2.6
-    from os.path import curdir, abspath, sep, commonprefix, pardir, join
-    def relpath(path, start=curdir):
-        """Return a relative version of a path"""
-
-        if not path:
-            raise ValueError("no path specified")
-
-        start_list = abspath(start).split(sep)
-        path_list = abspath(path).split(sep)
-
-        # Work out how much of the filepath is shared by start and path.
-        i = len(commonprefix([start_list, path_list]))
-
-        rel_list = [pardir] * (len(start_list)-i) + path_list[i:]
-        if not rel_list:
-            return curdir
-        return join(*rel_list)
-
-
-# XXX don't know why tests don't pass if I don't do that :
-_real_set, set = set, deprecated('set exists in builtins since py2.4')(set)
-if (2, 5) <= sys.version_info[:2]:
-    InheritableSet = _real_set
-else:
-    class InheritableSet(_real_set):
-        """hacked resolving inheritancy issue from old style class in 2.4"""
-        def __new__(cls, *args, **kwargs):
-            if args:
-                new_args = (args[0], )
-            else:
-                new_args = ()
-            obj = _real_set.__new__(cls, *new_args)
-            obj.__init__(*args, **kwargs)
-            return obj
-
-# XXX shouldn't we remove this and just let 2to3 do his job ?
-# range or xrange?
-try:
-    range = xrange
-except NameError:
-    range = range
-
-# ConfigParser was renamed to the more-standard configparser
-try:
-    import configparser
-except ImportError:
-    import ConfigParser as configparser
-
-try:
-    import json
-except ImportError:
-    try:
-        import simplejson as json
-    except ImportError:
-        json = None

Plik diff jest za duży
+ 0 - 1069
pylibs/logilab/common/configuration.py


+ 0 - 5
pylibs/logilab/common/contexts.py

@@ -1,5 +0,0 @@
-from warnings import warn
-warn('logilab.common.contexts module is deprecated, use logilab.common.shellutils instead',
-     DeprecationWarning, stacklevel=1)
-
-from logilab.common.shellutils import tempfile, pushd

+ 0 - 117
pylibs/logilab/common/corbautils.py

@@ -1,117 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""A set of utility function to ease the use of OmniORBpy.
-
-
-
-
-"""
-__docformat__ = "restructuredtext en"
-
-from omniORB import CORBA, PortableServer
-import CosNaming
-
-orb = None
-
-def get_orb():
-    """
-    returns a reference to the ORB.
-    The first call to the method initialized the ORB
-    This method is mainly used internally in the module.
-    """
-
-    global orb
-    if orb is None:
-        import sys
-        orb = CORBA.ORB_init(sys.argv, CORBA.ORB_ID)
-    return orb
-
-def get_root_context():
-    """
-    returns a reference to the NameService object.
-    This method is mainly used internally in the module.
-    """
-
-    orb = get_orb()
-    nss = orb.resolve_initial_references("NameService")
-    rootContext = nss._narrow(CosNaming.NamingContext)
-    assert rootContext is not None, "Failed to narrow root naming context"
-    return rootContext
-
-def register_object_name(object, namepath):
-    """
-    Registers a object in the NamingService.
-    The name path is a list of 2-uples (id,kind) giving the path.
-
-    For instance if the path of an object is [('foo',''),('bar','')],
-    it is possible to get a reference to the object using the URL
-    'corbaname::hostname#foo/bar'.
-    [('logilab','rootmodule'),('chatbot','application'),('chatter','server')]
-    is mapped to
-    'corbaname::hostname#logilab.rootmodule/chatbot.application/chatter.server'
-
-    The get_object_reference() function can be used to resolve such a URL.
-    """
-    context = get_root_context()
-    for id, kind in namepath[:-1]:
-        name = [CosNaming.NameComponent(id, kind)]
-        try:
-            context = context.bind_new_context(name)
-        except CosNaming.NamingContext.AlreadyBound, ex:
-            context = context.resolve(name)._narrow(CosNaming.NamingContext)
-            assert context is not None, \
-                   'test context exists but is not a NamingContext'
-
-    id, kind = namepath[-1]
-    name = [CosNaming.NameComponent(id, kind)]
-    try:
-        context.bind(name, object._this())
-    except CosNaming.NamingContext.AlreadyBound, ex:
-        context.rebind(name, object._this())
-
-def activate_POA():
-    """
-    This methods activates the Portable Object Adapter.
-    You need to call it to enable the reception of messages in your code,
-    on both the client and the server.
-    """
-    orb = get_orb()
-    poa = orb.resolve_initial_references('RootPOA')
-    poaManager = poa._get_the_POAManager()
-    poaManager.activate()
-
-def run_orb():
-    """
-    Enters the ORB mainloop on the server.
-    You should not call this method on the client.
-    """
-    get_orb().run()
-
-def get_object_reference(url):
-    """
-    Resolves a corbaname URL to an object proxy.
-    See register_object_name() for examples URLs
-    """
-    return get_orb().string_to_object(url)
-
-def get_object_string(host, namepath):
-    """given an host name and a name path as described in register_object_name,
-    return a corba string identifier
-    """
-    strname = '/'.join(['.'.join(path_elt) for path_elt in namepath])
-    return 'corbaname::%s#%s' % (host, strname)

+ 0 - 100
pylibs/logilab/common/daemon.py

@@ -1,100 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""A daemonize function (for Unices)"""
-
-__docformat__ = "restructuredtext en"
-
-import os
-import errno
-import signal
-import sys
-import time
-import warnings
-
-def setugid(user):
-    """Change process user and group ID
-
-    Argument is a numeric user id or a user name"""
-    try:
-        from pwd import getpwuid
-        passwd = getpwuid(int(user))
-    except ValueError:
-        from pwd import getpwnam
-        passwd = getpwnam(user)
-
-    if hasattr(os, 'initgroups'): # python >= 2.7
-        os.initgroups(passwd.pw_name, passwd.pw_gid)
-    else:
-        import ctypes
-        if ctypes.CDLL(None).initgroups(passwd.pw_name, passwd.pw_gid) < 0:
-            err = ctypes.c_int.in_dll(ctypes.pythonapi,"errno").value
-            raise OSError(err, os.strerror(err), 'initgroups')
-    os.setgid(passwd.pw_gid)
-    os.setuid(passwd.pw_uid)
-    os.environ['HOME'] = passwd.pw_dir
-
-
-def daemonize(pidfile=None, uid=None, umask=077):
-    """daemonize a Unix process. Set paranoid umask by default.
-
-    Return 1 in the original process, 2 in the first fork, and None for the
-    second fork (eg daemon process).
-    """
-    # http://www.faqs.org/faqs/unix-faq/programmer/faq/
-    #
-    # fork so the parent can exit
-    if os.fork():   # launch child and...
-        return 1
-    # disconnect from tty and create a new session
-    os.setsid()
-    # fork again so the parent, (the session group leader), can exit.
-    # as a non-session group leader, we can never regain a controlling
-    # terminal.
-    if os.fork():   # launch child again.
-        return 2
-    # move to the root to avoit mount pb
-    os.chdir('/')
-    # set umask if specified
-    if umask is not None:
-        os.umask(umask)
-    # redirect standard descriptors
-    null = os.open('/dev/null', os.O_RDWR)
-    for i in range(3):
-        try:
-            os.dup2(null, i)
-        except OSError, e:
-            if e.errno != errno.EBADF:
-                raise
-    os.close(null)
-    # filter warnings
-    warnings.filterwarnings('ignore')
-    # write pid in a file
-    if pidfile:
-        # ensure the directory where the pid-file should be set exists (for
-        # instance /var/run/cubicweb may be deleted on computer restart)
-        piddir = os.path.dirname(pidfile)
-        if not os.path.exists(piddir):
-            os.makedirs(piddir)
-        f = file(pidfile, 'w')
-        f.write(str(os.getpid()))
-        f.close()
-        os.chmod(pidfile, 0644)
-    # change process uid
-    if uid:
-        setugid(uid)
-    return None

+ 0 - 327
pylibs/logilab/common/date.py

@@ -1,327 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""Date manipulation helper functions."""
-from __future__ import division
-
-__docformat__ = "restructuredtext en"
-
-import math
-import re
-from locale import getpreferredencoding
-from datetime import date, time, datetime, timedelta
-from time import strptime as time_strptime
-from calendar import monthrange, timegm
-
-try:
-    from mx.DateTime import RelativeDateTime, Date, DateTimeType
-except ImportError:
-    endOfMonth = None
-    DateTimeType = datetime
-else:
-    endOfMonth = RelativeDateTime(months=1, day=-1)
-
-# NOTE: should we implement a compatibility layer between date representations
-#       as we have in lgc.db ?
-
-FRENCH_FIXED_HOLIDAYS = {
-    'jour_an': '%s-01-01',
-    'fete_travail': '%s-05-01',
-    'armistice1945': '%s-05-08',
-    'fete_nat': '%s-07-14',
-    'assomption': '%s-08-15',
-    'toussaint': '%s-11-01',
-    'armistice1918': '%s-11-11',
-    'noel': '%s-12-25',
-    }
-
-FRENCH_MOBILE_HOLIDAYS = {
-    'paques2004': '2004-04-12',
-    'ascension2004': '2004-05-20',
-    'pentecote2004': '2004-05-31',
-
-    'paques2005': '2005-03-28',
-    'ascension2005': '2005-05-05',
-    'pentecote2005': '2005-05-16',
-
-    'paques2006': '2006-04-17',
-    'ascension2006': '2006-05-25',
-    'pentecote2006': '2006-06-05',
-
-    'paques2007': '2007-04-09',
-    'ascension2007': '2007-05-17',
-    'pentecote2007': '2007-05-28',
-
-    'paques2008': '2008-03-24',
-    'ascension2008': '2008-05-01',
-    'pentecote2008': '2008-05-12',
-
-    'paques2009': '2009-04-13',
-    'ascension2009': '2009-05-21',
-    'pentecote2009': '2009-06-01',
-
-    'paques2010': '2010-04-05',
-    'ascension2010': '2010-05-13',
-    'pentecote2010': '2010-05-24',
-
-    'paques2011': '2011-04-25',
-    'ascension2011': '2011-06-02',
-    'pentecote2011': '2011-06-13',
-
-    'paques2012': '2012-04-09',
-    'ascension2012': '2012-05-17',
-    'pentecote2012': '2012-05-28',
-    }
-
-# XXX this implementation cries for multimethod dispatching
-
-def get_step(dateobj, nbdays=1):
-    # assume date is either a python datetime or a mx.DateTime object
-    if isinstance(dateobj, date):
-        return ONEDAY * nbdays
-    return nbdays # mx.DateTime is ok with integers
-
-def datefactory(year, month, day, sampledate):
-    # assume date is either a python datetime or a mx.DateTime object
-    if isinstance(sampledate, datetime):
-        return datetime(year, month, day)
-    if isinstance(sampledate, date):
-        return date(year, month, day)
-    return Date(year, month, day)
-
-def weekday(dateobj):
-    # assume date is either a python datetime or a mx.DateTime object
-    if isinstance(dateobj, date):
-        return dateobj.weekday()
-    return dateobj.day_of_week
-
-def str2date(datestr, sampledate):
-    # NOTE: datetime.strptime is not an option until we drop py2.4 compat
-    year, month, day = [int(chunk) for chunk in datestr.split('-')]
-    return datefactory(year, month, day, sampledate)
-
-def days_between(start, end):
-    if isinstance(start, date):
-        delta = end - start
-        # datetime.timedelta.days is always an integer (floored)
-        if delta.seconds:
-            return delta.days + 1
-        return delta.days
-    else:
-        return int(math.ceil((end - start).days))
-
-def get_national_holidays(begin, end):
-    """return french national days off between begin and end"""
-    begin = datefactory(begin.year, begin.month, begin.day, begin)
-    end = datefactory(end.year, end.month, end.day, end)
-    holidays = [str2date(datestr, begin)
-                for datestr in FRENCH_MOBILE_HOLIDAYS.values()]
-    for year in xrange(begin.year, end.year+1):
-        for datestr in FRENCH_FIXED_HOLIDAYS.values():
-            date = str2date(datestr % year, begin)
-            if date not in holidays:
-                holidays.append(date)
-    return [day for day in holidays if begin <= day < end]
-
-def add_days_worked(start, days):
-    """adds date but try to only take days worked into account"""
-    step = get_step(start)
-    weeks, plus = divmod(days, 5)
-    end = start + ((weeks * 7) + plus) * step
-    if weekday(end) >= 5: # saturday or sunday
-        end += (2 * step)
-    end += len([x for x in get_national_holidays(start, end + step)
-                if weekday(x) < 5]) * step
-    if weekday(end) >= 5: # saturday or sunday
-        end += (2 * step)
-    return end
-
-def nb_open_days(start, end):
-    assert start <= end
-    step = get_step(start)
-    days = days_between(start, end)
-    weeks, plus = divmod(days, 7)
-    if weekday(start) > weekday(end):
-        plus -= 2
-    elif weekday(end) == 6:
-        plus -= 1
-    open_days = weeks * 5 + plus
-    nb_week_holidays = len([x for x in get_national_holidays(start, end+step)
-                            if weekday(x) < 5 and x < end])
-    open_days -= nb_week_holidays
-    if open_days < 0:
-        return 0
-    return open_days
-
-def date_range(begin, end, incday=None, incmonth=None):
-    """yields each date between begin and end
-
-    :param begin: the start date
-    :param end: the end date
-    :param incr: the step to use to iterate over dates. Default is
-                 one day.
-    :param include: None (means no exclusion) or a function taking a
-                    date as parameter, and returning True if the date
-                    should be included.
-
-    When using mx datetime, you should *NOT* use incmonth argument, use instead
-    oneDay, oneHour, oneMinute, oneSecond, oneWeek or endOfMonth (to enumerate
-    months) as `incday` argument
-    """
-    assert not (incday and incmonth)
-    begin = todate(begin)
-    end = todate(end)
-    if incmonth:
-        while begin < end:
-            begin = next_month(begin, incmonth)
-            yield begin
-    else:
-        incr = get_step(begin, incday or 1)
-        while begin < end:
-           yield begin
-           begin += incr
-
-# makes py datetime usable #####################################################
-
-ONEDAY = timedelta(days=1)
-ONEWEEK = timedelta(days=7)
-
-try:
-    strptime = datetime.strptime
-except AttributeError: # py < 2.5
-    from time import strptime as time_strptime
-    def strptime(value, format):
-        return datetime(*time_strptime(value, format)[:6])
-
-def strptime_time(value, format='%H:%M'):
-    return time(*time_strptime(value, format)[3:6])
-
-def todate(somedate):
-    """return a date from a date (leaving unchanged) or a datetime"""
-    if isinstance(somedate, datetime):
-        return date(somedate.year, somedate.month, somedate.day)
-    assert isinstance(somedate, (date, DateTimeType)), repr(somedate)
-    return somedate
-
-def totime(somedate):
-    """return a time from a time (leaving unchanged), date or datetime"""
-    # XXX mx compat
-    if not isinstance(somedate, time):
-        return time(somedate.hour, somedate.minute, somedate.second)
-    assert isinstance(somedate, (time)), repr(somedate)
-    return somedate
-
-def todatetime(somedate):
-    """return a date from a date (leaving unchanged) or a datetime"""
-    # take care, datetime is a subclass of date
-    if isinstance(somedate, datetime):
-        return somedate
-    assert isinstance(somedate, (date, DateTimeType)), repr(somedate)
-    return datetime(somedate.year, somedate.month, somedate.day)
-
-def datetime2ticks(somedate):
-    return timegm(somedate.timetuple()) * 1000
-
-def ticks2datetime(ticks):
-    miliseconds, microseconds = divmod(ticks, 1000)
-    try:
-        return datetime.fromtimestamp(miliseconds)
-    except (ValueError, OverflowError):
-        epoch = datetime.fromtimestamp(0)
-        nb_days, seconds = divmod(int(miliseconds), 86400)
-        delta = timedelta(nb_days, seconds=seconds, microseconds=microseconds)
-        try:
-            return epoch + delta
-        except (ValueError, OverflowError):
-            raise
-
-def days_in_month(somedate):
-    return monthrange(somedate.year, somedate.month)[1]
-
-def days_in_year(somedate):
-    feb = date(somedate.year, 2, 1)
-    if days_in_month(feb) == 29:
-        return 366
-    else:
-        return 365
-
-def previous_month(somedate, nbmonth=1):
-    while nbmonth:
-        somedate = first_day(somedate) - ONEDAY
-        nbmonth -= 1
-    return somedate
-
-def next_month(somedate, nbmonth=1):
-    while nbmonth:
-        somedate = last_day(somedate) + ONEDAY
-        nbmonth -= 1
-    return somedate
-
-def first_day(somedate):
-    return date(somedate.year, somedate.month, 1)
-
-def last_day(somedate):
-    return date(somedate.year, somedate.month, days_in_month(somedate))
-
-def ustrftime(somedate, fmt='%Y-%m-%d'):
-    """like strftime, but returns a unicode string instead of an encoded
-    string which' may be problematic with localized date.
-
-    encoding is guessed by locale.getpreferredencoding()
-    """
-    encoding = getpreferredencoding(do_setlocale=False) or 'UTF-8'
-    try:
-        return unicode(somedate.strftime(str(fmt)), encoding)
-    except ValueError, exc:
-        if somedate.year >= 1900:
-            raise
-        # datetime is not happy with dates before 1900
-        # we try to work around this, assuming a simple
-        # format string
-        fields = {'Y': somedate.year,
-                  'm': somedate.month,
-                  'd': somedate.day,
-                  }
-        if isinstance(somedate, datetime):
-            fields.update({'H': somedate.hour,
-                           'M': somedate.minute,
-                           'S': somedate.second})
-        fmt = re.sub('%([YmdHMS])', r'%(\1)02d', fmt)
-        return unicode(fmt) % fields
-
-def utcdatetime(dt):
-    if dt.tzinfo is None:
-        return dt
-    return datetime(*dt.utctimetuple()[:7])
-
-def utctime(dt):
-    if dt.tzinfo is None:
-        return dt
-    return (dt + dt.utcoffset() + dt.dst()).replace(tzinfo=None)
-
-def datetime_to_seconds(date):
-    """return the number of seconds since the begining of the day for that date
-    """
-    return date.second+60*date.minute + 3600*date.hour
-
-def timedelta_to_days(delta):
-    """return the time delta as a number of seconds"""
-    return delta.days + delta.seconds / (3600*24)
-
-def timedelta_to_seconds(delta):
-    """return the time delta as a fraction of days"""
-    return delta.days*(3600*24) + delta.seconds

+ 0 - 229
pylibs/logilab/common/dbf.py

@@ -1,229 +0,0 @@
-# -*- coding: utf-8 -*-
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""This is a DBF reader which reads Visual Fox Pro DBF format with Memo field
-
-Usage:
-
->>> rec = readDbf('test.dbf')
->>> for line in rec:
->>>     print line['name']
-
-
-:date: 13/07/2007
-
-http://www.physics.ox.ac.uk/users/santoso/Software.Repository.html
-page says code is "available as is without any warranty or support".
-"""
-
-import struct
-import os, os.path
-import sys
-import csv
-import tempfile
-import ConfigParser
-
-class Dbase:
-    def __init__(self):
-        self.fdb = None
-        self.fmemo = None
-        self.db_data = None
-        self.memo_data = None
-        self.fields = None
-        self.num_records = 0
-        self.header = None
-        self.memo_file = ''
-        self.memo_header = None
-        self.memo_block_size = 0
-        self.memo_header_len = 0
-
-    def _drop_after_NULL(self, txt):
-        for i in range(0, len(txt)):
-            if ord(struct.unpack('c', txt[i])[0])==0:
-                return txt[:i]
-        return txt
-
-    def _reverse_endian(self, num):
-        if not len(num):
-            return 0
-        val = struct.unpack('<L', num)
-        val = struct.pack('>L', val[0])
-        val = struct.unpack('>L', val)
-        return val[0]
-
-    def _assign_ids(self, lst, ids):
-        result = {}
-        idx = 0
-        for item in lst:
-            id = ids[idx]
-            result[id] = item
-            idx += 1
-        return result
-
-    def open(self, db_name):
-        filesize = os.path.getsize(db_name)
-        if filesize <= 68:
-            raise IOError, 'The file is not large enough to be a dbf file'
-
-        self.fdb = open(db_name, 'rb')
-
-        self.memo_file = ''
-        if os.path.isfile(db_name[0:-1] + 't'):
-            self.memo_file = db_name[0:-1] + 't'
-        elif os.path.isfile(db_name[0:-3] + 'fpt'):
-            self.memo_file = db_name[0:-3] + 'fpt'
-
-        if self.memo_file:
-            #Read memo file
-            self.fmemo = open(self.memo_file, 'rb')
-            self.memo_data = self.fmemo.read()
-            self.memo_header = self._assign_ids(struct.unpack('>6x1H', self.memo_data[:8]), ['Block size'])
-            block_size = self.memo_header['Block size']
-            if not block_size:
-                block_size = 512
-            self.memo_block_size = block_size
-            self.memo_header_len = block_size
-            memo_size = os.path.getsize(self.memo_file)
-
-        #Start reading data file
-        data = self.fdb.read(32)
-        self.header = self._assign_ids(struct.unpack('<B 3B L 2H 20x', data), ['id', 'Year', 'Month', 'Day', '# of Records', 'Header Size', 'Record Size'])
-        self.header['id'] = hex(self.header['id'])
-
-        self.num_records = self.header['# of Records']
-        data = self.fdb.read(self.header['Header Size']-34)
-        self.fields = {}
-        x = 0
-        header_pattern = '<11s c 4x B B 14x'
-        ids = ['Field Name', 'Field Type', 'Field Length', 'Field Precision']
-        pattern_len = 32
-        for offset in range(0, len(data), 32):
-            if ord(data[offset])==0x0d:
-                break
-            x += 1
-            data_subset = data[offset: offset+pattern_len]
-            if len(data_subset) < pattern_len:
-                data_subset += ' '*(pattern_len-len(data_subset))
-            self.fields[x] = self._assign_ids(struct.unpack(header_pattern, data_subset), ids)
-            self.fields[x]['Field Name'] = self._drop_after_NULL(self.fields[x]['Field Name'])
-
-        self.fdb.read(3)
-        if self.header['# of Records']:
-            data_size = (self.header['# of Records'] * self.header['Record Size']) - 1
-            self.db_data = self.fdb.read(data_size)
-        else:
-            self.db_data = ''
-        self.row_format = '<'
-        self.row_ids = []
-        self.row_len = 0
-        for key in self.fields:
-            field = self.fields[key]
-            self.row_format += '%ds ' % (field['Field Length'])
-            self.row_ids.append(field['Field Name'])
-            self.row_len += field['Field Length']
-
-    def close(self):
-        if self.fdb:
-            self.fdb.close()
-        if self.fmemo:
-            self.fmemo.close()
-
-    def get_numrecords(self):
-        return self.num_records
-
-    def get_record_with_names(self, rec_no):
-        """
-        This function accept record number from 0 to N-1
-        """
-        if rec_no < 0 or rec_no > self.num_records:
-            raise Exception, 'Unable to extract data outside the range'
-
-        offset = self.header['Record Size'] * rec_no
-        data = self.db_data[offset:offset+self.row_len]
-        record = self._assign_ids(struct.unpack(self.row_format, data), self.row_ids)
-
-        if self.memo_file:
-            for key in self.fields:
-                field = self.fields[key]
-                f_type = field['Field Type']
-                f_name = field['Field Name']
-                c_data = record[f_name]
-
-                if f_type=='M' or f_type=='G' or f_type=='B' or f_type=='P':
-                    c_data = self._reverse_endian(c_data)
-                    if c_data:
-                        record[f_name] = self.read_memo(c_data-1).strip()
-                else:
-                    record[f_name] = c_data.strip()
-        return record
-
-    def read_memo_record(self, num, in_length):
-        """
-        Read the record of given number. The second parameter is the length of
-        the record to read. It can be undefined, meaning read the whole record,
-        and it can be negative, meaning at most the length
-        """
-        if in_length < 0:
-            in_length = -self.memo_block_size
-
-        offset = self.memo_header_len + num * self.memo_block_size
-        self.fmemo.seek(offset)
-        if in_length<0:
-            in_length = -in_length
-        if in_length==0:
-            return ''
-        return self.fmemo.read(in_length)
-
-    def read_memo(self, num):
-        result = ''
-        buffer = self.read_memo_record(num, -1)
-        if len(buffer)<=0:
-            return ''
-        length = struct.unpack('>L', buffer[4:4+4])[0] + 8
-
-        block_size = self.memo_block_size
-        if length < block_size:
-            return buffer[8:length]
-        rest_length = length - block_size
-        rest_data = self.read_memo_record(num+1, rest_length)
-        if len(rest_data)<=0:
-            return ''
-        return buffer[8:] + rest_data
-
-def readDbf(filename):
-    """
-    Read the DBF file specified by the filename and
-    return the records as a list of dictionary.
-
-    :param: filename File name of the DBF
-    :return: List of rows
-    """
-    db = Dbase()
-    db.open(filename)
-    num = db.get_numrecords()
-    rec = []
-    for i in range(0, num):
-        record = db.get_record_with_names(i)
-        rec.append(record)
-    db.close()
-    return  rec
-
-if __name__=='__main__':
-    rec = readDbf('dbf/sptable.dbf')
-    for line in rec:
-        print '%s %s' % (line['GENUS'].strip(), line['SPECIES'].strip())

+ 0 - 210
pylibs/logilab/common/debugger.py

@@ -1,210 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""Customized version of pdb's default debugger.
-
-- sets up a history file
-- uses ipython if available to colorize lines of code
-- overrides list command to search for current block instead
-  of using 5 lines of context
-
-
-
-
-"""
-__docformat__ = "restructuredtext en"
-
-try:
-    import readline
-except ImportError:
-    readline = None
-import os
-import os.path as osp
-import sys
-from pdb import Pdb
-from cStringIO import StringIO
-import inspect
-
-try:
-    from IPython import PyColorize
-except ImportError:
-    def colorize(source, *args):
-        """fallback colorize function"""
-        return source
-    def colorize_source(source, *args):
-        return source
-else:
-    def colorize(source, start_lineno, curlineno):
-        """colorize and annotate source with linenos
-        (as in pdb's list command)
-        """
-        parser = PyColorize.Parser()
-        output = StringIO()
-        parser.format(source, output)
-        annotated = []
-        for index, line in enumerate(output.getvalue().splitlines()):
-            lineno = index + start_lineno
-            if lineno == curlineno:
-                annotated.append('%4s\t->\t%s' % (lineno, line))
-            else:
-                annotated.append('%4s\t\t%s' % (lineno, line))
-        return '\n'.join(annotated)
-
-    def colorize_source(source):
-        """colorize given source"""
-        parser = PyColorize.Parser()
-        output = StringIO()
-        parser.format(source, output)
-        return output.getvalue()
-
-
-def getsource(obj):
-    """Return the text of the source code for an object.
-
-    The argument may be a module, class, method, function, traceback, frame,
-    or code object.  The source code is returned as a single string.  An
-    IOError is raised if the source code cannot be retrieved."""
-    lines, lnum = inspect.getsourcelines(obj)
-    return ''.join(lines), lnum
-
-
-################################################################
-class Debugger(Pdb):
-    """custom debugger
-
-    - sets up a history file
-    - uses ipython if available to colorize lines of code
-    - overrides list command to search for current block instead
-      of using 5 lines of context
-    """
-    def __init__(self, tcbk=None):
-        Pdb.__init__(self)
-        self.reset()
-        if tcbk:
-            while tcbk.tb_next is not None:
-                tcbk = tcbk.tb_next
-        self._tcbk = tcbk
-        self._histfile = os.path.expanduser("~/.pdbhist")
-
-    def setup_history_file(self):
-        """if readline is available, read pdb history file
-        """
-        if readline is not None:
-            try:
-                # XXX try..except shouldn't be necessary
-                # read_history_file() can accept None
-                readline.read_history_file(self._histfile)
-            except IOError:
-                pass
-
-    def start(self):
-        """starts the interactive mode"""
-        self.interaction(self._tcbk.tb_frame, self._tcbk)
-
-    def setup(self, frame, tcbk):
-        """setup hook: set up history file"""
-        self.setup_history_file()
-        Pdb.setup(self, frame, tcbk)
-
-    def set_quit(self):
-        """quit hook: save commands in the history file"""
-        if readline is not None:
-            readline.write_history_file(self._histfile)
-        Pdb.set_quit(self)
-
-    def complete_p(self, text, line, begin_idx, end_idx):
-        """provide variable names completion for the ``p`` command"""
-        namespace = dict(self.curframe.f_globals)
-        namespace.update(self.curframe.f_locals)
-        if '.' in text:
-            return self.attr_matches(text, namespace)
-        return [varname for varname in namespace if varname.startswith(text)]
-
-
-    def attr_matches(self, text, namespace):
-        """implementation coming from rlcompleter.Completer.attr_matches
-        Compute matches when text contains a dot.
-
-        Assuming the text is of the form NAME.NAME....[NAME], and is
-        evaluatable in self.namespace, it will be evaluated and its attributes
-        (as revealed by dir()) are used as possible completions.  (For class
-        instances, class members are also considered.)
-
-        WARNING: this can still invoke arbitrary C code, if an object
-        with a __getattr__ hook is evaluated.
-
-        """
-        import re
-        m = re.match(r"(\w+(\.\w+)*)\.(\w*)", text)
-        if not m:
-            return
-        expr, attr = m.group(1, 3)
-        object = eval(expr, namespace)
-        words = dir(object)
-        if hasattr(object, '__class__'):
-            words.append('__class__')
-            words = words + self.get_class_members(object.__class__)
-        matches = []
-        n = len(attr)
-        for word in words:
-            if word[:n] == attr and word != "__builtins__":
-                matches.append("%s.%s" % (expr, word))
-        return matches
-
-    def get_class_members(self, klass):
-        """implementation coming from rlcompleter.get_class_members"""
-        ret = dir(klass)
-        if hasattr(klass, '__bases__'):
-            for base in klass.__bases__:
-                ret = ret + self.get_class_members(base)
-        return ret
-
-    ## specific / overridden commands
-    def do_list(self, arg):
-        """overrides default list command to display the surrounding block
-        instead of 5 lines of context
-        """
-        self.lastcmd = 'list'
-        if not arg:
-            try:
-                source, start_lineno = getsource(self.curframe)
-                print colorize(''.join(source), start_lineno,
-                               self.curframe.f_lineno)
-            except KeyboardInterrupt:
-                pass
-            except IOError:
-                Pdb.do_list(self, arg)
-        else:
-            Pdb.do_list(self, arg)
-    do_l = do_list
-
-    def do_open(self, arg):
-        """opens source file corresponding to the current stack level"""
-        filename = self.curframe.f_code.co_filename
-        lineno = self.curframe.f_lineno
-        cmd = 'emacsclient --no-wait +%s %s' % (lineno, filename)
-        os.system(cmd)
-
-    do_o = do_open
-
-def pm():
-    """use our custom debugger"""
-    dbg = Debugger(sys.last_traceback)
-    dbg.start()
-
-def set_trace():
-    Debugger().set_trace(sys._getframe().f_back)

+ 0 - 283
pylibs/logilab/common/decorators.py

@@ -1,283 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-""" A few useful function/method decorators. """
-__docformat__ = "restructuredtext en"
-
-import sys
-from time import clock, time
-
-from logilab.common.compat import callable, method_type
-
-# XXX rewrite so we can use the decorator syntax when keyarg has to be specified
-
-def _is_generator_function(callableobj):
-    return callableobj.func_code.co_flags & 0x20
-
-class cached_decorator(object):
-    def __init__(self, cacheattr=None, keyarg=None):
-        self.cacheattr = cacheattr
-        self.keyarg = keyarg
-    def __call__(self, callableobj=None):
-        assert not _is_generator_function(callableobj), \
-               'cannot cache generator function: %s' % callableobj
-        if callableobj.func_code.co_argcount == 1 or self.keyarg == 0:
-            cache = _SingleValueCache(callableobj, self.cacheattr)
-        elif self.keyarg:
-            cache = _MultiValuesKeyArgCache(callableobj, self.keyarg, self.cacheattr)
-        else:
-            cache = _MultiValuesCache(callableobj, self.cacheattr)
-        return cache.closure()
-
-class _SingleValueCache(object):
-    def __init__(self, callableobj, cacheattr=None):
-        self.callable = callableobj
-        if cacheattr is None:
-            self.cacheattr = '_%s_cache_' % callableobj.__name__
-        else:
-            assert cacheattr != callableobj.__name__
-            self.cacheattr = cacheattr
-
-    def __call__(__me, self, *args):
-        try:
-            return self.__dict__[__me.cacheattr]
-        except KeyError:
-            value = __me.callable(self, *args)
-            setattr(self, __me.cacheattr, value)
-            return value
-
-    def closure(self):
-        def wrapped(*args, **kwargs):
-            return self.__call__(*args, **kwargs)
-        wrapped.cache_obj = self
-        try:
-            wrapped.__doc__ = self.callable.__doc__
-            wrapped.__name__ = self.callable.__name__
-            wrapped.func_name = self.callable.func_name
-        except:
-            pass
-        return wrapped
-
-    def clear(self, holder):
-        holder.__dict__.pop(self.cacheattr, None)
-
-
-class _MultiValuesCache(_SingleValueCache):
-    def _get_cache(self, holder):
-        try:
-            _cache = holder.__dict__[self.cacheattr]
-        except KeyError:
-            _cache = {}
-            setattr(holder, self.cacheattr, _cache)
-        return _cache
-
-    def __call__(__me, self, *args, **kwargs):
-        _cache = __me._get_cache(self)
-        try:
-            return _cache[args]
-        except KeyError:
-            _cache[args] = __me.callable(self, *args)
-            return _cache[args]
-
-class _MultiValuesKeyArgCache(_MultiValuesCache):
-    def __init__(self, callableobj, keyarg, cacheattr=None):
-        super(_MultiValuesKeyArgCache, self).__init__(callableobj, cacheattr)
-        self.keyarg = keyarg
-
-    def __call__(__me, self, *args, **kwargs):
-        _cache = __me._get_cache(self)
-        key = args[__me.keyarg-1]
-        try:
-            return _cache[key]
-        except KeyError:
-            _cache[key] = __me.callable(self, *args, **kwargs)
-            return _cache[key]
-
-
-def cached(callableobj=None, keyarg=None, **kwargs):
-    """Simple decorator to cache result of method call."""
-    kwargs['keyarg'] = keyarg
-    decorator = cached_decorator(**kwargs)
-    if callableobj is None:
-        return decorator
-    else:
-        return decorator(callableobj)
-
-
-class cachedproperty(object):
-    """ Provides a cached property equivalent to the stacking of
-    @cached and @property, but more efficient.
-
-    After first usage, the <property_name> becomes part of the object's
-    __dict__. Doing:
-
-      del obj.<property_name> empties the cache.
-
-    Idea taken from the pyramid_ framework and the mercurial_ project.
-
-    .. _pyramid: http://pypi.python.org/pypi/pyramid
-    .. _mercurial: http://pypi.python.org/pypi/Mercurial
-    """
-    __slots__ = ('wrapped',)
-
-    def __init__(self, wrapped):
-        try:
-            wrapped.__name__
-        except AttributeError:
-            raise TypeError('%s must have a __name__ attribute' %
-                            wrapped)
-        self.wrapped = wrapped
-
-    @property
-    def __doc__(self):
-        doc = getattr(self.wrapped, '__doc__', None)
-        return ('<wrapped by the cachedproperty decorator>%s'
-                % ('\n%s' % doc if doc else ''))
-
-    def __get__(self, inst, objtype=None):
-        if inst is None:
-            return self
-        val = self.wrapped(inst)
-        setattr(inst, self.wrapped.__name__, val)
-        return val
-
-
-def get_cache_impl(obj, funcname):
-    cls = obj.__class__
-    member = getattr(cls, funcname)
-    if isinstance(member, property):
-        member = member.fget
-    return member.cache_obj
-
-def clear_cache(obj, funcname):
-    """Clear a cache handled by the :func:`cached` decorator. If 'x' class has
-    @cached on its method `foo`, type
-
-    >>> clear_cache(x, 'foo')
-
-    to purge this method's cache on the instance.
-    """
-    get_cache_impl(obj, funcname).clear(obj)
-
-def copy_cache(obj, funcname, cacheobj):
-    """Copy cache for <funcname> from cacheobj to obj."""
-    cacheattr = get_cache_impl(obj, funcname).cacheattr
-    try:
-        setattr(obj, cacheattr, cacheobj.__dict__[cacheattr])
-    except KeyError:
-        pass
-
-
-class wproperty(object):
-    """Simple descriptor expecting to take a modifier function as first argument
-    and looking for a _<function name> to retrieve the attribute.
-    """
-    def __init__(self, setfunc):
-        self.setfunc = setfunc
-        self.attrname = '_%s' % setfunc.__name__
-
-    def __set__(self, obj, value):
-        self.setfunc(obj, value)
-
-    def __get__(self, obj, cls):
-        assert obj is not None
-        return getattr(obj, self.attrname)
-
-
-class classproperty(object):
-    """this is a simple property-like class but for class attributes.
-    """
-    def __init__(self, get):
-        self.get = get
-    def __get__(self, inst, cls):
-        return self.get(cls)
-
-
-class iclassmethod(object):
-    '''Descriptor for method which should be available as class method if called
-    on the class or instance method if called on an instance.
-    '''
-    def __init__(self, func):
-        self.func = func
-    def __get__(self, instance, objtype):
-        if instance is None:
-            return method_type(self.func, objtype, objtype.__class__)
-        return method_type(self.func, instance, objtype)
-    def __set__(self, instance, value):
-        raise AttributeError("can't set attribute")
-
-
-def timed(f):
-    def wrap(*args, **kwargs):
-        t = time()
-        c = clock()
-        res = f(*args, **kwargs)
-        print '%s clock: %.9f / time: %.9f' % (f.__name__,
-                                               clock() - c, time() - t)
-        return res
-    return wrap
-
-
-def locked(acquire, release):
-    """Decorator taking two methods to acquire/release a lock as argument,
-    returning a decorator function which will call the inner method after
-    having called acquire(self) et will call release(self) afterwards.
-    """
-    def decorator(f):
-        def wrapper(self, *args, **kwargs):
-            acquire(self)
-            try:
-                return f(self, *args, **kwargs)
-            finally:
-                release(self)
-        return wrapper
-    return decorator
-
-
-def monkeypatch(klass, methodname=None):
-    """Decorator extending class with the decorated callable
-    >>> class A:
-    ...     pass
-    >>> @monkeypatch(A)
-    ... def meth(self):
-    ...     return 12
-    ...
-    >>> a = A()
-    >>> a.meth()
-    12
-    >>> @monkeypatch(A, 'foo')
-    ... def meth(self):
-    ...     return 12
-    ...
-    >>> a.foo()
-    12
-    """
-    def decorator(func):
-        try:
-            name = methodname or func.__name__
-        except AttributeError:
-            raise AttributeError('%s has no __name__ attribute: '
-                                 'you should provide an explicit `methodname`'
-                                 % func)
-        if callable(func) and sys.version_info < (3, 0):
-            setattr(klass, name, method_type(func, None, klass))
-        else:
-            # likely a property
-            # this is quite borderline but usage already in the wild ...
-            setattr(klass, name, func)
-        return func
-    return decorator

+ 0 - 130
pylibs/logilab/common/deprecation.py

@@ -1,130 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""Deprecation utilities."""
-
-__docformat__ = "restructuredtext en"
-
-import sys
-from warnings import warn
-
-class class_deprecated(type):
-    """metaclass to print a warning on instantiation of a deprecated class"""
-
-    def __call__(cls, *args, **kwargs):
-        msg = getattr(cls, "__deprecation_warning__",
-                      "%(cls)s is deprecated") % {'cls': cls.__name__}
-        warn(msg, DeprecationWarning, stacklevel=2)
-        return type.__call__(cls, *args, **kwargs)
-
-
-def class_renamed(old_name, new_class, message=None):
-    """automatically creates a class which fires a DeprecationWarning
-    when instantiated.
-
-    >>> Set = class_renamed('Set', set, 'Set is now replaced by set')
-    >>> s = Set()
-    sample.py:57: DeprecationWarning: Set is now replaced by set
-      s = Set()
-    >>>
-    """
-    clsdict = {}
-    if message is None:
-        message = '%s is deprecated, use %s' % (old_name, new_class.__name__)
-    clsdict['__deprecation_warning__'] = message
-    try:
-        # new-style class
-        return class_deprecated(old_name, (new_class,), clsdict)
-    except (NameError, TypeError):
-        # old-style class
-        class DeprecatedClass(new_class):
-            """FIXME: There might be a better way to handle old/new-style class
-            """
-            def __init__(self, *args, **kwargs):
-                warn(message, DeprecationWarning, stacklevel=2)
-                new_class.__init__(self, *args, **kwargs)
-        return DeprecatedClass
-
-
-def class_moved(new_class, old_name=None, message=None):
-    """nice wrapper around class_renamed when a class has been moved into
-    another module
-    """
-    if old_name is None:
-        old_name = new_class.__name__
-    if message is None:
-        message = 'class %s is now available as %s.%s' % (
-            old_name, new_class.__module__, new_class.__name__)
-    return class_renamed(old_name, new_class, message)
-
-def deprecated(reason=None, stacklevel=2, name=None, doc=None):
-    """Decorator that raises a DeprecationWarning to print a message
-    when the decorated function is called.
-    """
-    def deprecated_decorator(func):
-        message = reason or 'The function "%s" is deprecated'
-        if '%s' in message:
-            message = message % func.func_name
-        def wrapped(*args, **kwargs):
-            warn(message, DeprecationWarning, stacklevel=stacklevel)
-            return func(*args, **kwargs)
-        try:
-            wrapped.__name__ = name or func.__name__
-        except TypeError: # readonly attribute in 2.3
-            pass
-        wrapped.__doc__ = doc or func.__doc__
-        return wrapped
-    return deprecated_decorator
-
-def moved(modpath, objname):
-    """use to tell that a callable has been moved to a new module.
-
-    It returns a callable wrapper, so that when its called a warning is printed
-    telling where the object can be found, import is done (and not before) and
-    the actual object is called.
-
-    NOTE: the usage is somewhat limited on classes since it will fail if the
-    wrapper is use in a class ancestors list, use the `class_moved` function
-    instead (which has no lazy import feature though).
-    """
-    def callnew(*args, **kwargs):
-        from logilab.common.modutils import load_module_from_name
-        message = "object %s has been moved to module %s" % (objname, modpath)
-        warn(message, DeprecationWarning, stacklevel=2)
-        m = load_module_from_name(modpath)
-        return getattr(m, objname)(*args, **kwargs)
-    return callnew
-
-
-
-class DeprecationWrapper(object):
-    """proxy to print a warning on access to any attribute of the wrapped object
-    """
-    def __init__(self, proxied, msg=None):
-        self._proxied = proxied
-        self._msg = msg
-
-    def __getattr__(self, attr):
-        warn(self._msg, DeprecationWarning, stacklevel=2)
-        return getattr(self._proxied, attr)
-
-    def __setattr__(self, attr, value):
-        if attr in ('_proxied', '_msg'):
-            self.__dict__[attr] = value
-        else:
-            warn(self._msg, DeprecationWarning, stacklevel=2)
-            setattr(self._proxied, attr, value)

+ 0 - 402
pylibs/logilab/common/fileutils.py

@@ -1,402 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""File and file-path manipulation utilities.
-
-:group path manipulation: first_level_directory, relative_path, is_binary,\
-get_by_ext, remove_dead_links
-:group file manipulation: norm_read, norm_open, lines, stream_lines, lines,\
-write_open_mode, ensure_fs_mode, export
-:sort: path manipulation, file manipulation
-"""
-__docformat__ = "restructuredtext en"
-
-import sys
-import shutil
-import mimetypes
-from os.path import isabs, isdir, islink, split, exists, normpath, join
-from os.path import abspath
-from os import sep, mkdir, remove, listdir, stat, chmod, walk
-from stat import ST_MODE, S_IWRITE
-from cStringIO import StringIO
-
-from logilab.common import STD_BLACKLIST as BASE_BLACKLIST, IGNORED_EXTENSIONS
-from logilab.common.shellutils import find
-from logilab.common.deprecation import deprecated
-from logilab.common.compat import FileIO, any
-
-def first_level_directory(path):
-    """Return the first level directory of a path.
-
-    >>> first_level_directory('home/syt/work')
-    'home'
-    >>> first_level_directory('/home/syt/work')
-    '/'
-    >>> first_level_directory('work')
-    'work'
-    >>>
-
-    :type path: str
-    :param path: the path for which we want the first level directory
-
-    :rtype: str
-    :return: the first level directory appearing in `path`
-    """
-    head, tail = split(path)
-    while head and tail:
-        head, tail = split(head)
-    if tail:
-        return tail
-    # path was absolute, head is the fs root
-    return head
-
-def abspath_listdir(path):
-    """Lists path's content using absolute paths.
-
-    >>> os.listdir('/home')
-    ['adim', 'alf', 'arthur', 'auc']
-    >>> abspath_listdir('/home')
-    ['/home/adim', '/home/alf', '/home/arthur', '/home/auc']
-    """
-    path = abspath(path)
-    return [join(path, filename) for filename in listdir(path)]
-
-
-def is_binary(filename):
-    """Return true if filename may be a binary file, according to it's
-    extension.
-
-    :type filename: str
-    :param filename: the name of the file
-
-    :rtype: bool
-    :return:
-      true if the file is a binary file (actually if it's mime type
-      isn't beginning by text/)
-    """
-    try:
-        return not mimetypes.guess_type(filename)[0].startswith('text')
-    except AttributeError:
-        return 1
-
-
-def write_open_mode(filename):
-    """Return the write mode that should used to open file.
-
-    :type filename: str
-    :param filename: the name of the file
-
-    :rtype: str
-    :return: the mode that should be use to open the file ('w' or 'wb')
-    """
-    if is_binary(filename):
-        return 'wb'
-    return 'w'
-
-
-def ensure_fs_mode(filepath, desired_mode=S_IWRITE):
-    """Check that the given file has the given mode(s) set, else try to
-    set it.
-
-    :type filepath: str
-    :param filepath: path of the file
-
-    :type desired_mode: int
-    :param desired_mode:
-      ORed flags describing the desired mode. Use constants from the
-      `stat` module for file permission's modes
-    """
-    mode = stat(filepath)[ST_MODE]
-    if not mode & desired_mode:
-        chmod(filepath, mode | desired_mode)
-
-
-# XXX (syt) unused? kill?
-class ProtectedFile(FileIO):
-    """A special file-object class that automatically does a 'chmod +w' when
-    needed.
-
-    XXX: for now, the way it is done allows 'normal file-objects' to be
-    created during the ProtectedFile object lifetime.
-    One way to circumvent this would be to chmod / unchmod on each
-    write operation.
-
-    One other way would be to :
-
-    - catch the IOError in the __init__
-
-    - if IOError, then create a StringIO object
-
-    - each write operation writes in this StringIO object
-
-    - on close()/del(), write/append the StringIO content to the file and
-      do the chmod only once
-    """
-    def __init__(self, filepath, mode):
-        self.original_mode = stat(filepath)[ST_MODE]
-        self.mode_changed = False
-        if mode in ('w', 'a', 'wb', 'ab'):
-            if not self.original_mode & S_IWRITE:
-                chmod(filepath, self.original_mode | S_IWRITE)
-                self.mode_changed = True
-        FileIO.__init__(self, filepath, mode)
-
-    def _restore_mode(self):
-        """restores the original mode if needed"""
-        if self.mode_changed:
-            chmod(self.name, self.original_mode)
-            # Don't re-chmod in case of several restore
-            self.mode_changed = False
-
-    def close(self):
-        """restore mode before closing"""
-        self._restore_mode()
-        FileIO.close(self)
-
-    def __del__(self):
-        if not self.closed:
-            self.close()
-
-
-class UnresolvableError(Exception):
-    """Exception raised by relative path when it's unable to compute relative
-    path between two paths.
-    """
-
-def relative_path(from_file, to_file):
-    """Try to get a relative path from `from_file` to `to_file`
-    (path will be absolute if to_file is an absolute file). This function
-    is useful to create link in `from_file` to `to_file`. This typical use
-    case is used in this function description.
-
-    If both files are relative, they're expected to be relative to the same
-    directory.
-
-    >>> relative_path( from_file='toto/index.html', to_file='index.html')
-    '../index.html'
-    >>> relative_path( from_file='index.html', to_file='toto/index.html')
-    'toto/index.html'
-    >>> relative_path( from_file='tutu/index.html', to_file='toto/index.html')
-    '../toto/index.html'
-    >>> relative_path( from_file='toto/index.html', to_file='/index.html')
-    '/index.html'
-    >>> relative_path( from_file='/toto/index.html', to_file='/index.html')
-    '../index.html'
-    >>> relative_path( from_file='/toto/index.html', to_file='/toto/summary.html')
-    'summary.html'
-    >>> relative_path( from_file='index.html', to_file='index.html')
-    ''
-    >>> relative_path( from_file='/index.html', to_file='toto/index.html')
-    Traceback (most recent call last):
-      File "<string>", line 1, in ?
-      File "<stdin>", line 37, in relative_path
-    UnresolvableError
-    >>> relative_path( from_file='/index.html', to_file='/index.html')
-    ''
-    >>>
-
-    :type from_file: str
-    :param from_file: source file (where links will be inserted)
-
-    :type to_file: str
-    :param to_file: target file (on which links point)
-
-    :raise UnresolvableError: if it has been unable to guess a correct path
-
-    :rtype: str
-    :return: the relative path of `to_file` from `from_file`
-    """
-    from_file = normpath(from_file)
-    to_file = normpath(to_file)
-    if from_file == to_file:
-        return ''
-    if isabs(to_file):
-        if not isabs(from_file):
-            return to_file
-    elif isabs(from_file):
-        raise UnresolvableError()
-    from_parts = from_file.split(sep)
-    to_parts = to_file.split(sep)
-    idem = 1
-    result = []
-    while len(from_parts) > 1:
-        dirname = from_parts.pop(0)
-        if idem and len(to_parts) > 1 and dirname == to_parts[0]:
-            to_parts.pop(0)
-        else:
-            idem = 0
-            result.append('..')
-    result += to_parts
-    return sep.join(result)
-
-
-def norm_read(path):
-    """Return the content of the file with normalized line feeds.
-
-    :type path: str
-    :param path: path to the file to read
-
-    :rtype: str
-    :return: the content of the file with normalized line feeds
-    """
-    return open(path, 'U').read()
-norm_read = deprecated("use \"open(path, 'U').read()\"")(norm_read)
-
-def norm_open(path):
-    """Return a stream for a file with content with normalized line feeds.
-
-    :type path: str
-    :param path: path to the file to open
-
-    :rtype: file or StringIO
-    :return: the opened file with normalized line feeds
-    """
-    return open(path, 'U')
-norm_open = deprecated("use \"open(path, 'U')\"")(norm_open)
-
-def lines(path, comments=None):
-    """Return a list of non empty lines in the file located at `path`.
-
-    :type path: str
-    :param path: path to the file
-
-    :type comments: str or None
-    :param comments:
-      optional string which can be used to comment a line in the file
-      (i.e. lines starting with this string won't be returned)
-
-    :rtype: list
-    :return:
-      a list of stripped line in the file, without empty and commented
-      lines
-
-    :warning: at some point this function will probably return an iterator
-    """
-    stream = open(path, 'U')
-    result = stream_lines(stream, comments)
-    stream.close()
-    return result
-
-
-def stream_lines(stream, comments=None):
-    """Return a list of non empty lines in the given `stream`.
-
-    :type stream: object implementing 'xreadlines' or 'readlines'
-    :param stream: file like object
-
-    :type comments: str or None
-    :param comments:
-      optional string which can be used to comment a line in the file
-      (i.e. lines starting with this string won't be returned)
-
-    :rtype: list
-    :return:
-      a list of stripped line in the file, without empty and commented
-      lines
-
-    :warning: at some point this function will probably return an iterator
-    """
-    try:
-        readlines = stream.xreadlines
-    except AttributeError:
-        readlines = stream.readlines
-    result = []
-    for line in readlines():
-        line = line.strip()
-        if line and (comments is None or not line.startswith(comments)):
-            result.append(line)
-    return result
-
-
-def export(from_dir, to_dir,
-           blacklist=BASE_BLACKLIST, ignore_ext=IGNORED_EXTENSIONS,
-           verbose=0):
-    """Make a mirror of `from_dir` in `to_dir`, omitting directories and
-    files listed in the black list or ending with one of the given
-    extensions.
-
-    :type from_dir: str
-    :param from_dir: directory to export
-
-    :type to_dir: str
-    :param to_dir: destination directory
-
-    :type blacklist: list or tuple
-    :param blacklist:
-      list of files or directories to ignore, default to the content of
-      `BASE_BLACKLIST`
-
-    :type ignore_ext: list or tuple
-    :param ignore_ext:
-      list of extensions to ignore, default to  the content of
-      `IGNORED_EXTENSIONS`
-
-    :type verbose: bool
-    :param verbose:
-      flag indicating whether information about exported files should be
-      printed to stderr, default to False
-    """
-    try:
-        mkdir(to_dir)
-    except OSError:
-        pass # FIXME we should use "exists" if the point is about existing dir
-             # else (permission problems?) shouldn't return / raise ?
-    for directory, dirnames, filenames in walk(from_dir):
-        for norecurs in blacklist:
-            try:
-                dirnames.remove(norecurs)
-            except ValueError:
-                continue
-        for dirname in dirnames:
-            src = join(directory, dirname)
-            dest = to_dir + src[len(from_dir):]
-            if isdir(src):
-                if not exists(dest):
-                    mkdir(dest)
-        for filename in filenames:
-            # don't include binary files
-            # endswith does not accept tuple in 2.4
-            if any([filename.endswith(ext) for ext in ignore_ext]):
-                continue
-            src = join(directory, filename)
-            dest = to_dir + src[len(from_dir):]
-            if verbose:
-                print >> sys.stderr, src, '->', dest
-            if exists(dest):
-                remove(dest)
-            shutil.copy2(src, dest)
-
-
-def remove_dead_links(directory, verbose=0):
-    """Recursively traverse directory and remove all dead links.
-
-    :type directory: str
-    :param directory: directory to cleanup
-
-    :type verbose: bool
-    :param verbose:
-      flag indicating whether information about deleted links should be
-      printed to stderr, default to False
-    """
-    for dirpath, dirname, filenames in walk(directory):
-        for filename in dirnames + filenames:
-            src = join(dirpath, filename)
-            if islink(src) and not exists(src):
-                if verbose:
-                    print 'remove dead link', src
-                remove(src)
-

+ 0 - 273
pylibs/logilab/common/graph.py

@@ -1,273 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""Graph manipulation utilities.
-
-(dot generation adapted from pypy/translator/tool/make_dot.py)
-"""
-
-__docformat__ = "restructuredtext en"
-
-__metaclass__ = type
-
-import os.path as osp
-import os
-import sys
-import tempfile
-from logilab.common.compat import str_encode
-
-def escape(value):
-    """Make <value> usable in a dot file."""
-    lines = [line.replace('"', '\\"') for line in value.split('\n')]
-    data = '\\l'.join(lines)
-    return '\\n' + data
-
-def target_info_from_filename(filename):
-    """Transforms /some/path/foo.png into ('/some/path', 'foo.png', 'png')."""
-    basename = osp.basename(filename)
-    storedir = osp.dirname(osp.abspath(filename))
-    target = filename.split('.')[-1]
-    return storedir, basename, target
-
-
-class DotBackend:
-    """Dot File backend."""
-    def __init__(self, graphname, rankdir=None, size=None, ratio=None,
-            charset='utf-8', renderer='dot', additionnal_param={}):
-        self.graphname = graphname
-        self.renderer = renderer
-        self.lines = []
-        self._source = None
-        self.emit("digraph %s {" % normalize_node_id(graphname))
-        if rankdir:
-            self.emit('rankdir=%s' % rankdir)
-        if ratio:
-            self.emit('ratio=%s' % ratio)
-        if size:
-            self.emit('size="%s"' % size)
-        if charset:
-            assert charset.lower() in ('utf-8', 'iso-8859-1', 'latin1'), \
-                   'unsupported charset %s' % charset
-            self.emit('charset="%s"' % charset)
-        for param in additionnal_param.iteritems():
-            self.emit('='.join(param))
-
-    def get_source(self):
-        """returns self._source"""
-        if self._source is None:
-            self.emit("}\n")
-            self._source = '\n'.join(self.lines)
-            del self.lines
-        return self._source
-
-    source = property(get_source)
-
-    def generate(self, outputfile=None, dotfile=None, mapfile=None):
-        """Generates a graph file.
-
-        :param outputfile: filename and path [defaults to graphname.png]
-        :param dotfile: filename and path [defaults to graphname.dot]
-
-        :rtype: str
-        :return: a path to the generated file
-        """
-        import subprocess # introduced in py 2.4
-        name = self.graphname
-        if not dotfile:
-            # if 'outputfile' is a dot file use it as 'dotfile'
-            if outputfile and outputfile.endswith(".dot"):
-                dotfile = outputfile
-            else:
-                dotfile = '%s.dot' % name
-        if outputfile is not None:
-            storedir, basename, target = target_info_from_filename(outputfile)
-            if target != "dot":
-                pdot, dot_sourcepath = tempfile.mkstemp(".dot", name)
-                os.close(pdot)
-            else:
-                dot_sourcepath = osp.join(storedir, dotfile)
-        else:
-            target = 'png'
-            pdot, dot_sourcepath = tempfile.mkstemp(".dot", name)
-            ppng, outputfile = tempfile.mkstemp(".png", name)
-            os.close(pdot)
-            os.close(ppng)
-        pdot = open(dot_sourcepath, 'w')
-        pdot.write(str_encode(self.source, 'utf8'))
-        pdot.close()
-        if target != 'dot':
-            if sys.platform == 'win32':
-                use_shell = True
-            else:
-                use_shell = False
-            if mapfile:
-                subprocess.call([self.renderer,  '-Tcmapx', '-o', mapfile, '-T', target, dot_sourcepath, '-o', outputfile],
-                                shell=use_shell)
-            else:
-                subprocess.call([self.renderer, '-T',  target,
-                                 dot_sourcepath, '-o',  outputfile],
-                                shell=use_shell)
-            os.unlink(dot_sourcepath)
-        return outputfile
-
-    def emit(self, line):
-        """Adds <line> to final output."""
-        self.lines.append(line)
-
-    def emit_edge(self, name1, name2, **props):
-        """emit an edge from <name1> to <name2>.
-        edge properties: see http://www.graphviz.org/doc/info/attrs.html
-        """
-        attrs = ['%s="%s"' % (prop, value) for prop, value in props.items()]
-        n_from, n_to = normalize_node_id(name1), normalize_node_id(name2)
-        self.emit('%s -> %s [%s];' % (n_from, n_to, ", ".join(attrs)) )
-
-    def emit_node(self, name, **props):
-        """emit a node with given properties.
-        node properties: see http://www.graphviz.org/doc/info/attrs.html
-        """
-        attrs = ['%s="%s"' % (prop, value) for prop, value in props.items()]
-        self.emit('%s [%s];' % (normalize_node_id(name), ", ".join(attrs)))
-
-def normalize_node_id(nid):
-    """Returns a suitable DOT node id for `nid`."""
-    return '"%s"' % nid
-
-class GraphGenerator:
-    def __init__(self, backend):
-        # the backend is responsible to output the graph in a particular format
-        self.backend = backend
-
-    # XXX doesn't like space in outpufile / mapfile
-    def generate(self, visitor, propshdlr, outputfile=None, mapfile=None):
-        # the visitor
-        # the property handler is used to get node and edge properties
-        # according to the graph and to the backend
-        self.propshdlr = propshdlr
-        for nodeid, node in visitor.nodes():
-            props = propshdlr.node_properties(node)
-            self.backend.emit_node(nodeid, **props)
-        for subjnode, objnode, edge in visitor.edges():
-            props = propshdlr.edge_properties(edge, subjnode, objnode)
-            self.backend.emit_edge(subjnode, objnode, **props)
-        return self.backend.generate(outputfile=outputfile, mapfile=mapfile)
-
-
-class UnorderableGraph(Exception):
-    pass
-
-def ordered_nodes(graph):
-    """takes a dependency graph dict as arguments and return an ordered tuple of
-    nodes starting with nodes without dependencies and up to the outermost node.
-
-    If there is some cycle in the graph, :exc:`UnorderableGraph` will be raised.
-
-    Also the given graph dict will be emptied.
-    """
-    # check graph consistency
-    cycles = get_cycles(graph)
-    if cycles:
-        cycles = '\n'.join([' -> '.join(cycle) for cycle in cycles])
-        raise UnorderableGraph('cycles in graph: %s' % cycles)
-    vertices = set(graph)
-    to_vertices = set()
-    for edges in graph.values():
-        to_vertices |= set(edges)
-    missing_vertices = to_vertices - vertices
-    if missing_vertices:
-        raise UnorderableGraph('missing vertices: %s' % ', '.join(missing_vertices))
-    # order vertices
-    order = []
-    order_set = set()
-    old_len = None
-    while graph:
-        if old_len == len(graph):
-            raise UnorderableGraph('unknown problem with %s' % graph)
-        old_len = len(graph)
-        deps_ok = []
-        for node, node_deps in graph.items():
-            for dep in node_deps:
-                if dep not in order_set:
-                    break
-            else:
-                deps_ok.append(node)
-        order.append(deps_ok)
-        order_set |= set(deps_ok)
-        for node in deps_ok:
-            del graph[node]
-    result = []
-    for grp in reversed(order):
-        result.extend(sorted(grp))
-    return tuple(result)
-
-
-def get_cycles(graph_dict, vertices=None):
-    '''given a dictionary representing an ordered graph (i.e. key are vertices
-    and values is a list of destination vertices representing edges), return a
-    list of detected cycles
-    '''
-    if not graph_dict:
-        return ()
-    result = []
-    if vertices is None:
-        vertices = graph_dict.keys()
-    for vertice in vertices:
-        _get_cycles(graph_dict, vertice, [], result)
-    return result
-
-def _get_cycles(graph_dict, vertice=None, path=None, result=None):
-    """recursive function doing the real work for get_cycles"""
-    if vertice in path:
-        cycle = [vertice]
-        for node in path[::-1]:
-            if node == vertice:
-                break
-            cycle.insert(0, node)
-        # make a canonical representation
-        start_from = min(cycle)
-        index = cycle.index(start_from)
-        cycle = cycle[index:] + cycle[0:index]
-        # append it to result if not already in
-        if not cycle in result:
-            result.append(cycle)
-        return
-    path.append(vertice)
-    try:
-        for node in graph_dict[vertice]:
-            _get_cycles(graph_dict, node, path, result)
-    except KeyError:
-        pass
-    path.pop()
-
-def has_path(graph_dict, fromnode, tonode, path=None):
-    """generic function taking a simple graph definition as a dictionary, with
-    node has key associated to a list of nodes directly reachable from it.
-
-    Return None if no path exists to go from `fromnode` to `tonode`, else the
-    first path found (as a list including the destination node at last)
-    """
-    if path is None:
-        path = []
-    elif fromnode in path:
-        return None
-    path.append(fromnode)
-    for destnode in graph_dict[fromnode]:
-        if destnode == tonode or has_path(graph_dict, destnode, tonode, path):
-            return path[1:] + [tonode]
-    path.pop()
-    return None
-

+ 0 - 130
pylibs/logilab/common/hg.py

@@ -1,130 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""mercurial utilities (mercurial should be installed)"""
-
-__docformat__ = "restructuredtext en"
-
-import os
-import sys
-import os.path as osp
-
-try:
-    from mercurial.error import RepoError
-    from mercurial.__version__ import version as hg_version
-except ImportError:
-    from mercurial.repo import RepoError
-    from mercurial.version import get_version
-    hg_version = get_version()
-
-from mercurial.hg import repository as Repository
-from mercurial.ui import ui as Ui
-from mercurial.node import short
-try:
-    # mercurial >= 1.2 (?)
-    from mercurial.cmdutil import walkchangerevs
-except ImportError, ex:
-    from mercurial.commands import walkchangerevs
-try:
-    # mercurial >= 1.1 (.1?)
-    from mercurial.util import cachefunc
-except ImportError, ex:
-    def cachefunc(func):
-        return func
-try:
-    # mercurial >= 1.3.1
-    from mercurial import encoding
-    _encoding = encoding.encoding
-except ImportError:
-    try:
-        from mercurial.util import _encoding
-    except ImportError:
-        import locale
-        # stay compatible with mercurial 0.9.1 (etch debian release)
-        # (borrowed from mercurial.util 1.1.2)
-        try:
-            _encoding = os.environ.get("HGENCODING")
-            if sys.platform == 'darwin' and not _encoding:
-                # On darwin, getpreferredencoding ignores the locale environment and
-                # always returns mac-roman. We override this if the environment is
-                # not C (has been customized by the user).
-                locale.setlocale(locale.LC_CTYPE, '')
-                _encoding = locale.getlocale()[1]
-            if not _encoding:
-                _encoding = locale.getpreferredencoding() or 'ascii'
-        except locale.Error:
-            _encoding = 'ascii'
-try:
-    # demandimport causes problems when activated, ensure it isn't
-    # XXX put this in apycot where the pb has been noticed?
-    from mercurial import demandimport
-    demandimport.disable()
-except:
-    pass
-
-Ui.warn = lambda *args, **kwargs: 0 # make it quiet
-
-def find_repository(path):
-    """returns <path>'s mercurial repository
-
-    None if <path> is not under hg control
-    """
-    path = osp.realpath(osp.abspath(path))
-    while not osp.isdir(osp.join(path, ".hg")):
-        oldpath = path
-        path = osp.dirname(path)
-        if path == oldpath:
-            return None
-    return path
-
-
-def get_repository(path):
-    """Simple function that open a hg repository"""
-    repopath = find_repository(path)
-    if repopath is None:
-        raise RuntimeError('no repository found in %s' % osp.abspath(path))
-    return Repository(Ui(), path=repopath)
-
-def incoming(wdrepo, masterrepo):
-    try:
-        return wdrepo.findincoming(masterrepo)
-    except AttributeError:
-        from mercurial import hg, discovery
-        revs, checkout = hg.addbranchrevs(wdrepo, masterrepo, ('', []), None)
-        common, incoming, rheads = discovery.findcommonincoming(
-            wdrepo, masterrepo, heads=revs)
-        if not masterrepo.local():
-            from mercurial import bundlerepo, changegroup
-            if revs is None and masterrepo.capable('changegroupsubset'):
-                revs = rheads
-            if revs is None:
-                cg = masterrepo.changegroup(incoming, "incoming")
-            else:
-                cg = masterrepo.changegroupsubset(incoming, revs, 'incoming')
-            fname = changegroup.writebundle(cg, None, "HG10UN")
-            # use the created uncompressed bundlerepo
-            masterrepo = bundlerepo.bundlerepository(wdrepo.ui, wdrepo.root, fname)
-        return masterrepo.changelog.nodesbetween(incoming, revs)[0]
-
-def outgoing(wdrepo, masterrepo):
-    try:
-        return wdrepo.findoutgoing(masterrepo)
-    except AttributeError:
-        from mercurial import hg, discovery
-        revs, checkout = hg.addbranchrevs(wdrepo, wdrepo, ('', []), None)
-        o = discovery.findoutgoing(wdrepo, masterrepo)
-        return wdrepo.changelog.nodesbetween(o, revs)[0]

+ 0 - 71
pylibs/logilab/common/interface.py

@@ -1,71 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""Bases class for interfaces to provide 'light' interface handling.
-
- TODO:
-  _ implements a check method which check that an object implements the
-    interface
-  _ Attribute objects
-
-  This module requires at least python 2.2
-"""
-__docformat__ = "restructuredtext en"
-
-
-class Interface(object):
-    """Base class for interfaces."""
-    def is_implemented_by(cls, instance):
-        return implements(instance, cls)
-    is_implemented_by = classmethod(is_implemented_by)
-
-
-def implements(obj, interface):
-    """Return true if the give object (maybe an instance or class) implements
-    the interface.
-    """
-    kimplements = getattr(obj, '__implements__', ())
-    if not isinstance(kimplements, (list, tuple)):
-        kimplements = (kimplements,)
-    for implementedinterface in kimplements:
-        if issubclass(implementedinterface, interface):
-            return True
-    return False
-
-
-def extend(klass, interface, _recurs=False):
-    """Add interface to klass'__implements__ if not already implemented in.
-
-    If klass is subclassed, ensure subclasses __implements__ it as well.
-
-    NOTE: klass should be e new class.
-    """
-    if not implements(klass, interface):
-        try:
-            kimplements = klass.__implements__
-            kimplementsklass = type(kimplements)
-            kimplements = list(kimplements)
-        except AttributeError:
-            kimplementsklass = tuple
-            kimplements = []
-        kimplements.append(interface)
-        klass.__implements__ = kimplementsklass(kimplements)
-        for subklass in klass.__subclasses__():
-            extend(subklass, interface, _recurs=True)
-    elif _recurs:
-        for subklass in klass.__subclasses__():
-            extend(subklass, interface, _recurs=True)

+ 0 - 178
pylibs/logilab/common/logging_ext.py

@@ -1,178 +0,0 @@
-# -*- coding: utf-8 -*-
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""Extends the logging module from the standard library."""
-
-__docformat__ = "restructuredtext en"
-
-import os
-import sys
-import logging
-
-from logilab.common.textutils import colorize_ansi
-
-
-def set_log_methods(cls, logger):
-    """bind standard logger's methods as methods on the class"""
-    cls.__logger = logger
-    for attr in ('debug', 'info', 'warning', 'error', 'critical', 'exception'):
-        setattr(cls, attr, getattr(logger, attr))
-
-
-def xxx_cyan(record):
-    if 'XXX' in record.message:
-        return 'cyan'
-
-class ColorFormatter(logging.Formatter):
-    """
-    A color Formatter for the logging standard module.
-
-    By default, colorize CRITICAL and ERROR in red, WARNING in orange, INFO in
-    green and DEBUG in yellow.
-
-    self.colors is customizable via the 'color' constructor argument (dictionary).
-
-    self.colorfilters is a list of functions that get the LogRecord
-    and return a color name or None.
-    """
-
-    def __init__(self, fmt=None, datefmt=None, colors=None):
-        logging.Formatter.__init__(self, fmt, datefmt)
-        self.colorfilters = []
-        self.colors = {'CRITICAL': 'red',
-                       'ERROR': 'red',
-                       'WARNING': 'magenta',
-                       'INFO': 'green',
-                       'DEBUG': 'yellow',
-                       }
-        if colors is not None:
-            assert isinstance(colors, dict)
-            self.colors.update(colors)
-
-    def format(self, record):
-        msg = logging.Formatter.format(self, record)
-        if record.levelname in self.colors:
-            color = self.colors[record.levelname]
-            return colorize_ansi(msg, color)
-        else:
-            for cf in self.colorfilters:
-                color = cf(record)
-                if color:
-                    return colorize_ansi(msg, color)
-        return msg
-
-def set_color_formatter(logger=None, **kw):
-    """
-    Install a color formatter on the 'logger'. If not given, it will
-    defaults to the default logger.
-
-    Any additional keyword will be passed as-is to the ColorFormatter
-    constructor.
-    """
-    if logger is None:
-        logger = logging.getLogger()
-        if not logger.handlers:
-            logging.basicConfig()
-    format_msg = logger.handlers[0].formatter._fmt
-    fmt = ColorFormatter(format_msg, **kw)
-    fmt.colorfilters.append(xxx_cyan)
-    logger.handlers[0].setFormatter(fmt)
-
-
-LOG_FORMAT = '%(asctime)s - (%(name)s) %(levelname)s: %(message)s'
-LOG_DATE_FORMAT = '%Y-%m-%d %H:%M:%S'
-
-def get_handler(debug=False, syslog=False, logfile=None, rotation_parameters=None):
-    """get an apropriate handler according to given parameters"""
-    if os.environ.get('APYCOT_ROOT'):
-        handler = logging.StreamHandler(sys.stdout)
-    if debug:
-        handler = logging.StreamHandler()
-    elif logfile is None:
-        if syslog:
-            from logging import handlers
-            handler = handlers.SysLogHandler()
-        else:
-            handler = logging.StreamHandler()
-    else:
-        try:
-            if rotation_parameters is None:
-                handler = logging.FileHandler(logfile)
-            else:
-                from logging.handlers import TimedRotatingFileHandler
-                handler = TimedRotatingFileHandler(
-                    logfile, **rotation_parameters)
-        except IOError:
-            handler = logging.StreamHandler()
-    return handler
-
-def get_threshold(debug=False, logthreshold=None):
-    if logthreshold is None:
-        if debug:
-            logthreshold = logging.DEBUG
-        else:
-            logthreshold = logging.ERROR
-    elif isinstance(logthreshold, basestring):
-        logthreshold = getattr(logging, THRESHOLD_MAP.get(logthreshold,
-                                                          logthreshold))
-    return logthreshold
-
-def get_formatter(logformat=LOG_FORMAT, logdateformat=LOG_DATE_FORMAT):
-    isatty = hasattr(sys.__stdout__, 'isatty') and sys.__stdout__.isatty()
-    if isatty and sys.platform != 'win32':
-        fmt = ColorFormatter(logformat, logdateformat)
-        def col_fact(record):
-            if 'XXX' in record.message:
-                return 'cyan'
-            if 'kick' in record.message:
-                return 'red'
-        fmt.colorfilters.append(col_fact)
-    else:
-        fmt = logging.Formatter(logformat, logdateformat)
-    return fmt
-
-def init_log(debug=False, syslog=False, logthreshold=None, logfile=None,
-             logformat=LOG_FORMAT, logdateformat=LOG_DATE_FORMAT, fmt=None,
-             rotation_parameters=None, handler=None):
-    """init the log service"""
-    logger = logging.getLogger()
-    if handler is None:
-        handler = get_handler(debug, syslog, logfile, rotation_parameters)
-    # only addHandler and removeHandler method while I would like a setHandler
-    # method, so do it this way :$
-    logger.handlers = [handler]
-    logthreshold = get_threshold(debug, logthreshold)
-    logger.setLevel(logthreshold)
-    if fmt is None:
-        if debug:
-            fmt = get_formatter(logformat=logformat, logdateformat=logdateformat)
-        else:
-            fmt = logging.Formatter(logformat, logdateformat)
-    handler.setFormatter(fmt)
-    return handler
-
-# map logilab.common.logger thresholds to logging thresholds
-THRESHOLD_MAP = {'LOG_DEBUG':   'DEBUG',
-                 'LOG_INFO':    'INFO',
-                 'LOG_NOTICE':  'INFO',
-                 'LOG_WARN':    'WARNING',
-                 'LOG_WARNING': 'WARNING',
-                 'LOG_ERR':     'ERROR',
-                 'LOG_ERROR':   'ERROR',
-                 'LOG_CRIT':    'CRITICAL',
-                 }

+ 0 - 653
pylibs/logilab/common/modutils.py

@@ -1,653 +0,0 @@
-# -*- coding: utf-8 -*-
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""Python modules manipulation utility functions.
-
-:type PY_SOURCE_EXTS: tuple(str)
-:var PY_SOURCE_EXTS: list of possible python source file extension
-
-:type STD_LIB_DIR: str
-:var STD_LIB_DIR: directory where standard modules are located
-
-:type BUILTIN_MODULES: dict
-:var BUILTIN_MODULES: dictionary with builtin module names has key
-"""
-__docformat__ = "restructuredtext en"
-
-import sys
-import os
-from os.path import splitext, join, abspath, isdir, dirname, exists, basename
-from imp import find_module, load_module, C_BUILTIN, PY_COMPILED, PKG_DIRECTORY
-from distutils.sysconfig import get_config_var, get_python_lib, get_python_version
-
-try:
-    import zipimport
-except ImportError:
-    zipimport = None
-
-ZIPFILE = object()
-
-from logilab.common import STD_BLACKLIST, _handle_blacklist
-
-# Notes about STD_LIB_DIR
-# Consider arch-specific installation for STD_LIB_DIR definition
-# :mod:`distutils.sysconfig` contains to much hardcoded values to rely on
-#
-# :see: `Problems with /usr/lib64 builds <http://bugs.python.org/issue1294959>`_
-# :see: `FHS <http://www.pathname.com/fhs/pub/fhs-2.3.html#LIBLTQUALGTALTERNATEFORMATESSENTIAL>`_
-if sys.platform.startswith('win'):
-    PY_SOURCE_EXTS = ('py', 'pyw')
-    PY_COMPILED_EXTS = ('dll', 'pyd')
-    STD_LIB_DIR = get_python_lib(standard_lib=1)
-else:
-    PY_SOURCE_EXTS = ('py',)
-    PY_COMPILED_EXTS = ('so',)
-    # extend lib dir with some arch-dependant paths
-    STD_LIB_DIR = join(get_config_var("LIBDIR"), "python%s" % get_python_version())
-
-BUILTIN_MODULES = dict(zip(sys.builtin_module_names,
-                           [1]*len(sys.builtin_module_names)))
-
-
-class NoSourceFile(Exception):
-    """exception raised when we are not able to get a python
-    source file for a precompiled file
-    """
-
-class LazyObject(object):
-    def __init__(self, module, obj):
-        self.module = module
-        self.obj = obj
-        self._imported = None
-
-    def _getobj(self):
-        if self._imported is None:
-           self._imported = getattr(load_module_from_name(self.module),
-                                    self.obj)
-        return self._imported
-
-    def __getattribute__(self, attr):
-        try:
-            return super(LazyObject, self).__getattribute__(attr)
-        except AttributeError, ex:
-            return getattr(self._getobj(), attr)
-
-    def __call__(self, *args, **kwargs):
-        return self._getobj()(*args, **kwargs)
-
-
-def load_module_from_name(dotted_name, path=None, use_sys=1):
-    """Load a Python module from its name.
-
-    :type dotted_name: str
-    :param dotted_name: python name of a module or package
-
-    :type path: list or None
-    :param path:
-      optional list of path where the module or package should be
-      searched (use sys.path if nothing or None is given)
-
-    :type use_sys: bool
-    :param use_sys:
-      boolean indicating whether the sys.modules dictionary should be
-      used or not
-
-
-    :raise ImportError: if the module or package is not found
-
-    :rtype: module
-    :return: the loaded module
-    """
-    return load_module_from_modpath(dotted_name.split('.'), path, use_sys)
-
-
-def load_module_from_modpath(parts, path=None, use_sys=1):
-    """Load a python module from its splitted name.
-
-    :type parts: list(str) or tuple(str)
-    :param parts:
-      python name of a module or package splitted on '.'
-
-    :type path: list or None
-    :param path:
-      optional list of path where the module or package should be
-      searched (use sys.path if nothing or None is given)
-
-    :type use_sys: bool
-    :param use_sys:
-      boolean indicating whether the sys.modules dictionary should be used or not
-
-    :raise ImportError: if the module or package is not found
-
-    :rtype: module
-    :return: the loaded module
-    """
-    if use_sys:
-        try:
-            return sys.modules['.'.join(parts)]
-        except KeyError:
-            pass
-    modpath = []
-    prevmodule = None
-    for part in parts:
-        modpath.append(part)
-        curname = '.'.join(modpath)
-        module = None
-        if len(modpath) != len(parts):
-            # even with use_sys=False, should try to get outer packages from sys.modules
-            module = sys.modules.get(curname)
-        if module is None:
-            mp_file, mp_filename, mp_desc = find_module(part, path)
-            module = load_module(curname, mp_file, mp_filename, mp_desc)
-        if prevmodule:
-            setattr(prevmodule, part, module)
-        _file = getattr(module, '__file__', '')
-        if not _file and len(modpath) != len(parts):
-            raise ImportError('no module in %s' % '.'.join(parts[len(modpath):]) )
-        path = [dirname( _file )]
-        prevmodule = module
-    return module
-
-
-def load_module_from_file(filepath, path=None, use_sys=1, extrapath=None):
-    """Load a Python module from it's path.
-
-    :type filepath: str
-    :param filepath: path to the python module or package
-
-    :type path: list or None
-    :param path:
-      optional list of path where the module or package should be
-      searched (use sys.path if nothing or None is given)
-
-    :type use_sys: bool
-    :param use_sys:
-      boolean indicating whether the sys.modules dictionary should be
-      used or not
-
-
-    :raise ImportError: if the module or package is not found
-
-    :rtype: module
-    :return: the loaded module
-    """
-    modpath = modpath_from_file(filepath, extrapath)
-    return load_module_from_modpath(modpath, path, use_sys)
-
-
-def _check_init(path, mod_path):
-    """check there are some __init__.py all along the way"""
-    for part in mod_path:
-        path = join(path, part)
-        if not _has_init(path):
-            return False
-    return True
-
-
-def modpath_from_file(filename, extrapath=None):
-    """given a file path return the corresponding splitted module's name
-    (i.e name of a module or package splitted on '.')
-
-    :type filename: str
-    :param filename: file's path for which we want the module's name
-
-    :type extrapath: dict
-    :param extrapath:
-      optional extra search path, with path as key and package name for the path
-      as value. This is usually useful to handle package splitted in multiple
-      directories using __path__ trick.
-
-
-    :raise ImportError:
-      if the corresponding module's name has not been found
-
-    :rtype: list(str)
-    :return: the corresponding splitted module's name
-    """
-    base = splitext(abspath(filename))[0]
-    if extrapath is not None:
-        for path_ in extrapath:
-            path = abspath(path_)
-            if path and base[:len(path)] == path:
-                submodpath = [pkg for pkg in base[len(path):].split(os.sep)
-                              if pkg]
-                if _check_init(path, submodpath[:-1]):
-                    return extrapath[path_].split('.') + submodpath
-    for path in sys.path:
-        path = abspath(path)
-        if path and base[:len(path)] == path:
-            if filename.find('site-packages') != -1 and \
-                   path.find('site-packages') == -1:
-                continue
-            modpath = [pkg for pkg in base[len(path):].split(os.sep) if pkg]
-            if _check_init(path, modpath[:-1]):
-                return modpath
-    raise ImportError('Unable to find module for %s in %s' % (
-        filename, ', \n'.join(sys.path)))
-
-
-
-def file_from_modpath(modpath, path=None, context_file=None):
-    """given a mod path (i.e. splitted module / package name), return the
-    corresponding file, giving priority to source file over precompiled
-    file if it exists
-
-    :type modpath: list or tuple
-    :param modpath:
-      splitted module's name (i.e name of a module or package splitted
-      on '.')
-      (this means explicit relative imports that start with dots have
-      empty strings in this list!)
-
-    :type path: list or None
-    :param path:
-      optional list of path where the module or package should be
-      searched (use sys.path if nothing or None is given)
-
-    :type context_file: str or None
-    :param context_file:
-      context file to consider, necessary if the identifier has been
-      introduced using a relative import unresolvable in the actual
-      context (i.e. modutils)
-
-    :raise ImportError: if there is no such module in the directory
-
-    :rtype: str or None
-    :return:
-      the path to the module's file or None if it's an integrated
-      builtin module such as 'sys'
-    """
-    if context_file is not None:
-        context = dirname(context_file)
-    else:
-        context = context_file
-    if modpath[0] == 'xml':
-        # handle _xmlplus
-        try:
-            return _file_from_modpath(['_xmlplus'] + modpath[1:], path, context)
-        except ImportError:
-            return _file_from_modpath(modpath, path, context)
-    elif modpath == ['os', 'path']:
-        # FIXME: currently ignoring search_path...
-        return os.path.__file__
-    return _file_from_modpath(modpath, path, context)
-
-
-
-def get_module_part(dotted_name, context_file=None):
-    """given a dotted name return the module part of the name :
-
-    >>> get_module_part('logilab.common.modutils.get_module_part')
-    'logilab.common.modutils'
-
-    :type dotted_name: str
-    :param dotted_name: full name of the identifier we are interested in
-
-    :type context_file: str or None
-    :param context_file:
-      context file to consider, necessary if the identifier has been
-      introduced using a relative import unresolvable in the actual
-      context (i.e. modutils)
-
-
-    :raise ImportError: if there is no such module in the directory
-
-    :rtype: str or None
-    :return:
-      the module part of the name or None if we have not been able at
-      all to import the given name
-
-    XXX: deprecated, since it doesn't handle package precedence over module
-    (see #10066)
-    """
-    # os.path trick
-    if dotted_name.startswith('os.path'):
-        return 'os.path'
-    parts = dotted_name.split('.')
-    if context_file is not None:
-        # first check for builtin module which won't be considered latter
-        # in that case (path != None)
-        if parts[0] in BUILTIN_MODULES:
-            if len(parts) > 2:
-                raise ImportError(dotted_name)
-            return parts[0]
-        # don't use += or insert, we want a new list to be created !
-    path = None
-    starti = 0
-    if parts[0] == '':
-        assert context_file is not None, \
-                'explicit relative import, but no context_file?'
-        path = [] # prevent resolving the import non-relatively
-        starti = 1
-    while parts[starti] == '': # for all further dots: change context
-        starti += 1
-        context_file = dirname(context_file)
-    for i in range(starti, len(parts)):
-        try:
-            file_from_modpath(parts[starti:i+1],
-                    path=path, context_file=context_file)
-        except ImportError:
-            if not i >= max(1, len(parts) - 2):
-                raise
-            return '.'.join(parts[:i])
-    return dotted_name
-
-
-def get_modules(package, src_directory, blacklist=STD_BLACKLIST):
-    """given a package directory return a list of all available python
-    modules in the package and its subpackages
-
-    :type package: str
-    :param package: the python name for the package
-
-    :type src_directory: str
-    :param src_directory:
-      path of the directory corresponding to the package
-
-    :type blacklist: list or tuple
-    :param blacklist:
-      optional list of files or directory to ignore, default to
-      the value of `logilab.common.STD_BLACKLIST`
-
-    :rtype: list
-    :return:
-      the list of all available python modules in the package and its
-      subpackages
-    """
-    modules = []
-    for directory, dirnames, filenames in os.walk(src_directory):
-        _handle_blacklist(blacklist, dirnames, filenames)
-        # check for __init__.py
-        if not '__init__.py' in filenames:
-            dirnames[:] = ()
-            continue
-        if directory != src_directory:
-            dir_package = directory[len(src_directory):].replace(os.sep, '.')
-            modules.append(package + dir_package)
-        for filename in filenames:
-            if _is_python_file(filename) and filename != '__init__.py':
-                src = join(directory, filename)
-                module = package + src[len(src_directory):-3]
-                modules.append(module.replace(os.sep, '.'))
-    return modules
-
-
-
-def get_module_files(src_directory, blacklist=STD_BLACKLIST):
-    """given a package directory return a list of all available python
-    module's files in the package and its subpackages
-
-    :type src_directory: str
-    :param src_directory:
-      path of the directory corresponding to the package
-
-    :type blacklist: list or tuple
-    :param blacklist:
-      optional list of files or directory to ignore, default to the value of
-      `logilab.common.STD_BLACKLIST`
-
-    :rtype: list
-    :return:
-      the list of all available python module's files in the package and
-      its subpackages
-    """
-    files = []
-    for directory, dirnames, filenames in os.walk(src_directory):
-        _handle_blacklist(blacklist, dirnames, filenames)
-        # check for __init__.py
-        if not '__init__.py' in filenames:
-            dirnames[:] = ()
-            continue
-        for filename in filenames:
-            if _is_python_file(filename):
-                src = join(directory, filename)
-                files.append(src)
-    return files
-
-
-def get_source_file(filename, include_no_ext=False):
-    """given a python module's file name return the matching source file
-    name (the filename will be returned identically if it's a already an
-    absolute path to a python source file...)
-
-    :type filename: str
-    :param filename: python module's file name
-
-
-    :raise NoSourceFile: if no source file exists on the file system
-
-    :rtype: str
-    :return: the absolute path of the source file if it exists
-    """
-    base, orig_ext = splitext(abspath(filename))
-    for ext in PY_SOURCE_EXTS:
-        source_path = '%s.%s' % (base, ext)
-        if exists(source_path):
-            return source_path
-    if include_no_ext and not orig_ext and exists(base):
-        return base
-    raise NoSourceFile(filename)
-
-
-def cleanup_sys_modules(directories):
-    """remove submodules of `directories` from `sys.modules`"""
-    for modname, module in sys.modules.items():
-        modfile = getattr(module, '__file__', None)
-        if modfile:
-            for directory in directories:
-                if modfile.startswith(directory):
-                    del sys.modules[modname]
-                    break
-
-
-def is_python_source(filename):
-    """
-    rtype: bool
-    return: True if the filename is a python source file
-    """
-    return splitext(filename)[1][1:] in PY_SOURCE_EXTS
-
-
-
-def is_standard_module(modname, std_path=(STD_LIB_DIR,)):
-    """try to guess if a module is a standard python module (by default,
-    see `std_path` parameter's description)
-
-    :type modname: str
-    :param modname: name of the module we are interested in
-
-    :type std_path: list(str) or tuple(str)
-    :param std_path: list of path considered has standard
-
-
-    :rtype: bool
-    :return:
-      true if the module:
-      - is located on the path listed in one of the directory in `std_path`
-      - is a built-in module
-    """
-    modname = modname.split('.')[0]
-    try:
-        filename = file_from_modpath([modname])
-    except ImportError, ex:
-        # import failed, i'm probably not so wrong by supposing it's
-        # not standard...
-        return 0
-    # modules which are not living in a file are considered standard
-    # (sys and __builtin__ for instance)
-    if filename is None:
-        return 1
-    filename = abspath(filename)
-    for path in std_path:
-        path = abspath(path)
-        if filename.startswith(path):
-            pfx_len = len(path)
-            if filename[pfx_len+1:pfx_len+14] != 'site-packages':
-                return 1
-            return 0
-    return False
-
-
-
-def is_relative(modname, from_file):
-    """return true if the given module name is relative to the given
-    file name
-
-    :type modname: str
-    :param modname: name of the module we are interested in
-
-    :type from_file: str
-    :param from_file:
-      path of the module from which modname has been imported
-
-    :rtype: bool
-    :return:
-      true if the module has been imported relatively to `from_file`
-    """
-    if not isdir(from_file):
-        from_file = dirname(from_file)
-    if from_file in sys.path:
-        return False
-    try:
-        find_module(modname.split('.')[0], [from_file])
-        return True
-    except ImportError:
-        return False
-
-
-# internal only functions #####################################################
-
-def _file_from_modpath(modpath, path=None, context=None):
-    """given a mod path (i.e. splitted module / package name), return the
-    corresponding file
-
-    this function is used internally, see `file_from_modpath`'s
-    documentation for more information
-    """
-    assert len(modpath) > 0
-    if context is not None:
-        try:
-            mtype, mp_filename = _module_file(modpath, [context])
-        except ImportError:
-            mtype, mp_filename = _module_file(modpath, path)
-    else:
-        mtype, mp_filename = _module_file(modpath, path)
-    if mtype == PY_COMPILED:
-        try:
-            return get_source_file(mp_filename)
-        except NoSourceFile:
-            return mp_filename
-    elif mtype == C_BUILTIN:
-        # integrated builtin module
-        return None
-    elif mtype == PKG_DIRECTORY:
-        mp_filename = _has_init(mp_filename)
-    return mp_filename
-
-def _search_zip(modpath, pic):
-    for filepath, importer in pic.items():
-        if importer is not None:
-            if importer.find_module(modpath[0]):
-                if not importer.find_module('/'.join(modpath)):
-                    raise ImportError('No module named %s in %s/%s' % (
-                        '.'.join(modpath[1:]), file, modpath))
-                return ZIPFILE, abspath(filepath) + '/' + '/'.join(modpath), filepath
-    raise ImportError('No module named %s' % '.'.join(modpath))
-
-def _module_file(modpath, path=None):
-    """get a module type / file path
-
-    :type modpath: list or tuple
-    :param modpath:
-      splitted module's name (i.e name of a module or package splitted
-      on '.'), with leading empty strings for explicit relative import
-
-    :type path: list or None
-    :param path:
-      optional list of path where the module or package should be
-      searched (use sys.path if nothing or None is given)
-
-
-    :rtype: tuple(int, str)
-    :return: the module type flag and the file path for a module
-    """
-    # egg support compat
-    try:
-        pic = sys.path_importer_cache
-        _path = (path is None and sys.path or path)
-        for __path in _path:
-            if not __path in pic:
-                try:
-                    pic[__path] = zipimport.zipimporter(__path)
-                except zipimport.ZipImportError:
-                    pic[__path] = None
-        checkeggs = True
-    except AttributeError:
-        checkeggs = False
-    imported = []
-    while modpath:
-        try:
-            _, mp_filename, mp_desc = find_module(modpath[0], path)
-        except ImportError:
-            if checkeggs:
-                return _search_zip(modpath, pic)[:2]
-            raise
-        else:
-            if checkeggs:
-                fullabspath = [abspath(x) for x in _path]
-                try:
-                    pathindex = fullabspath.index(dirname(abspath(mp_filename)))
-                    emtype, emp_filename, zippath = _search_zip(modpath, pic)
-                    if pathindex > _path.index(zippath):
-                        # an egg takes priority
-                        return emtype, emp_filename
-                except ValueError:
-                    # XXX not in _path
-                    pass
-                except ImportError:
-                    pass
-                checkeggs = False
-        imported.append(modpath.pop(0))
-        mtype = mp_desc[2]
-        if modpath:
-            if mtype != PKG_DIRECTORY:
-                raise ImportError('No module %s in %s' % ('.'.join(modpath),
-                                                          '.'.join(imported)))
-            path = [mp_filename]
-    return mtype, mp_filename
-
-def _is_python_file(filename):
-    """return true if the given filename should be considered as a python file
-
-    .pyc and .pyo are ignored
-    """
-    for ext in ('.py', '.so', '.pyd', '.pyw'):
-        if filename.endswith(ext):
-            return True
-    return False
-
-
-def _has_init(directory):
-    """if the given directory has a valid __init__ file, return its path,
-    else return None
-    """
-    mod_or_pack = join(directory, '__init__')
-    for ext in PY_SOURCE_EXTS + ('pyc', 'pyo'):
-        if exists(mod_or_pack + '.' + ext):
-            return mod_or_pack + '.' + ext
-    return None

+ 0 - 397
pylibs/logilab/common/optik_ext.py

@@ -1,397 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""Add an abstraction level to transparently import optik classes from optparse
-(python >= 2.3) or the optik package.
-
-It also defines three new types for optik/optparse command line parser :
-
-  * regexp
-    argument of this type will be converted using re.compile
-  * csv
-    argument of this type will be converted using split(',')
-  * yn
-    argument of this type will be true if 'y' or 'yes', false if 'n' or 'no'
-  * named
-    argument of this type are in the form <NAME>=<VALUE> or <NAME>:<VALUE>
-  * password
-    argument of this type wont be converted but this is used by other tools
-    such as interactive prompt for configuration to double check value and
-    use an invisible field
-  * multiple_choice
-    same as default "choice" type but multiple choices allowed
-  * file
-    argument of this type wont be converted but checked that the given file exists
-  * color
-    argument of this type wont be converted but checked its either a
-    named color or a color specified using hexadecimal notation (preceded by a #)
-  * time
-    argument of this type will be converted to a float value in seconds
-    according to time units (ms, s, min, h, d)
-  * bytes
-    argument of this type will be converted to a float value in bytes
-    according to byte units (b, kb, mb, gb, tb)
-"""
-__docformat__ = "restructuredtext en"
-
-import re
-import sys
-import time
-from copy import copy
-from os.path import exists
-
-# python >= 2.3
-from optparse import OptionParser as BaseParser, Option as BaseOption, \
-     OptionGroup, OptionContainer, OptionValueError, OptionError, \
-     Values, HelpFormatter, NO_DEFAULT, SUPPRESS_HELP
-
-try:
-    from mx import DateTime
-    HAS_MX_DATETIME = True
-except ImportError:
-    HAS_MX_DATETIME = False
-
-
-OPTPARSE_FORMAT_DEFAULT = sys.version_info >= (2, 4)
-
-from logilab.common.textutils import splitstrip
-
-def check_regexp(option, opt, value):
-    """check a regexp value by trying to compile it
-    return the compiled regexp
-    """
-    if hasattr(value, 'pattern'):
-        return value
-    try:
-        return re.compile(value)
-    except ValueError:
-        raise OptionValueError(
-            "option %s: invalid regexp value: %r" % (opt, value))
-
-def check_csv(option, opt, value):
-    """check a csv value by trying to split it
-    return the list of separated values
-    """
-    if isinstance(value, (list, tuple)):
-        return value
-    try:
-        return splitstrip(value)
-    except ValueError:
-        raise OptionValueError(
-            "option %s: invalid csv value: %r" % (opt, value))
-
-def check_yn(option, opt, value):
-    """check a yn value
-    return true for yes and false for no
-    """
-    if isinstance(value, int):
-        return bool(value)
-    if value in ('y', 'yes'):
-        return True
-    if value in ('n', 'no'):
-        return False
-    msg = "option %s: invalid yn value %r, should be in (y, yes, n, no)"
-    raise OptionValueError(msg % (opt, value))
-
-def check_named(option, opt, value):
-    """check a named value
-    return a dictionary containing (name, value) associations
-    """
-    if isinstance(value, dict):
-        return value
-    values = []
-    for value in check_csv(option, opt, value):
-        if value.find('=') != -1:
-            values.append(value.split('=', 1))
-        elif value.find(':') != -1:
-            values.append(value.split(':', 1))
-    if values:
-        return dict(values)
-    msg = "option %s: invalid named value %r, should be <NAME>=<VALUE> or \
-<NAME>:<VALUE>"
-    raise OptionValueError(msg % (opt, value))
-
-def check_password(option, opt, value):
-    """check a password value (can't be empty)
-    """
-    # no actual checking, monkey patch if you want more
-    return value
-
-def check_file(option, opt, value):
-    """check a file value
-    return the filepath
-    """
-    if exists(value):
-        return value
-    msg = "option %s: file %r does not exist"
-    raise OptionValueError(msg % (opt, value))
-
-# XXX use python datetime
-def check_date(option, opt, value):
-    """check a file value
-    return the filepath
-    """
-    try:
-        return DateTime.strptime(value, "%Y/%m/%d")
-    except DateTime.Error :
-        raise OptionValueError(
-            "expected format of %s is yyyy/mm/dd" % opt)
-
-def check_color(option, opt, value):
-    """check a color value and returns it
-    /!\ does *not* check color labels (like 'red', 'green'), only
-    checks hexadecimal forms
-    """
-    # Case (1) : color label, we trust the end-user
-    if re.match('[a-z0-9 ]+$', value, re.I):
-        return value
-    # Case (2) : only accepts hexadecimal forms
-    if re.match('#[a-f0-9]{6}', value, re.I):
-        return value
-    # Else : not a color label neither a valid hexadecimal form => error
-    msg = "option %s: invalid color : %r, should be either hexadecimal \
-    value or predefined color"
-    raise OptionValueError(msg % (opt, value))
-
-def check_time(option, opt, value):
-    from logilab.common.textutils import TIME_UNITS, apply_units
-    if isinstance(value, (int, long, float)):
-        return value
-    return apply_units(value, TIME_UNITS)
-
-def check_bytes(option, opt, value):
-    from logilab.common.textutils import BYTE_UNITS, apply_units
-    if hasattr(value, '__int__'):
-        return value
-    return apply_units(value, BYTE_UNITS)
-
-import types
-
-class Option(BaseOption):
-    """override optik.Option to add some new option types
-    """
-    TYPES = BaseOption.TYPES + ('regexp', 'csv', 'yn', 'named', 'password',
-                                'multiple_choice', 'file', 'color',
-                                'time', 'bytes')
-    ATTRS = BaseOption.ATTRS + ['hide', 'level']
-    TYPE_CHECKER = copy(BaseOption.TYPE_CHECKER)
-    TYPE_CHECKER['regexp'] = check_regexp
-    TYPE_CHECKER['csv'] = check_csv
-    TYPE_CHECKER['yn'] = check_yn
-    TYPE_CHECKER['named'] = check_named
-    TYPE_CHECKER['multiple_choice'] = check_csv
-    TYPE_CHECKER['file'] = check_file
-    TYPE_CHECKER['color'] = check_color
-    TYPE_CHECKER['password'] = check_password
-    TYPE_CHECKER['time'] = check_time
-    TYPE_CHECKER['bytes'] = check_bytes
-    if HAS_MX_DATETIME:
-        TYPES += ('date',)
-        TYPE_CHECKER['date'] = check_date
-
-    def __init__(self, *opts, **attrs):
-        BaseOption.__init__(self, *opts, **attrs)
-        if hasattr(self, "hide") and self.hide:
-            self.help = SUPPRESS_HELP
-
-    def _check_choice(self):
-        """FIXME: need to override this due to optik misdesign"""
-        if self.type in ("choice", "multiple_choice"):
-            if self.choices is None:
-                raise OptionError(
-                    "must supply a list of choices for type 'choice'", self)
-            elif type(self.choices) not in (types.TupleType, types.ListType):
-                raise OptionError(
-                    "choices must be a list of strings ('%s' supplied)"
-                    % str(type(self.choices)).split("'")[1], self)
-        elif self.choices is not None:
-            raise OptionError(
-                "must not supply choices for type %r" % self.type, self)
-    BaseOption.CHECK_METHODS[2] = _check_choice
-
-
-    def process(self, opt, value, values, parser):
-        # First, convert the value(s) to the right type.  Howl if any
-        # value(s) are bogus.
-        try:
-            value = self.convert_value(opt, value)
-        except AttributeError: # py < 2.4
-            value = self.check_value(opt, value)
-        if self.type == 'named':
-            existant = getattr(values, self.dest)
-            if existant:
-                existant.update(value)
-                value = existant
-       # And then take whatever action is expected of us.
-        # This is a separate method to make life easier for
-        # subclasses to add new actions.
-        return self.take_action(
-            self.action, self.dest, opt, value, values, parser)
-
-
-class OptionParser(BaseParser):
-    """override optik.OptionParser to use our Option class
-    """
-    def __init__(self, option_class=Option, *args, **kwargs):
-        BaseParser.__init__(self, option_class=Option, *args, **kwargs)
-
-    def format_option_help(self, formatter=None):
-        if formatter is None:
-            formatter = self.formatter
-        outputlevel = getattr(formatter, 'output_level', 0)
-        formatter.store_option_strings(self)
-        result = []
-        result.append(formatter.format_heading("Options"))
-        formatter.indent()
-        if self.option_list:
-            result.append(OptionContainer.format_option_help(self, formatter))
-            result.append("\n")
-        for group in self.option_groups:
-            if group.level <= outputlevel and (
-                group.description or level_options(group, outputlevel)):
-                result.append(group.format_help(formatter))
-                result.append("\n")
-        formatter.dedent()
-        # Drop the last "\n", or the header if no options or option groups:
-        return "".join(result[:-1])
-
-
-OptionGroup.level = 0
-
-def level_options(group, outputlevel):
-    return [option for option in group.option_list
-            if (getattr(option, 'level', 0) or 0) <= outputlevel
-            and not option.help is SUPPRESS_HELP]
-
-def format_option_help(self, formatter):
-    result = []
-    outputlevel = getattr(formatter, 'output_level', 0) or 0
-    for option in level_options(self, outputlevel):
-        result.append(formatter.format_option(option))
-    return "".join(result)
-OptionContainer.format_option_help = format_option_help
-
-
-class ManHelpFormatter(HelpFormatter):
-    """Format help using man pages ROFF format"""
-
-    def __init__ (self,
-                  indent_increment=0,
-                  max_help_position=24,
-                  width=79,
-                  short_first=0):
-        HelpFormatter.__init__ (
-            self, indent_increment, max_help_position, width, short_first)
-
-    def format_heading(self, heading):
-        return '.SH %s\n' % heading.upper()
-
-    def format_description(self, description):
-        return description
-
-    def format_option(self, option):
-        try:
-            optstring = option.option_strings
-        except AttributeError:
-            optstring = self.format_option_strings(option)
-        if option.help:
-            help_text = self.expand_default(option)
-            help = ' '.join([l.strip() for l in help_text.splitlines()])
-        else:
-            help = ''
-        return '''.IP "%s"
-%s
-''' % (optstring, help)
-
-    def format_head(self, optparser, pkginfo, section=1):
-        long_desc = ""
-        try:
-            pgm = optparser._get_prog_name()
-        except AttributeError:
-            # py >= 2.4.X (dunno which X exactly, at least 2)
-            pgm = optparser.get_prog_name()
-        short_desc = self.format_short_description(pgm, pkginfo.description)
-        if hasattr(pkginfo, "long_desc"):
-            long_desc = self.format_long_description(pgm, pkginfo.long_desc)
-        return '%s\n%s\n%s\n%s' % (self.format_title(pgm, section),
-                                   short_desc, self.format_synopsis(pgm),
-                                   long_desc)
-
-    def format_title(self, pgm, section):
-        date = '-'.join([str(num) for num in time.localtime()[:3]])
-        return '.TH %s %s "%s" %s' % (pgm, section, date, pgm)
-
-    def format_short_description(self, pgm, short_desc):
-        return '''.SH NAME
-.B %s
-\- %s
-''' % (pgm, short_desc.strip())
-
-    def format_synopsis(self, pgm):
-        return '''.SH SYNOPSIS
-.B  %s
-[
-.I OPTIONS
-] [
-.I <arguments>
-]
-''' % pgm
-
-    def format_long_description(self, pgm, long_desc):
-        long_desc = '\n'.join([line.lstrip()
-                               for line in long_desc.splitlines()])
-        long_desc = long_desc.replace('\n.\n', '\n\n')
-        if long_desc.lower().startswith(pgm):
-            long_desc = long_desc[len(pgm):]
-        return '''.SH DESCRIPTION
-.B %s
-%s
-''' % (pgm, long_desc.strip())
-
-    def format_tail(self, pkginfo):
-        tail = '''.SH SEE ALSO
-/usr/share/doc/pythonX.Y-%s/
-
-.SH BUGS
-Please report bugs on the project\'s mailing list:
-%s
-
-.SH AUTHOR
-%s <%s>
-''' % (getattr(pkginfo, 'debian_name', pkginfo.modname),
-       pkginfo.mailinglist, pkginfo.author, pkginfo.author_email)
-
-        if hasattr(pkginfo, "copyright"):
-            tail += '''
-.SH COPYRIGHT
-%s
-''' % pkginfo.copyright
-
-        return tail
-
-def generate_manpage(optparser, pkginfo, section=1, stream=sys.stdout, level=0):
-    """generate a man page from an optik parser"""
-    formatter = ManHelpFormatter()
-    formatter.output_level = level
-    formatter.parser = optparser
-    print >> stream, formatter.format_head(optparser, pkginfo, section)
-    print >> stream, optparser.format_option_help(formatter)
-    print >> stream, formatter.format_tail(pkginfo)
-
-
-__all__ = ('OptionParser', 'Option', 'OptionGroup', 'OptionValueError',
-           'Values')

+ 0 - 90
pylibs/logilab/common/optparser.py

@@ -1,90 +0,0 @@
-# -*- coding: utf-8 -*-
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""Extend OptionParser with commands.
-
-Example:
-
->>> parser = OptionParser()
->>> parser.usage = '%prog COMMAND [options] <arg> ...'
->>> parser.add_command('build', 'mymod.build')
->>> parser.add_command('clean', run_clean, add_opt_clean)
->>> run, options, args = parser.parse_command(sys.argv[1:])
->>> return run(options, args[1:])
-
-With mymod.build that defines two functions run and add_options
-"""
-__docformat__ = "restructuredtext en"
-
-from warnings import warn
-warn('lgc.optparser module is deprecated, use lgc.clcommands instead', DeprecationWarning,
-     stacklevel=2)
-
-import sys
-import optparse
-
-class OptionParser(optparse.OptionParser):
-
-    def __init__(self, *args, **kwargs):
-        optparse.OptionParser.__init__(self, *args, **kwargs)
-        self._commands = {}
-        self.min_args, self.max_args = 0, 1
-
-    def add_command(self, name, mod_or_funcs, help=''):
-        """name of the command, name of module or tuple of functions
-        (run, add_options)
-        """
-        assert isinstance(mod_or_funcs, str) or isinstance(mod_or_funcs, tuple), \
-            "mod_or_funcs has to be a module name or a tuple of functions"
-        self._commands[name] = (mod_or_funcs, help)
-
-    def print_main_help(self):
-        optparse.OptionParser.print_help(self)
-        print '\ncommands:'
-        for cmdname, (_, help) in self._commands.items():
-            print '% 10s - %s' % (cmdname, help)
-
-    def parse_command(self, args):
-        if len(args) == 0:
-            self.print_main_help()
-            sys.exit(1)
-        cmd = args[0]
-        args = args[1:]
-        if cmd not in self._commands:
-            if cmd in ('-h', '--help'):
-                self.print_main_help()
-                sys.exit(0)
-            elif self.version is not None and cmd == "--version":
-                self.print_version()
-                sys.exit(0)
-            self.error('unknown command')
-        self.prog = '%s %s' % (self.prog, cmd)
-        mod_or_f, help = self._commands[cmd]
-        # optparse inserts self.description between usage and options help
-        self.description = help
-        if isinstance(mod_or_f, str):
-            exec 'from %s import run, add_options' % mod_or_f
-        else:
-            run, add_options = mod_or_f
-        add_options(self)
-        (options, args) = self.parse_args(args)
-        if not (self.min_args <= len(args) <= self.max_args):
-            self.error('incorrect number of arguments')
-        return run, options, args
-
-

+ 0 - 111
pylibs/logilab/common/pdf_ext.py

@@ -1,111 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""Manipulate pdf and fdf files (pdftk recommended).
-
-Notes regarding pdftk, pdf forms and fdf files (form definition file)
-fields names can be extracted with:
-
-    pdftk orig.pdf generate_fdf output truc.fdf
-
-to merge fdf and pdf:
-
-    pdftk orig.pdf fill_form test.fdf output result.pdf [flatten]
-
-without flatten, one could further edit the resulting form.
-with flatten, everything is turned into text.
-
-
-
-
-"""
-__docformat__ = "restructuredtext en"
-# XXX seems very unix specific
-# TODO: check availability of pdftk at import
-
-
-import os
-
-HEAD="""%FDF-1.2
-%\xE2\xE3\xCF\xD3
-1 0 obj
-<<
-/FDF
-<<
-/Fields [
-"""
-
-TAIL="""]
->>
->>
-endobj
-trailer
-
-<<
-/Root 1 0 R
->>
-%%EOF
-"""
-
-def output_field( f ):
-    return "\xfe\xff" + "".join( [ "\x00"+c for c in f ] )
-
-def extract_keys(lines):
-    keys = []
-    for line in lines:
-        if line.startswith('/V'):
-            pass #print 'value',line
-        elif line.startswith('/T'):
-            key = line[7:-2]
-            key = ''.join(key.split('\x00'))
-            keys.append( key )
-    return keys
-
-def write_field(out, key, value):
-    out.write("<<\n")
-    if value:
-        out.write("/V (%s)\n" %value)
-    else:
-        out.write("/V /\n")
-    out.write("/T (%s)\n" % output_field(key) )
-    out.write(">> \n")
-
-def write_fields(out, fields):
-    out.write(HEAD)
-    for (key, value, comment) in fields:
-        write_field(out, key, value)
-        write_field(out, key+"a", value) # pour copie-carbone sur autres pages
-    out.write(TAIL)
-
-def extract_keys_from_pdf(filename):
-    # what about using 'pdftk filename dump_data_fields' and parsing the output ?
-    os.system('pdftk %s generate_fdf output /tmp/toto.fdf' % filename)
-    lines = file('/tmp/toto.fdf').readlines()
-    return extract_keys(lines)
-
-
-def fill_pdf(infile, outfile, fields):
-    write_fields(file('/tmp/toto.fdf', 'w'), fields)
-    os.system('pdftk %s fill_form /tmp/toto.fdf output %s flatten' % (infile, outfile))
-
-def testfill_pdf(infile, outfile):
-    keys = extract_keys_from_pdf(infile)
-    fields = []
-    for key in keys:
-        fields.append( (key, key, '') )
-    fill_pdf(infile, outfile, fields)
-

+ 0 - 277
pylibs/logilab/common/proc.py

@@ -1,277 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""module providing:
-* process information (linux specific: rely on /proc)
-* a class for resource control (memory / time / cpu time)
-
-This module doesn't work on windows platforms (only tested on linux)
-
-:organization: Logilab
-
-
-
-"""
-__docformat__ = "restructuredtext en"
-
-import os
-import stat
-from resource import getrlimit, setrlimit, RLIMIT_CPU, RLIMIT_AS
-from signal import signal, SIGXCPU, SIGKILL, SIGUSR2, SIGUSR1
-from threading import Timer, currentThread, Thread, Event
-from time import time
-
-from logilab.common.tree import Node
-
-class NoSuchProcess(Exception): pass
-
-def proc_exists(pid):
-    """check the a pid is registered in /proc
-    raise NoSuchProcess exception if not
-    """
-    if not os.path.exists('/proc/%s' % pid):
-        raise NoSuchProcess()
-
-PPID = 3
-UTIME = 13
-STIME = 14
-CUTIME = 15
-CSTIME = 16
-VSIZE = 22
-
-class ProcInfo(Node):
-    """provide access to process information found in /proc"""
-
-    def __init__(self, pid):
-        self.pid = int(pid)
-        Node.__init__(self, self.pid)
-        proc_exists(self.pid)
-        self.file = '/proc/%s/stat' % self.pid
-        self.ppid = int(self.status()[PPID])
-
-    def memory_usage(self):
-        """return the memory usage of the process in Ko"""
-        try :
-            return int(self.status()[VSIZE])
-        except IOError:
-            return 0
-
-    def lineage_memory_usage(self):
-        return self.memory_usage() + sum([child.lineage_memory_usage()
-                                          for child in self.children])
-
-    def time(self, children=0):
-        """return the number of jiffies that this process has been scheduled
-        in user and kernel mode"""
-        status = self.status()
-        time = int(status[UTIME]) + int(status[STIME])
-        if children:
-            time += int(status[CUTIME]) + int(status[CSTIME])
-        return time
-
-    def status(self):
-        """return the list of fields found in /proc/<pid>/stat"""
-        return open(self.file).read().split()
-
-    def name(self):
-        """return the process name found in /proc/<pid>/stat
-        """
-        return self.status()[1].strip('()')
-
-    def age(self):
-        """return the age of the process
-        """
-        return os.stat(self.file)[stat.ST_MTIME]
-
-class ProcInfoLoader:
-    """manage process information"""
-
-    def __init__(self):
-        self._loaded = {}
-
-    def list_pids(self):
-        """return a list of existent process ids"""
-        for subdir in os.listdir('/proc'):
-            if subdir.isdigit():
-                yield int(subdir)
-
-    def load(self, pid):
-        """get a ProcInfo object for a given pid"""
-        pid = int(pid)
-        try:
-            return self._loaded[pid]
-        except KeyError:
-            procinfo = ProcInfo(pid)
-            procinfo.manager = self
-            self._loaded[pid] = procinfo
-            return procinfo
-
-
-    def load_all(self):
-        """load all processes information"""
-        for pid in self.list_pids():
-            try:
-                procinfo = self.load(pid)
-                if procinfo.parent is None and procinfo.ppid:
-                    pprocinfo = self.load(procinfo.ppid)
-                    pprocinfo.append(procinfo)
-            except NoSuchProcess:
-                pass
-
-
-try:
-    class ResourceError(BaseException):
-        """Error raise when resource limit is reached"""
-        limit = "Unknown Resource Limit"
-except NameError:
-    class ResourceError(Exception):
-        """Error raise when resource limit is reached"""
-        limit = "Unknown Resource Limit"
-
-
-class XCPUError(ResourceError):
-    """Error raised when CPU Time limit is reached"""
-    limit = "CPU Time"
-
-class LineageMemoryError(ResourceError):
-    """Error raised when the total amount of memory used by a process and
-    it's child is reached"""
-    limit = "Lineage total Memory"
-
-class TimeoutError(ResourceError):
-    """Error raised when the process is running for to much time"""
-    limit = "Real Time"
-
-# Can't use subclass because the StandardError MemoryError raised
-RESOURCE_LIMIT_EXCEPTION = (ResourceError, MemoryError)
-
-
-class MemorySentinel(Thread):
-    """A class checking a process don't use too much memory in a separated
-    daemonic thread
-    """
-    def __init__(self, interval, memory_limit, gpid=os.getpid()):
-        Thread.__init__(self, target=self._run, name="Test.Sentinel")
-        self.memory_limit = memory_limit
-        self._stop = Event()
-        self.interval = interval
-        self.setDaemon(True)
-        self.gpid = gpid
-
-    def stop(self):
-        """stop ap"""
-        self._stop.set()
-
-    def _run(self):
-        pil = ProcInfoLoader()
-        while not self._stop.isSet():
-            if self.memory_limit <= pil.load(self.gpid).lineage_memory_usage():
-                os.killpg(self.gpid, SIGUSR1)
-            self._stop.wait(self.interval)
-
-
-class ResourceController:
-
-    def __init__(self, max_cpu_time=None, max_time=None, max_memory=None,
-                 max_reprieve=60):
-        if SIGXCPU == -1:
-            raise RuntimeError("Unsupported platform")
-        self.max_time = max_time
-        self.max_memory = max_memory
-        self.max_cpu_time = max_cpu_time
-        self._reprieve = max_reprieve
-        self._timer = None
-        self._msentinel = None
-        self._old_max_memory = None
-        self._old_usr1_hdlr = None
-        self._old_max_cpu_time = None
-        self._old_usr2_hdlr = None
-        self._old_sigxcpu_hdlr = None
-        self._limit_set = 0
-        self._abort_try = 0
-        self._start_time = None
-        self._elapse_time = 0
-
-    def _hangle_sig_timeout(self, sig, frame):
-        raise TimeoutError()
-
-    def _hangle_sig_memory(self, sig, frame):
-        if self._abort_try < self._reprieve:
-            self._abort_try += 1
-            raise LineageMemoryError("Memory limit reached")
-        else:
-            os.killpg(os.getpid(), SIGKILL)
-
-    def _handle_sigxcpu(self, sig, frame):
-        if self._abort_try < self._reprieve:
-            self._abort_try += 1
-            raise XCPUError("Soft CPU time limit reached")
-        else:
-            os.killpg(os.getpid(), SIGKILL)
-
-    def _time_out(self):
-        if self._abort_try < self._reprieve:
-            self._abort_try += 1
-            os.killpg(os.getpid(), SIGUSR2)
-            if self._limit_set > 0:
-                self._timer = Timer(1, self._time_out)
-                self._timer.start()
-        else:
-            os.killpg(os.getpid(), SIGKILL)
-
-    def setup_limit(self):
-        """set up the process limit"""
-        assert currentThread().getName() == 'MainThread'
-        os.setpgrp()
-        if self._limit_set <= 0:
-            if self.max_time is not None:
-                self._old_usr2_hdlr = signal(SIGUSR2, self._hangle_sig_timeout)
-                self._timer = Timer(max(1, int(self.max_time) - self._elapse_time),
-                                    self._time_out)
-                self._start_time = int(time())
-                self._timer.start()
-            if self.max_cpu_time is not None:
-                self._old_max_cpu_time = getrlimit(RLIMIT_CPU)
-                cpu_limit = (int(self.max_cpu_time), self._old_max_cpu_time[1])
-                self._old_sigxcpu_hdlr = signal(SIGXCPU, self._handle_sigxcpu)
-                setrlimit(RLIMIT_CPU, cpu_limit)
-            if self.max_memory is not None:
-                self._msentinel = MemorySentinel(1, int(self.max_memory) )
-                self._old_max_memory = getrlimit(RLIMIT_AS)
-                self._old_usr1_hdlr = signal(SIGUSR1, self._hangle_sig_memory)
-                as_limit = (int(self.max_memory), self._old_max_memory[1])
-                setrlimit(RLIMIT_AS, as_limit)
-                self._msentinel.start()
-        self._limit_set += 1
-
-    def clean_limit(self):
-        """reinstall the old process limit"""
-        if self._limit_set > 0:
-            if self.max_time is not None:
-                self._timer.cancel()
-                self._elapse_time += int(time())-self._start_time
-                self._timer = None
-                signal(SIGUSR2, self._old_usr2_hdlr)
-            if self.max_cpu_time is not None:
-                setrlimit(RLIMIT_CPU, self._old_max_cpu_time)
-                signal(SIGXCPU, self._old_sigxcpu_hdlr)
-            if self.max_memory is not None:
-                self._msentinel.stop()
-                self._msentinel = None
-                setrlimit(RLIMIT_AS, self._old_max_memory)
-                signal(SIGUSR1, self._old_usr1_hdlr)
-        self._limit_set -= 1

+ 0 - 180
pylibs/logilab/common/pyro_ext.py

@@ -1,180 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""Python Remote Object utilities
-
-Main functions available:
-
-* `register_object` to expose arbitrary object through pyro using delegation
-  approach and register it in the nameserver.
-* `ns_unregister` unregister an object identifier from the nameserver.
-* `ns_get_proxy` get a pyro proxy from a nameserver object identifier.
-"""
-
-__docformat__ = "restructuredtext en"
-
-import logging
-import tempfile
-
-from Pyro import core, naming, errors, util, config
-
-_LOGGER = logging.getLogger('pyro')
-_MARKER = object()
-
-config.PYRO_STORAGE = tempfile.gettempdir()
-
-def ns_group_and_id(idstr, defaultnsgroup=_MARKER):
-    try:
-        nsgroup, nsid = idstr.rsplit('.', 1)
-    except ValueError:
-        if defaultnsgroup is _MARKER:
-            nsgroup = config.PYRO_NS_DEFAULTGROUP
-        else:
-            nsgroup = defaultnsgroup
-        nsid = idstr
-    if nsgroup is not None and not nsgroup.startswith(':'):
-        nsgroup = ':' + nsgroup
-    return nsgroup, nsid
-
-def host_and_port(hoststr):
-    if not hoststr:
-        return None, None
-    try:
-        hoststr, port = hoststr.split(':')
-    except ValueError:
-        port = None
-    else:
-        port = int(port)
-    return hoststr, port
-
-_DAEMONS = {}
-_PYRO_OBJS = {}
-def _get_daemon(daemonhost, start=True):
-    if not daemonhost in _DAEMONS:
-        if not start:
-            raise Exception('no daemon for %s' % daemonhost)
-        if not _DAEMONS:
-            core.initServer(banner=0)
-        host, port = host_and_port(daemonhost)
-        daemon = core.Daemon(host=host, port=port)
-        _DAEMONS[daemonhost] = daemon
-    return _DAEMONS[daemonhost]
-
-
-def locate_ns(nshost):
-    """locate and return the pyro name server to the daemon"""
-    core.initClient(banner=False)
-    return naming.NameServerLocator().getNS(*host_and_port(nshost))
-
-
-def register_object(object, nsid, defaultnsgroup=_MARKER,
-                    daemonhost=None, nshost=None, use_pyrons=True):
-    """expose the object as a pyro object and register it in the name-server
-
-    if use_pyrons is False, then the object is exposed, but no
-    attempt to register it to a pyro nameserver is made.
-
-    return the pyro daemon object
-    """
-    nsgroup, nsid = ns_group_and_id(nsid, defaultnsgroup)
-    daemon = _get_daemon(daemonhost)
-    if use_pyrons:
-        nsd = locate_ns(nshost)
-        # make sure our namespace group exists
-        try:
-            nsd.createGroup(nsgroup)
-        except errors.NamingError:
-            pass
-        daemon.useNameServer(nsd)
-    # use Delegation approach
-    impl = core.ObjBase()
-    impl.delegateTo(object)
-    qnsid = '%s.%s' % (nsgroup, nsid)
-    uri = daemon.connect(impl, qnsid)
-    _PYRO_OBJS[qnsid] = str(uri)
-    _LOGGER.info('registered %s a pyro object using group %s and id %s',
-                 object, nsgroup, nsid)
-    return daemon
-
-def get_object_uri(qnsid):
-    return _PYRO_OBJS[qnsid]
-
-def ns_unregister(nsid, defaultnsgroup=_MARKER, nshost=None):
-    """unregister the object with the given nsid from the pyro name server"""
-    nsgroup, nsid = ns_group_and_id(nsid, defaultnsgroup)
-    try:
-        nsd = locate_ns(nshost)
-    except errors.PyroError, ex:
-        # name server not responding
-        _LOGGER.error('can\'t locate pyro name server: %s', ex)
-    else:
-        try:
-            nsd.unregister('%s.%s' % (nsgroup, nsid))
-            _LOGGER.info('%s unregistered from pyro name server', nsid)
-        except errors.NamingError:
-            _LOGGER.warning('%s not registered in pyro name server', nsid)
-
-
-def ns_reregister(nsid, defaultnsgroup=_MARKER, nshost=None):
-    """reregister a pyro object into the name server. You only have to specify
-    the name-server id of the object (though you MUST have gone through
-    `register_object` for the given object previously).
-
-    This is especially useful for long running server while the name server may
-    have been restarted, and its records lost.
-    """
-    nsgroup, nsid = ns_group_and_id(nsid, defaultnsgroup)
-    qnsid = '%s.%s' % (nsgroup, nsid)
-    nsd = locate_ns(nshost)
-    try:
-        nsd.unregister(qnsid)
-    except errors.NamingError:
-        # make sure our namespace group exists
-        try:
-            nsd.createGroup(nsgroup)
-        except errors.NamingError:
-            pass
-    nsd.register(qnsid, _PYRO_OBJS[qnsid])
-
-def ns_get_proxy(nsid, defaultnsgroup=_MARKER, nshost=None):
-    """
-    if nshost is None, the nameserver is found by a broadcast.
-    """
-    # resolve the Pyro object
-    nsgroup, nsid = ns_group_and_id(nsid, defaultnsgroup)
-    try:
-        nsd = locate_ns(nshost)
-        pyrouri = nsd.resolve('%s.%s' % (nsgroup, nsid))
-    except errors.ProtocolError, ex:
-        raise errors.PyroError(
-            'Could not connect to the Pyro name server (host: %s)' % nshost)
-    except errors.NamingError:
-        raise errors.PyroError(
-            'Could not get proxy for %s (not registered in Pyro), '
-            'you may have to restart your server-side application' % nsid)
-    return core.getProxyForURI(pyrouri)
-
-def get_proxy(pyro_uri):
-    """get a proxy for the passed pyro uri without using a nameserver
-    """
-    return core.getProxyForURI(pyro_uri)
-
-def set_pyro_log_threshold(level):
-    pyrologger = logging.getLogger('Pyro.%s' % str(id(util.Log)))
-    # remove handlers so only the root handler is used
-    pyrologger.handlers = []
-    pyrologger.setLevel(level)

Plik diff jest za duży
+ 0 - 1177
pylibs/logilab/common/pytest.py


+ 0 - 973
pylibs/logilab/common/registry.py

@@ -1,973 +0,0 @@
-# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of Logilab-common.
-#
-# Logilab-common is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 2.1 of the License, or (at your
-# option) any later version.
-#
-# Logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with Logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""This module provides bases for predicates dispatching (the pattern in use
-here is similar to what's refered as multi-dispatch or predicate-dispatch in the
-literature, though a bit different since the idea is to select across different
-implementation 'e.g. classes), not to dispatch a message to a function or
-method. It contains the following classes:
-
-* :class:`RegistryStore`, the top level object which loads implementation
-  objects and stores them into registries. You'll usually use it to access
-  registries and their contained objects;
-
-* :class:`Registry`, the base class which contains objects semantically grouped
-  (for instance, sharing a same API, hence the 'implementation' name). You'll
-  use it to select the proper implementation according to a context. Notice you
-  may use registries on their own without using the store.
-
-.. Note::
-
-  implementation objects are usually designed to be accessed through the
-  registry and not by direct instantiation, besides to use it as base classe.
-
-The selection procedure is delegated to a selector, which is responsible for
-scoring the object according to some context. At the end of the selection, if an
-implementation has been found, an instance of this class is returned. A selector
-is built from one or more predicates combined together using AND, OR, NOT
-operators (actually `&`, `|` and `~`). You'll thus find some base classes to
-build predicates:
-
-* :class:`Predicate`, the abstract base predicate class
-
-* :class:`AndPredicate`, :class:`OrPredicate`, :class:`NotPredicate`, which you
-  shouldn't have to use directly. You'll use `&`, `|` and '~' operators between
-  predicates directly
-
-* :func:`objectify_predicate`
-
-You'll eventually find one concrete predicate: :class:`yes`
-
-.. autoclass:: RegistryStore
-.. autoclass:: Registry
-
-Predicates
-----------
-.. autoclass:: Predicate
-.. autofunc:: objectify_predicate
-.. autoclass:: yes
-
-Debugging
----------
-.. autoclass:: traced_selection
-
-Exceptions
-----------
-.. autoclass:: RegistryException
-.. autoclass:: RegistryNotFound
-.. autoclass:: ObjectNotFound
-.. autoclass:: NoSelectableObject
-"""
-
-__docformat__ = "restructuredtext en"
-
-import sys
-import types
-import weakref
-from os import listdir, stat
-from os.path import join, isdir, exists
-from logging import getLogger
-
-from logilab.common.logging_ext import set_log_methods
-
-
-class RegistryException(Exception):
-    """Base class for registry exception."""
-
-class RegistryNotFound(RegistryException):
-    """Raised when an unknown registry is requested.
-
-    This is usually a programming/typo error.
-    """
-
-class ObjectNotFound(RegistryException):
-    """Raised when an unregistered object is requested.
-
-    This may be a programming/typo or a misconfiguration error.
-    """
-
-class NoSelectableObject(RegistryException):
-    """Raised when no object is selectable for a given context."""
-    def __init__(self, args, kwargs, objects):
-        self.args = args
-        self.kwargs = kwargs
-        self.objects = objects
-
-    def __str__(self):
-        return ('args: %s, kwargs: %s\ncandidates: %s'
-                % (self.args, self.kwargs.keys(), self.objects))
-
-
-def _toload_info(path, extrapath, _toload=None):
-    """Return a dictionary of <modname>: <modpath> and an ordered list of
-    (file, module name) to load
-    """
-    from logilab.common.modutils import modpath_from_file
-    if _toload is None:
-        assert isinstance(path, list)
-        _toload = {}, []
-    for fileordir in path:
-        if isdir(fileordir) and exists(join(fileordir, '__init__.py')):
-            subfiles = [join(fileordir, fname) for fname in listdir(fileordir)]
-            _toload_info(subfiles, extrapath, _toload)
-        elif fileordir[-3:] == '.py':
-            modpath = modpath_from_file(fileordir, extrapath)
-            # omit '__init__' from package's name to avoid loading that module
-            # once for each name when it is imported by some other object
-            # module. This supposes import in modules are done as::
-            #
-            #   from package import something
-            #
-            # not::
-            #
-            #   from package.__init__ import something
-            #
-            # which seems quite correct.
-            if modpath[-1] == '__init__':
-                modpath.pop()
-            modname = '.'.join(modpath)
-            _toload[0][modname] = fileordir
-            _toload[1].append((fileordir, modname))
-    return _toload
-
-
-def classid(cls):
-    """returns a unique identifier for an object class"""
-    return '%s.%s' % (cls.__module__, cls.__name__)
-
-def class_registries(cls, registryname):
-    """return a tuple of registry names (see __registries__)"""
-    if registryname:
-        return (registryname,)
-    return cls.__registries__
-
-
-class Registry(dict):
-    """The registry store a set of implementations associated to identifier:
-
-    * to each identifier are associated a list of implementations
-
-    * to select an implementation of a given identifier, you should use one of the
-      :meth:`select` or :meth:`select_or_none` method
-
-    * to select a list of implementations for a context, you should use the
-      :meth:`possible_objects` method
-
-    * dictionary like access to an identifier will return the bare list of
-      implementations for this identifier.
-
-    To be usable in a registry, the only requirement is to have a `__select__`
-    attribute.
-
-    At the end of the registration process, the :meth:`__registered__`
-    method is called on each registered object which have them, given the
-    registry in which it's registered as argument.
-
-    Registration methods:
-
-    .. automethod: register
-    .. automethod: unregister
-
-    Selection methods:
-
-    .. automethod: select
-    .. automethod: select_or_none
-    .. automethod: possible_objects
-    .. automethod: object_by_id
-    """
-    def __init__(self, debugmode):
-        super(Registry, self).__init__()
-        self.debugmode = debugmode
-
-    def __getitem__(self, name):
-        """return the registry (list of implementation objects) associated to
-        this name
-        """
-        try:
-            return super(Registry, self).__getitem__(name)
-        except KeyError:
-            raise ObjectNotFound(name), None, sys.exc_info()[-1]
-
-    def initialization_completed(self):
-        """call method __registered__() on registered objects when the callback
-        is defined"""
-        for objects in self.itervalues():
-            for objectcls in objects:
-                registered = getattr(objectcls, '__registered__', None)
-                if registered:
-                    registered(self)
-        if self.debugmode:
-            wrap_predicates(_lltrace)
-
-    def register(self, obj, oid=None, clear=False):
-        """base method to add an object in the registry"""
-        assert not '__abstract__' in obj.__dict__
-        assert obj.__select__
-        oid = oid or obj.__regid__
-        assert oid
-        if clear:
-            objects = self[oid] =  []
-        else:
-            objects = self.setdefault(oid, [])
-        assert not obj in objects, \
-               'object %s is already registered' % obj
-        objects.append(obj)
-
-    def register_and_replace(self, obj, replaced):
-        """remove <replaced> and register <obj>"""
-        # XXXFIXME this is a duplication of unregister()
-        # remove register_and_replace in favor of unregister + register
-        # or simplify by calling unregister then register here
-        if not isinstance(replaced, basestring):
-            replaced = classid(replaced)
-        # prevent from misspelling
-        assert obj is not replaced, 'replacing an object by itself: %s' % obj
-        registered_objs = self.get(obj.__regid__, ())
-        for index, registered in enumerate(registered_objs):
-            if classid(registered) == replaced:
-                del registered_objs[index]
-                break
-        else:
-            self.warning('trying to replace %s that is not registered with %s',
-                         replaced, obj)
-        self.register(obj)
-
-    def unregister(self, obj):
-        """remove object <obj> from this registry"""
-        clsid = classid(obj)
-        oid = obj.__regid__
-        for registered in self.get(oid, ()):
-            # use classid() to compare classes because vreg will probably
-            # have its own version of the class, loaded through execfile
-            if classid(registered) == clsid:
-                self[oid].remove(registered)
-                break
-        else:
-            self.warning('can\'t remove %s, no id %s in the registry',
-                         clsid, oid)
-
-    def all_objects(self):
-        """return a list containing all objects in this registry.
-        """
-        result = []
-        for objs in self.values():
-            result += objs
-        return result
-
-    # dynamic selection methods ################################################
-
-    def object_by_id(self, oid, *args, **kwargs):
-        """return object with the `oid` identifier. Only one object is expected
-        to be found.
-
-        raise :exc:`ObjectNotFound` if not object with id <oid> in <registry>
-
-        raise :exc:`AssertionError` if there is more than one object there
-        """
-        objects = self[oid]
-        assert len(objects) == 1, objects
-        return objects[0](*args, **kwargs)
-
-    def select(self, __oid, *args, **kwargs):
-        """return the most specific object among those with the given oid
-        according to the given context.
-
-        raise :exc:`ObjectNotFound` if not object with id <oid> in <registry>
-
-        raise :exc:`NoSelectableObject` if not object apply
-        """
-        obj =  self._select_best(self[__oid], *args, **kwargs)
-        if obj is None:
-            raise NoSelectableObject(args, kwargs, self[__oid] )
-        return obj
-
-    def select_or_none(self, __oid, *args, **kwargs):
-        """return the most specific object among those with the given oid
-        according to the given context, or None if no object applies.
-        """
-        try:
-            return self.select(__oid, *args, **kwargs)
-        except (NoSelectableObject, ObjectNotFound):
-            return None
-
-    def possible_objects(self, *args, **kwargs):
-        """return an iterator on possible objects in this registry for the given
-        context
-        """
-        for objects in self.itervalues():
-            obj = self._select_best(objects,  *args, **kwargs)
-            if obj is None:
-                continue
-            yield obj
-
-    def _select_best(self, objects, *args, **kwargs):
-        """return an instance of the most specific object according
-        to parameters
-
-        return None if not object apply (don't raise `NoSelectableObject` since
-        it's costly when searching objects using `possible_objects`
-        (e.g. searching for hooks).
-        """
-        score, winners = 0, None
-        for obj in objects:
-            objectscore = obj.__select__(obj, *args, **kwargs)
-            if objectscore > score:
-                score, winners = objectscore, [obj]
-            elif objectscore > 0 and objectscore == score:
-                winners.append(obj)
-        if winners is None:
-            return None
-        if len(winners) > 1:
-            # log in production environement / test, error while debugging
-            msg = 'select ambiguity: %s\n(args: %s, kwargs: %s)'
-            if self.debugmode:
-                # raise bare exception in debug mode
-                raise Exception(msg % (winners, args, kwargs.keys()))
-            self.error(msg, winners, args, kwargs.keys())
-        # return the result of calling the object
-        return winners[0](*args, **kwargs)
-
-    # these are overridden by set_log_methods below
-    # only defining here to prevent pylint from complaining
-    info = warning = error = critical = exception = debug = lambda msg, *a, **kw: None
-
-
-class RegistryStore(dict):
-    """This class is responsible for loading implementations and storing them
-    in their registry which are created on the fly as needed.
-
-    It handles dynamic registration of objects and provides a convenient api to
-    access them. To be recognized as an object that should be stored into one of
-    the store's registry (:class:`Registry`), an object (usually a class) has
-    the following attributes, used control how they interact with the registry:
-
-    :attr:`__registry__` or `__registries__`
-      name of the registry for this object (string like 'views', 'templates'...)
-      or list of registry names if you want your object to be added to multiple
-      registries
-
-    :attr:`__regid__`
-      implementation's identifier in the registry (string like 'main',
-      'primary', 'folder_box')
-
-    :attr:`__select__`
-      the implementation's selector
-
-    Moreover, the :attr:`__abstract__` attribute may be set to `True` to
-    indicate that a class is abstract and should not be registered (inherited
-    attributes not considered).
-
-    .. Note::
-
-      When using the store to load objects dynamically, you *always* have
-      to use **super()** to get the methods and attributes of the
-      superclasses, and not use the class identifier. Else, you'll get into
-      trouble when reloading comes into the place.
-
-      For example, instead of writing::
-
-          class Thing(Parent):
-              __regid__ = 'athing'
-              __select__ = yes()
-              def f(self, arg1):
-                  Parent.f(self, arg1)
-
-      You must write::
-
-          class Thing(Parent):
-              __regid__ = 'athing'
-              __select__ = yes()
-              def f(self, arg1):
-                  super(Parent, self).f(arg1)
-
-    Controlling objects registration
-    --------------------------------
-
-    Dynamic loading is triggered by calling the :meth:`register_objects` method,
-    given a list of directory to inspect for python modules.
-
-    .. automethod: register_objects
-
-    For each module, by default, all compatible objects are registered
-    automatically, though if some objects have to replace other objects, or have
-    to be included only if some condition is met, you'll have to define a
-    `registration_callback(vreg)` function in your module and explicitly
-    register **all objects** in this module, using the api defined below.
-
-
-    .. automethod:: RegistryStore.register_all
-    .. automethod:: RegistryStore.register_and_replace
-    .. automethod:: RegistryStore.register
-    .. automethod:: RegistryStore.unregister
-
-    .. Note::
-        Once the function `registration_callback(vreg)` is implemented in a
-        module, all the objects from this module have to be explicitly
-        registered as it disables the automatic objects registration.
-
-
-    Examples:
-
-    .. sourcecode:: python
-
-       # cubicweb/web/views/basecomponents.py
-       def registration_callback(store):
-          # register everything in the module except SeeAlsoComponent
-          store.register_all(globals().values(), __name__, (SeeAlsoVComponent,))
-          # conditionally register SeeAlsoVComponent
-          if 'see_also' in store.schema:
-              store.register(SeeAlsoVComponent)
-
-    In this example, we register all application object classes defined in the module
-    except `SeeAlsoVComponent`. This class is then registered only if the 'see_also'
-    relation type is defined in the instance'schema.
-
-    .. sourcecode:: python
-
-       # goa/appobjects/sessions.py
-       def registration_callback(store):
-          store.register(SessionsCleaner)
-          # replace AuthenticationManager by GAEAuthenticationManager
-          store.register_and_replace(GAEAuthenticationManager, AuthenticationManager)
-          # replace PersistentSessionManager by GAEPersistentSessionManager
-          store.register_and_replace(GAEPersistentSessionManager, PersistentSessionManager)
-
-    In this example, we explicitly register classes one by one:
-
-    * the `SessionCleaner` class
-    * the `GAEAuthenticationManager` to replace the `AuthenticationManager`
-    * the `GAEPersistentSessionManager` to replace the `PersistentSessionManager`
-
-    If at some point we register a new appobject class in this module, it won't be
-    registered at all without modification to the `registration_callback`
-    implementation. The previous example will register it though, thanks to the call
-    to the `register_all` method.
-
-    Controlling registry instantation
-    ---------------------------------
-    The `REGISTRY_FACTORY` class dictionary allows to specify which class should
-    be instantiated for a given registry name. The class associated to `None` in
-    it will be the class used when there is no specific class for a name.
-    """
-
-    def __init__(self, debugmode=False):
-        super(RegistryStore, self).__init__()
-        self.debugmode = debugmode
-
-    def reset(self):
-        """clear all registries managed by this store"""
-        # don't use self.clear, we want to keep existing subdictionaries
-        for subdict in self.itervalues():
-            subdict.clear()
-        self._lastmodifs = {}
-
-    def __getitem__(self, name):
-        """return the registry (dictionary of class objects) associated to
-        this name
-        """
-        try:
-            return super(RegistryStore, self).__getitem__(name)
-        except KeyError:
-            raise RegistryNotFound(name), None, sys.exc_info()[-1]
-
-    # methods for explicit (un)registration ###################################
-
-    # default class, when no specific class set
-    REGISTRY_FACTORY = {None: Registry}
-
-    def registry_class(self, regid):
-        """return existing registry named regid or use factory to create one and
-        return it"""
-        try:
-            return self.REGISTRY_FACTORY[regid]
-        except KeyError:
-            return self.REGISTRY_FACTORY[None]
-
-    def setdefault(self, regid):
-        try:
-            return self[regid]
-        except KeyError:
-            self[regid] = self.registry_class(regid)(self.debugmode)
-            return self[regid]
-
-    def register_all(self, objects, modname, butclasses=()):
-        """register all `objects` given. Objects which are not from the module
-        `modname` or which are in `butclasses` won't be registered.
-
-        Typical usage is:
-
-        .. sourcecode:: python
-
-            store.register_all(globals().values(), __name__, (ClassIWantToRegisterExplicitly,))
-
-        So you get partially automatic registration, keeping manual registration
-        for some object (to use
-        :meth:`~logilab.common.registry.RegistryStore.register_and_replace`
-        for instance)
-        """
-        for obj in objects:
-            try:
-                if obj.__module__ != modname or obj in butclasses:
-                    continue
-                oid = obj.__regid__
-            except AttributeError:
-                continue
-            if oid and not obj.__dict__.get('__abstract__'):
-                self.register(obj, oid=oid)
-
-    def register(self, obj, registryname=None, oid=None, clear=False):
-        """register `obj` implementation into `registryname` or
-        `obj.__registry__` if not specified, with identifier `oid` or
-        `obj.__regid__` if not specified.
-
-        If `clear` is true, all objects with the same identifier will be
-        previously unregistered.
-        """
-        assert not obj.__dict__.get('__abstract__')
-        try:
-            vname = obj.__name__
-        except AttributeError:
-            # XXX may occurs?
-            vname = obj.__class__.__name__
-        for registryname in class_registries(obj, registryname):
-            registry = self.setdefault(registryname)
-            registry.register(obj, oid=oid, clear=clear)
-            self.debug('register %s in %s[\'%s\']',
-                       vname, registryname, oid or obj.__regid__)
-        self._loadedmods.setdefault(obj.__module__, {})[classid(obj)] = obj
-
-    def unregister(self, obj, registryname=None):
-        """unregister `obj` implementation object from the registry
-        `registryname` or `obj.__registry__` if not specified.
-        """
-        for registryname in class_registries(obj, registryname):
-            self[registryname].unregister(obj)
-
-    def register_and_replace(self, obj, replaced, registryname=None):
-        """register `obj` implementation object into `registryname` or
-        `obj.__registry__` if not specified. If found, the `replaced` object
-        will be unregistered first (else a warning will be issued as it's
-        generally unexpected).
-        """
-        for registryname in class_registries(obj, registryname):
-            self[registryname].register_and_replace(obj, replaced)
-
-    # initialization methods ###################################################
-
-    def init_registration(self, path, extrapath=None):
-        """reset registry and walk down path to return list of (path, name)
-        file modules to be loaded"""
-        # XXX make this private by renaming it to _init_registration ?
-        self.reset()
-        # compute list of all modules that have to be loaded
-        self._toloadmods, filemods = _toload_info(path, extrapath)
-        # XXX is _loadedmods still necessary ? It seems like it's useful
-        #     to avoid loading same module twice, especially with the
-        #     _load_ancestors_then_object logic but this needs to be checked
-        self._loadedmods = {}
-        return filemods
-
-    def register_objects(self, path, extrapath=None):
-        """register all objects found walking down <path>"""
-        # load views from each directory in the instance's path
-        # XXX inline init_registration ?
-        filemods = self.init_registration(path, extrapath)
-        for filepath, modname in filemods:
-            self.load_file(filepath, modname)
-        self.initialization_completed()
-
-    def initialization_completed(self):
-        """call initialization_completed() on all known registries"""
-        for reg in self.itervalues():
-            reg.initialization_completed()
-
-    def _mdate(self, filepath):
-        try:
-            return stat(filepath)[-2]
-        except OSError:
-            # this typically happens on emacs backup files (.#foo.py)
-            self.warning('Unable to load %s. It is likely to be a backup file',
-                         filepath)
-            return None
-
-    def is_reload_needed(self, path):
-        """return True if something module changed and the registry should be
-        reloaded
-        """
-        lastmodifs = self._lastmodifs
-        for fileordir in path:
-            if isdir(fileordir) and exists(join(fileordir, '__init__.py')):
-                if self.is_reload_needed([join(fileordir, fname)
-                                          for fname in listdir(fileordir)]):
-                    return True
-            elif fileordir[-3:] == '.py':
-                mdate = self._mdate(fileordir)
-                if mdate is None:
-                    continue # backup file, see _mdate implementation
-                elif "flymake" in fileordir:
-                    # flymake + pylint in use, don't consider these they will corrupt the registry
-                    continue
-                if fileordir not in lastmodifs or lastmodifs[fileordir] < mdate:
-                    self.info('File %s changed since last visit', fileordir)
-                    return True
-        return False
-
-    def load_file(self, filepath, modname):
-        """load app objects from a python file"""
-        from logilab.common.modutils import load_module_from_name
-        if modname in self._loadedmods:
-            return
-        self._loadedmods[modname] = {}
-        mdate = self._mdate(filepath)
-        if mdate is None:
-            return # backup file, see _mdate implementation
-        elif "flymake" in filepath:
-            # flymake + pylint in use, don't consider these they will corrupt the registry
-            return
-        # set update time before module loading, else we get some reloading
-        # weirdness in case of syntax error or other error while importing the
-        # module
-        self._lastmodifs[filepath] = mdate
-        # load the module
-        module = load_module_from_name(modname)
-        self.load_module(module)
-
-    def load_module(self, module):
-        """load objects from a module using registration_callback() when it exists
-        """
-        self.info('loading %s from %s', module.__name__, module.__file__)
-        if hasattr(module, 'registration_callback'):
-            module.registration_callback(self)
-        else:
-            for objname, obj in vars(module).items():
-                if objname.startswith('_'):
-                    continue
-                self._load_ancestors_then_object(module.__name__, obj)
-
-    def _load_ancestors_then_object(self, modname, objectcls):
-        """handle automatic object class registration:
-
-        - first ensure parent classes are already registered
-
-        - class with __abstract__ == True in their local dictionary or
-          with a name starting with an underscore are not registered
-
-        - object class needs to have __registry__ and __regid__ attributes
-          set to a non empty string to be registered.
-        """
-        # imported classes
-        objmodname = getattr(objectcls, '__module__', None)
-        if objmodname != modname:
-            if objmodname in self._toloadmods:
-                self.load_file(self._toloadmods[objmodname], objmodname)
-            return
-        # skip non registerable object
-        try:
-            if not (getattr(objectcls, '__regid__', None)
-                    and getattr(objectcls, '__select__', None)):
-                return
-        except TypeError:
-            return
-        clsid = classid(objectcls)
-        if clsid in self._loadedmods[modname]:
-            return
-        self._loadedmods[modname][clsid] = objectcls
-        for parent in objectcls.__bases__:
-            self._load_ancestors_then_object(modname, parent)
-        if (objectcls.__dict__.get('__abstract__')
-            or objectcls.__name__[0] == '_'
-            or not objectcls.__registries__
-            or not objectcls.__regid__):
-            return
-        try:
-            self.register(objectcls)
-        except Exception, ex:
-            if self.debugmode:
-                raise
-            self.exception('object %s registration failed: %s',
-                           objectcls, ex)
-
-    # these are overridden by set_log_methods below
-    # only defining here to prevent pylint from complaining
-    info = warning = error = critical = exception = debug = lambda msg, *a, **kw: None
-
-
-# init logging
-set_log_methods(RegistryStore, getLogger('registry.store'))
-set_log_methods(Registry, getLogger('registry'))
-
-
-# helpers for debugging selectors
-TRACED_OIDS = None
-
-def _trace_selector(cls, selector, args, ret):
-    vobj = args[0]
-    if TRACED_OIDS == 'all' or vobj.__regid__ in TRACED_OIDS:
-        print '%s -> %s for %s(%s)' % (cls, ret, vobj, vobj.__regid__)
-
-def _lltrace(selector):
-    """use this decorator on your predicates so they become traceable with
-    :class:`traced_selection`
-    """
-    def traced(cls, *args, **kwargs):
-        ret = selector(cls, *args, **kwargs)
-        if TRACED_OIDS is not None:
-            _trace_selector(cls, selector, args, ret)
-        return ret
-    traced.__name__ = selector.__name__
-    traced.__doc__ = selector.__doc__
-    return traced
-
-class traced_selection(object): # pylint: disable=C0103
-    """
-    Typical usage is :
-
-    .. sourcecode:: python
-
-        >>> from logilab.common.registry import traced_selection
-        >>> with traced_selection():
-        ...     # some code in which you want to debug selectors
-        ...     # for all objects
-
-    Don't forget the 'from __future__ import with_statement' at the module top-level
-    if you're using python prior to 2.6.
-
-    This will yield lines like this in the logs::
-
-        selector one_line_rset returned 0 for <class 'cubicweb.web.views.basecomponents.WFHistoryVComponent'>
-
-    You can also give to :class:`traced_selection` the identifiers of objects on
-    which you want to debug selection ('oid1' and 'oid2' in the example above).
-
-    .. sourcecode:: python
-
-        >>> with traced_selection( ('regid1', 'regid2') ):
-        ...     # some code in which you want to debug selectors
-        ...     # for objects with __regid__ 'regid1' and 'regid2'
-
-    A potentially useful point to set up such a tracing function is
-    the `logilab.common.registry.Registry.select` method body.
-    """
-
-    def __init__(self, traced='all'):
-        self.traced = traced
-
-    def __enter__(self):
-        global TRACED_OIDS
-        TRACED_OIDS = self.traced
-
-    def __exit__(self, exctype, exc, traceback):
-        global TRACED_OIDS
-        TRACED_OIDS = None
-        return traceback is None
-
-# selector base classes and operations ########################################
-
-def objectify_predicate(selector_func):
-    """Most of the time, a simple score function is enough to build a selector.
-    The :func:`objectify_predicate` decorator turn it into a proper selector
-    class::
-
-        @objectify_predicate
-        def one(cls, req, rset=None, **kwargs):
-            return 1
-
-        class MyView(View):
-            __select__ = View.__select__ & one()
-
-    """
-    return type(selector_func.__name__, (Predicate,),
-                {'__doc__': selector_func.__doc__,
-                 '__call__': lambda self, *a, **kw: selector_func(*a, **kw)})
-
-
-_PREDICATES = {}
-
-def wrap_predicates(decorator):
-    for predicate in _PREDICATES.itervalues():
-        if not '_decorators' in predicate.__dict__:
-            predicate._decorators = set()
-        if decorator in predicate._decorators:
-            continue
-        predicate._decorators.add(decorator)
-        predicate.__call__ = decorator(predicate.__call__)
-
-class PredicateMetaClass(type):
-    def __new__(cls, *args, **kwargs):
-        # use __new__ so subclasses doesn't have to call Predicate.__init__
-        inst = type.__new__(cls, *args, **kwargs)
-        proxy = weakref.proxy(inst, lambda p: _PREDICATES.pop(id(p)))
-        _PREDICATES[id(proxy)] = proxy
-        return inst
-
-class Predicate(object):
-    """base class for selector classes providing implementation
-    for operators ``&``, ``|`` and  ``~``
-
-    This class is only here to give access to binary operators, the selector
-    logic itself should be implemented in the :meth:`__call__` method. Notice it
-    should usually accept any arbitrary arguments (the context), though that may
-    vary depending on your usage of the registry.
-
-    a selector is called to help choosing the correct object for a
-    particular context by returning a score (`int`) telling how well
-    the implementation given as first argument fit to the given context.
-
-    0 score means that the class doesn't apply.
-    """
-    __metaclass__ = PredicateMetaClass
-
-    @property
-    def func_name(self):
-        # backward compatibility
-        return self.__class__.__name__
-
-    def search_selector(self, selector):
-        """search for the given selector, selector instance or tuple of
-        selectors in the selectors tree. Return None if not found.
-        """
-        if self is selector:
-            return self
-        if (isinstance(selector, type) or isinstance(selector, tuple)) and \
-               isinstance(self, selector):
-            return self
-        return None
-
-    def __str__(self):
-        return self.__class__.__name__
-
-    def __and__(self, other):
-        return AndPredicate(self, other)
-    def __rand__(self, other):
-        return AndPredicate(other, self)
-    def __iand__(self, other):
-        return AndPredicate(self, other)
-    def __or__(self, other):
-        return OrPredicate(self, other)
-    def __ror__(self, other):
-        return OrPredicate(other, self)
-    def __ior__(self, other):
-        return OrPredicate(self, other)
-
-    def __invert__(self):
-        return NotPredicate(self)
-
-    # XXX (function | function) or (function & function) not managed yet
-
-    def __call__(self, cls, *args, **kwargs):
-        return NotImplementedError("selector %s must implement its logic "
-                                   "in its __call__ method" % self.__class__)
-
-    def __repr__(self):
-        return u'<Predicate %s at %x>' % (self.__class__.__name__, id(self))
-
-
-class MultiPredicate(Predicate):
-    """base class for compound selector classes"""
-
-    def __init__(self, *selectors):
-        self.selectors = self.merge_selectors(selectors)
-
-    def __str__(self):
-        return '%s(%s)' % (self.__class__.__name__,
-                           ','.join(str(s) for s in self.selectors))
-
-    @classmethod
-    def merge_selectors(cls, selectors):
-        """deal with selector instanciation when necessary and merge
-        multi-selectors if possible:
-
-        AndPredicate(AndPredicate(sel1, sel2), AndPredicate(sel3, sel4))
-        ==> AndPredicate(sel1, sel2, sel3, sel4)
-        """
-        merged_selectors = []
-        for selector in selectors:
-            # XXX do we really want magic-transformations below?
-            # if so, wanna warn about them?
-            if isinstance(selector, types.FunctionType):
-                selector = objectify_predicate(selector)()
-            if isinstance(selector, type) and issubclass(selector, Predicate):
-                selector = selector()
-            assert isinstance(selector, Predicate), selector
-            if isinstance(selector, cls):
-                merged_selectors += selector.selectors
-            else:
-                merged_selectors.append(selector)
-        return merged_selectors
-
-    def search_selector(self, selector):
-        """search for the given selector or selector instance (or tuple of
-        selectors) in the selectors tree. Return None if not found
-        """
-        for childselector in self.selectors:
-            if childselector is selector:
-                return childselector
-            found = childselector.search_selector(selector)
-            if found is not None:
-                return found
-        # if not found in children, maybe we are looking for self?
-        return super(MultiPredicate, self).search_selector(selector)
-
-
-class AndPredicate(MultiPredicate):
-    """and-chained selectors"""
-    def __call__(self, cls, *args, **kwargs):
-        score = 0
-        for selector in self.selectors:
-            partscore = selector(cls, *args, **kwargs)
-            if not partscore:
-                return 0
-            score += partscore
-        return score
-
-
-class OrPredicate(MultiPredicate):
-    """or-chained selectors"""
-    def __call__(self, cls, *args, **kwargs):
-        for selector in self.selectors:
-            partscore = selector(cls, *args, **kwargs)
-            if partscore:
-                return partscore
-        return 0
-
-class NotPredicate(Predicate):
-    """negation selector"""
-    def __init__(self, selector):
-        self.selector = selector
-
-    def __call__(self, cls, *args, **kwargs):
-        score = self.selector(cls, *args, **kwargs)
-        return int(not score)
-
-    def __str__(self):
-        return 'NOT(%s)' % self.selector
-
-
-class yes(Predicate): # pylint: disable=C0103
-    """Return the score given as parameter, with a default score of 0.5 so any
-    other selector take precedence.
-
-    Usually used for objects which can be selected whatever the context, or
-    also sometimes to add arbitrary points to a score.
-
-    Take care, `yes(0)` could be named 'no'...
-    """
-    def __init__(self, score=0.5):
-        self.score = score
-
-    def __call__(self, *args, **kwargs):
-        return self.score

+ 0 - 456
pylibs/logilab/common/shellutils.py

@@ -1,456 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""shell/term utilities, useful to write some python scripts instead of shell
-scripts.
-"""
-__docformat__ = "restructuredtext en"
-
-import os
-import glob
-import shutil
-import stat
-import sys
-import tempfile
-import time
-import fnmatch
-import errno
-import string
-import random
-from os.path import exists, isdir, islink, basename, join
-
-from logilab.common import STD_BLACKLIST, _handle_blacklist
-from logilab.common.compat import raw_input
-from logilab.common.compat import str_to_bytes
-
-try:
-    from logilab.common.proc import ProcInfo, NoSuchProcess
-except ImportError:
-    # windows platform
-    class NoSuchProcess(Exception): pass
-
-    def ProcInfo(pid):
-        raise NoSuchProcess()
-
-
-class tempdir(object):
-
-    def __enter__(self):
-        self.path = tempfile.mkdtemp()
-        return self.path
-
-    def __exit__(self, exctype, value, traceback):
-        # rmtree in all cases
-        shutil.rmtree(self.path)
-        return traceback is None
-
-
-class pushd(object):
-    def __init__(self, directory):
-        self.directory = directory
-
-    def __enter__(self):
-        self.cwd = os.getcwd()
-        os.chdir(self.directory)
-        return self.directory
-
-    def __exit__(self, exctype, value, traceback):
-        os.chdir(self.cwd)
-
-
-def chown(path, login=None, group=None):
-    """Same as `os.chown` function but accepting user login or group name as
-    argument. If login or group is omitted, it's left unchanged.
-
-    Note: you must own the file to chown it (or be root). Otherwise OSError is raised.
-    """
-    if login is None:
-        uid = -1
-    else:
-        try:
-            uid = int(login)
-        except ValueError:
-            import pwd # Platforms: Unix
-            uid = pwd.getpwnam(login).pw_uid
-    if group is None:
-        gid = -1
-    else:
-        try:
-            gid = int(group)
-        except ValueError:
-            import grp
-            gid = grp.getgrnam(group).gr_gid
-    os.chown(path, uid, gid)
-
-def mv(source, destination, _action=shutil.move):
-    """A shell-like mv, supporting wildcards.
-    """
-    sources = glob.glob(source)
-    if len(sources) > 1:
-        assert isdir(destination)
-        for filename in sources:
-            _action(filename, join(destination, basename(filename)))
-    else:
-        try:
-            source = sources[0]
-        except IndexError:
-            raise OSError('No file matching %s' % source)
-        if isdir(destination) and exists(destination):
-            destination = join(destination, basename(source))
-        try:
-            _action(source, destination)
-        except OSError, ex:
-            raise OSError('Unable to move %r to %r (%s)' % (
-                source, destination, ex))
-
-def rm(*files):
-    """A shell-like rm, supporting wildcards.
-    """
-    for wfile in files:
-        for filename in glob.glob(wfile):
-            if islink(filename):
-                os.remove(filename)
-            elif isdir(filename):
-                shutil.rmtree(filename)
-            else:
-                os.remove(filename)
-
-def cp(source, destination):
-    """A shell-like cp, supporting wildcards.
-    """
-    mv(source, destination, _action=shutil.copy)
-
-def find(directory, exts, exclude=False, blacklist=STD_BLACKLIST):
-    """Recursively find files ending with the given extensions from the directory.
-
-    :type directory: str
-    :param directory:
-      directory where the search should start
-
-    :type exts: basestring or list or tuple
-    :param exts:
-      extensions or lists or extensions to search
-
-    :type exclude: boolean
-    :param exts:
-      if this argument is True, returning files NOT ending with the given
-      extensions
-
-    :type blacklist: list or tuple
-    :param blacklist:
-      optional list of files or directory to ignore, default to the value of
-      `logilab.common.STD_BLACKLIST`
-
-    :rtype: list
-    :return:
-      the list of all matching files
-    """
-    if isinstance(exts, basestring):
-        exts = (exts,)
-    if exclude:
-        def match(filename, exts):
-            for ext in exts:
-                if filename.endswith(ext):
-                    return False
-            return True
-    else:
-        def match(filename, exts):
-            for ext in exts:
-                if filename.endswith(ext):
-                    return True
-            return False
-    files = []
-    for dirpath, dirnames, filenames in os.walk(directory):
-        _handle_blacklist(blacklist, dirnames, filenames)
-        # don't append files if the directory is blacklisted
-        dirname = basename(dirpath)
-        if dirname in blacklist:
-            continue
-        files.extend([join(dirpath, f) for f in filenames if match(f, exts)])
-    return files
-
-
-def globfind(directory, pattern, blacklist=STD_BLACKLIST):
-    """Recursively finds files matching glob `pattern` under `directory`.
-
-    This is an alternative to `logilab.common.shellutils.find`.
-
-    :type directory: str
-    :param directory:
-      directory where the search should start
-
-    :type pattern: basestring
-    :param pattern:
-      the glob pattern (e.g *.py, foo*.py, etc.)
-
-    :type blacklist: list or tuple
-    :param blacklist:
-      optional list of files or directory to ignore, default to the value of
-      `logilab.common.STD_BLACKLIST`
-
-    :rtype: iterator
-    :return:
-      iterator over the list of all matching files
-    """
-    for curdir, dirnames, filenames in os.walk(directory):
-        _handle_blacklist(blacklist, dirnames, filenames)
-        for fname in fnmatch.filter(filenames, pattern):
-            yield join(curdir, fname)
-
-def unzip(archive, destdir):
-    import zipfile
-    if not exists(destdir):
-        os.mkdir(destdir)
-    zfobj = zipfile.ZipFile(archive)
-    for name in zfobj.namelist():
-        if name.endswith('/'):
-            os.mkdir(join(destdir, name))
-        else:
-            outfile = open(join(destdir, name), 'wb')
-            outfile.write(zfobj.read(name))
-            outfile.close()
-
-class Execute:
-    """This is a deadlock safe version of popen2 (no stdin), that returns
-    an object with errorlevel, out and err.
-    """
-
-    def __init__(self, command):
-        outfile = tempfile.mktemp()
-        errfile = tempfile.mktemp()
-        self.status = os.system("( %s ) >%s 2>%s" %
-                                (command, outfile, errfile)) >> 8
-        self.out = open(outfile, "r").read()
-        self.err = open(errfile, "r").read()
-        os.remove(outfile)
-        os.remove(errfile)
-
-def acquire_lock(lock_file, max_try=10, delay=10, max_delay=3600):
-    """Acquire a lock represented by a file on the file system
-
-    If the process written in lock file doesn't exist anymore, we remove the
-    lock file immediately
-    If age of the lock_file is greater than max_delay, then we raise a UserWarning
-    """
-    count = abs(max_try)
-    while count:
-        try:
-            fd = os.open(lock_file, os.O_EXCL | os.O_RDWR | os.O_CREAT)
-            os.write(fd, str_to_bytes(str(os.getpid())) )
-            os.close(fd)
-            return True
-        except OSError, e:
-            if e.errno == errno.EEXIST:
-                try:
-                    fd = open(lock_file, "r")
-                    pid = int(fd.readline())
-                    pi = ProcInfo(pid)
-                    age = (time.time() - os.stat(lock_file)[stat.ST_MTIME])
-                    if age / max_delay > 1 :
-                        raise UserWarning("Command '%s' (pid %s) has locked the "
-                                          "file '%s' for %s minutes"
-                                          % (pi.name(), pid, lock_file, age/60))
-                except UserWarning:
-                    raise
-                except NoSuchProcess:
-                    os.remove(lock_file)
-                except Exception:
-                    # The try block is not essential. can be skipped.
-                    # Note: ProcInfo object is only available for linux
-                    # process information are not accessible...
-                    # or lock_file is no more present...
-                    pass
-            else:
-                raise
-            count -= 1
-            time.sleep(delay)
-    else:
-        raise Exception('Unable to acquire %s' % lock_file)
-
-def release_lock(lock_file):
-    """Release a lock represented by a file on the file system."""
-    os.remove(lock_file)
-
-
-class ProgressBar(object):
-    """A simple text progression bar."""
-
-    def __init__(self, nbops, size=20, stream=sys.stdout, title=''):
-        if title:
-            self._fstr = '\r%s [%%-%ss]' % (title, int(size))
-        else:
-            self._fstr = '\r[%%-%ss]' % int(size)
-        self._stream = stream
-        self._total = nbops
-        self._size = size
-        self._current = 0
-        self._progress = 0
-        self._current_text = None
-        self._last_text_write_size = 0
-
-    def _get_text(self):
-        return self._current_text
-
-    def _set_text(self, text=None):
-        if text != self._current_text:
-            self._current_text = text
-            self.refresh()
-
-    def _del_text(self):
-        self.text = None
-
-    text = property(_get_text, _set_text, _del_text)
-
-    def update(self, offset=1, exact=False):
-        """Move FORWARD to new cursor position (cursor will never go backward).
-
-        :offset: fraction of ``size``
-
-        :exact:
-
-          - False: offset relative to current cursor position if True
-          - True: offset as an asbsolute position
-
-        """
-        if exact:
-            self._current = offset
-        else:
-            self._current += offset
-
-        progress = int((float(self._current)/float(self._total))*self._size)
-        if progress > self._progress:
-            self._progress = progress
-            self.refresh()
-
-    def refresh(self):
-        """Refresh the progression bar display."""
-        self._stream.write(self._fstr % ('.' * min(self._progress, self._size)) )
-        if self._last_text_write_size or self._current_text:
-            template = ' %%-%is' % (self._last_text_write_size)
-            text = self._current_text
-            if text is None:
-                text = ''
-            self._stream.write(template % text)
-            self._last_text_write_size = len(text.rstrip())
-        self._stream.flush()
-
-    def finish(self):
-        self._stream.write('\n')
-        self._stream.flush()
-
-
-class DummyProgressBar(object):
-    __slot__ = ('text',)
-
-    def refresh(self):
-        pass
-    def update(self):
-        pass
-    def finish(self):
-        pass
-
-
-_MARKER = object()
-class progress(object):
-
-    def __init__(self, nbops=_MARKER, size=_MARKER, stream=_MARKER, title=_MARKER, enabled=True):
-        self.nbops = nbops
-        self.size = size
-        self.stream = stream
-        self.title = title
-        self.enabled = enabled
-
-    def __enter__(self):
-        if self.enabled:
-            kwargs = {}
-            for attr in ('nbops', 'size', 'stream', 'title'):
-                value = getattr(self, attr)
-                if value is not _MARKER:
-                    kwargs[attr] = value
-            self.pb = ProgressBar(**kwargs)
-        else:
-            self.pb =  DummyProgressBar()
-        return self.pb
-
-    def __exit__(self, exc_type, exc_val, exc_tb):
-        self.pb.finish()
-
-class RawInput(object):
-
-    def __init__(self, input=None, printer=None):
-        self._input = input or raw_input
-        self._print = printer
-
-    def ask(self, question, options, default):
-        assert default in options
-        choices = []
-        for option in options:
-            if option == default:
-                label = option[0].upper()
-            else:
-                label = option[0].lower()
-            if len(option) > 1:
-                label += '(%s)' % option[1:].lower()
-            choices.append((option, label))
-        prompt = "%s [%s]: " % (question,
-                                '/'.join([opt[1] for opt in choices]))
-        tries = 3
-        while tries > 0:
-            answer = self._input(prompt).strip().lower()
-            if not answer:
-                return default
-            possible = [option for option, label in choices
-                        if option.lower().startswith(answer)]
-            if len(possible) == 1:
-                return possible[0]
-            elif len(possible) == 0:
-                msg = '%s is not an option.' % answer
-            else:
-                msg = ('%s is an ambiguous answer, do you mean %s ?' % (
-                        answer, ' or '.join(possible)))
-            if self._print:
-                self._print(msg)
-            else:
-                print msg
-            tries -= 1
-        raise Exception('unable to get a sensible answer')
-
-    def confirm(self, question, default_is_yes=True):
-        default = default_is_yes and 'y' or 'n'
-        answer = self.ask(question, ('y', 'n'), default)
-        return answer == 'y'
-
-ASK = RawInput()
-
-
-def getlogin():
-    """avoid using os.getlogin() because of strange tty / stdin problems
-    (man 3 getlogin)
-    Another solution would be to use $LOGNAME, $USER or $USERNAME
-    """
-    if sys.platform != 'win32':
-        import pwd # Platforms: Unix
-        return pwd.getpwuid(os.getuid())[0]
-    else:
-        return os.environ['USERNAME']
-
-def generate_password(length=8, vocab=string.ascii_letters + string.digits):
-    """dumb password generation function"""
-    pwd = ''
-    for i in xrange(length):
-        pwd += random.choice(vocab)
-    return pwd

+ 0 - 87
pylibs/logilab/common/sphinx_ext.py

@@ -1,87 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-from logilab.common.decorators import monkeypatch
-
-from sphinx.ext import autodoc
-
-class DocstringOnlyModuleDocumenter(autodoc.ModuleDocumenter):
-    objtype = 'docstring'
-    def format_signature(self):
-        pass
-    def add_directive_header(self, sig):
-        pass
-    def document_members(self, all_members=False):
-        pass
-
-    def resolve_name(self, modname, parents, path, base):
-        if modname is not None:
-            return modname, parents + [base]
-        return (path or '') + base, []
-
-
-#autodoc.add_documenter(DocstringOnlyModuleDocumenter)
-
-def setup(app):
-    app.add_autodocumenter(DocstringOnlyModuleDocumenter)
-
-
-
-from sphinx.ext.autodoc import (ViewList, Options, AutodocReporter, nodes,
-                                assemble_option_dict, nested_parse_with_titles)
-
-@monkeypatch(autodoc.AutoDirective)
-def run(self):
-    self.filename_set = set()  # a set of dependent filenames
-    self.reporter = self.state.document.reporter
-    self.env = self.state.document.settings.env
-    self.warnings = []
-    self.result = ViewList()
-
-    # find out what documenter to call
-    objtype = self.name[4:]
-    doc_class = self._registry[objtype]
-    # process the options with the selected documenter's option_spec
-    self.genopt = Options(assemble_option_dict(
-        self.options.items(), doc_class.option_spec))
-    # generate the output
-    documenter = doc_class(self, self.arguments[0])
-    documenter.generate(more_content=self.content)
-    if not self.result:
-        return self.warnings
-
-    # record all filenames as dependencies -- this will at least
-    # partially make automatic invalidation possible
-    for fn in self.filename_set:
-        self.env.note_dependency(fn)
-
-    # use a custom reporter that correctly assigns lines to source
-    # filename/description and lineno
-    old_reporter = self.state.memo.reporter
-    self.state.memo.reporter = AutodocReporter(self.result,
-                                               self.state.memo.reporter)
-    if self.name in ('automodule', 'autodocstring'):
-        node = nodes.section()
-        # necessary so that the child nodes get the right source/line set
-        node.document = self.state.document
-        nested_parse_with_titles(self.state, self.result, node)
-    else:
-        node = nodes.paragraph()
-        node.document = self.state.document
-        self.state.nested_parse(self.result, 0, node)
-    self.state.memo.reporter = old_reporter
-    return self.warnings + node.children

+ 0 - 122
pylibs/logilab/common/sphinxutils.py

@@ -1,122 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""Sphinx utils
-
-ModuleGenerator: Generate a file that lists all the modules of a list of
-packages in order to pull all the docstring.
-This should not be used in a makefile to systematically generate sphinx
-documentation!
-
-Typical usage:
-
->>> from logilab.common.sphinxutils import ModuleGenerator
->>> mgen = ModuleGenerator('logilab common', '/home/adim/src/logilab/common')
->>> mgen.generate('api_logilab_common.rst', exclude_dirs=('test',))
-"""
-
-import os, sys
-import os.path as osp
-import inspect
-
-from logilab.common import STD_BLACKLIST
-from logilab.common.shellutils import globfind
-from logilab.common.modutils import load_module_from_file, modpath_from_file
-
-def module_members(module):
-    members = []
-    for name, value in inspect.getmembers(module):
-        if getattr(value, '__module__', None) == module.__name__:
-            members.append( (name, value) )
-    return sorted(members)
-
-
-def class_members(klass):
-    return sorted([name for name in vars(klass)
-                   if name not in ('__doc__', '__module__',
-                                   '__dict__', '__weakref__')])
-
-class ModuleGenerator:
-    file_header = """.. -*- coding: utf-8 -*-\n\n%s\n"""
-    module_def = """
-:mod:`%s`
-=======%s
-
-.. automodule:: %s
-   :members: %s
-"""
-    class_def = """
-
-.. autoclass:: %s
-   :members: %s
-
-"""
-
-    def __init__(self, project_title, code_dir):
-        self.title = project_title
-        self.code_dir = osp.abspath(code_dir)
-
-    def generate(self, dest_file, exclude_dirs=STD_BLACKLIST):
-        """make the module file"""
-        self.fn = open(dest_file, 'w')
-        num = len(self.title) + 6
-        title = "=" * num + "\n %s API\n" % self.title + "=" * num
-        self.fn.write(self.file_header % title)
-        self.gen_modules(exclude_dirs=exclude_dirs)
-        self.fn.close()
-
-    def gen_modules(self, exclude_dirs):
-        """generate all modules"""
-        for module in self.find_modules(exclude_dirs):
-            modname = module.__name__
-            classes = []
-            modmembers = []
-            for objname, obj in module_members(module):
-                if inspect.isclass(obj):
-                    classmembers = class_members(obj)
-                    classes.append( (objname, classmembers) )
-                else:
-                    modmembers.append(objname)
-            self.fn.write(self.module_def % (modname, '=' * len(modname),
-                                             modname,
-                                             ', '.join(modmembers)))
-            for klass, members in classes:
-                self.fn.write(self.class_def % (klass, ', '.join(members)))
-
-    def find_modules(self, exclude_dirs):
-        basepath = osp.dirname(self.code_dir)
-        basedir = osp.basename(basepath) + osp.sep
-        if basedir not in sys.path:
-            sys.path.insert(1, basedir)
-        for filepath in globfind(self.code_dir, '*.py', exclude_dirs):
-            if osp.basename(filepath) in ('setup.py', '__pkginfo__.py'):
-                continue
-            try:
-                module = load_module_from_file(filepath)
-            except: # module might be broken or magic
-                dotted_path = modpath_from_file(filepath)
-                module = type('.'.join(dotted_path), (), {}) # mock it
-            yield module
-
-
-if __name__ == '__main__':
-    # example :
-    title, code_dir, outfile = sys.argv[1:]
-    generator = ModuleGenerator(title, code_dir)
-    # XXX modnames = ['logilab']
-    generator.generate(outfile, ('test', 'tests', 'examples',
-                             'data', 'doc', '.hg', 'migration'))

+ 0 - 923
pylibs/logilab/common/table.py

@@ -1,923 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""Table management module."""
-__docformat__ = "restructuredtext en"
-
-
-class Table(object):
-    """Table defines a data table with column and row names.
-    inv:
-        len(self.data) <= len(self.row_names)
-        forall(self.data, lambda x: len(x) <= len(self.col_names))
-    """
-
-    def __init__(self, default_value=0, col_names=None, row_names=None):
-        self.col_names = []
-        self.row_names = []
-        self.data = []
-        self.default_value = default_value
-        if col_names:
-            self.create_columns(col_names)
-        if row_names:
-            self.create_rows(row_names)
-
-    def _next_row_name(self):
-        return 'row%s' % (len(self.row_names)+1)
-
-    def __iter__(self):
-        return iter(self.data)
-
-    def __eq__(self, other):
-        if other is None:
-            return False
-        else:
-            return list(self) == list(other)
-
-    def __ne__(self, other):
-        return not self == other
-
-    def __len__(self):
-        return len(self.row_names)
-
-    ## Rows / Columns creation #################################################
-    def create_rows(self, row_names):
-        """Appends row_names to the list of existing rows
-        """
-        self.row_names.extend(row_names)
-        for row_name in row_names:
-            self.data.append([self.default_value]*len(self.col_names))
-
-    def create_columns(self, col_names):
-        """Appends col_names to the list of existing columns
-        """
-        for col_name in col_names:
-            self.create_column(col_name)
-
-    def create_row(self, row_name=None):
-        """Creates a rowname to the row_names list
-        """
-        row_name = row_name or self._next_row_name()
-        self.row_names.append(row_name)
-        self.data.append([self.default_value]*len(self.col_names))
-
-
-    def create_column(self, col_name):
-        """Creates a colname to the col_names list
-        """
-        self.col_names.append(col_name)
-        for row in self.data:
-            row.append(self.default_value)
-
-    ## Sort by column ##########################################################
-    def sort_by_column_id(self, col_id, method = 'asc'):
-        """Sorts the table (in-place) according to data stored in col_id
-        """
-        try:
-            col_index = self.col_names.index(col_id)
-            self.sort_by_column_index(col_index, method)
-        except ValueError:
-            raise KeyError("Col (%s) not found in table" % (col_id))
-
-
-    def sort_by_column_index(self, col_index, method = 'asc'):
-        """Sorts the table 'in-place' according to data stored in col_index
-
-        method should be in ('asc', 'desc')
-        """
-        sort_list = sorted([(row[col_index], row, row_name)
-                     for row, row_name in zip(self.data, self.row_names)])
-        # Sorting sort_list will sort according to col_index
-        # If we want reverse sort, then reverse list
-        if method.lower() == 'desc':
-            sort_list.reverse()
-
-        # Rebuild data / row names
-        self.data = []
-        self.row_names = []
-        for val, row, row_name in sort_list:
-            self.data.append(row)
-            self.row_names.append(row_name)
-
-    def groupby(self, colname, *others):
-        """builds indexes of data
-        :returns: nested dictionaries pointing to actual rows
-        """
-        groups = {}
-        colnames = (colname,) + others
-        col_indexes = [self.col_names.index(col_id) for col_id in colnames]
-        for row in self.data:
-            ptr = groups
-            for col_index in col_indexes[:-1]:
-                ptr = ptr.setdefault(row[col_index], {})
-            ptr = ptr.setdefault(row[col_indexes[-1]],
-                                 Table(default_value=self.default_value,
-                                       col_names=self.col_names))
-            ptr.append_row(tuple(row))
-        return groups
-
-    def select(self, colname, value):
-        grouped = self.groupby(colname)
-        try:
-            return grouped[value]
-        except KeyError:
-            return []
-
-    def remove(self, colname, value):
-        col_index = self.col_names.index(colname)
-        for row in self.data[:]:
-            if row[col_index] == value:
-                self.data.remove(row)
-
-
-    ## The 'setter' part #######################################################
-    def set_cell(self, row_index, col_index, data):
-        """sets value of cell 'row_indew', 'col_index' to data
-        """
-        self.data[row_index][col_index] = data
-
-
-    def set_cell_by_ids(self, row_id, col_id, data):
-        """sets value of cell mapped by row_id and col_id to data
-        Raises a KeyError if row_id or col_id are not found in the table
-        """
-        try:
-            row_index = self.row_names.index(row_id)
-        except ValueError:
-            raise KeyError("Row (%s) not found in table" % (row_id))
-        else:
-            try:
-                col_index = self.col_names.index(col_id)
-                self.data[row_index][col_index] = data
-            except ValueError:
-                raise KeyError("Column (%s) not found in table" % (col_id))
-
-
-    def set_row(self, row_index, row_data):
-        """sets the 'row_index' row
-        pre:
-            type(row_data) == types.ListType
-            len(row_data) == len(self.col_names)
-        """
-        self.data[row_index] = row_data
-
-
-    def set_row_by_id(self, row_id, row_data):
-        """sets the 'row_id' column
-        pre:
-            type(row_data) == types.ListType
-            len(row_data) == len(self.row_names)
-        Raises a KeyError if row_id is not found
-        """
-        try:
-            row_index = self.row_names.index(row_id)
-            self.set_row(row_index, row_data)
-        except ValueError:
-            raise KeyError('Row (%s) not found in table' % (row_id))
-
-
-    def append_row(self, row_data, row_name=None):
-        """Appends a row to the table
-        pre:
-            type(row_data) == types.ListType
-            len(row_data) == len(self.col_names)
-        """
-        row_name = row_name or self._next_row_name()
-        self.row_names.append(row_name)
-        self.data.append(row_data)
-        return len(self.data) - 1
-
-    def insert_row(self, index, row_data, row_name=None):
-        """Appends row_data before 'index' in the table. To make 'insert'
-        behave like 'list.insert', inserting in an out of range index will
-        insert row_data to the end of the list
-        pre:
-            type(row_data) == types.ListType
-            len(row_data) == len(self.col_names)
-        """
-        row_name = row_name or self._next_row_name()
-        self.row_names.insert(index, row_name)
-        self.data.insert(index, row_data)
-
-
-    def delete_row(self, index):
-        """Deletes the 'index' row in the table, and returns it.
-        Raises an IndexError if index is out of range
-        """
-        self.row_names.pop(index)
-        return self.data.pop(index)
-
-
-    def delete_row_by_id(self, row_id):
-        """Deletes the 'row_id' row in the table.
-        Raises a KeyError if row_id was not found.
-        """
-        try:
-            row_index = self.row_names.index(row_id)
-            self.delete_row(row_index)
-        except ValueError:
-            raise KeyError('Row (%s) not found in table' % (row_id))
-
-
-    def set_column(self, col_index, col_data):
-        """sets the 'col_index' column
-        pre:
-            type(col_data) == types.ListType
-            len(col_data) == len(self.row_names)
-        """
-
-        for row_index, cell_data in enumerate(col_data):
-            self.data[row_index][col_index] = cell_data
-
-
-    def set_column_by_id(self, col_id, col_data):
-        """sets the 'col_id' column
-        pre:
-            type(col_data) == types.ListType
-            len(col_data) == len(self.col_names)
-        Raises a KeyError if col_id is not found
-        """
-        try:
-            col_index = self.col_names.index(col_id)
-            self.set_column(col_index, col_data)
-        except ValueError:
-            raise KeyError('Column (%s) not found in table' % (col_id))
-
-
-    def append_column(self, col_data, col_name):
-        """Appends the 'col_index' column
-        pre:
-            type(col_data) == types.ListType
-            len(col_data) == len(self.row_names)
-        """
-        self.col_names.append(col_name)
-        for row_index, cell_data in enumerate(col_data):
-            self.data[row_index].append(cell_data)
-
-
-    def insert_column(self, index, col_data, col_name):
-        """Appends col_data before 'index' in the table. To make 'insert'
-        behave like 'list.insert', inserting in an out of range index will
-        insert col_data to the end of the list
-        pre:
-            type(col_data) == types.ListType
-            len(col_data) == len(self.row_names)
-        """
-        self.col_names.insert(index, col_name)
-        for row_index, cell_data in enumerate(col_data):
-            self.data[row_index].insert(index, cell_data)
-
-
-    def delete_column(self, index):
-        """Deletes the 'index' column in the table, and returns it.
-        Raises an IndexError if index is out of range
-        """
-        self.col_names.pop(index)
-        return [row.pop(index) for row in self.data]
-
-
-    def delete_column_by_id(self, col_id):
-        """Deletes the 'col_id' col in the table.
-        Raises a KeyError if col_id was not found.
-        """
-        try:
-            col_index = self.col_names.index(col_id)
-            self.delete_column(col_index)
-        except ValueError:
-            raise KeyError('Column (%s) not found in table' % (col_id))
-
-
-    ## The 'getter' part #######################################################
-
-    def get_shape(self):
-        """Returns a tuple which represents the table's shape
-        """
-        return len(self.row_names), len(self.col_names)
-    shape = property(get_shape)
-
-    def __getitem__(self, indices):
-        """provided for convenience"""
-        rows, multirows = None, False
-        cols, multicols = None, False
-        if isinstance(indices, tuple):
-            rows = indices[0]
-            if len(indices) > 1:
-                cols = indices[1]
-        else:
-            rows = indices
-        # define row slice
-        if isinstance(rows, str):
-            try:
-                rows = self.row_names.index(rows)
-            except ValueError:
-                raise KeyError("Row (%s) not found in table" % (rows))
-        if isinstance(rows, int):
-            rows = slice(rows, rows+1)
-            multirows = False
-        else:
-            rows = slice(None)
-            multirows = True
-        # define col slice
-        if isinstance(cols, str):
-            try:
-                cols = self.col_names.index(cols)
-            except ValueError:
-                raise KeyError("Column (%s) not found in table" % (cols))
-        if isinstance(cols, int):
-            cols = slice(cols, cols+1)
-            multicols = False
-        else:
-            cols = slice(None)
-            multicols = True
-        # get sub-table
-        tab = Table()
-        tab.default_value = self.default_value
-        tab.create_rows(self.row_names[rows])
-        tab.create_columns(self.col_names[cols])
-        for idx, row in enumerate(self.data[rows]):
-            tab.set_row(idx, row[cols])
-        if multirows :
-            if multicols:
-                return tab
-            else:
-                return [item[0] for item in tab.data]
-        else:
-            if multicols:
-                return tab.data[0]
-            else:
-                return tab.data[0][0]
-
-    def get_cell_by_ids(self, row_id, col_id):
-        """Returns the element at [row_id][col_id]
-        """
-        try:
-            row_index = self.row_names.index(row_id)
-        except ValueError:
-            raise KeyError("Row (%s) not found in table" % (row_id))
-        else:
-            try:
-                col_index = self.col_names.index(col_id)
-            except ValueError:
-                raise KeyError("Column (%s) not found in table" % (col_id))
-        return self.data[row_index][col_index]
-
-    def get_row_by_id(self, row_id):
-        """Returns the 'row_id' row
-        """
-        try:
-            row_index = self.row_names.index(row_id)
-        except ValueError:
-            raise KeyError("Row (%s) not found in table" % (row_id))
-        return self.data[row_index]
-
-    def get_column_by_id(self, col_id, distinct=False):
-        """Returns the 'col_id' col
-        """
-        try:
-            col_index = self.col_names.index(col_id)
-        except ValueError:
-            raise KeyError("Column (%s) not found in table" % (col_id))
-        return self.get_column(col_index, distinct)
-
-    def get_columns(self):
-        """Returns all the columns in the table
-        """
-        return [self[:, index] for index in range(len(self.col_names))]
-
-    def get_column(self, col_index, distinct=False):
-        """get a column by index"""
-        col = [row[col_index] for row in self.data]
-        if distinct:
-            col = list(set(col))
-        return col
-
-    def apply_stylesheet(self, stylesheet):
-        """Applies the stylesheet to this table
-        """
-        for instruction in stylesheet.instructions:
-            eval(instruction)
-
-
-    def transpose(self):
-        """Keeps the self object intact, and returns the transposed (rotated)
-        table.
-        """
-        transposed = Table()
-        transposed.create_rows(self.col_names)
-        transposed.create_columns(self.row_names)
-        for col_index, column in enumerate(self.get_columns()):
-            transposed.set_row(col_index, column)
-        return transposed
-
-
-    def pprint(self):
-        """returns a string representing the table in a pretty
-        printed 'text' format.
-        """
-        # The maximum row name (to know the start_index of the first col)
-        max_row_name = 0
-        for row_name in self.row_names:
-            if len(row_name) > max_row_name:
-                max_row_name = len(row_name)
-        col_start = max_row_name + 5
-
-        lines = []
-        # Build the 'first' line <=> the col_names one
-        # The first cell <=> an empty one
-        col_names_line = [' '*col_start]
-        for col_name in self.col_names:
-            col_names_line.append(col_name.encode('iso-8859-1') + ' '*5)
-        lines.append('|' + '|'.join(col_names_line) + '|')
-        max_line_length = len(lines[0])
-
-        # Build the table
-        for row_index, row in enumerate(self.data):
-            line = []
-            # First, build the row_name's cell
-            row_name = self.row_names[row_index].encode('iso-8859-1')
-            line.append(row_name + ' '*(col_start-len(row_name)))
-
-            # Then, build all the table's cell for this line.
-            for col_index, cell in enumerate(row):
-                col_name_length = len(self.col_names[col_index]) + 5
-                data = str(cell)
-                line.append(data + ' '*(col_name_length - len(data)))
-            lines.append('|' + '|'.join(line) + '|')
-            if len(lines[-1]) > max_line_length:
-                max_line_length = len(lines[-1])
-
-        # Wrap the table with '-' to make a frame
-        lines.insert(0, '-'*max_line_length)
-        lines.append('-'*max_line_length)
-        return '\n'.join(lines)
-
-
-    def __repr__(self):
-        return repr(self.data)
-
-    def as_text(self):
-        data = []
-        # We must convert cells into strings before joining them
-        for row in self.data:
-            data.append([str(cell) for cell in row])
-        lines = ['\t'.join(row) for row in data]
-        return '\n'.join(lines)
-
-
-
-class TableStyle:
-    """Defines a table's style
-    """
-
-    def __init__(self, table):
-
-        self._table = table
-        self.size = dict([(col_name, '1*') for col_name in table.col_names])
-        # __row_column__ is a special key to define the first column which
-        # actually has no name (<=> left most column <=> row names column)
-        self.size['__row_column__'] = '1*'
-        self.alignment = dict([(col_name, 'right')
-                               for col_name in table.col_names])
-        self.alignment['__row_column__'] = 'right'
-
-        # We shouldn't have to create an entry for
-        # the 1st col (the row_column one)
-        self.units = dict([(col_name, '') for col_name in table.col_names])
-        self.units['__row_column__'] = ''
-
-    # XXX FIXME : params order should be reversed for all set() methods
-    def set_size(self, value, col_id):
-        """sets the size of the specified col_id to value
-        """
-        self.size[col_id] = value
-
-    def set_size_by_index(self, value, col_index):
-        """Allows to set the size according to the column index rather than
-        using the column's id.
-        BE CAREFUL : the '0' column is the '__row_column__' one !
-        """
-        if col_index == 0:
-            col_id = '__row_column__'
-        else:
-            col_id = self._table.col_names[col_index-1]
-
-        self.size[col_id] = value
-
-
-    def set_alignment(self, value, col_id):
-        """sets the alignment of the specified col_id to value
-        """
-        self.alignment[col_id] = value
-
-
-    def set_alignment_by_index(self, value, col_index):
-        """Allows to set the alignment according to the column index rather than
-        using the column's id.
-        BE CAREFUL : the '0' column is the '__row_column__' one !
-        """
-        if col_index == 0:
-            col_id = '__row_column__'
-        else:
-            col_id = self._table.col_names[col_index-1]
-
-        self.alignment[col_id] = value
-
-
-    def set_unit(self, value, col_id):
-        """sets the unit of the specified col_id to value
-        """
-        self.units[col_id] = value
-
-
-    def set_unit_by_index(self, value, col_index):
-        """Allows to set the unit according to the column index rather than
-        using the column's id.
-        BE CAREFUL :  the '0' column is the '__row_column__' one !
-        (Note that in the 'unit' case, you shouldn't have to set a unit
-        for the 1st column (the __row__column__ one))
-        """
-        if col_index == 0:
-            col_id = '__row_column__'
-        else:
-            col_id = self._table.col_names[col_index-1]
-
-        self.units[col_id] = value
-
-
-    def get_size(self, col_id):
-        """Returns the size of the specified col_id
-        """
-        return self.size[col_id]
-
-
-    def get_size_by_index(self, col_index):
-        """Allows to get the size  according to the column index rather than
-        using the column's id.
-        BE CAREFUL : the '0' column is the '__row_column__' one !
-        """
-        if col_index == 0:
-            col_id = '__row_column__'
-        else:
-            col_id = self._table.col_names[col_index-1]
-
-        return self.size[col_id]
-
-
-    def get_alignment(self, col_id):
-        """Returns the alignment of the specified col_id
-        """
-        return self.alignment[col_id]
-
-
-    def get_alignment_by_index(self, col_index):
-        """Allors to get the alignment according to the column index rather than
-        using the column's id.
-        BE CAREFUL : the '0' column is the '__row_column__' one !
-        """
-        if col_index == 0:
-            col_id = '__row_column__'
-        else:
-            col_id = self._table.col_names[col_index-1]
-
-        return self.alignment[col_id]
-
-
-    def get_unit(self, col_id):
-        """Returns the unit of the specified col_id
-        """
-        return self.units[col_id]
-
-
-    def get_unit_by_index(self, col_index):
-        """Allors to get the unit according to the column index rather than
-        using the column's id.
-        BE CAREFUL : the '0' column is the '__row_column__' one !
-        """
-        if col_index == 0:
-            col_id = '__row_column__'
-        else:
-            col_id = self._table.col_names[col_index-1]
-
-        return self.units[col_id]
-
-
-import re
-CELL_PROG = re.compile("([0-9]+)_([0-9]+)")
-
-class TableStyleSheet:
-    """A simple Table stylesheet
-    Rules are expressions where cells are defined by the row_index
-    and col_index separated by an underscore ('_').
-    For example, suppose you want to say that the (2,5) cell must be
-    the sum of its two preceding cells in the row, you would create
-    the following rule :
-        2_5 = 2_3 + 2_4
-    You can also use all the math.* operations you want. For example:
-        2_5 = sqrt(2_3**2 + 2_4**2)
-    """
-
-    def __init__(self, rules = None):
-        rules = rules or []
-        self.rules = []
-        self.instructions = []
-        for rule in rules:
-            self.add_rule(rule)
-
-
-    def add_rule(self, rule):
-        """Adds a rule to the stylesheet rules
-        """
-        try:
-            source_code = ['from math import *']
-            source_code.append(CELL_PROG.sub(r'self.data[\1][\2]', rule))
-            self.instructions.append(compile('\n'.join(source_code),
-                'table.py', 'exec'))
-            self.rules.append(rule)
-        except SyntaxError:
-            print "Bad Stylesheet Rule : %s [skipped]"%rule
-
-
-    def add_rowsum_rule(self, dest_cell, row_index, start_col, end_col):
-        """Creates and adds a rule to sum over the row at row_index from
-        start_col to end_col.
-        dest_cell is a tuple of two elements (x,y) of the destination cell
-        No check is done for indexes ranges.
-        pre:
-            start_col >= 0
-            end_col > start_col
-        """
-        cell_list = ['%d_%d'%(row_index, index) for index in range(start_col,
-                                                                   end_col + 1)]
-        rule = '%d_%d=' % dest_cell + '+'.join(cell_list)
-        self.add_rule(rule)
-
-
-    def add_rowavg_rule(self, dest_cell, row_index, start_col, end_col):
-        """Creates and adds a rule to make the row average (from start_col
-        to end_col)
-        dest_cell is a tuple of two elements (x,y) of the destination cell
-        No check is done for indexes ranges.
-        pre:
-            start_col >= 0
-            end_col > start_col
-        """
-        cell_list = ['%d_%d'%(row_index, index) for index in range(start_col,
-                                                                   end_col + 1)]
-        num = (end_col - start_col + 1)
-        rule = '%d_%d=' % dest_cell + '('+'+'.join(cell_list)+')/%f'%num
-        self.add_rule(rule)
-
-
-    def add_colsum_rule(self, dest_cell, col_index, start_row, end_row):
-        """Creates and adds a rule to sum over the col at col_index from
-        start_row to end_row.
-        dest_cell is a tuple of two elements (x,y) of the destination cell
-        No check is done for indexes ranges.
-        pre:
-            start_row >= 0
-            end_row > start_row
-        """
-        cell_list = ['%d_%d'%(index, col_index) for index in range(start_row,
-                                                                   end_row + 1)]
-        rule = '%d_%d=' % dest_cell + '+'.join(cell_list)
-        self.add_rule(rule)
-
-
-    def add_colavg_rule(self, dest_cell, col_index, start_row, end_row):
-        """Creates and adds a rule to make the col average (from start_row
-        to end_row)
-        dest_cell is a tuple of two elements (x,y) of the destination cell
-        No check is done for indexes ranges.
-        pre:
-            start_row >= 0
-            end_row > start_row
-        """
-        cell_list = ['%d_%d'%(index, col_index) for index in range(start_row,
-                                                                   end_row + 1)]
-        num = (end_row - start_row + 1)
-        rule = '%d_%d=' % dest_cell + '('+'+'.join(cell_list)+')/%f'%num
-        self.add_rule(rule)
-
-
-
-class TableCellRenderer:
-    """Defines a simple text renderer
-    """
-
-    def __init__(self, **properties):
-        """keywords should be properties with an associated boolean as value.
-        For example :
-            renderer = TableCellRenderer(units = True, alignment = False)
-        An unspecified property will have a 'False' value by default.
-        Possible properties are :
-            alignment, unit
-        """
-        self.properties = properties
-
-
-    def render_cell(self, cell_coord, table, table_style):
-        """Renders the cell at 'cell_coord' in the table, using table_style
-        """
-        row_index, col_index = cell_coord
-        cell_value = table.data[row_index][col_index]
-        final_content = self._make_cell_content(cell_value,
-                                                table_style, col_index  +1)
-        return self._render_cell_content(final_content,
-                                         table_style, col_index + 1)
-
-
-    def render_row_cell(self, row_name, table, table_style):
-        """Renders the cell for 'row_id' row
-        """
-        cell_value = row_name.encode('iso-8859-1')
-        return self._render_cell_content(cell_value, table_style, 0)
-
-
-    def render_col_cell(self, col_name, table, table_style):
-        """Renders the cell for 'col_id' row
-        """
-        cell_value = col_name.encode('iso-8859-1')
-        col_index = table.col_names.index(col_name)
-        return self._render_cell_content(cell_value, table_style, col_index +1)
-
-
-
-    def _render_cell_content(self, content, table_style, col_index):
-        """Makes the appropriate rendering for this cell content.
-        Rendering properties will be searched using the
-        *table_style.get_xxx_by_index(col_index)' methods
-
-        **This method should be overridden in the derived renderer classes.**
-        """
-        return content
-
-
-    def _make_cell_content(self, cell_content, table_style, col_index):
-        """Makes the cell content (adds decoration data, like units for
-        example)
-        """
-        final_content = cell_content
-        if 'skip_zero' in self.properties:
-            replacement_char = self.properties['skip_zero']
-        else:
-            replacement_char = 0
-        if replacement_char and final_content == 0:
-            return replacement_char
-
-        try:
-            units_on = self.properties['units']
-            if units_on:
-                final_content = self._add_unit(
-                    cell_content, table_style, col_index)
-        except KeyError:
-            pass
-
-        return final_content
-
-
-    def _add_unit(self, cell_content, table_style, col_index):
-        """Adds unit to the cell_content if needed
-        """
-        unit = table_style.get_unit_by_index(col_index)
-        return str(cell_content) + " " + unit
-
-
-
-class DocbookRenderer(TableCellRenderer):
-    """Defines how to render a cell for a docboook table
-    """
-
-    def define_col_header(self, col_index, table_style):
-        """Computes the colspec element according to the style
-        """
-        size = table_style.get_size_by_index(col_index)
-        return '<colspec colname="c%d" colwidth="%s"/>\n' % \
-               (col_index, size)
-
-
-    def _render_cell_content(self, cell_content, table_style, col_index):
-        """Makes the appropriate rendering for this cell content.
-        Rendering properties will be searched using the
-        table_style.get_xxx_by_index(col_index)' methods.
-        """
-        try:
-            align_on = self.properties['alignment']
-            alignment = table_style.get_alignment_by_index(col_index)
-            if align_on:
-                return "<entry align='%s'>%s</entry>\n" % \
-                       (alignment, cell_content)
-        except KeyError:
-            # KeyError <=> Default alignment
-            return "<entry>%s</entry>\n" % cell_content
-
-
-class TableWriter:
-    """A class to write tables
-    """
-
-    def __init__(self, stream, table, style, **properties):
-        self._stream = stream
-        self.style = style or TableStyle(table)
-        self._table = table
-        self.properties = properties
-        self.renderer = None
-
-
-    def set_style(self, style):
-        """sets the table's associated style
-        """
-        self.style = style
-
-
-    def set_renderer(self, renderer):
-        """sets the way to render cell
-        """
-        self.renderer = renderer
-
-
-    def update_properties(self, **properties):
-        """Updates writer's properties (for cell rendering)
-        """
-        self.properties.update(properties)
-
-
-    def write_table(self, title = ""):
-        """Writes the table
-        """
-        raise NotImplementedError("write_table must be implemented !")
-
-
-
-class DocbookTableWriter(TableWriter):
-    """Defines an implementation of TableWriter to write a table in Docbook
-    """
-
-    def _write_headers(self):
-        """Writes col headers
-        """
-        # Define col_headers (colstpec elements)
-        for col_index in range(len(self._table.col_names)+1):
-            self._stream.write(self.renderer.define_col_header(col_index,
-                                                              self.style))
-
-        self._stream.write("<thead>\n<row>\n")
-        # XXX FIXME : write an empty entry <=> the first (__row_column) column
-        self._stream.write('<entry></entry>\n')
-        for col_name in self._table.col_names:
-            self._stream.write(self.renderer.render_col_cell(
-                col_name, self._table,
-                self.style))
-
-        self._stream.write("</row>\n</thead>\n")
-
-
-    def _write_body(self):
-        """Writes the table body
-        """
-        self._stream.write('<tbody>\n')
-
-        for row_index, row in enumerate(self._table.data):
-            self._stream.write('<row>\n')
-            row_name = self._table.row_names[row_index]
-            # Write the first entry (row_name)
-            self._stream.write(self.renderer.render_row_cell(row_name,
-                                                            self._table,
-                                                            self.style))
-
-            for col_index, cell in enumerate(row):
-                self._stream.write(self.renderer.render_cell(
-                    (row_index, col_index),
-                    self._table, self.style))
-
-            self._stream.write('</row>\n')
-
-        self._stream.write('</tbody>\n')
-
-
-    def write_table(self, title = ""):
-        """Writes the table
-        """
-        self._stream.write('<table>\n<title>%s></title>\n'%(title))
-        self._stream.write(
-            '<tgroup cols="%d" align="left" colsep="1" rowsep="1">\n'%
-            (len(self._table.col_names)+1))
-        self._write_headers()
-        self._write_body()
-
-        self._stream.write('</tgroup>\n</table>\n')
-
-

+ 0 - 98
pylibs/logilab/common/tasksqueue.py

@@ -1,98 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""Prioritized tasks queue"""
-
-__docformat__ = "restructuredtext en"
-
-from bisect import insort_left
-from Queue import Queue
-
-LOW = 0
-MEDIUM = 10
-HIGH = 100
-
-PRIORITY = {
-    'LOW': LOW,
-    'MEDIUM': MEDIUM,
-    'HIGH': HIGH,
-    }
-REVERSE_PRIORITY = dict((values, key) for key, values in PRIORITY.iteritems())
-
-
-
-class PrioritizedTasksQueue(Queue):
-
-    def _init(self, maxsize):
-        """Initialize the queue representation"""
-        self.maxsize = maxsize
-        # ordered list of task, from the lowest to the highest priority
-        self.queue = []
-
-    def _put(self, item):
-        """Put a new item in the queue"""
-        for i, task in enumerate(self.queue):
-            # equivalent task
-            if task == item:
-                # if new task has a higher priority, remove the one already
-                # queued so the new priority will be considered
-                if task < item:
-                    item.merge(task)
-                    del self.queue[i]
-                    break
-                # else keep it so current order is kept
-                task.merge(item)
-                return
-        insort_left(self.queue, item)
-
-    def _get(self):
-        """Get an item from the queue"""
-        return self.queue.pop()
-
-    def __iter__(self):
-        return iter(self.queue)
-
-    def remove(self, tid):
-        """remove a specific task from the queue"""
-        # XXX acquire lock
-        for i, task in enumerate(self):
-            if task.id == tid:
-                self.queue.pop(i)
-                return
-        raise ValueError('not task of id %s in queue' % tid)
-
-class Task(object):
-    def __init__(self, tid, priority=LOW):
-        # task id
-        self.id = tid
-        # task priority
-        self.priority = priority
-
-    def __repr__(self):
-        return '<Task %s @%#x>' % (self.id, id(self))
-
-    def __cmp__(self, other):
-        return cmp(self.priority, other.priority)
-
-    def __lt__(self, other):
-        return self.priority < other.priority
-
-    def __eq__(self, other):
-        return self.id == other.id
-
-    def merge(self, other):
-        pass

Plik diff jest za duży
+ 0 - 1389
pylibs/logilab/common/testlib.py


+ 0 - 534
pylibs/logilab/common/textutils.py

@@ -1,534 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""Some text manipulation utility functions.
-
-
-:group text formatting: normalize_text, normalize_paragraph, pretty_match,\
-unquote, colorize_ansi
-:group text manipulation: searchall, splitstrip
-:sort: text formatting, text manipulation
-
-:type ANSI_STYLES: dict(str)
-:var ANSI_STYLES: dictionary mapping style identifier to ANSI terminal code
-
-:type ANSI_COLORS: dict(str)
-:var ANSI_COLORS: dictionary mapping color identifier to ANSI terminal code
-
-:type ANSI_PREFIX: str
-:var ANSI_PREFIX:
-  ANSI terminal code notifying the start of an ANSI escape sequence
-
-:type ANSI_END: str
-:var ANSI_END:
-  ANSI terminal code notifying the end of an ANSI escape sequence
-
-:type ANSI_RESET: str
-:var ANSI_RESET:
-  ANSI terminal code resetting format defined by a previous ANSI escape sequence
-"""
-__docformat__ = "restructuredtext en"
-
-import sys
-import re
-import os.path as osp
-from warnings import warn
-from unicodedata import normalize as _uninormalize
-try:
-    from os import linesep
-except ImportError:
-    linesep = '\n' # gae
-
-from logilab.common.deprecation import deprecated
-
-MANUAL_UNICODE_MAP = {
-    u'\xa1': u'!',    # INVERTED EXCLAMATION MARK
-    u'\u0142': u'l',  # LATIN SMALL LETTER L WITH STROKE
-    u'\u2044': u'/',  # FRACTION SLASH
-    u'\xc6': u'AE',   # LATIN CAPITAL LETTER AE
-    u'\xa9': u'(c)',  # COPYRIGHT SIGN
-    u'\xab': u'"',    # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
-    u'\xe6': u'ae',   # LATIN SMALL LETTER AE
-    u'\xae': u'(r)',  # REGISTERED SIGN
-    u'\u0153': u'oe', # LATIN SMALL LIGATURE OE
-    u'\u0152': u'OE', # LATIN CAPITAL LIGATURE OE
-    u'\xd8': u'O',    # LATIN CAPITAL LETTER O WITH STROKE
-    u'\xf8': u'o',    # LATIN SMALL LETTER O WITH STROKE
-    u'\xbb': u'"',    # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
-    u'\xdf': u'ss',   # LATIN SMALL LETTER SHARP S
-    }
-
-def unormalize(ustring, ignorenonascii=None, substitute=None):
-    """replace diacritical characters with their corresponding ascii characters
-
-    Convert the unicode string to its long normalized form (unicode character
-    will be transform into several characters) and keep the first one only.
-    The normal form KD (NFKD) will apply the compatibility decomposition, i.e.
-    replace all compatibility characters with their equivalents.
-
-    :type substitute: str
-    :param substitute: replacement character to use if decomposition fails
-
-    :see: Another project about ASCII transliterations of Unicode text
-          http://pypi.python.org/pypi/Unidecode
-    """
-    # backward compatibility, ignorenonascii was a boolean
-    if ignorenonascii is not None:
-        warn("ignorenonascii is deprecated, use substitute named parameter instead",
-             DeprecationWarning, stacklevel=2)
-        if ignorenonascii:
-            substitute = ''
-    res = []
-    for letter in ustring[:]:
-        try:
-            replacement = MANUAL_UNICODE_MAP[letter]
-        except KeyError:
-            replacement = _uninormalize('NFKD', letter)[0]
-            if ord(replacement) >= 2 ** 7:
-                if substitute is None:
-                    raise ValueError("can't deal with non-ascii based characters")
-                replacement = substitute
-        res.append(replacement)
-    return u''.join(res)
-
-def unquote(string):
-    """remove optional quotes (simple or double) from the string
-
-    :type string: str or unicode
-    :param string: an optionally quoted string
-
-    :rtype: str or unicode
-    :return: the unquoted string (or the input string if it wasn't quoted)
-    """
-    if not string:
-        return string
-    if string[0] in '"\'':
-        string = string[1:]
-    if string[-1] in '"\'':
-        string = string[:-1]
-    return string
-
-
-_BLANKLINES_RGX = re.compile('\r?\n\r?\n')
-_NORM_SPACES_RGX = re.compile('\s+')
-
-def normalize_text(text, line_len=80, indent='', rest=False):
-    """normalize a text to display it with a maximum line size and
-    optionally arbitrary indentation. Line jumps are normalized but blank
-    lines are kept. The indentation string may be used to insert a
-    comment (#) or a quoting (>) mark  for instance.
-
-    :type text: str or unicode
-    :param text: the input text to normalize
-
-    :type line_len: int
-    :param line_len: expected maximum line's length, default to 80
-
-    :type indent: str or unicode
-    :param indent: optional string to use as indentation
-
-    :rtype: str or unicode
-    :return:
-      the input text normalized to fit on lines with a maximized size
-      inferior to `line_len`, and optionally prefixed by an
-      indentation string
-    """
-    if rest:
-        normp = normalize_rest_paragraph
-    else:
-        normp = normalize_paragraph
-    result = []
-    for text in _BLANKLINES_RGX.split(text):
-        result.append(normp(text, line_len, indent))
-    return ('%s%s%s' % (linesep, indent, linesep)).join(result)
-
-
-def normalize_paragraph(text, line_len=80, indent=''):
-    """normalize a text to display it with a maximum line size and
-    optionally arbitrary indentation. Line jumps are normalized. The
-    indentation string may be used top insert a comment mark for
-    instance.
-
-    :type text: str or unicode
-    :param text: the input text to normalize
-
-    :type line_len: int
-    :param line_len: expected maximum line's length, default to 80
-
-    :type indent: str or unicode
-    :param indent: optional string to use as indentation
-
-    :rtype: str or unicode
-    :return:
-      the input text normalized to fit on lines with a maximized size
-      inferior to `line_len`, and optionally prefixed by an
-      indentation string
-    """
-    text = _NORM_SPACES_RGX.sub(' ', text)
-    line_len = line_len - len(indent)
-    lines = []
-    while text:
-        aline, text = splittext(text.strip(), line_len)
-        lines.append(indent + aline)
-    return linesep.join(lines)
-
-def normalize_rest_paragraph(text, line_len=80, indent=''):
-    """normalize a ReST text to display it with a maximum line size and
-    optionally arbitrary indentation. Line jumps are normalized. The
-    indentation string may be used top insert a comment mark for
-    instance.
-
-    :type text: str or unicode
-    :param text: the input text to normalize
-
-    :type line_len: int
-    :param line_len: expected maximum line's length, default to 80
-
-    :type indent: str or unicode
-    :param indent: optional string to use as indentation
-
-    :rtype: str or unicode
-    :return:
-      the input text normalized to fit on lines with a maximized size
-      inferior to `line_len`, and optionally prefixed by an
-      indentation string
-    """
-    toreport = ''
-    lines = []
-    line_len = line_len - len(indent)
-    for line in text.splitlines():
-        line = toreport + _NORM_SPACES_RGX.sub(' ', line.strip())
-        toreport = ''
-        while len(line) > line_len:
-            # too long line, need split
-            line, toreport = splittext(line, line_len)
-            lines.append(indent + line)
-            if toreport:
-                line = toreport + ' '
-                toreport = ''
-            else:
-                line = ''
-        if line:
-            lines.append(indent + line.strip())
-    return linesep.join(lines)
-
-
-def splittext(text, line_len):
-    """split the given text on space according to the given max line size
-
-    return a 2-uple:
-    * a line <= line_len if possible
-    * the rest of the text which has to be reported on another line
-    """
-    if len(text) <= line_len:
-        return text, ''
-    pos = min(len(text)-1, line_len)
-    while pos > 0 and text[pos] != ' ':
-        pos -= 1
-    if pos == 0:
-        pos = min(len(text), line_len)
-        while len(text) > pos and text[pos] != ' ':
-            pos += 1
-    return text[:pos], text[pos+1:].strip()
-
-
-def splitstrip(string, sep=','):
-    """return a list of stripped string by splitting the string given as
-    argument on `sep` (',' by default). Empty string are discarded.
-
-    >>> splitstrip('a, b, c   ,  4,,')
-    ['a', 'b', 'c', '4']
-    >>> splitstrip('a')
-    ['a']
-    >>>
-
-    :type string: str or unicode
-    :param string: a csv line
-
-    :type sep: str or unicode
-    :param sep: field separator, default to the comma (',')
-
-    :rtype: str or unicode
-    :return: the unquoted string (or the input string if it wasn't quoted)
-    """
-    return [word.strip() for word in string.split(sep) if word.strip()]
-
-get_csv = deprecated('get_csv is deprecated, use splitstrip')(splitstrip)
-
-
-def split_url_or_path(url_or_path):
-    """return the latest component of a string containing either an url of the
-    form <scheme>://<path> or a local file system path
-    """
-    if '://' in url_or_path:
-        return url_or_path.rstrip('/').rsplit('/', 1)
-    return osp.split(url_or_path.rstrip(osp.sep))
-
-
-def text_to_dict(text):
-    """parse multilines text containing simple 'key=value' lines and return a
-    dict of {'key': 'value'}. When the same key is encountered multiple time,
-    value is turned into a list containing all values.
-
-    >>> text_to_dict('''multiple=1
-    ... multiple= 2
-    ... single =3
-    ... ''')
-    {'single': '3', 'multiple': ['1', '2']}
-
-    """
-    res = {}
-    if not text:
-        return res
-    for line in text.splitlines():
-        line = line.strip()
-        if line and not line.startswith('#'):
-            key, value = [w.strip() for w in line.split('=', 1)]
-            if key in res:
-                try:
-                    res[key].append(value)
-                except AttributeError:
-                    res[key] = [res[key], value]
-            else:
-                res[key] = value
-    return res
-
-
-_BLANK_URE = r'(\s|,)+'
-_BLANK_RE = re.compile(_BLANK_URE)
-__VALUE_URE = r'-?(([0-9]+\.[0-9]*)|((0x?)?[0-9]+))'
-__UNITS_URE = r'[a-zA-Z]+'
-_VALUE_RE = re.compile(r'(?P<value>%s)(?P<unit>%s)?'%(__VALUE_URE, __UNITS_URE))
-_VALIDATION_RE = re.compile(r'^((%s)(%s))*(%s)?$' % (__VALUE_URE, __UNITS_URE,
-                                                    __VALUE_URE))
-
-BYTE_UNITS = {
-    "b": 1,
-    "kb": 1024,
-    "mb": 1024 ** 2,
-    "gb": 1024 ** 3,
-    "tb": 1024 ** 4,
-}
-
-TIME_UNITS = {
-    "ms": 0.0001,
-    "s": 1,
-    "min": 60,
-    "h": 60 * 60,
-    "d": 60 * 60 *24,
-}
-
-def apply_units(string, units, inter=None, final=float, blank_reg=_BLANK_RE,
-                value_reg=_VALUE_RE):
-    """Parse the string applying the units defined in units
-    (e.g.: "1.5m",{'m',60} -> 80).
-
-    :type string: str or unicode
-    :param string: the string to parse
-
-    :type units: dict (or any object with __getitem__ using basestring key)
-    :param units: a dict mapping a unit string repr to its value
-
-    :type inter: type
-    :param inter: used to parse every intermediate value (need __sum__)
-
-    :type blank_reg: regexp
-    :param blank_reg: should match every blank char to ignore.
-
-    :type value_reg: regexp with "value" and optional "unit" group
-    :param value_reg: match a value and it's unit into the
-    """
-    if inter is None:
-        inter = final
-    fstring = _BLANK_RE.sub('', string)
-    if not (fstring and _VALIDATION_RE.match(fstring)):
-        raise ValueError("Invalid unit string: %r." % string)
-    values = []
-    for match in value_reg.finditer(fstring):
-        dic = match.groupdict()
-        lit, unit = dic["value"], dic.get("unit")
-        value = inter(lit)
-        if unit is not None:
-            try:
-                value *= units[unit.lower()]
-            except KeyError:
-                raise KeyError('invalid unit %s. valid units are %s' %
-                               (unit, units.keys()))
-        values.append(value)
-    return final(sum(values))
-
-
-_LINE_RGX = re.compile('\r\n|\r+|\n')
-
-def pretty_match(match, string, underline_char='^'):
-    """return a string with the match location underlined:
-
-    >>> import re
-    >>> print(pretty_match(re.search('mange', 'il mange du bacon'), 'il mange du bacon'))
-    il mange du bacon
-       ^^^^^
-    >>>
-
-    :type match: _sre.SRE_match
-    :param match: object returned by re.match, re.search or re.finditer
-
-    :type string: str or unicode
-    :param string:
-      the string on which the regular expression has been applied to
-      obtain the `match` object
-
-    :type underline_char: str or unicode
-    :param underline_char:
-      character to use to underline the matched section, default to the
-      carret '^'
-
-    :rtype: str or unicode
-    :return:
-      the original string with an inserted line to underline the match
-      location
-    """
-    start = match.start()
-    end = match.end()
-    string = _LINE_RGX.sub(linesep, string)
-    start_line_pos = string.rfind(linesep, 0, start)
-    if start_line_pos == -1:
-        start_line_pos = 0
-        result = []
-    else:
-        result = [string[:start_line_pos]]
-        start_line_pos += len(linesep)
-    offset = start - start_line_pos
-    underline = ' ' * offset + underline_char * (end - start)
-    end_line_pos = string.find(linesep, end)
-    if end_line_pos == -1:
-        string = string[start_line_pos:]
-        result.append(string)
-        result.append(underline)
-    else:
-        end = string[end_line_pos + len(linesep):]
-        string = string[start_line_pos:end_line_pos]
-        result.append(string)
-        result.append(underline)
-        result.append(end)
-    return linesep.join(result).rstrip()
-
-
-# Ansi colorization ###########################################################
-
-ANSI_PREFIX = '\033['
-ANSI_END = 'm'
-ANSI_RESET = '\033[0m'
-ANSI_STYLES = {
-    'reset': "0",
-    'bold': "1",
-    'italic': "3",
-    'underline': "4",
-    'blink': "5",
-    'inverse': "7",
-    'strike': "9",
-}
-ANSI_COLORS = {
-    'reset': "0",
-    'black': "30",
-    'red': "31",
-    'green': "32",
-    'yellow': "33",
-    'blue': "34",
-    'magenta': "35",
-    'cyan': "36",
-    'white': "37",
-}
-
-def _get_ansi_code(color=None, style=None):
-    """return ansi escape code corresponding to color and style
-
-    :type color: str or None
-    :param color:
-      the color name (see `ANSI_COLORS` for available values)
-      or the color number when 256 colors are available
-
-    :type style: str or None
-    :param style:
-      style string (see `ANSI_COLORS` for available values). To get
-      several style effects at the same time, use a coma as separator.
-
-    :raise KeyError: if an unexistent color or style identifier is given
-
-    :rtype: str
-    :return: the built escape code
-    """
-    ansi_code = []
-    if style:
-        style_attrs = splitstrip(style)
-        for effect in style_attrs:
-            ansi_code.append(ANSI_STYLES[effect])
-    if color:
-        if color.isdigit():
-            ansi_code.extend(['38', '5'])
-            ansi_code.append(color)
-        else:
-            ansi_code.append(ANSI_COLORS[color])
-    if ansi_code:
-        return ANSI_PREFIX + ';'.join(ansi_code) + ANSI_END
-    return ''
-
-def colorize_ansi(msg, color=None, style=None):
-    """colorize message by wrapping it with ansi escape codes
-
-    :type msg: str or unicode
-    :param msg: the message string to colorize
-
-    :type color: str or None
-    :param color:
-      the color identifier (see `ANSI_COLORS` for available values)
-
-    :type style: str or None
-    :param style:
-      style string (see `ANSI_COLORS` for available values). To get
-      several style effects at the same time, use a coma as separator.
-
-    :raise KeyError: if an unexistent color or style identifier is given
-
-    :rtype: str or unicode
-    :return: the ansi escaped string
-    """
-    # If both color and style are not defined, then leave the text as is
-    if color is None and style is None:
-        return msg
-    escape_code = _get_ansi_code(color, style)
-    # If invalid (or unknown) color, don't wrap msg with ansi codes
-    if escape_code:
-        return '%s%s%s' % (escape_code, msg, ANSI_RESET)
-    return msg
-
-DIFF_STYLE = {'separator': 'cyan', 'remove': 'red', 'add': 'green'}
-
-def diff_colorize_ansi(lines, out=sys.stdout, style=DIFF_STYLE):
-    for line in lines:
-        if line[:4] in ('--- ', '+++ '):
-            out.write(colorize_ansi(line, style['separator']))
-        elif line[0] == '-':
-            out.write(colorize_ansi(line, style['remove']))
-        elif line[0] == '+':
-            out.write(colorize_ansi(line, style['add']))
-        elif line[:4] == '--- ':
-            out.write(colorize_ansi(line, style['separator']))
-        elif line[:4] == '+++ ':
-            out.write(colorize_ansi(line, style['separator']))
-        else:
-            out.write(line)
-

+ 0 - 369
pylibs/logilab/common/tree.py

@@ -1,369 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""Base class to represent a tree structure.
-
-
-
-
-"""
-__docformat__ = "restructuredtext en"
-
-import sys
-
-from logilab.common import flatten
-from logilab.common.visitor import VisitedMixIn, FilteredIterator, no_filter
-
-## Exceptions #################################################################
-
-class NodeNotFound(Exception):
-    """raised when a node has not been found"""
-
-EX_SIBLING_NOT_FOUND = "No such sibling as '%s'"
-EX_CHILD_NOT_FOUND = "No such child as '%s'"
-EX_NODE_NOT_FOUND = "No such node as '%s'"
-
-
-# Base node ###################################################################
-
-class Node(object):
-    """a basic tree node, characterized by an id"""
-
-    def __init__(self, nid=None) :
-        self.id = nid
-        # navigation
-        self.parent = None
-        self.children = []
-
-    def __iter__(self):
-        return iter(self.children)
-
-    def __str__(self, indent=0):
-        s = ['%s%s %s' % (' '*indent, self.__class__.__name__, self.id)]
-        indent += 2
-        for child in self.children:
-            try:
-                s.append(child.__str__(indent))
-            except TypeError:
-                s.append(child.__str__())
-        return '\n'.join(s)
-
-    def is_leaf(self):
-        return not self.children
-
-    def append(self, child):
-        """add a node to children"""
-        self.children.append(child)
-        child.parent = self
-
-    def remove(self, child):
-        """remove a child node"""
-        self.children.remove(child)
-        child.parent = None
-
-    def insert(self, index, child):
-        """insert a child node"""
-        self.children.insert(index, child)
-        child.parent = self
-
-    def replace(self, old_child, new_child):
-        """replace a child node with another"""
-        i = self.children.index(old_child)
-        self.children.pop(i)
-        self.children.insert(i, new_child)
-        new_child.parent = self
-
-    def get_sibling(self, nid):
-        """return the sibling node that has given id"""
-        try:
-            return self.parent.get_child_by_id(nid)
-        except NodeNotFound :
-            raise NodeNotFound(EX_SIBLING_NOT_FOUND % nid)
-
-    def next_sibling(self):
-        """
-        return the next sibling for this node if any
-        """
-        parent = self.parent
-        if parent is None:
-            # root node has no sibling
-            return None
-        index = parent.children.index(self)
-        try:
-            return parent.children[index+1]
-        except IndexError:
-            return None
-
-    def previous_sibling(self):
-        """
-        return the previous sibling for this node if any
-        """
-        parent = self.parent
-        if parent is None:
-            # root node has no sibling
-            return None
-        index = parent.children.index(self)
-        if index > 0:
-            return parent.children[index-1]
-        return None
-
-    def get_node_by_id(self, nid):
-        """
-        return node in whole hierarchy that has given id
-        """
-        root = self.root()
-        try:
-            return root.get_child_by_id(nid, 1)
-        except NodeNotFound :
-            raise NodeNotFound(EX_NODE_NOT_FOUND % nid)
-
-    def get_child_by_id(self, nid, recurse=None):
-        """
-        return child of given id
-        """
-        if self.id == nid:
-            return self
-        for c in self.children :
-            if recurse:
-                try:
-                    return c.get_child_by_id(nid, 1)
-                except NodeNotFound :
-                    continue
-            if c.id == nid :
-                return c
-        raise NodeNotFound(EX_CHILD_NOT_FOUND % nid)
-
-    def get_child_by_path(self, path):
-        """
-        return child of given path (path is a list of ids)
-        """
-        if len(path) > 0 and path[0] == self.id:
-            if len(path) == 1 :
-                return self
-            else :
-                for c in self.children :
-                    try:
-                        return c.get_child_by_path(path[1:])
-                    except NodeNotFound :
-                        pass
-        raise NodeNotFound(EX_CHILD_NOT_FOUND % path)
-
-    def depth(self):
-        """
-        return depth of this node in the tree
-        """
-        if self.parent is not None:
-            return 1 + self.parent.depth()
-        else :
-            return 0
-
-    def depth_down(self):
-        """
-        return depth of the tree from this node
-        """
-        if self.children:
-            return 1 + max([c.depth_down() for c in self.children])
-        return 1
-
-    def width(self):
-        """
-        return the width of the tree from this node
-        """
-        return len(self.leaves())
-
-    def root(self):
-        """
-        return the root node of the tree
-        """
-        if self.parent is not None:
-            return self.parent.root()
-        return self
-
-    def leaves(self):
-        """
-        return a list with all the leaves nodes descendant from this node
-        """
-        leaves = []
-        if self.children:
-            for child in self.children:
-                leaves += child.leaves()
-            return leaves
-        else:
-            return [self]
-
-    def flatten(self, _list=None):
-        """
-        return a list with all the nodes descendant from this node
-        """
-        if _list is None:
-            _list = []
-        _list.append(self)
-        for c in self.children:
-            c.flatten(_list)
-        return _list
-
-    def lineage(self):
-        """
-        return list of parents up to root node
-        """
-        lst = [self]
-        if self.parent is not None:
-            lst.extend(self.parent.lineage())
-        return lst
-
-class VNode(Node, VisitedMixIn):
-    """a visitable node
-    """
-    pass
-
-
-class BinaryNode(VNode):
-    """a binary node (i.e. only two children
-    """
-    def __init__(self, lhs=None, rhs=None) :
-        VNode.__init__(self)
-        if lhs is not None or rhs is not None:
-            assert lhs and rhs
-            self.append(lhs)
-            self.append(rhs)
-
-    def remove(self, child):
-        """remove the child and replace this node with the other child
-        """
-        self.children.remove(child)
-        self.parent.replace(self, self.children[0])
-
-    def get_parts(self):
-        """
-        return the left hand side and the right hand side of this node
-        """
-        return self.children[0], self.children[1]
-
-
-
-if sys.version_info[0:2] >= (2, 2):
-    list_class = list
-else:
-    from UserList import UserList
-    list_class = UserList
-
-class ListNode(VNode, list_class):
-    """Used to manipulate Nodes as Lists
-    """
-    def __init__(self):
-        list_class.__init__(self)
-        VNode.__init__(self)
-        self.children = self
-
-    def __str__(self, indent=0):
-        return '%s%s %s' % (indent*' ', self.__class__.__name__,
-                            ', '.join([str(v) for v in self]))
-
-    def append(self, child):
-        """add a node to children"""
-        list_class.append(self, child)
-        child.parent = self
-
-    def insert(self, index, child):
-        """add a node to children"""
-        list_class.insert(self, index, child)
-        child.parent = self
-
-    def remove(self, child):
-        """add a node to children"""
-        list_class.remove(self, child)
-        child.parent = None
-
-    def pop(self, index):
-        """add a node to children"""
-        child = list_class.pop(self, index)
-        child.parent = None
-
-    def __iter__(self):
-        return list_class.__iter__(self)
-
-# construct list from tree ####################################################
-
-def post_order_list(node, filter_func=no_filter):
-    """
-    create a list with tree nodes for which the <filter> function returned true
-    in a post order fashion
-    """
-    l, stack = [], []
-    poped, index = 0, 0
-    while node:
-        if filter_func(node):
-            if node.children and not poped:
-                stack.append((node, index))
-                index = 0
-                node = node.children[0]
-            else:
-                l.append(node)
-                index += 1
-                try:
-                    node = stack[-1][0].children[index]
-                except IndexError:
-                    node = None
-        else:
-            node = None
-        poped = 0
-        if node is None and stack:
-            node, index = stack.pop()
-            poped = 1
-    return l
-
-def pre_order_list(node, filter_func=no_filter):
-    """
-    create a list with tree nodes for which the <filter> function returned true
-    in a pre order fashion
-    """
-    l, stack = [], []
-    poped, index = 0, 0
-    while node:
-        if filter_func(node):
-            if not poped:
-                l.append(node)
-            if node.children and not poped:
-                stack.append((node, index))
-                index = 0
-                node = node.children[0]
-            else:
-                index += 1
-                try:
-                    node = stack[-1][0].children[index]
-                except IndexError:
-                    node = None
-        else:
-            node = None
-        poped = 0
-        if node is None and len(stack) > 1:
-            node, index = stack.pop()
-            poped = 1
-    return l
-
-class PostfixedDepthFirstIterator(FilteredIterator):
-    """a postfixed depth first iterator, designed to be used with visitors
-    """
-    def __init__(self, node, filter_func=None):
-        FilteredIterator.__init__(self, node, post_order_list, filter_func)
-
-class PrefixedDepthFirstIterator(FilteredIterator):
-    """a prefixed depth first iterator, designed to be used with visitors
-    """
-    def __init__(self, node, filter_func=None):
-        FilteredIterator.__init__(self, node, pre_order_list, filter_func)
-

+ 0 - 167
pylibs/logilab/common/umessage.py

@@ -1,167 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""Unicode email support (extends email from stdlib).
-
-
-
-
-"""
-__docformat__ = "restructuredtext en"
-
-import email
-from encodings import search_function
-import sys
-if sys.version_info >= (2, 5):
-    from email.utils import parseaddr, parsedate
-    from email.header import decode_header
-else:
-    from email.Utils import parseaddr, parsedate
-    from email.Header import decode_header
-
-from datetime import datetime
-
-try:
-    from mx.DateTime import DateTime
-except ImportError:
-    DateTime = datetime
-
-import logilab.common as lgc
-
-
-def decode_QP(string):
-    parts = []
-    for decoded, charset in decode_header(string):
-        if not charset :
-            charset = 'iso-8859-15'
-        parts.append(unicode(decoded, charset, 'replace'))
-
-    return u' '.join(parts)
-
-def message_from_file(fd):
-    try:
-        return UMessage(email.message_from_file(fd))
-    except email.Errors.MessageParseError:
-        return ''
-
-def message_from_string(string):
-    try:
-        return UMessage(email.message_from_string(string))
-    except email.Errors.MessageParseError:
-        return ''
-
-class UMessage:
-    """Encapsulates an email.Message instance and returns only unicode objects.
-    """
-
-    def __init__(self, message):
-        self.message = message
-
-    # email.Message interface #################################################
-
-    def get(self, header, default=None):
-        value = self.message.get(header, default)
-        if value:
-            return decode_QP(value)
-        return value
-
-    def get_all(self, header, default=()):
-        return [decode_QP(val) for val in self.message.get_all(header, default)
-                if val is not None]
-
-    def get_payload(self, index=None, decode=False):
-        message = self.message
-        if index is None:
-            payload = message.get_payload(index, decode)
-            if isinstance(payload, list):
-                return [UMessage(msg) for msg in payload]
-            if message.get_content_maintype() != 'text':
-                return payload
-
-            charset = message.get_content_charset() or 'iso-8859-1'
-            if search_function(charset) is None:
-                charset = 'iso-8859-1'
-            return unicode(payload or '', charset, "replace")
-        else:
-            payload = UMessage(message.get_payload(index, decode))
-        return payload
-
-    def is_multipart(self):
-        return self.message.is_multipart()
-
-    def get_boundary(self):
-        return self.message.get_boundary()
-
-    def walk(self):
-        for part in self.message.walk():
-            yield UMessage(part)
-
-    def get_content_maintype(self):
-        return unicode(self.message.get_content_maintype())
-
-    def get_content_type(self):
-        return unicode(self.message.get_content_type())
-
-    def get_filename(self, failobj=None):
-        value = self.message.get_filename(failobj)
-        if value is failobj:
-            return value
-        try:
-            return unicode(value)
-        except UnicodeDecodeError:
-            return u'error decoding filename'
-
-    # other convenience methods ###############################################
-
-    def headers(self):
-        """return an unicode string containing all the message's headers"""
-        values = []
-        for header in self.message.keys():
-            values.append(u'%s: %s' % (header, self.get(header)))
-        return '\n'.join(values)
-
-    def multi_addrs(self, header):
-        """return a list of 2-uple (name, address) for the given address (which
-        is expected to be an header containing address such as from, to, cc...)
-        """
-        persons = []
-        for person in self.get_all(header, ()):
-            name, mail = parseaddr(person)
-            persons.append((name, mail))
-        return persons
-
-    def date(self, alternative_source=False, return_str=False):
-        """return a datetime object for the email's date or None if no date is
-        set or if it can't be parsed
-        """
-        value = self.get('date')
-        if value is None and alternative_source:
-            unix_from = self.message.get_unixfrom()
-            if unix_from is not None:
-                try:
-                    value = unix_from.split(" ", 2)[2]
-                except IndexError:
-                    pass
-        if value is not None:
-            datetuple = parsedate(value)
-            if datetuple:
-                if lgc.USE_MX_DATETIME:
-                    return DateTime(*datetuple[:6])
-                return datetime(*datetuple[:6])
-            elif not return_str:
-                return None
-        return value

+ 0 - 174
pylibs/logilab/common/ureports/__init__.py

@@ -1,174 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""Universal report objects and some formatting drivers.
-
-A way to create simple reports using python objects, primarily designed to be
-formatted as text and html.
-"""
-from __future__ import generators
-__docformat__ = "restructuredtext en"
-
-import sys
-from cStringIO import StringIO
-from StringIO import StringIO as UStringIO
-
-from logilab.common.textutils import linesep
-
-
-def get_nodes(node, klass):
-    """return an iterator on all children node of the given klass"""
-    for child in node.children:
-        if isinstance(child, klass):
-            yield child
-        # recurse (FIXME: recursion controled by an option)
-        for grandchild in get_nodes(child, klass):
-            yield grandchild
-
-def layout_title(layout):
-    """try to return the layout's title as string, return None if not found
-    """
-    for child in layout.children:
-        if isinstance(child, Title):
-            return ' '.join([node.data for node in get_nodes(child, Text)])
-
-def build_summary(layout, level=1):
-    """make a summary for the report, including X level"""
-    assert level > 0
-    level -= 1
-    summary = List(klass='summary')
-    for child in layout.children:
-        if not isinstance(child, Section):
-            continue
-        label = layout_title(child)
-        if not label and not child.id:
-            continue
-        if not child.id:
-            child.id = label.replace(' ', '-')
-        node = Link('#'+child.id, label=label or child.id)
-        # FIXME: Three following lines produce not very compliant
-        # docbook: there are some useless <para><para>. They might be
-        # replaced by the three commented lines but this then produces
-        # a bug in html display...
-        if level and [n for n in child.children if isinstance(n, Section)]:
-            node = Paragraph([node, build_summary(child, level)])
-        summary.append(node)
-#         summary.append(node)
-#         if level and [n for n in child.children if isinstance(n, Section)]:
-#             summary.append(build_summary(child, level))
-    return summary
-
-
-class BaseWriter(object):
-    """base class for ureport writers"""
-
-    def format(self, layout, stream=None, encoding=None):
-        """format and write the given layout into the stream object
-
-        unicode policy: unicode strings may be found in the layout;
-        try to call stream.write with it, but give it back encoded using
-        the given encoding if it fails
-        """
-        if stream is None:
-            stream = sys.stdout
-        if not encoding:
-            encoding = getattr(stream, 'encoding', 'UTF-8')
-        self.encoding = encoding or 'UTF-8'
-        self.__compute_funcs = []
-        self.out = stream
-        self.begin_format(layout)
-        layout.accept(self)
-        self.end_format(layout)
-
-    def format_children(self, layout):
-        """recurse on the layout children and call their accept method
-        (see the Visitor pattern)
-        """
-        for child in getattr(layout, 'children', ()):
-            child.accept(self)
-
-    def writeln(self, string=''):
-        """write a line in the output buffer"""
-        self.write(string + linesep)
-
-    def write(self, string):
-        """write a string in the output buffer"""
-        try:
-            self.out.write(string)
-        except UnicodeEncodeError:
-            self.out.write(string.encode(self.encoding))
-
-    def begin_format(self, layout):
-        """begin to format a layout"""
-        self.section = 0
-
-    def end_format(self, layout):
-        """finished to format a layout"""
-
-    def get_table_content(self, table):
-        """trick to get table content without actually writing it
-
-        return an aligned list of lists containing table cells values as string
-        """
-        result = [[]]
-        cols = table.cols
-        for cell in self.compute_content(table):
-            if cols == 0:
-                result.append([])
-                cols = table.cols
-            cols -= 1
-            result[-1].append(cell)
-        # fill missing cells
-        while len(result[-1]) < cols:
-            result[-1].append('')
-        return result
-
-    def compute_content(self, layout):
-        """trick to compute the formatting of children layout before actually
-        writing it
-
-        return an iterator on strings (one for each child element)
-        """
-        # use cells !
-        def write(data):
-            try:
-                stream.write(data)
-            except UnicodeEncodeError:
-                stream.write(data.encode(self.encoding))
-        def writeln(data=''):
-            try:
-                stream.write(data+linesep)
-            except UnicodeEncodeError:
-                stream.write(data.encode(self.encoding)+linesep)
-        self.write = write
-        self.writeln = writeln
-        self.__compute_funcs.append((write, writeln))
-        for child in layout.children:
-            stream = UStringIO()
-            child.accept(self)
-            yield stream.getvalue()
-        self.__compute_funcs.pop()
-        try:
-            self.write, self.writeln = self.__compute_funcs[-1]
-        except IndexError:
-            del self.write
-            del self.writeln
-
-
-from logilab.common.ureports.nodes import *
-from logilab.common.ureports.text_writer import TextWriter
-from logilab.common.ureports.html_writer import HTMLWriter

+ 0 - 139
pylibs/logilab/common/ureports/docbook_writer.py

@@ -1,139 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""HTML formatting drivers for ureports"""
-from __future__ import generators
-__docformat__ = "restructuredtext en"
-
-from logilab.common.ureports import HTMLWriter
-
-class DocbookWriter(HTMLWriter):
-    """format layouts as HTML"""
-
-    def begin_format(self, layout):
-        """begin to format a layout"""
-        super(HTMLWriter, self).begin_format(layout)
-        if self.snippet is None:
-            self.writeln('<?xml version="1.0" encoding="ISO-8859-1"?>')
-            self.writeln("""
-<book xmlns:xi='http://www.w3.org/2001/XInclude'
-      lang='fr'>
-""")
-
-    def end_format(self, layout):
-        """finished to format a layout"""
-        if self.snippet is None:
-            self.writeln('</book>')
-
-    def visit_section(self, layout):
-        """display a section (using <chapter> (level 0) or <section>)"""
-        if self.section == 0:
-            tag = "chapter"
-        else:
-            tag = "section"
-        self.section += 1
-        self.writeln(self._indent('<%s%s>' % (tag, self.handle_attrs(layout))))
-        self.format_children(layout)
-        self.writeln(self._indent('</%s>'% tag))
-        self.section -= 1
-
-    def visit_title(self, layout):
-        """display a title using <title>"""
-        self.write(self._indent('  <title%s>' % self.handle_attrs(layout)))
-        self.format_children(layout)
-        self.writeln('</title>')
-
-    def visit_table(self, layout):
-        """display a table as html"""
-        self.writeln(self._indent('  <table%s><title>%s</title>' \
-                     % (self.handle_attrs(layout), layout.title)))
-        self.writeln(self._indent('    <tgroup cols="%s">'% layout.cols))
-        for i in range(layout.cols):
-            self.writeln(self._indent('      <colspec colname="c%s" colwidth="1*"/>' % i))
-
-        table_content = self.get_table_content(layout)
-        # write headers
-        if layout.cheaders:
-            self.writeln(self._indent('      <thead>'))
-            self._write_row(table_content[0])
-            self.writeln(self._indent('      </thead>'))
-            table_content = table_content[1:]
-        elif layout.rcheaders:
-            self.writeln(self._indent('      <thead>'))
-            self._write_row(table_content[-1])
-            self.writeln(self._indent('      </thead>'))
-            table_content = table_content[:-1]
-        # write body
-        self.writeln(self._indent('      <tbody>'))
-        for i in range(len(table_content)):
-            row = table_content[i]
-            self.writeln(self._indent('        <row>'))
-            for j in range(len(row)):
-                cell = row[j] or '&#160;'
-                self.writeln(self._indent('          <entry>%s</entry>' % cell))
-            self.writeln(self._indent('        </row>'))
-        self.writeln(self._indent('      </tbody>'))
-        self.writeln(self._indent('    </tgroup>'))
-        self.writeln(self._indent('  </table>'))
-
-    def _write_row(self, row):
-        """write content of row (using <row> <entry>)"""
-        self.writeln('        <row>')
-        for j in range(len(row)):
-            cell = row[j] or '&#160;'
-            self.writeln('          <entry>%s</entry>' % cell)
-        self.writeln(self._indent('        </row>'))
-
-    def visit_list(self, layout):
-        """display a list (using <itemizedlist>)"""
-        self.writeln(self._indent('  <itemizedlist%s>' % self.handle_attrs(layout)))
-        for row in list(self.compute_content(layout)):
-            self.writeln('    <listitem><para>%s</para></listitem>' % row)
-        self.writeln(self._indent('  </itemizedlist>'))
-
-    def visit_paragraph(self, layout):
-        """display links (using <para>)"""
-        self.write(self._indent('  <para>'))
-        self.format_children(layout)
-        self.writeln('</para>')
-
-    def visit_span(self, layout):
-        """display links (using <p>)"""
-        #TODO: translate in docbook
-        self.write('<literal %s>' % self.handle_attrs(layout))
-        self.format_children(layout)
-        self.write('</literal>')
-
-    def visit_link(self, layout):
-        """display links (using <ulink>)"""
-        self.write('<ulink url="%s"%s>%s</ulink>' % (layout.url,
-                                               self.handle_attrs(layout),
-                                               layout.label))
-
-    def visit_verbatimtext(self, layout):
-        """display verbatim text (using <programlisting>)"""
-        self.writeln(self._indent('  <programlisting>'))
-        self.write(layout.data.replace('&', '&amp;').replace('<', '&lt;'))
-        self.writeln(self._indent('  </programlisting>'))
-
-    def visit_text(self, layout):
-        """add some text"""
-        self.write(layout.data.replace('&', '&amp;').replace('<', '&lt;'))
-
-    def _indent(self, string):
-        """correctly indent string according to section"""
-        return ' ' * 2*(self.section) + string

+ 0 - 131
pylibs/logilab/common/ureports/html_writer.py

@@ -1,131 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""HTML formatting drivers for ureports"""
-__docformat__ = "restructuredtext en"
-
-from cgi import escape
-
-from logilab.common.ureports import BaseWriter
-
-
-class HTMLWriter(BaseWriter):
-    """format layouts as HTML"""
-
-    def __init__(self, snippet=None):
-        super(HTMLWriter, self).__init__()
-        self.snippet = snippet
-
-    def handle_attrs(self, layout):
-        """get an attribute string from layout member attributes"""
-        attrs = ''
-        klass = getattr(layout, 'klass', None)
-        if klass:
-            attrs += ' class="%s"' % klass
-        nid = getattr(layout, 'id', None)
-        if nid:
-            attrs += ' id="%s"' % nid
-        return attrs
-
-    def begin_format(self, layout):
-        """begin to format a layout"""
-        super(HTMLWriter, self).begin_format(layout)
-        if self.snippet is None:
-            self.writeln('<html>')
-            self.writeln('<body>')
-
-    def end_format(self, layout):
-        """finished to format a layout"""
-        if self.snippet is None:
-            self.writeln('</body>')
-            self.writeln('</html>')
-
-
-    def visit_section(self, layout):
-        """display a section as html, using div + h[section level]"""
-        self.section += 1
-        self.writeln('<div%s>' % self.handle_attrs(layout))
-        self.format_children(layout)
-        self.writeln('</div>')
-        self.section -= 1
-
-    def visit_title(self, layout):
-        """display a title using <hX>"""
-        self.write('<h%s%s>' % (self.section, self.handle_attrs(layout)))
-        self.format_children(layout)
-        self.writeln('</h%s>' % self.section)
-
-    def visit_table(self, layout):
-        """display a table as html"""
-        self.writeln('<table%s>' % self.handle_attrs(layout))
-        table_content = self.get_table_content(layout)
-        for i in range(len(table_content)):
-            row = table_content[i]
-            if i == 0 and layout.rheaders:
-                self.writeln('<tr class="header">')
-            elif i+1 == len(table_content) and layout.rrheaders:
-                self.writeln('<tr class="header">')
-            else:
-                self.writeln('<tr class="%s">' % (i%2 and 'even' or 'odd'))
-            for j in range(len(row)):
-                cell = row[j] or '&#160;'
-                if (layout.rheaders and i == 0) or \
-                   (layout.cheaders and j == 0) or \
-                   (layout.rrheaders and i+1 == len(table_content)) or \
-                   (layout.rcheaders and j+1 == len(row)):
-                    self.writeln('<th>%s</th>' % cell)
-                else:
-                    self.writeln('<td>%s</td>' % cell)
-            self.writeln('</tr>')
-        self.writeln('</table>')
-
-    def visit_list(self, layout):
-        """display a list as html"""
-        self.writeln('<ul%s>' % self.handle_attrs(layout))
-        for row in list(self.compute_content(layout)):
-            self.writeln('<li>%s</li>' % row)
-        self.writeln('</ul>')
-
-    def visit_paragraph(self, layout):
-        """display links (using <p>)"""
-        self.write('<p>')
-        self.format_children(layout)
-        self.write('</p>')
-
-    def visit_span(self, layout):
-        """display links (using <p>)"""
-        self.write('<span%s>' % self.handle_attrs(layout))
-        self.format_children(layout)
-        self.write('</span>')
-
-    def visit_link(self, layout):
-        """display links (using <a>)"""
-        self.write(' <a href="%s"%s>%s</a>' % (layout.url,
-                                               self.handle_attrs(layout),
-                                               layout.label))
-    def visit_verbatimtext(self, layout):
-        """display verbatim text (using <pre>)"""
-        self.write('<pre>')
-        self.write(layout.data.replace('&', '&amp;').replace('<', '&lt;'))
-        self.write('</pre>')
-
-    def visit_text(self, layout):
-        """add some text"""
-        data = layout.data
-        if layout.escaped:
-            data = data.replace('&', '&amp;').replace('<', '&lt;')
-        self.write(data)

+ 0 - 201
pylibs/logilab/common/ureports/nodes.py

@@ -1,201 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""Micro reports objects.
-
-A micro report is a tree of layout and content objects.
-"""
-__docformat__ = "restructuredtext en"
-
-from logilab.common.tree import VNode
-
-class BaseComponent(VNode):
-    """base report component
-
-    attributes
-    * id : the component's optional id
-    * klass : the component's optional klass
-    """
-    def __init__(self, id=None, klass=None):
-        VNode.__init__(self, id)
-        self.klass = klass
-
-class BaseLayout(BaseComponent):
-    """base container node
-
-    attributes
-    * BaseComponent attributes
-    * children : components in this table (i.e. the table's cells)
-    """
-    def __init__(self, children=(), **kwargs):
-        super(BaseLayout, self).__init__(**kwargs)
-        for child in children:
-            if isinstance(child, BaseComponent):
-                self.append(child)
-            else:
-                self.add_text(child)
-
-    def append(self, child):
-        """overridden to detect problems easily"""
-        assert child not in self.parents()
-        VNode.append(self, child)
-
-    def parents(self):
-        """return the ancestor nodes"""
-        assert self.parent is not self
-        if self.parent is None:
-            return []
-        return [self.parent] + self.parent.parents()
-
-    def add_text(self, text):
-        """shortcut to add text data"""
-        self.children.append(Text(text))
-
-
-# non container nodes #########################################################
-
-class Text(BaseComponent):
-    """a text portion
-
-    attributes :
-    * BaseComponent attributes
-    * data : the text value as an encoded or unicode string
-    """
-    def __init__(self, data, escaped=True, **kwargs):
-        super(Text, self).__init__(**kwargs)
-        #if isinstance(data, unicode):
-        #    data = data.encode('ascii')
-        assert isinstance(data, (str, unicode)), data.__class__
-        self.escaped = escaped
-        self.data = data
-
-class VerbatimText(Text):
-    """a verbatim text, display the raw data
-
-    attributes :
-    * BaseComponent attributes
-    * data : the text value as an encoded or unicode string
-    """
-
-class Link(BaseComponent):
-    """a labelled link
-
-    attributes :
-    * BaseComponent attributes
-    * url : the link's target (REQUIRED)
-    * label : the link's label as a string (use the url by default)
-    """
-    def __init__(self, url, label=None, **kwargs):
-        super(Link, self).__init__(**kwargs)
-        assert url
-        self.url = url
-        self.label = label or url
-
-
-class Image(BaseComponent):
-    """an embedded or a single image
-
-    attributes :
-    * BaseComponent attributes
-    * filename : the image's filename (REQUIRED)
-    * stream : the stream object containing the image data (REQUIRED)
-    * title : the image's optional title
-    """
-    def __init__(self, filename, stream, title=None, **kwargs):
-        super(Image, self).__init__(**kwargs)
-        assert filename
-        assert stream
-        self.filename = filename
-        self.stream = stream
-        self.title = title
-
-
-# container nodes #############################################################
-
-class Section(BaseLayout):
-    """a section
-
-    attributes :
-    * BaseLayout attributes
-
-    a title may also be given to the constructor, it'll be added
-    as a first element
-    a description may also be given to the constructor, it'll be added
-    as a first paragraph
-    """
-    def __init__(self, title=None, description=None, **kwargs):
-        super(Section, self).__init__(**kwargs)
-        if description:
-            self.insert(0, Paragraph([Text(description)]))
-        if title:
-            self.insert(0, Title(children=(title,)))
-
-class Title(BaseLayout):
-    """a title
-
-    attributes :
-    * BaseLayout attributes
-
-    A title must not contains a section nor a paragraph!
-    """
-
-class Span(BaseLayout):
-    """a title
-
-    attributes :
-    * BaseLayout attributes
-
-    A span should only contains Text and Link nodes (in-line elements)
-    """
-
-class Paragraph(BaseLayout):
-    """a simple text paragraph
-
-    attributes :
-    * BaseLayout attributes
-
-    A paragraph must not contains a section !
-    """
-
-class Table(BaseLayout):
-    """some tabular data
-
-    attributes :
-    * BaseLayout attributes
-    * cols : the number of columns of the table (REQUIRED)
-    * rheaders : the first row's elements are table's header
-    * cheaders : the first col's elements are table's header
-    * title : the table's optional title
-    """
-    def __init__(self, cols, title=None,
-                 rheaders=0, cheaders=0, rrheaders=0, rcheaders=0,
-                 **kwargs):
-        super(Table, self).__init__(**kwargs)
-        assert isinstance(cols, int)
-        self.cols = cols
-        self.title = title
-        self.rheaders = rheaders
-        self.cheaders = cheaders
-        self.rrheaders = rrheaders
-        self.rcheaders = rcheaders
-
-class List(BaseLayout):
-    """some list data
-
-    attributes :
-    * BaseLayout attributes
-    """

+ 0 - 140
pylibs/logilab/common/ureports/text_writer.py

@@ -1,140 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""Text formatting drivers for ureports"""
-__docformat__ = "restructuredtext en"
-
-from logilab.common.textutils import linesep
-from logilab.common.ureports import BaseWriter
-
-
-TITLE_UNDERLINES = ['', '=', '-', '`', '.', '~', '^']
-BULLETS = ['*', '-']
-
-class TextWriter(BaseWriter):
-    """format layouts as text
-    (ReStructured inspiration but not totally handled yet)
-    """
-    def begin_format(self, layout):
-        super(TextWriter, self).begin_format(layout)
-        self.list_level = 0
-        self.pending_urls = []
-
-    def visit_section(self, layout):
-        """display a section as text
-        """
-        self.section += 1
-        self.writeln()
-        self.format_children(layout)
-        if self.pending_urls:
-            self.writeln()
-            for label, url in self.pending_urls:
-                self.writeln('.. _`%s`: %s' % (label, url))
-            self.pending_urls = []
-        self.section -= 1
-        self.writeln()
-
-    def visit_title(self, layout):
-        title = ''.join(list(self.compute_content(layout)))
-        self.writeln(title)
-        try:
-            self.writeln(TITLE_UNDERLINES[self.section] * len(title))
-        except IndexError:
-            print "FIXME TITLE TOO DEEP. TURNING TITLE INTO TEXT"
-
-    def visit_paragraph(self, layout):
-        """enter a paragraph"""
-        self.format_children(layout)
-        self.writeln()
-
-    def visit_span(self, layout):
-        """enter a span"""
-        self.format_children(layout)
-
-    def visit_table(self, layout):
-        """display a table as text"""
-        table_content = self.get_table_content(layout)
-        # get columns width
-        cols_width = [0]*len(table_content[0])
-        for row in table_content:
-            for index in range(len(row)):
-                col = row[index]
-                cols_width[index] = max(cols_width[index], len(col))
-        if layout.klass == 'field':
-            self.field_table(layout, table_content, cols_width)
-        else:
-            self.default_table(layout, table_content, cols_width)
-        self.writeln()
-
-    def default_table(self, layout, table_content, cols_width):
-        """format a table"""
-        cols_width = [size+1 for size in cols_width]
-        format_strings = ' '.join(['%%-%ss'] * len(cols_width))
-        format_strings = format_strings % tuple(cols_width)
-        format_strings = format_strings.split(' ')
-        table_linesep = '\n+' + '+'.join(['-'*w for w in cols_width]) + '+\n'
-        headsep = '\n+' + '+'.join(['='*w for w in cols_width]) + '+\n'
-        # FIXME: layout.cheaders
-        self.write(table_linesep)
-        for i in range(len(table_content)):
-            self.write('|')
-            line = table_content[i]
-            for j in range(len(line)):
-                self.write(format_strings[j] % line[j])
-                self.write('|')
-            if i == 0 and layout.rheaders:
-                self.write(headsep)
-            else:
-                self.write(table_linesep)
-
-    def field_table(self, layout, table_content, cols_width):
-        """special case for field table"""
-        assert layout.cols == 2
-        format_string = '%s%%-%ss: %%s' % (linesep, cols_width[0])
-        for field, value in table_content:
-            self.write(format_string % (field, value))
-
-
-    def visit_list(self, layout):
-        """display a list layout as text"""
-        bullet = BULLETS[self.list_level % len(BULLETS)]
-        indent = '  ' * self.list_level
-        self.list_level += 1
-        for child in layout.children:
-            self.write('%s%s%s ' % (linesep, indent, bullet))
-            child.accept(self)
-        self.list_level -= 1
-
-    def visit_link(self, layout):
-        """add a hyperlink"""
-        if layout.label != layout.url:
-            self.write('`%s`_' % layout.label)
-            self.pending_urls.append( (layout.label, layout.url) )
-        else:
-            self.write(layout.url)
-
-    def visit_verbatimtext(self, layout):
-        """display a verbatim layout as text (so difficult ;)
-        """
-        self.writeln('::\n')
-        for line in layout.data.splitlines():
-            self.writeln('    ' + line)
-        self.writeln()
-
-    def visit_text(self, layout):
-        """add some text"""
-        self.write(layout.data)

+ 0 - 87
pylibs/logilab/common/urllib2ext.py

@@ -1,87 +0,0 @@
-import logging
-import urllib2
-
-import kerberos as krb
-
-class GssapiAuthError(Exception):
-    """raised on error during authentication process"""
-
-import re
-RGX = re.compile('(?:.*,)*\s*Negotiate\s*([^,]*),?', re.I)
-
-def get_negociate_value(headers):
-    for authreq in headers.getheaders('www-authenticate'):
-        match = RGX.search(authreq)
-        if match:
-            return match.group(1)
-
-class HTTPGssapiAuthHandler(urllib2.BaseHandler):
-    """Negotiate HTTP authentication using context from GSSAPI"""
-
-    handler_order = 400 # before Digest Auth
-
-    def __init__(self):
-        self._reset()
-
-    def _reset(self):
-        self._retried = 0
-        self._context = None
-
-    def clean_context(self):
-        if self._context is not None:
-            krb.authGSSClientClean(self._context)
-
-    def http_error_401(self, req, fp, code, msg, headers):
-        try:
-            if self._retried > 5:
-                raise urllib2.HTTPError(req.get_full_url(), 401,
-                                        "negotiate auth failed", headers, None)
-            self._retried += 1
-            logging.debug('gssapi handler, try %s' % self._retried)
-            negotiate = get_negociate_value(headers)
-            if negotiate is None:
-                logging.debug('no negociate found in a www-authenticate header')
-                return None
-            logging.debug('HTTPGssapiAuthHandler: negotiate 1 is %r' % negotiate)
-            result, self._context = krb.authGSSClientInit("HTTP@%s" % req.get_host())
-            if result < 1:
-                raise GssapiAuthError("HTTPGssapiAuthHandler: init failed with %d" % result)
-            result = krb.authGSSClientStep(self._context, negotiate)
-            if result < 0:
-                raise GssapiAuthError("HTTPGssapiAuthHandler: step 1 failed with %d" % result)
-            client_response = krb.authGSSClientResponse(self._context)
-            logging.debug('HTTPGssapiAuthHandler: client response is %s...' % client_response[:10])
-            req.add_unredirected_header('Authorization', "Negotiate %s" % client_response)
-            server_response = self.parent.open(req)
-            negotiate = get_negociate_value(server_response.info())
-            if negotiate is None:
-                logging.warning('HTTPGssapiAuthHandler: failed to authenticate server')
-            else:
-                logging.debug('HTTPGssapiAuthHandler negotiate 2: %s' % negotiate)
-                result = krb.authGSSClientStep(self._context, negotiate)
-                if result < 1:
-                    raise GssapiAuthError("HTTPGssapiAuthHandler: step 2 failed with %d" % result)
-            return server_response
-        except GssapiAuthError, exc:
-            logging.error(repr(exc))
-        finally:
-            self.clean_context()
-            self._reset()
-
-if __name__ == '__main__':
-    import sys
-    # debug
-    import httplib
-    httplib.HTTPConnection.debuglevel = 1
-    httplib.HTTPSConnection.debuglevel = 1
-    # debug
-    import logging
-    logging.basicConfig(level=logging.DEBUG)
-    # handle cookies
-    import cookielib
-    cj = cookielib.CookieJar()
-    ch = urllib2.HTTPCookieProcessor(cj)
-    # test with url sys.argv[1]
-    h = HTTPGssapiAuthHandler()
-    response = urllib2.build_opener(h, ch).open(sys.argv[1])
-    print '\nresponse: %s\n--------------\n' % response.code, response.info()

+ 0 - 216
pylibs/logilab/common/vcgutils.py

@@ -1,216 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""Functions to generate files readable with Georg Sander's vcg
-(Visualization of Compiler Graphs).
-
-You can download vcg at http://rw4.cs.uni-sb.de/~sander/html/gshome.html
-Note that vcg exists as a debian package.
-
-See vcg's documentation for explanation about the different values that
-maybe used for the functions parameters.
-
-
-
-
-"""
-__docformat__ = "restructuredtext en"
-
-import string
-
-ATTRS_VAL = {
-    'algos':       ('dfs', 'tree', 'minbackward',
-                    'left_to_right', 'right_to_left',
-                    'top_to_bottom', 'bottom_to_top',
-                    'maxdepth', 'maxdepthslow', 'mindepth', 'mindepthslow',
-                    'mindegree', 'minindegree', 'minoutdegree',
-                    'maxdegree', 'maxindegree', 'maxoutdegree'),
-    'booleans':    ('yes', 'no'),
-    'colors':      ('black', 'white', 'blue', 'red', 'green', 'yellow',
-                    'magenta', 'lightgrey',
-                    'cyan', 'darkgrey', 'darkblue', 'darkred', 'darkgreen',
-                    'darkyellow', 'darkmagenta', 'darkcyan', 'gold',
-                    'lightblue', 'lightred', 'lightgreen', 'lightyellow',
-                    'lightmagenta', 'lightcyan', 'lilac', 'turquoise',
-                    'aquamarine', 'khaki', 'purple', 'yellowgreen', 'pink',
-                    'orange', 'orchid'),
-    'shapes':      ('box', 'ellipse', 'rhomb', 'triangle'),
-    'textmodes':   ('center', 'left_justify', 'right_justify'),
-    'arrowstyles': ('solid', 'line', 'none'),
-    'linestyles':  ('continuous', 'dashed', 'dotted', 'invisible'),
-    }
-
-# meaning of possible values:
-#   O    -> string
-#   1    -> int
-#   list -> value in list
-GRAPH_ATTRS = {
-    'title':              0,
-    'label':              0,
-    'color':               ATTRS_VAL['colors'],
-    'textcolor':           ATTRS_VAL['colors'],
-    'bordercolor':         ATTRS_VAL['colors'],
-    'width':               1,
-    'height':              1,
-    'borderwidth':         1,
-    'textmode':            ATTRS_VAL['textmodes'],
-    'shape':               ATTRS_VAL['shapes'],
-    'shrink':              1,
-    'stretch':             1,
-    'orientation':         ATTRS_VAL['algos'],
-    'vertical_order':      1,
-    'horizontal_order':    1,
-    'xspace':              1,
-    'yspace':              1,
-    'layoutalgorithm':    ATTRS_VAL['algos'],
-    'late_edge_labels':   ATTRS_VAL['booleans'],
-    'display_edge_labels': ATTRS_VAL['booleans'],
-    'dirty_edge_labels':  ATTRS_VAL['booleans'],
-    'finetuning':          ATTRS_VAL['booleans'],
-    'manhattan_edges':     ATTRS_VAL['booleans'],
-    'smanhattan_edges':    ATTRS_VAL['booleans'],
-    'port_sharing':        ATTRS_VAL['booleans'],
-    'edges':               ATTRS_VAL['booleans'],
-    'nodes':               ATTRS_VAL['booleans'],
-    'splines':             ATTRS_VAL['booleans'],
-    }
-NODE_ATTRS = {
-    'title':              0,
-    'label':              0,
-    'color':               ATTRS_VAL['colors'],
-    'textcolor':           ATTRS_VAL['colors'],
-    'bordercolor':         ATTRS_VAL['colors'],
-    'width':               1,
-    'height':              1,
-    'borderwidth':         1,
-    'textmode':            ATTRS_VAL['textmodes'],
-    'shape':               ATTRS_VAL['shapes'],
-    'shrink':              1,
-    'stretch':             1,
-    'vertical_order':      1,
-    'horizontal_order':    1,
-    }
-EDGE_ATTRS = {
-    'sourcename':         0,
-    'targetname':         0,
-    'label':              0,
-    'linestyle':          ATTRS_VAL['linestyles'],
-    'class':              1,
-    'thickness':          0,
-    'color':               ATTRS_VAL['colors'],
-    'textcolor':           ATTRS_VAL['colors'],
-    'arrowcolor':          ATTRS_VAL['colors'],
-    'backarrowcolor':      ATTRS_VAL['colors'],
-    'arrowsize':           1,
-    'backarrowsize':       1,
-    'arrowstyle':          ATTRS_VAL['arrowstyles'],
-    'backarrowstyle':      ATTRS_VAL['arrowstyles'],
-    'textmode':            ATTRS_VAL['textmodes'],
-    'priority':            1,
-    'anchor':              1,
-    'horizontal_order':    1,
-    }
-
-
-# Misc utilities ###############################################################
-
-def latin_to_vcg(st):
-    """Convert latin characters using vcg escape sequence.
-    """
-    for char in st:
-        if char not in string.ascii_letters:
-            try:
-                num = ord(char)
-                if num >= 192:
-                    st = st.replace(char, r'\fi%d'%ord(char))
-            except:
-                pass
-    return st
-
-
-class VCGPrinter:
-    """A vcg graph writer.
-    """
-
-    def __init__(self, output_stream):
-        self._stream = output_stream
-        self._indent = ''
-
-    def open_graph(self, **args):
-        """open a vcg graph
-        """
-        self._stream.write('%sgraph:{\n'%self._indent)
-        self._inc_indent()
-        self._write_attributes(GRAPH_ATTRS, **args)
-
-    def close_graph(self):
-        """close a vcg graph
-        """
-        self._dec_indent()
-        self._stream.write('%s}\n'%self._indent)
-
-
-    def node(self, title, **args):
-        """draw a node
-        """
-        self._stream.write('%snode: {title:"%s"' % (self._indent, title))
-        self._write_attributes(NODE_ATTRS, **args)
-        self._stream.write('}\n')
-
-
-    def edge(self, from_node, to_node, edge_type='', **args):
-        """draw an edge from a node to another.
-        """
-        self._stream.write(
-            '%s%sedge: {sourcename:"%s" targetname:"%s"' % (
-            self._indent, edge_type, from_node, to_node))
-        self._write_attributes(EDGE_ATTRS, **args)
-        self._stream.write('}\n')
-
-
-    # private ##################################################################
-
-    def _write_attributes(self, attributes_dict, **args):
-        """write graph, node or edge attributes
-        """
-        for key, value in args.items():
-            try:
-                _type =  attributes_dict[key]
-            except KeyError:
-                raise Exception('''no such attribute %s
-possible attributes are %s''' % (key, attributes_dict.keys()))
-
-            if not _type:
-                self._stream.write('%s%s:"%s"\n' % (self._indent, key, value))
-            elif _type == 1:
-                self._stream.write('%s%s:%s\n' % (self._indent, key,
-                                                  int(value)))
-            elif value in _type:
-                self._stream.write('%s%s:%s\n' % (self._indent, key, value))
-            else:
-                raise Exception('''value %s isn\'t correct for attribute %s
-correct values are %s''' % (value, key, _type))
-
-    def _inc_indent(self):
-        """increment indentation
-        """
-        self._indent = '  %s' % self._indent
-
-    def _dec_indent(self):
-        """decrement indentation
-        """
-        self._indent = self._indent[:-2]

+ 0 - 107
pylibs/logilab/common/visitor.py

@@ -1,107 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""A generic visitor abstract implementation.
-
-
-
-
-"""
-__docformat__ = "restructuredtext en"
-
-def no_filter(_):
-    return 1
-
-# Iterators ###################################################################
-class FilteredIterator(object):
-
-    def __init__(self, node, list_func, filter_func=None):
-        self._next = [(node, 0)]
-        if filter_func is None:
-            filter_func = no_filter
-        self._list = list_func(node, filter_func)
-
-    def next(self):
-        try:
-            return self._list.pop(0)
-        except :
-            return None
-
-# Base Visitor ################################################################
-class Visitor(object):
-
-    def __init__(self, iterator_class, filter_func=None):
-        self._iter_class = iterator_class
-        self.filter = filter_func
-
-    def visit(self, node, *args, **kargs):
-        """
-        launch the visit on a given node
-
-        call 'open_visit' before the beginning of the visit, with extra args
-        given
-        when all nodes have been visited, call the 'close_visit' method
-        """
-        self.open_visit(node, *args, **kargs)
-        return self.close_visit(self._visit(node))
-
-    def _visit(self, node):
-        iterator = self._get_iterator(node)
-        n = iterator.next()
-        while n:
-            result = n.accept(self)
-            n = iterator.next()
-        return result
-
-    def _get_iterator(self, node):
-        return self._iter_class(node, self.filter)
-
-    def open_visit(self, *args, **kargs):
-        """
-        method called at the beginning of the visit
-        """
-        pass
-
-    def close_visit(self, result):
-        """
-        method called at the end of the visit
-        """
-        return result
-
-# standard visited mixin ######################################################
-class VisitedMixIn(object):
-    """
-    Visited interface allow node visitors to use the node
-    """
-    def get_visit_name(self):
-        """
-        return the visit name for the mixed class. When calling 'accept', the
-        method <'visit_' + name returned by this method> will be called on the
-        visitor
-        """
-        try:
-            return self.TYPE.replace('-', '_')
-        except:
-            return self.__class__.__name__.lower()
-
-    def accept(self, visitor, *args, **kwargs):
-        func = getattr(visitor, 'visit_%s' % self.get_visit_name())
-        return func(self, *args, **kwargs)
-
-    def leave(self, visitor, *args, **kwargs):
-        func = getattr(visitor, 'leave_%s' % self.get_visit_name())
-        return func(self, *args, **kwargs)

+ 0 - 131
pylibs/logilab/common/xmlrpcutils.py

@@ -1,131 +0,0 @@
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""XML-RPC utilities."""
-__docformat__ = "restructuredtext en"
-
-import xmlrpclib
-from base64 import encodestring
-#from cStringIO import StringIO
-
-ProtocolError = xmlrpclib.ProtocolError
-
-## class BasicAuthTransport(xmlrpclib.Transport):
-##     def __init__(self, username=None, password=None):
-##         self.username = username
-##         self.password = password
-##         self.verbose = None
-##         self.has_ssl = httplib.__dict__.has_key("HTTPConnection")
-
-##     def request(self, host, handler, request_body, verbose=None):
-##         # issue XML-RPC request
-##         if self.has_ssl:
-##             if host.startswith("https:"): h = httplib.HTTPSConnection(host)
-##             else: h = httplib.HTTPConnection(host)
-##         else: h = httplib.HTTP(host)
-
-##         h.putrequest("POST", handler)
-
-##         # required by HTTP/1.1
-##         if not self.has_ssl: # HTTPConnection already does 1.1
-##             h.putheader("Host", host)
-##         h.putheader("Connection", "close")
-
-##         if request_body: h.send(request_body)
-##         if self.has_ssl:
-##             response = h.getresponse()
-##             if response.status != 200:
-##                 raise xmlrpclib.ProtocolError(host + handler,
-##                                               response.status,
-##                                               response.reason,
-##                                               response.msg)
-##             file = response.fp
-##         else:
-##             errcode, errmsg, headers = h.getreply()
-##             if errcode != 200:
-##                 raise xmlrpclib.ProtocolError(host + handler, errcode,
-##                                               errmsg, headers)
-
-##             file = h.getfile()
-
-##         return self.parse_response(file)
-
-
-
-class AuthMixin:
-    """basic http authentication mixin for xmlrpc transports"""
-
-    def __init__(self, username, password, encoding):
-        self.verbose = 0
-        self.username = username
-        self.password = password
-        self.encoding = encoding
-
-    def request(self, host, handler, request_body, verbose=0):
-        """issue XML-RPC request"""
-        h = self.make_connection(host)
-        h.putrequest("POST", handler)
-        # required by XML-RPC
-        h.putheader("User-Agent", self.user_agent)
-        h.putheader("Content-Type", "text/xml")
-        h.putheader("Content-Length", str(len(request_body)))
-        h.putheader("Host", host)
-        h.putheader("Connection", "close")
-        # basic auth
-        if self.username is not None and self.password is not None:
-            h.putheader("AUTHORIZATION", "Basic %s" % encodestring(
-                "%s:%s" % (self.username, self.password)).replace("\012", ""))
-        h.endheaders()
-        # send body
-        if request_body:
-            h.send(request_body)
-        # get and check reply
-        errcode, errmsg, headers = h.getreply()
-        if errcode != 200:
-            raise ProtocolError(host + handler, errcode, errmsg, headers)
-        file = h.getfile()
-##         # FIXME: encoding ??? iirc, this fix a bug in xmlrpclib but...
-##         data = h.getfile().read()
-##         if self.encoding != 'UTF-8':
-##             data = data.replace("version='1.0'",
-##                                 "version='1.0' encoding='%s'" % self.encoding)
-##         result = StringIO()
-##         result.write(data)
-##         result.seek(0)
-##         return self.parse_response(result)
-        return self.parse_response(file)
-
-class BasicAuthTransport(AuthMixin, xmlrpclib.Transport):
-    """basic http authentication transport"""
-
-class BasicAuthSafeTransport(AuthMixin, xmlrpclib.SafeTransport):
-    """basic https authentication transport"""
-
-
-def connect(url, user=None, passwd=None, encoding='ISO-8859-1'):
-    """return an xml rpc server on <url>, using user / password if specified
-    """
-    if user or passwd:
-        assert user and passwd is not None
-        if url.startswith('https://'):
-            transport = BasicAuthSafeTransport(user, passwd, encoding)
-        else:
-            transport = BasicAuthTransport(user, passwd, encoding)
-    else:
-        transport = None
-    server = xmlrpclib.ServerProxy(url, transport, encoding=encoding)
-    return server

+ 0 - 61
pylibs/logilab/common/xmlutils.py

@@ -1,61 +0,0 @@
-# -*- coding: utf-8 -*-
-# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
-# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#
-# This file is part of logilab-common.
-#
-# logilab-common is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation, either version 2.1 of the License, or (at your option) any
-# later version.
-#
-# logilab-common is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-# details.
-#
-# You should have received a copy of the GNU Lesser General Public License along
-# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""XML utilities.
-
-This module contains useful functions for parsing and using XML data. For the
-moment, there is only one function that can parse the data inside a processing
-instruction and return a Python dictionary.
-
-
-
-
-"""
-__docformat__ = "restructuredtext en"
-
-import re
-
-RE_DOUBLE_QUOTE = re.compile('([\w\-\.]+)="([^"]+)"')
-RE_SIMPLE_QUOTE = re.compile("([\w\-\.]+)='([^']+)'")
-
-def parse_pi_data(pi_data):
-    """
-    Utility function that parses the data contained in an XML
-    processing instruction and returns a dictionary of keywords and their
-    associated values (most of the time, the processing instructions contain
-    data like ``keyword="value"``, if a keyword is not associated to a value,
-    for example ``keyword``, it will be associated to ``None``).
-
-    :param pi_data: data contained in an XML processing instruction.
-    :type pi_data: unicode
-
-    :returns: Dictionary of the keywords (Unicode strings) associated to
-              their values (Unicode strings) as they were defined in the
-              data.
-    :rtype: dict
-    """
-    results = {}
-    for elt in pi_data.split():
-        if RE_DOUBLE_QUOTE.match(elt):
-            kwd, val = RE_DOUBLE_QUOTE.match(elt).groups()
-        elif RE_SIMPLE_QUOTE.match(elt):
-            kwd, val = RE_SIMPLE_QUOTE.match(elt).groups()
-        else:
-            kwd, val = elt, None
-        results[kwd] = val
-    return results

+ 0 - 293
pylibs/mccabe.py

@@ -1,293 +0,0 @@
-""" Meager code path measurement tool.
-    Ned Batchelder
-    http://nedbatchelder.com/blog/200803/python_code_complexity_microtool.html
-    MIT License.
-"""
-try:
-    from compiler import parse      # NOQA
-    iter_child_nodes = None         # NOQA
-except ImportError:
-    from ast import parse, iter_child_nodes     # NOQA
-
-import optparse
-import sys
-from collections import defaultdict
-
-WARNING_CODE = "W901"
-
-
-class ASTVisitor:
-
-    VERBOSE = 0
-
-    def __init__(self):
-        self.node = None
-        self._cache = {}
-
-    def default(self, node, *args):
-        if hasattr(node, 'getChildNodes'):
-            children = node.getChildNodes()
-        else:
-            children = iter_child_nodes(node)
-
-        for child in children:
-            self.dispatch(child, *args)
-
-    def dispatch(self, node, *args):
-        self.node = node
-        klass = node.__class__
-        meth = self._cache.get(klass)
-        if meth is None:
-            className = klass.__name__
-            meth = getattr(self.visitor, 'visit' + className, self.default)
-            self._cache[klass] = meth
-
-        return meth(node, *args)
-
-    def preorder(self, tree, visitor, *args):
-        """Do preorder walk of tree using visitor"""
-        self.visitor = visitor
-        visitor.visit = self.dispatch
-        self.dispatch(tree, *args)  # XXX *args make sense?
-
-
-class PathNode:
-    def __init__(self, name, look="circle"):
-        self.name = name
-        self.look = look
-
-    def to_dot(self):
-        print('node [shape=%s,label="%s"] %d;' % \
-                (self.look, self.name, self.dot_id()))
-
-    def dot_id(self):
-        return id(self)
-
-
-class PathGraph:
-    def __init__(self, name, entity, lineno):
-        self.name = name
-        self.entity = entity
-        self.lineno = lineno
-        self.nodes = defaultdict(list)
-
-    def connect(self, n1, n2):
-        self.nodes[n1].append(n2)
-
-    def to_dot(self):
-        print('subgraph {')
-        for node in self.nodes:
-            node.to_dot()
-        for node, nexts in self.nodes.items():
-            for next in nexts:
-                print('%s -- %s;' % (node.dot_id(), next.dot_id()))
-        print('}')
-
-    def complexity(self):
-        """ Return the McCabe complexity for the graph.
-            V-E+2
-        """
-        num_edges = sum([len(n) for n in self.nodes.values()])
-        num_nodes = len(self.nodes)
-        return num_edges - num_nodes + 2
-
-
-class PathGraphingAstVisitor(ASTVisitor):
-    """ A visitor for a parsed Abstract Syntax Tree which finds executable
-        statements.
-    """
-
-    def __init__(self):
-        ASTVisitor.__init__(self)
-        self.classname = ""
-        self.graphs = {}
-        self.reset()
-
-    def reset(self):
-        self.graph = None
-        self.tail = None
-
-    def visitFunction(self, node):
-
-        if self.classname:
-            entity = '%s%s' % (self.classname, node.name)
-        else:
-            entity = node.name
-
-        name = '%d:1: %r' % (node.lineno, entity)
-
-        if self.graph is not None:
-            # closure
-            pathnode = self.appendPathNode(name)
-            self.tail = pathnode
-            self.default(node)
-            bottom = PathNode("", look='point')
-            self.graph.connect(self.tail, bottom)
-            self.graph.connect(pathnode, bottom)
-            self.tail = bottom
-        else:
-            self.graph = PathGraph(name, entity, node.lineno)
-            pathnode = PathNode(name)
-            self.tail = pathnode
-            self.default(node)
-            self.graphs["%s%s" % (self.classname, node.name)] = self.graph
-            self.reset()
-
-    visitFunctionDef = visitFunction
-
-    def visitClass(self, node):
-        old_classname = self.classname
-        self.classname += node.name + "."
-        self.default(node)
-        self.classname = old_classname
-
-    def appendPathNode(self, name):
-        if not self.tail:
-            return
-        pathnode = PathNode(name)
-        self.graph.connect(self.tail, pathnode)
-        self.tail = pathnode
-        return pathnode
-
-    def visitSimpleStatement(self, node):
-        if node.lineno is None:
-            lineno = 0
-        else:
-            lineno = node.lineno
-        name = "Stmt %d" % lineno
-        self.appendPathNode(name)
-
-    visitAssert = visitAssign = visitAssTuple = visitPrint = \
-        visitPrintnl = visitRaise = visitSubscript = visitDecorators = \
-        visitPass = visitDiscard = visitGlobal = visitReturn = \
-        visitSimpleStatement
-
-    def visitLoop(self, node):
-        name = "Loop %d" % node.lineno
-
-        if self.graph is None:
-            # global loop
-            self.graph = PathGraph(name, name, node.lineno)
-            pathnode = PathNode(name)
-            self.tail = pathnode
-            self.default(node)
-            self.graphs["%s%s" % (self.classname, name)] = self.graph
-            self.reset()
-        else:
-            pathnode = self.appendPathNode(name)
-            self.tail = pathnode
-            self.default(node.body)
-            bottom = PathNode("", look='point')
-            self.graph.connect(self.tail, bottom)
-            self.graph.connect(pathnode, bottom)
-            self.tail = bottom
-
-        # TODO: else clause in node.else_
-
-    visitFor = visitWhile = visitLoop
-
-    def visitIf(self, node):
-        name = "If %d" % node.lineno
-        pathnode = self.appendPathNode(name)
-        if not pathnode:
-            return  # TODO: figure out what to do with if's outside def's.
-        loose_ends = []
-        for t, n in node.tests:
-            self.tail = pathnode
-            self.default(n)
-            loose_ends.append(self.tail)
-        if node.else_:
-            self.tail = pathnode
-            self.default(node.else_)
-            loose_ends.append(self.tail)
-        else:
-            loose_ends.append(pathnode)
-        bottom = PathNode("", look='point')
-        for le in loose_ends:
-            self.graph.connect(le, bottom)
-        self.tail = bottom
-
-    # TODO: visitTryExcept
-    # TODO: visitTryFinally
-    # TODO: visitWith
-
-    # XXX todo: determine which ones can add to the complexity
-    # py2
-    # TODO: visitStmt
-    # TODO: visitAssName
-    # TODO: visitCallFunc
-    # TODO: visitConst
-
-    # py3
-    # TODO: visitStore
-    # TODO: visitCall
-    # TODO: visitLoad
-    # TODO: visitNum
-    # TODO: visitarguments
-    # TODO: visitExpr
-
-
-def get_code_complexity(code, min=7, filename='stdin'):
-    complex = []
-    try:
-        ast = parse(code)
-    except AttributeError:
-        e = sys.exc_info()[1]
-        sys.stderr.write("Unable to parse %s: %s\n" % (filename, e))
-        return 0
-
-    visitor = PathGraphingAstVisitor()
-    visitor.preorder(ast, visitor)
-    for graph in visitor.graphs.values():
-        if graph is None:
-            # ?
-            continue
-        if graph.complexity() >= min:
-            complex.append(dict(
-                type = 'W',
-                lnum = graph.lineno,
-                text = '%s %r is too complex (%d)' % (
-                    WARNING_CODE,
-                    graph.entity,
-                    graph.complexity(),
-                )
-            ))
-
-    return complex
-
-
-def get_module_complexity(module_path, min=7):
-    """Returns the complexity of a module"""
-    code = open(module_path, "rU").read() + '\n\n'
-    return get_code_complexity(code, min, filename=module_path)
-
-
-def main(argv):
-    opar = optparse.OptionParser()
-    opar.add_option("-d", "--dot", dest="dot",
-                    help="output a graphviz dot file", action="store_true")
-    opar.add_option("-m", "--min", dest="min",
-                    help="minimum complexity for output", type="int",
-                    default=2)
-
-    options, args = opar.parse_args(argv)
-
-    text = open(args[0], "rU").read() + '\n\n'
-    ast = parse(text)
-    visitor = PathGraphingAstVisitor()
-    visitor.preorder(ast, visitor)
-
-    if options.dot:
-        print('graph {')
-        for graph in visitor.graphs.values():
-            if graph.complexity() >= options.min:
-                graph.to_dot()
-        print('}')
-    else:
-        for graph in visitor.graphs.values():
-            if graph.complexity() >= options.min:
-                print(graph.name, graph.complexity())
-
-
-if __name__ == '__main__':
-    main(sys.argv[1:])

BIN
pylibs/mccabe.pyc


Plik diff jest za duży
+ 0 - 1931
pylibs/pep8.py


BIN
pylibs/pep8.pyc


+ 0 - 2
pylibs/pyflakes/__init__.py

@@ -1,2 +0,0 @@
-
-__version__ = '0.4.0'

BIN
pylibs/pyflakes/__init__.pyc


+ 0 - 635
pylibs/pyflakes/checker.py

@@ -1,635 +0,0 @@
-# -*- test-case-name: pyflakes -*-
-# (c) 2005-2010 Divmod, Inc.
-# See LICENSE file for details
-
-import __builtin__
-import os.path
-import _ast
-
-from . import messages
-
-
-# utility function to iterate over an AST node's children, adapted
-# from Python 2.6's standard ast module
-try:
-    import ast
-    iter_child_nodes = ast.iter_child_nodes
-except (ImportError, AttributeError):
-    def iter_child_nodes(node, astcls=_ast.AST):
-        """
-        Yield all direct child nodes of *node*, that is, all fields that are nodes
-        and all items of fields that are lists of nodes.
-        """
-        for name in node._fields:
-            field = getattr(node, name, None)
-            if isinstance(field, astcls):
-                yield field
-            elif isinstance(field, list):
-                for item in field:
-                    yield item
-
-
-class Binding(object):
-    """
-    Represents the binding of a value to a name.
-
-    The checker uses this to keep track of which names have been bound and
-    which names have not. See L{Assignment} for a special type of binding that
-    is checked with stricter rules.
-
-    @ivar used: pair of (L{Scope}, line-number) indicating the scope and
-                line number that this binding was last used
-    """
-
-    def __init__(self, name, source):
-        self.name = name
-        self.source = source
-        self.used = False
-
-
-    def __str__(self):
-        return self.name
-
-
-    def __repr__(self):
-        return '<%s object %r from line %r at 0x%x>' % (self.__class__.__name__,
-                                                        self.name,
-                                                        self.source.lineno,
-                                                        id(self))
-
-
-
-class UnBinding(Binding):
-    '''Created by the 'del' operator.'''
-
-
-
-class Importation(Binding):
-    """
-    A binding created by an import statement.
-
-    @ivar fullName: The complete name given to the import statement,
-        possibly including multiple dotted components.
-    @type fullName: C{str}
-    """
-    def __init__(self, name, source):
-        self.fullName = name
-        name = name.split('.')[0]
-        super(Importation, self).__init__(name, source)
-
-
-
-class Argument(Binding):
-    """
-    Represents binding a name as an argument.
-    """
-
-
-
-class Assignment(Binding):
-    """
-    Represents binding a name with an explicit assignment.
-
-    The checker will raise warnings for any Assignment that isn't used. Also,
-    the checker does not consider assignments in tuple/list unpacking to be
-    Assignments, rather it treats them as simple Bindings.
-    """
-
-
-
-class FunctionDefinition(Binding):
-    _property_decorator = False
-
-
-
-class ExportBinding(Binding):
-    """
-    A binding created by an C{__all__} assignment.  If the names in the list
-    can be determined statically, they will be treated as names for export and
-    additional checking applied to them.
-
-    The only C{__all__} assignment that can be recognized is one which takes
-    the value of a literal list containing literal strings.  For example::
-
-        __all__ = ["foo", "bar"]
-
-    Names which are imported and not otherwise used but appear in the value of
-    C{__all__} will not have an unused import warning reported for them.
-    """
-    def names(self):
-        """
-        Return a list of the names referenced by this binding.
-        """
-        names = []
-        if isinstance(self.source, _ast.List):
-            for node in self.source.elts:
-                if isinstance(node, _ast.Str):
-                    names.append(node.s)
-        return names
-
-
-
-class Scope(dict):
-    importStarred = False       # set to True when import * is found
-
-
-    def __repr__(self):
-        return '<%s at 0x%x %s>' % (self.__class__.__name__, id(self), dict.__repr__(self))
-
-
-    def __init__(self):
-        super(Scope, self).__init__()
-
-
-
-class ClassScope(Scope):
-    pass
-
-
-
-class FunctionScope(Scope):
-    """
-    I represent a name scope for a function.
-
-    @ivar globals: Names declared 'global' in this function.
-    """
-    def __init__(self):
-        super(FunctionScope, self).__init__()
-        self.globals = {}
-
-
-
-class ModuleScope(Scope):
-    pass
-
-
-# Globally defined names which are not attributes of the __builtin__ module.
-_MAGIC_GLOBALS = ['__file__', '__builtins__']
-
-
-
-class Checker(object):
-    """
-    I check the cleanliness and sanity of Python code.
-
-    @ivar _deferredFunctions: Tracking list used by L{deferFunction}.  Elements
-        of the list are two-tuples.  The first element is the callable passed
-        to L{deferFunction}.  The second element is a copy of the scope stack
-        at the time L{deferFunction} was called.
-
-    @ivar _deferredAssignments: Similar to C{_deferredFunctions}, but for
-        callables which are deferred assignment checks.
-    """
-
-    nodeDepth = 0
-    traceTree = False
-
-    def __init__(self, tree, filename=None):
-        if filename is None:
-            filename = '(none)'
-        self._deferredFunctions = []
-        self._deferredAssignments = []
-        self.dead_scopes = []
-        self.messages = []
-        self.filename = filename
-        self.scopeStack = [ModuleScope()]
-        self.futuresAllowed = True
-        self.handleChildren(tree)
-        self._runDeferred(self._deferredFunctions)
-        # Set _deferredFunctions to None so that deferFunction will fail
-        # noisily if called after we've run through the deferred functions.
-        self._deferredFunctions = None
-        self._runDeferred(self._deferredAssignments)
-        # Set _deferredAssignments to None so that deferAssignment will fail
-        # noisly if called after we've run through the deferred assignments.
-        self._deferredAssignments = None
-        del self.scopeStack[1:]
-        self.popScope()
-        self.check_dead_scopes()
-
-
-    def deferFunction(self, callable):
-        '''
-        Schedule a function handler to be called just before completion.
-
-        This is used for handling function bodies, which must be deferred
-        because code later in the file might modify the global scope. When
-        `callable` is called, the scope at the time this is called will be
-        restored, however it will contain any new bindings added to it.
-        '''
-        self._deferredFunctions.append((callable, self.scopeStack[:]))
-
-
-    def deferAssignment(self, callable):
-        """
-        Schedule an assignment handler to be called just after deferred
-        function handlers.
-        """
-        self._deferredAssignments.append((callable, self.scopeStack[:]))
-
-
-    def _runDeferred(self, deferred):
-        """
-        Run the callables in C{deferred} using their associated scope stack.
-        """
-        for handler, scope in deferred:
-            self.scopeStack = scope
-            handler()
-
-
-    def scope(self):
-        return self.scopeStack[-1]
-    scope = property(scope)
-
-    def popScope(self):
-        self.dead_scopes.append(self.scopeStack.pop())
-
-
-    def check_dead_scopes(self):
-        """
-        Look at scopes which have been fully examined and report names in them
-        which were imported but unused.
-        """
-        for scope in self.dead_scopes:
-            export = isinstance(scope.get('__all__'), ExportBinding)
-            if export:
-                all = scope['__all__'].names()
-                if os.path.split(self.filename)[1] != '__init__.py':
-                    # Look for possible mistakes in the export list
-                    undefined = set(all) - set(scope)
-                    for name in undefined:
-                        self.report(
-                            messages.UndefinedExport,
-                            scope['__all__'].source,
-                            name)
-            else:
-                all = []
-
-            # Look for imported names that aren't used.
-            for importation in scope.itervalues():
-                if isinstance(importation, Importation):
-                    if not importation.used and importation.name not in all:
-                        self.report(
-                            messages.UnusedImport,
-                            importation.source,
-                            importation.name)
-
-
-    def pushFunctionScope(self):
-        self.scopeStack.append(FunctionScope())
-
-    def pushClassScope(self):
-        self.scopeStack.append(ClassScope())
-
-    def report(self, messageClass, *args, **kwargs):
-        self.messages.append(messageClass(self.filename, *args, **kwargs))
-
-    def handleChildren(self, tree):
-        for node in iter_child_nodes(tree):
-            self.handleNode(node, tree)
-
-    def isDocstring(self, node):
-        """
-        Determine if the given node is a docstring, as long as it is at the
-        correct place in the node tree.
-        """
-        return isinstance(node, _ast.Str) or \
-               (isinstance(node, _ast.Expr) and
-                isinstance(node.value, _ast.Str))
-
-    def handleNode(self, node, parent):
-        node.parent = parent
-        if self.traceTree:
-            print '  ' * self.nodeDepth + node.__class__.__name__
-        self.nodeDepth += 1
-        if self.futuresAllowed and not \
-               (isinstance(node, _ast.ImportFrom) or self.isDocstring(node)):
-            self.futuresAllowed = False
-        nodeType = node.__class__.__name__.upper()
-        try:
-            handler = getattr(self, nodeType)
-            handler(node)
-        finally:
-            self.nodeDepth -= 1
-        if self.traceTree:
-            print '  ' * self.nodeDepth + 'end ' + node.__class__.__name__
-
-    def ignore(self, node):
-        pass
-
-    # "stmt" type nodes
-    RETURN = DELETE = PRINT = WHILE = IF = WITH = RAISE = TRYEXCEPT = \
-        TRYFINALLY = ASSERT = EXEC = EXPR = handleChildren
-
-    CONTINUE = BREAK = PASS = ignore
-
-    # "expr" type nodes
-    BOOLOP = BINOP = UNARYOP = IFEXP = DICT = SET = YIELD = COMPARE = \
-    CALL = REPR = ATTRIBUTE = SUBSCRIPT = LIST = TUPLE = handleChildren
-
-    NUM = STR = ELLIPSIS = ignore
-
-    # "slice" type nodes
-    SLICE = EXTSLICE = INDEX = handleChildren
-
-    # expression contexts are node instances too, though being constants
-    LOAD = STORE = DEL = AUGLOAD = AUGSTORE = PARAM = ignore
-
-    # same for operators
-    AND = OR = ADD = SUB = MULT = DIV = MOD = POW = LSHIFT = RSHIFT = \
-    BITOR = BITXOR = BITAND = FLOORDIV = INVERT = NOT = UADD = USUB = \
-    EQ = NOTEQ = LT = LTE = GT = GTE = IS = ISNOT = IN = NOTIN = ignore
-
-    # additional node types
-    COMPREHENSION = EXCEPTHANDLER = KEYWORD = handleChildren
-
-    def addBinding(self, loc, value, reportRedef=True):
-        '''Called when a binding is altered.
-
-        - `loc` is the location (an object with lineno and optionally
-          col_offset attributes) of the statement responsible for the change
-        - `value` is the optional new value, a Binding instance, associated
-          with the binding; if None, the binding is deleted if it exists.
-        - if `reportRedef` is True (default), rebinding while unused will be
-          reported.
-        '''
-        if (isinstance(self.scope.get(value.name), FunctionDefinition)
-                    and isinstance(value, FunctionDefinition)):
-            if not value._property_decorator:
-                self.report(messages.RedefinedFunction,
-                            loc, value.name, self.scope[value.name].source)
-
-        if not isinstance(self.scope, ClassScope):
-            for scope in self.scopeStack[::-1]:
-                existing = scope.get(value.name)
-                if (isinstance(existing, Importation)
-                        and not existing.used
-                        and (not isinstance(value, Importation) or value.fullName == existing.fullName)
-                        and reportRedef):
-
-                    self.report(messages.RedefinedWhileUnused,
-                                loc, value.name, scope[value.name].source)
-
-        if isinstance(value, UnBinding):
-            try:
-                del self.scope[value.name]
-            except KeyError:
-                self.report(messages.UndefinedName, loc, value.name)
-        else:
-            self.scope[value.name] = value
-
-    def GLOBAL(self, node):
-        """
-        Keep track of globals declarations.
-        """
-        if isinstance(self.scope, FunctionScope):
-            self.scope.globals.update(dict.fromkeys(node.names))
-
-    def LISTCOMP(self, node):
-        # handle generators before element
-        for gen in node.generators:
-            self.handleNode(gen, node)
-        self.handleNode(node.elt, node)
-
-    GENERATOREXP = SETCOMP = LISTCOMP
-
-    # dictionary comprehensions; introduced in Python 2.7
-    def DICTCOMP(self, node):
-        for gen in node.generators:
-            self.handleNode(gen, node)
-        self.handleNode(node.key, node)
-        self.handleNode(node.value, node)
-
-    def FOR(self, node):
-        """
-        Process bindings for loop variables.
-        """
-        vars = []
-        def collectLoopVars(n):
-            if isinstance(n, _ast.Name):
-                vars.append(n.id)
-            elif isinstance(n, _ast.expr_context):
-                return
-            else:
-                for c in iter_child_nodes(n):
-                    collectLoopVars(c)
-
-        collectLoopVars(node.target)
-        for varn in vars:
-            if (isinstance(self.scope.get(varn), Importation)
-                    # unused ones will get an unused import warning
-                    and self.scope[varn].used):
-                self.report(messages.ImportShadowedByLoopVar,
-                            node, varn, self.scope[varn].source)
-
-        self.handleChildren(node)
-
-    def NAME(self, node):
-        """
-        Handle occurrence of Name (which can be a load/store/delete access.)
-        """
-        # Locate the name in locals / function / globals scopes.
-        if isinstance(node.ctx, (_ast.Load, _ast.AugLoad)):
-            # try local scope
-            importStarred = self.scope.importStarred
-            try:
-                self.scope[node.id].used = (self.scope, node)
-            except KeyError:
-                pass
-            else:
-                return
-
-            # try enclosing function scopes
-
-            for scope in self.scopeStack[-2:0:-1]:
-                importStarred = importStarred or scope.importStarred
-                if not isinstance(scope, FunctionScope):
-                    continue
-                try:
-                    scope[node.id].used = (self.scope, node)
-                except KeyError:
-                    pass
-                else:
-                    return
-
-            # try global scope
-
-            importStarred = importStarred or self.scopeStack[0].importStarred
-            try:
-                self.scopeStack[0][node.id].used = (self.scope, node)
-            except KeyError:
-                if ((not hasattr(__builtin__, node.id))
-                        and node.id not in _MAGIC_GLOBALS
-                        and not importStarred):
-                    if (os.path.basename(self.filename) == '__init__.py' and
-                        node.id == '__path__'):
-                        # the special name __path__ is valid only in packages
-                        pass
-                    else:
-                        self.report(messages.UndefinedName, node, node.id)
-        elif isinstance(node.ctx, (_ast.Store, _ast.AugStore)):
-            # if the name hasn't already been defined in the current scope
-            if isinstance(self.scope, FunctionScope) and node.id not in self.scope:
-                # for each function or module scope above us
-                for scope in self.scopeStack[:-1]:
-                    if not isinstance(scope, (FunctionScope, ModuleScope)):
-                        continue
-                    # if the name was defined in that scope, and the name has
-                    # been accessed already in the current scope, and hasn't
-                    # been declared global
-                    if (node.id in scope
-                            and scope[node.id].used
-                            and scope[node.id].used[0] is self.scope
-                            and node.id not in self.scope.globals):
-                        # then it's probably a mistake
-                        self.report(messages.UndefinedLocal,
-                                    scope[node.id].used[1],
-                                    node.id,
-                                    scope[node.id].source)
-                        break
-
-            if isinstance(node.parent,
-                          (_ast.For, _ast.comprehension, _ast.Tuple, _ast.List)):
-                binding = Binding(node.id, node)
-            elif (node.id == '__all__' and
-                  isinstance(self.scope, ModuleScope)):
-                binding = ExportBinding(node.id, node.parent.value)
-            else:
-                binding = Assignment(node.id, node)
-            if node.id in self.scope:
-                binding.used = self.scope[node.id].used
-            self.addBinding(node, binding)
-        elif isinstance(node.ctx, _ast.Del):
-            if isinstance(self.scope, FunctionScope) and \
-                   node.id in self.scope.globals:
-                del self.scope.globals[node.id]
-            else:
-                self.addBinding(node, UnBinding(node.id, node))
-        else:
-            # must be a Param context -- this only happens for names in function
-            # arguments, but these aren't dispatched through here
-            raise RuntimeError(
-                "Got impossible expression context: %r" % (node.ctx,))
-
-
-    def FUNCTIONDEF(self, node):
-        # the decorators attribute is called decorator_list as of Python 2.6
-        if hasattr(node, 'decorators'):
-            for deco in node.decorators:
-                self.handleNode(deco, node)
-        else:
-            for deco in node.decorator_list:
-                self.handleNode(deco, node)
-
-        # Check for property decorator
-        func_def = FunctionDefinition(node.name, node)
-        for decorator in node.decorator_list:
-            if getattr(decorator, 'attr', None) in ('setter', 'deleter'):
-                func_def._property_decorator = True
-
-        self.addBinding(node, func_def)
-        self.LAMBDA(node)
-
-    def LAMBDA(self, node):
-        for default in node.args.defaults:
-            self.handleNode(default, node)
-
-        def runFunction():
-            args = []
-
-            def addArgs(arglist):
-                for arg in arglist:
-                    if isinstance(arg, _ast.Tuple):
-                        addArgs(arg.elts)
-                    else:
-                        if arg.id in args:
-                            self.report(messages.DuplicateArgument,
-                                        node, arg.id)
-                        args.append(arg.id)
-
-            self.pushFunctionScope()
-            addArgs(node.args.args)
-            # vararg/kwarg identifiers are not Name nodes
-            if node.args.vararg:
-                args.append(node.args.vararg)
-            if node.args.kwarg:
-                args.append(node.args.kwarg)
-            for name in args:
-                self.addBinding(node, Argument(name, node), reportRedef=False)
-            if isinstance(node.body, list):
-                # case for FunctionDefs
-                for stmt in node.body:
-                    self.handleNode(stmt, node)
-            else:
-                # case for Lambdas
-                self.handleNode(node.body, node)
-            def checkUnusedAssignments():
-                """
-                Check to see if any assignments have not been used.
-                """
-                for name, binding in self.scope.iteritems():
-                    if (not binding.used and not name in self.scope.globals
-                        and isinstance(binding, Assignment)):
-                        self.report(messages.UnusedVariable,
-                                    binding.source, name)
-            self.deferAssignment(checkUnusedAssignments)
-            self.popScope()
-
-        self.deferFunction(runFunction)
-
-
-    def CLASSDEF(self, node):
-        """
-        Check names used in a class definition, including its decorators, base
-        classes, and the body of its definition.  Additionally, add its name to
-        the current scope.
-        """
-        # decorator_list is present as of Python 2.6
-        for deco in getattr(node, 'decorator_list', []):
-            self.handleNode(deco, node)
-        for baseNode in node.bases:
-            self.handleNode(baseNode, node)
-        self.pushClassScope()
-        for stmt in node.body:
-            self.handleNode(stmt, node)
-        self.popScope()
-        self.addBinding(node, Binding(node.name, node))
-
-    def ASSIGN(self, node):
-        self.handleNode(node.value, node)
-        for target in node.targets:
-            self.handleNode(target, node)
-
-    def AUGASSIGN(self, node):
-        # AugAssign is awkward: must set the context explicitly and visit twice,
-        # once with AugLoad context, once with AugStore context
-        node.target.ctx = _ast.AugLoad()
-        self.handleNode(node.target, node)
-        self.handleNode(node.value, node)
-        node.target.ctx = _ast.AugStore()
-        self.handleNode(node.target, node)
-
-    def IMPORT(self, node):
-        for alias in node.names:
-            name = alias.asname or alias.name
-            importation = Importation(name, node)
-            self.addBinding(node, importation)
-
-    def IMPORTFROM(self, node):
-        if node.module == '__future__':
-            if not self.futuresAllowed:
-                self.report(messages.LateFutureImport, node,
-                            [n.name for n in node.names])
-        else:
-            self.futuresAllowed = False
-
-        for alias in node.names:
-            if alias.name == '*':
-                self.scope.importStarred = True
-                self.report(messages.ImportStarUsed, node, node.module)
-                continue
-            name = alias.asname or alias.name
-            importation = Importation(name, node)
-            if node.module == '__future__':
-                importation.used = (self.scope, node)
-            self.addBinding(node, importation)

BIN
pylibs/pyflakes/checker.pyc


+ 0 - 106
pylibs/pyflakes/messages.py

@@ -1,106 +0,0 @@
-# (c) 2005 Divmod, Inc.  See LICENSE file for details
-
-class Message(object):
-    message = ''
-    message_args = ()
-    def __init__(self, filename, loc, use_column=True):
-        self.filename = filename
-        self.lineno = loc.lineno
-        self.col = getattr(loc, 'col_offset', None) if use_column else None
-
-    def __str__(self):
-        return '%s:%s: %s' % (self.filename, self.lineno, self.message % self.message_args)
-
-
-class UnusedImport(Message):
-    message = 'W402 %r imported but unused'
-
-    def __init__(self, filename, lineno, name):
-        Message.__init__(self, filename, lineno)
-        self.message_args = (name,)
-
-
-class RedefinedWhileUnused(Message):
-    message = 'W801 redefinition of unused %r from line %r'
-
-    def __init__(self, filename, lineno, name, orig_lineno):
-        Message.__init__(self, filename, lineno)
-        self.message_args = (name, orig_lineno)
-
-
-class ImportShadowedByLoopVar(Message):
-    message = 'W403 import %r from line %r shadowed by loop variable'
-
-    def __init__(self, filename, lineno, name, orig_lineno):
-        Message.__init__(self, filename, lineno)
-        self.message_args = (name, orig_lineno)
-
-
-class ImportStarUsed(Message):
-    message = "W404 'from %s import *' used; unable to detect undefined names"
-
-    def __init__(self, filename, lineno, modname):
-        Message.__init__(self, filename, lineno)
-        self.message_args = (modname,)
-
-
-class UndefinedName(Message):
-    message = 'W802 undefined name %r'
-
-    def __init__(self, filename, lineno, name):
-        Message.__init__(self, filename, lineno)
-        self.message_args = (name,)
-
-
-class UndefinedExport(Message):
-    message = 'W803 undefined name %r in __all__'
-
-    def __init__(self, filename, lineno, name):
-        Message.__init__(self, filename, lineno)
-        self.message_args = (name,)
-
-
-class UndefinedLocal(Message):
-    message = "W804 local variable %r (defined in enclosing scope on line " \
-            "%r) referenced before assignment"
-
-    def __init__(self, filename, lineno, name, orig_lineno):
-        Message.__init__(self, filename, lineno)
-        self.message_args = (name, orig_lineno)
-
-
-class DuplicateArgument(Message):
-    message = 'W805 duplicate argument %r in function definition'
-
-    def __init__(self, filename, lineno, name):
-        Message.__init__(self, filename, lineno)
-        self.message_args = (name,)
-
-
-class RedefinedFunction(Message):
-    message = 'W806 redefinition of function %r from line %r'
-
-    def __init__(self, filename, lineno, name, orig_lineno):
-        Message.__init__(self, filename, lineno)
-        self.message_args = (name, orig_lineno)
-
-
-class LateFutureImport(Message):
-    message = 'W405 future import(s) %r after other statements'
-
-    def __init__(self, filename, lineno, names):
-        Message.__init__(self, filename, lineno)
-        self.message_args = (names,)
-
-
-class UnusedVariable(Message):
-    """
-    Indicates that a variable has been explicity assigned to but not actually
-    used.
-    """
-
-    message = 'W806 local variable %r is assigned to but never used'
-
-    def __init__(self, filename, lineno, names):
-        Message.__init__(self, filename, lineno)
-        self.message_args = (names,)

BIN
pylibs/pyflakes/messages.pyc


+ 0 - 70
pylibs/pylint/README

@@ -1,70 +0,0 @@
-README for PyLint
-=================
-
-Dependencies
-------------
-Pylint requires the logilab-astng (version >= 0.21.0), logilab-common
-(version >= 0.53).
-
-* http://www.logilab.org/projects/astng
-* http://www.logilab.org/projects/common
-
-Install
--------
-From the source distribution, extract the tarball and run ::
-
-    python setup.py install
-
-You'll have to install dependencies in a similar way. For debian and
-rpm packages, use your usual tools according to your Linux distribution.
-
-More information about installation and available distribution format
-may be found in the user manual in the *doc* subdirectory.
-
-Documentation
--------------
-Look in the doc/ subdirectory or at the project home page
-http://www.logilab.org/project/pylint
-
-Pylint is shipped with following additional commands:
-
-* pyreverse: an UML diagram generator
-* symilar: an independent similarities checker
-* epylint: Emacs and Flymake compatible Pylint
-* pylint-gui: a graphical interface
-
-Comments, support, bug reports
-------------------------------
-
-Project page and tracker on :
-http://www.logilab.org/project/pylint
-
-Use the python-projects@logilab.org mailing list.
-You can subscribe to this mailing list at
-http://lists.logilab.org/mailman/listinfo/python-projects
-
-Archives are available at
-http://lists.logilab.org/pipermail/python-projects/
-
-Contributors
-------------
-
-order doesn't matter...
-
-* Sylvain Thenault: main author / maintainer
-* Alexandre Fayolle: TkInter gui, documentation, debian support
-* Emile Anclin: used to maintain, py3k support
-* Mads Kiilerich: various patches
-* Torsten Marek, various patches
-* Boris Feld, various patches
-* Brian van den Broek: windows installation documentation
-* Amaury Forgeot d'Arc: patch to check names imported from a module
-  exists in the module
-* Benjamin Niemann: patch to allow block level enabling/disabling of messages
-* Nathaniel Manista: suspicious lambda checking
-* Wolfgang Grafen, Axel Muller, Fabio Zadrozny, Pierre Rouleau,
-  Maarten ter Huurne, Mirko Friedenhagen (among others):
-  bug reports, feedback, feature requests...
-* All the Logilab's team: daily use, bug reports, feature requests
-* Other people have contributed by their feedback, if I've forgotten
-  you, send me a note !

+ 0 - 37
pylibs/pylint/README.Python3

@@ -1,37 +0,0 @@
-Python3
-=======
-
-Compatibility
--------------
-
-Please, consider python3 >= 3.2 only.
-
-
-Approach
---------
-
-We maintain a Python 2 base and use 2to3 to generate Python 3 code.
-
-2to3 is integrated into the distutils installation process and will be run as a
-build step when invoked by the python3 interpreter::
-
-  NO_SETUPTOOLS=1 python3 setup.py install --no-compile
-
-In order to run pylint locally, you have to install the dependencies::
-
-  easy_install-3.2 logilab-common
-  easy_install-3.2 logilab-astng
-
-
-Debian
-------
-
-For the Debian packaging, you can use the debian.py3k/ content against
-the debian/ folder::
-
-  cp debian.py3k/* debian/
-
-
-Resources
----------
-http://wiki.python.org/moin/PortingPythonToPy3k

+ 0 - 0
pylibs/pylint/__init__.py


Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików